npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-composition-crud

v1.22.1

Published

CRUD API Composables for Vue

Downloads

7

Readme

Vue Composition CRUD

This package supplies modules and classes to allow for easy interaction with a CRUD-based API, including Vue Composition providers.

Installation

yarn add vue-composition-crud

API Documentation

Full API documentation is created with typedoc and can be generated by running yarn docs.

The latest full API documentation is generated as part of the CI/CD pipeline.

Documentation generated on demand is placed in the docs folder.

Overview of Key Package Contents

API

The API class supplies a layer to provide HTTP(S) operations, which can be augmented with middleware.

The API class emits the following events:

  • authenticated - when an authentication provider handles the authentication operation
  • authentication-failed - when a request fails due to a 401 HTTP error
  • deauthenticated - when an authentication provider handles the deauthentication operation
  • request-failed - when a request fails due to a different HTTP error

Middleware

Middlware classes are used to provide additional functionality when performing requests. This can include things like:

  • performing authentication
  • tweaking request and response URLs, headers, and content
  • performing logging operations

The built-in middleware currently includes:

  • SessionAuthenticationMiddleware - authenticate with a username and password, and then persist the session with a cookie.
  • TokenAuthenticationMiddleware - authenticate with either a username and password, or an access and/or refresh token, or an API key, and then persist the session by supplying a bearer token header with each request.
  • CsrfTokenMiddleware - receive a CSRF token from a header, a cookie, or by supplying a custom function to retrieve the value, and then send the CSRF token when making requests by supplying it as a request header or injecting it into the body of the request.
  • TrailingSlashMiddleware - tweak all outgoing URLs to either include or not include trailing slashes.
  • PageMiddlware - advanced pagination features to allow you to use the built-in pagination class with APIs that don't supply objects in exactly the same way as expected. This allows for the use of an offset-limit style pagniation system, allows the transformation of query parameters, and allows for the response from the remote server to be mapped to an object that has the shape that this package expects.

Composables

useApi

useApi(options, middlewares) => {
    api: Ref<CrudApi>
}

Creates a new Api instance and returns it as a Ref.

useGlobalApi

useGlobalApi(options, middlewares) => {
    api: Ref<CrudApi>
}

The same as useApi, but creates a global instance. The first time you call this, it will create the API instance and initialize the ref. Every subsequent call to this function simply retrieves the initial ref. I'd recommend using provide() and inject() over a global mechanism, but some people are into it, so here you go.

useResource

useResource<ItemType>(api, resourceName) => {
    isUnloaded: Ref<boolean>,
    isLoading: Ref<boolean>,
    isLoaded: Ref<boolean>,
    isFailed: Ref<boolean>,
    error: Ref<Error>,
    item: Ref<ItemType>,
    createItem(value: ItemType): Promise<ItemType>,
    retrieveItem(id: string | number): Promise<ItemType>,
    updateItem(id: string | number, value: ItemType): Promise<ItemType>,
    deleteItem(id: string | number): Promise<void>,
}

Create a resource to handle Create, Retrieve, Update, and Delete (CRUD) operations for a specific API resource.

The resourceName parameter is just the API endpoint name, and is appended to the Base URL that is supplied when you create the Api instance with new Api({...}) or useApi({...}). For example, if your URL was https://www.example.com/api/users, then the baseUrl would be https://www.example.com/api/, and the resourceName would be users.

The four boolean refs are used to determine the current state of the resource.

  • isUnloaded is true when the resource has not yet been used.
  • isLoading is true when any CRUD operation is being performed.
  • isLoaded is true when any CRUD operation completes successfully.
  • isFailed is true when any CRUD operation fails.
  • error is the last error object thrown to cause the CRUD operation to fail.
  • item is set to the content of the resource when a create, retrieve, or update operation completes successfully. item is cleared when a delete operation completes successfully.
  • createItem, retrieveItem, updateItem, and deleteItem call upon the underlying API instance to perform the relevant queries. These queries match to POST, GET, PATCH, and DELETE HTTP method operations.

useCollection

useCollection<ItemType>(api, resourceName) => {
    isUnloaded: Ref<boolean>,
    isLoading: Ref<boolean>,
    isLoaded: Ref<boolean>,
    isFailed: Ref<boolean>,
    error: Ref<Error>,
    items: Ref<Array<ItemType>>,
    listItems(queryOptions): Promise<Array<ItemType>>,
}

Create a collection to perform list operations against a specific API resource.

Most of the returned refs are the same as in useResource. The notable differences are that:

  • Instead of a single resource item, you have an array of items
  • Instead of CRUD methods, you have a listItems method

The listItems method allows you to supply queryOptions, which can be used to search and filter the resultset on the server side. For example:

const collection = useCollection
collection.listItems({search: "my search text", filter: {"name": "john", "age": "33"}})

usePage

usePage<ItemType>(api, resourceName) => {
    isUnloaded: Ref<boolean>,
    isLoading: Ref<boolean>,
    isLoaded: Ref<boolean>,
    isFailed: Ref<boolean>,
    error: Ref<Error>,
    page: Ref<Page<ItemType>>,
    items: Ref<Array<ItemType>>,
    listItems(queryOptions): Promise<Page<ItemType>>,
}

Much the same as useCollection, but instead of expecting an array of items, this expects a Page. One page supplies a subset of results, as well as some extra details like what the next page is, the total number of pages, and any metadata that the remote server might like to supply.

The items ref will be updated with the current set of items based on the page that is being viewed.

The expected structure of a Page response is:

{
    page: {
        previous?: number;
        current: number;
        next?: number;
        last?: number;
    };
    items: Array<ItemType>;
    meta?: unknown;
}

Basic Usage

/*
 * symbols.ts
 */

// Define the `API` symbol, which is used to provide
// and inject an api instance in Vue components.
export const API = Symbol("API");
<!--
  -- App.vue
  -->

<template>
...
</template>

<script lang="ts">
import { ref, provide, defineComponent } from "vue";
import { useApi } from "vue-composition-crud";
import { API } from "./symbols.ts"

export default defineComponent({
    setup() {
        // Create an API instance.
        // Note that the `useApi` composition method gives
        // you a Ref<CrudApi> instance so to use it you will
        // need to call `api.value.xxxx()`
        const { api } = useApi({
            baseUrl: "https://www.example.com/api/",
        });

        // Supply the `api` instance to all children using
        // the `API` symbol as a key.
        provide(API, api);

        return {};
    }
})
</script>
<!--
  -- UserInformation.vue
  -->

<template>
    <div v-if="resource.isLoading.value">Loading - just a moment...</div>
    <div v-if="resource.isFailed.value">Loading failed: {{ resource.error.value }}</div>
    <div v-if="resource.isLoaded.value">
        <h1>{{ user.name }}</h1>
        <h2>{{ user.age }} years old</h2>
        <address>{{ user.address }}</address>
        <div>
            <a :href="'mailto:' + user.email">{{ user.email }}</a>
        </div>
    </div>
</template>

<script lang="ts">
import { Ref, inject, defineComponent, onMounted } from "vue";
import { useApi, useResource, CrudApi } from "vue-composition-crud";
import { CrudApi } from "vue-composition-crud/api/types";
import { API } from "./symbols.ts"

export default defineComponent({
    setup() {
        // Inject the `api` instance from the parent context.
        // Remember that this is a `Ref<CrudApi>` instance.
        const api = inject(API) as Ref<CrudApi>;
        
        // Use the API *value* to set up the useful composition
        // elements like lists, pages, and resources.
        const resource = useResource(api.value, "users");

        // When the component is mounted, load user #123
        onMounted(() => {
            resource.retrieve(123)
        })

        // Supply the interesting stuff (e.g., the resource) to
        // the component.
        return {
            resource,
            user: resource.item.value,
        }
    },

})
</script>

Examples

Typescript

This package is developed in typescript, compiled down to javascript, and supplies declaration files.

Testing

This package uses mocha and chai for testing.

Tests can be run with yarn test and code coverage can be generated with yarn coverage.

The latest coverage reports are generated as part of the CI/CD pipeline.