Skip to content

Proxy

A Proxy is the transport layer of the data stack. Stores ask the proxy to fetch records; the proxy returns raw data which the store turns into records.

Two proxies ship with the package:

MemoryProxy

Use this when you have data already in JavaScript (test fixtures, static lists, embedded JSON). For convenience, you can usually skip it and use MemoryStore directly.

typescript
import { MemoryProxy, Store } from '@jimka/typescript-ui/data';
const proxy = new MemoryProxy({
    data: [
        { id: 1, name: 'Alice' },
        { id: 2, name: 'Bob' },
    ],
});

const store = new Store(PersonModel, proxy);
await store.load();

See MemoryProxyOptions for the full options. The legacy alias MemoryProxyConfig remains as a deprecated type re-export.

AjaxProxy

Fetches JSON over HTTP via the browser's fetch API. For convenience, you can usually skip the proxy and use AjaxStore directly, which constructs the proxy from the same config.

typescript
import { AjaxProxy, Store } from '@jimka/typescript-ui/data';
const proxy = new AjaxProxy({
    url:    '/api/people',
    root:   'data',         // extract response.data instead of using the whole body
    method: 'GET',          // default
});

const store = new Store(PersonModel, proxy);
await store.load();
OptionPurpose
urlEndpoint URL
methodHTTP method (default GET)
rootJSON path to the records array (e.g. 'data' for { data: [...] })

See AjaxProxyOptions for the complete option list. The legacy alias AjaxProxyConfig remains as a deprecated type re-export.

Server-side pagination

When the Store has had setPageSize(n) called on it, the store's load() forwards a ReadParams object to proxy.read(). AjaxProxy appends page and pageSize as query-string parameters and expects an envelope response:

json
{ "data": [...], "total": 1234 }

Stores that never call setPageSize are unaffected — read() is still called with no arguments and the response shape is the legacy top-level array (or json[root]).

typescript
const store = new Store(PersonModel, new AjaxProxy({ url: '/api/people' }));
store.setPageSize(25);
await store.load();
// → GET /api/people?page=1&pageSize=25
// → response: { data: [...], total: 1234 }

If root is configured, the envelope is read from json[root] first, then .data and .total are extracted. The total count is exposed on the store via getTotalCount() and getTotalPages(), and on the proxy itself via getLastTotalCount().

Custom proxies

Subclass Proxy and implement load(). This is the path for GraphQL, WebSocket, IndexedDB, or any other transport.

typescript
import { Proxy } from '@jimka/typescript-ui/data';
class GraphQLProxy extends Proxy {
    constructor(private query: string) { super(); }

    async load() {
        const res = await fetch('/graphql', {
            method:  'POST',
            headers: { 'Content-Type': 'application/json' },
            body:    JSON.stringify({ query: this.query }),
        });
        const json = await res.json();
        return json.data.results;
    }
}

Pass the custom proxy to a Store like any built-in proxy.

See also

  • Store — uses a proxy under the hood.
  • Model — defines the shape the proxy's data must match.