Socket
Book a DemoInstallSign in
Socket

@tcn/resource-store

Package Overview
Dependencies
Maintainers
6
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tcn/resource-store

TCN FE Template

latest
npmnpm
Version
2.2.0
Version published
Weekly downloads
604
142.57%
Maintainers
6
Weekly downloads
 
Created
Source

Resource Stores

Table of Contents

  • Overview
  • Core Concepts
  • Usage Examples

Overview

This package defines some useful interfaces for working with AIP resources, and some concrete implementations that you can use with the Table and other components.

Core Concepts

ResourceStore

The ResourceStore fills the role of "API Adapter". It is not an interface or implementation, but rather a name we give to a class that has a specific role (similar to Domain or Presenter).

The job of the ResourceStore is to represent a resource, which could be local or remote. This concept is driven by the resource-oriented API design influenced by AIP, similar to the "repository pattern". The ResourceStore insulates the application from where the data comes from.

Key responsibilities:

  • Representing a resource (local or remote)
  • Abstracting data source from application logic
  • Managing caching when needed
  • Providing a 1:1 mapping between API actions and methods

A ResourceStore will typically extend a DataSource implementation, which handles list features according to AIP standards, adding to it actions corresponding to those provided by the REST API. We expect there will generally be a 1:1 relationship between actions surfaced by the API and methods on the ResourceStore.

The ResourceStore instances will be injected into your domain, which may use it directly, and will expose them as properties on itself so the stores are available to presenters. By this pattern, the Domain will often become a "bag of resources", and may contain very little else.

If your application needs to cache entities, the ResourceStore is an appropriate place to manage that caching. In cases where coordination between resources is necessary, each store should stay "pure" to the entity it is intended to represent (unaware of other resources), and the Domain should handle cross-store interactions, surfacing additional methods to the presenters as necessary.

DataSource

The DataSource handles AIP-160 compliant list features, including filtering, sorting, and paging. There are two implementations provided (perhaps more to follow): the AIPDataSource and the StaticDataSource. In each case, you configure the source with the list of fields you wish to work with on the represented entity, and then can page through results, apply a filter, and sort by field.

Important: the DataSource is not aware of or directely attached to a UI view. It might be thought of as a "view" only in database terms (a "view" of a set of data), but since "view" is overloaded, we'll avoid using it in this document. The DataSource does not format, localize, or otherwise prepare data for user consumption.

See the DataSource interface for more details.

Usage Examples

AIPDataSource Example

The AIPDataSource takes two type parameters: AIPDataSource<TLocal, TRemote>. The first represents what the DataSource will present on the table. The second is the incoming type, or the type of the resource as provided from the service. In the field definitions, the getValue function will give you a TRemote, and you should return a field that belongs to TLocal.

const fields = [
  {
    fieldName: 'name',
    sourceFieldName: 'name',
    getValue: (i: AIPOrganization) => i.name,
  },
  {
    fieldName: 'displayName',
    sourceFieldName: 'display_name',
    getValue: (i: AIPOrganization) => i.displayName,
  },
  {
    fieldName: 'billingId',
    sourceFieldName: 'billing_id',
    getValue: (i: AIPOrganization) => i.billingId,
  },
  {
    fieldName: 'clientSid',
    sourceFieldName: 'client_sid',
    getValue: (i: AIPOrganization) => i.clientSid,
  },
  {
    fieldName: 'timeZone',
    sourceFieldName: 'time_zone',
    getValue: (i: AIPOrganization) => i.timeZone,
  },
  {
    fieldName: 'createTime',
    sourceFieldName: 'create_time',
    getValue: (i: AIPOrganization) => new Date(i.createTime),
  },
  {
    fieldName: 'updateTime',
    sourceFieldName: 'update_time',
    getValue: (i: AIPOrganization) => new Date(i.updateTime),
  },
];

return new AIPDataSource<Organization, AIPOrganization>({
  resourceUrl: "https://api.dev.tcn.com/tcn/org/organizations/v1alpha1/organizations",
  resourceName: "organizations",
  fields,
  authToken,
});

For each field, the fieldName will become the property name on the entity, the sourceFieldName corresponds to the property name as defined in the proto (annoying, yes -- we're looking a options to automate that), and getValue allows you to extract the value for the field (including converting timestamps to Dates, etc.).

Because the returned JSON data is untyped, you may wish to define a type for the JSON data, or you may treat the argument to the getValue handler as an explicit any.

StaticDataSource Example

This class presents a local, static array of data as a DataSource, permitting filtering, sorting, and paging.

type DataItem = {
  id: string;
  name: string;
  age: number;
};

const items: DataItem[] = [
  { id: 'one', name: 'Sam Spade', age: 22 },
  { id: 'two', name: 'Kelsior', age: 166 },
  { id: 'three', name: 'Tress', age: 17 },
  { id: 'four', name: 'Breeze', age: 45 },
  { id: 'five', name: 'Spook', age: 17 },
  { id: 'six', name: 'Anne', age: 32 },
  { id: 'seven', name: 'Hoid', age: 1934 },
  { id: 'eight', name: 'Vasher', age: 320 },
];

return new StaticDataSource<DataItem>(items, [
  new StringField('name', i => i.name),
  new NumberField('age', i => i.age),
]);

Note the difference in how field definitions are supplied to the StaticDataSource. In an AIP source, filtering and sorting is handled by the service, but for static data, it is handled in the fields themselves. These fields implement StaticDataSourceField, and are fairly trivial to implement for whatever data type you need to work with.

FAQs

Package last updated on 04 Sep 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts