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

@ember-data-types/store

v5.3.9

Published

Type Declarations for @ember-data/store

Downloads

8,567

Readme

This package provides EmberData's Store class.

The Store coordinates interaction between your application, a Cache, and sources of data (such as your API or a local persistence layer) accessed via a RequestManager.

flowchart LR
    A[fa:fa-terminal App] ===> D{fa:fa-code-fork Store}
    B{{fa:fa-sitemap RequestManager}} <--> C[(fa:fa-database Source)]
    D <--> E[(fa:fa-archive Cache)]
    D <--> B
    click B href "https://github.com/emberjs/data/tree/main/packages/request" "Go to @ember-data/request" _blank
    click E href "https://github.com/emberjs/data/tree/main/packages/json-api" "Go to @ember-data/json-api" _blank
    style B color:#58a6ff;
    style E color:#58a6ff;

Optionally, the Store can be configured to hydrate the response data into rich presentation classes.

flowchart LR
    A[fa:fa-terminal App] --- B(Model)
    A === C{fa:fa-code-fork Store}
    B --- C
    click B href "https://github.com/emberjs/data/tree/main/packages/model" "Go to @ember-data/model" _blank
    style B color:#58a6ff;

Installation

Install using your javascript package manager of choice. For instance with pnpm

pnpm add @ember-data/store

After installing you will want to configure your first Store. Read more below for how to create and configure stores for your application.

Tagged Releases

  • NPM Canary Version
  • NPM Beta Version
  • NPM Stable Version
  • NPM LTS Version
  • NPM LTS 4.12 Version

🔨 Creating A Store

To use a Store we will need to do few things: add a Cache to store data in-memory, add a Handler to fetch data from a source, and implement instantiateRecord to tell the store how to display the data for individual resources.

Note If you are using the package ember-data then a JSON:API cache and instantiateRecord are configured for you by default.

Configuring A Cache

To start, let's install a JSON:API cache. If your app uses GraphQL or REST other caches may better fit your data. You can author your own cache by creating one that conforms to the spec.

The package @ember-data/json-api provides a JSON:API cache we can use. After installing it, we can configure the store to use this cache.

import Store from '@ember-data/store';
import Cache from '@ember-data/json-api';

class extends Store {
  createCache(storeWrapper) {
    return new Cache(storeWrapper);
  }
}

Now that we have a cache let's setup something to handle fetching and saving data via our API.

Note The ember-data package automatically includes and configures the @ember-data/json-api cache for you.

Handling Requests

When EmberData needs to fetch or save data it will pass that request to your application's RequestManager for fulfillment. How this fulfillment occurs (in-memory, device storage, via single or multiple API requests, etc.) is then up to the registered request handlers.

To start, let's install the RequestManager from @ember-data/request and the basic Fetch handler from ``@ember-data/request/fetch`.

Note If your app uses GraphQL, REST or different conventions for JSON:API than your cache expects, other handlers may better fit your data. You can author your own handler by creating one that conforms to the handler interface.

import Store, { CacheHandler } from '@ember-data/store';
import RequestManager from '@ember-data/request';
import Fetch from '@ember-data/request/fetch';

export default class extends Store {
  constructor() {
    super(...arguments);
    this.requestManager = new RequestManager();
    this.requestManager.use([Fetch]);
    this.requestManager.useCache(CacheHandler);
  }
}

Using RequestManager as a Service

Alternatively if you have configured the RequestManager to be a service you may re-use it.

app/services/request.js

import RequestManager from '@ember-data/request';
import { CacheHandler } from '@ember-data/store';
import Fetch from '@ember-data/request/fetch';

export default class extends RequestManager {
  constructor(createArgs) {
    super(createArgs);
    this.use([Fetch]);
    this.useCache(CacheHandler);
  }
}

app/services/store.js

import Store from '@ember-data/store';
import { service } from '@ember/service';

export default class extends Store {
  @service('request') requestManager
}

Presenting Data from the Cache

Now that we have a source and a cach for our data, we need to configure how the Store delivers that data back to our application. We do this via the hook instantiateRecord, which allows us to transform the data for a resource before handing it to the application.

A naive way to present the data would be to return it as JSON. Typically instead this hook will be used to add reactivity and make each unique resource a singleton, ensuring that if the cache updates our presented data will reflect the new state.

Below is an example of using the hooks instantiateRecord and a teardownRecord to provide minimal read-only reactive state for simple resources.

import Store, { recordIdentifierFor } from '@ember-data/store';
import { TrackedObject } from 'tracked-built-ins';

class extends Store {
  instantiateRecord(identifier) {
    const { cache, notifications } = this;

    // create a TrackedObject with our attributes, id and type
    const record = new TrackedObject(Object.assign({}, cache.peek(identifier)));
    record.type = identifier.type;
    record.id = identifier.id;
    
    // update the TrackedObject whenever attributes change
    const token = notifications.subscribe(identifier, (_, change) => {
      if (change === 'attributes') {
        Object.assign(record, cache.peek(identifier));
      }
    });

    record.destroy = () => {
      this.notifications.unsubscribe(token);
    };

    return record;
  }

  teardownRecord(record: FakeRecord) {
    record.destroy();
  }
}

Because instantiateRecord is opaque to the nature of the record, an implementation can be anything from a fairly simple object to a robust proxy that intelligently links together associated records through relationships.

This also enables creating a record that separates edit flows from create flows entirely. A record class might choose to implement a checkout method that gives access to an editable instance while the primary record continues to be read-only and reflect only persisted (non-mutated) state.

Typically you will choose an existing record implementation such as @ember-data/model for your application.

Because of the boundaries around instantiation and the cache, record implementations should be capable of interop both with each other and with any Cache. Due to this, if needed an application can utilize multiple record implementations and multiple cache implementations either to support enhanced features for only a subset of records or to be able to incrementally migrate from one record/cache to another record or cache.

Note The ember-data package automatically includes the @ember-data/model package and configures it for you.