@bjornharrtell/json-api 2.0.4 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +27 -23
  2. package/dist/lib.d.ts +26 -39
  3. package/dist/lib.js +152 -140
  4. package/dist/lib.js.map +1 -1
  5. package/package.json +1 -1
  6. package/dist/docs/.nojekyll +0 -1
  7. package/dist/docs/assets/hierarchy.js +0 -1
  8. package/dist/docs/assets/highlight.css +0 -85
  9. package/dist/docs/assets/icons.js +0 -18
  10. package/dist/docs/assets/icons.svg +0 -1
  11. package/dist/docs/assets/main.js +0 -60
  12. package/dist/docs/assets/navigation.js +0 -1
  13. package/dist/docs/assets/search.js +0 -1
  14. package/dist/docs/assets/style.css +0 -1633
  15. package/dist/docs/classes/Model.html +0 -4
  16. package/dist/docs/enums/RelationshipType.html +0 -3
  17. package/dist/docs/functions/camel.html +0 -2
  18. package/dist/docs/functions/useJsonApi.html +0 -1
  19. package/dist/docs/hierarchy.html +0 -1
  20. package/dist/docs/index.html +0 -11
  21. package/dist/docs/interfaces/FetchOptions.html +0 -7
  22. package/dist/docs/interfaces/FetchParams.html +0 -1
  23. package/dist/docs/interfaces/JsonApiDocument.html +0 -6
  24. package/dist/docs/interfaces/JsonApiError.html +0 -7
  25. package/dist/docs/interfaces/JsonApiFetcher.html +0 -7
  26. package/dist/docs/interfaces/JsonApiLinkObject.html +0 -8
  27. package/dist/docs/interfaces/JsonApiLinks.html +0 -8
  28. package/dist/docs/interfaces/JsonApiMeta.html +0 -8
  29. package/dist/docs/interfaces/JsonApiRelationship.html +0 -2
  30. package/dist/docs/interfaces/JsonApiResource.html +0 -5
  31. package/dist/docs/interfaces/JsonApiResourceIdentifier.html +0 -3
  32. package/dist/docs/interfaces/JsonApiStore.html +0 -14
  33. package/dist/docs/interfaces/JsonApiStoreConfig.html +0 -7
  34. package/dist/docs/interfaces/ModelDefinition.html +0 -7
  35. package/dist/docs/interfaces/PageOption.html +0 -3
  36. package/dist/docs/interfaces/Relationship.html +0 -4
  37. package/dist/docs/modules.html +0 -1
  38. package/dist/docs/types/JsonApiLink.html +0 -1
  39. package/dist/docs/types/JsonApiStoreUseFunction.html +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # json-api
2
2
 
3
- json-api can fetch typed data models via an JSON:API endpoint into record instances.
3
+ json-api can fetch typed data models via a JSON:API endpoint into record instances.
4
4
 
5
5
  An instance is created with an endpoint and model definitions and the instance API provides methods `findAll`, `findRecord` to fetch record(s). Included relationships will be automatically resolved. If relationships for a record are not included they can be fetched later using `findRelated`.
6
6
 
@@ -9,44 +9,45 @@ An instance is created with an endpoint and model definitions and the instance A
9
9
  A service returning the canonical example JSON:API document at https://jsonapi.org/ can be consumed this way:
10
10
 
11
11
  ```ts
12
- import { useJsonApi, Model, type ModelDefinition, RelationshipType } from '@bjornharrtell/json-api'
12
+ import { useJsonApi, type BaseRecord, type ModelDefinition, RelationshipType } from '@bjornharrtell/json-api'
13
13
 
14
- export class Person extends Model {
14
+ export interface Person extends BaseRecord {
15
15
  firstName?: string
16
16
  lastName?: string
17
17
  twitter?: string
18
18
  }
19
19
 
20
- export class Comment extends Model {
20
+ export interface Comment extends BaseRecord {
21
21
  body?: string
22
+ author?: Person | null
22
23
  }
23
24
 
24
- export class Article extends Model {
25
+ export interface Article extends BaseRecord {
25
26
  title?: string
26
- author: Person | null = null
27
- comments: Comment[] = []
27
+ author?: Person | null
28
+ comments?: Comment[]
28
29
  }
29
30
 
30
31
  const modelDefinitions: ModelDefinition[] = [
31
32
  {
32
- type: 'person',
33
- ctor: Person,
33
+ type: 'people',
34
34
  },
35
35
  {
36
- type: 'comment',
37
- ctor: Comment,
36
+ type: 'comments',
37
+ relationships: {
38
+ author: { type: 'people', relationshipType: RelationshipType.BelongsTo },
39
+ },
38
40
  },
39
41
  {
40
- type: 'article',
41
- ctor: Article,
42
- rels: {
43
- author: { ctor: Person, type: RelationshipType.BelongsTo },
44
- comments: { ctor: Comment, type: RelationshipType.HasMany },
42
+ type: 'articles',
43
+ relationships: {
44
+ author: { type: 'people', relationshipType: RelationshipType.BelongsTo },
45
+ comments: { type: 'comments', relationshipType: RelationshipType.HasMany },
45
46
  },
46
47
  },
47
48
  ]
48
49
 
49
- export const aticlesApi = useJsonApi({
50
+ export const articlesApi = useJsonApi({
50
51
  endpoint: 'http://localhost/api',
51
52
  modelDefinitions,
52
53
  })
@@ -55,14 +56,17 @@ export const aticlesApi = useJsonApi({
55
56
  The above can then be used as follows:
56
57
 
57
58
  ```ts
58
- import aticlesApi from './api/articles'
59
- const { records: articles } = await aticlesApi.findAll(Article, { include: ['comments', 'author'] })
59
+ import { articlesApi, type Article } from './api/articles'
60
+
61
+ const { records: articles } = await articlesApi.findAll<Article>('articles', {
62
+ include: ['comments', 'author']
63
+ })
60
64
  expect(articles.length).toBe(1)
61
65
  const article = articles[0]
62
66
  expect(article.id).toBe('1')
63
67
  expect(article.title).toBe('JSON:API paints my bikeshed!')
64
- expect(article.comments.length).toBe(2)
65
- expect(article.comments[0].body).toBe('First!')
66
- expect(article.comments[1].body).toBe('I like XML better')
68
+ expect(article.comments?.length).toBe(2)
69
+ expect(article.comments?.[0]?.body).toBe('First!')
70
+ expect(article.comments?.[1]?.body).toBe('I like XML better')
67
71
  expect(article.author?.firstName).toBe('Dan')
68
- ```
72
+ ```
package/dist/lib.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ export declare interface BaseEntity {
2
+ id: string;
3
+ }
4
+
1
5
  /**
2
6
  * Convert str from kebab-case to camelCase
3
7
  */
@@ -92,33 +96,34 @@ export declare interface JsonApiResourceIdentifier {
92
96
  }
93
97
 
94
98
  export declare interface JsonApiStore {
95
- /**
96
- * Models registered with this store
97
- */
98
- modelRegistry: Map<typeof Model, string>;
99
- /**
100
- * Relationships registered with this store
101
- */
102
- relRegistry: Map<typeof Model, Record<string, Relationship>>;
103
- /* Excluded from this release type: createRecord */
104
99
  /**
105
100
  * Find all records of a given type
106
101
  * @returns the JSON API document that was fetched and the records that were found
107
102
  */
108
- findAll<T extends typeof Model>(ctor: T, options?: FetchOptions, params?: FetchParams): Promise<{
103
+ findAll<T extends BaseEntity>(type: string, options?: FetchOptions, params?: FetchParams): Promise<{
109
104
  doc: JsonApiDocument;
110
- records: InstanceType<T>[];
105
+ records: T[];
111
106
  }>;
112
107
  /**
113
108
  * Find a single record by id
114
109
  * @returns the record that was found
115
110
  */
116
- findRecord<T extends typeof Model>(ctor: T, id: string, options?: FetchOptions, params?: FetchParams): Promise<InstanceType<T>>;
111
+ findRecord<T extends BaseEntity>(type: string, id: string, options?: FetchOptions, params?: FetchParams): Promise<T>;
117
112
  /**
118
113
  * Find related records for a given record and relationship name
119
114
  * @returns the JSON API document that was fetched
120
115
  */
121
- findRelated(record: Model, name: string, options?: FetchOptions, params?: FetchParams): Promise<JsonApiDocument>;
116
+ findRelated<T extends BaseEntity>(record: T, relationshipName: string, options?: FetchOptions, params?: FetchParams): Promise<JsonApiDocument>;
117
+ /**
118
+ * Create a new record instance
119
+ */
120
+ createRecord<T extends BaseEntity>(type: string, properties: Partial<T> & {
121
+ id?: string;
122
+ }): T;
123
+ /**
124
+ * Save a record
125
+ */
126
+ saveRecord<T extends BaseEntity>(record: T): Promise<void>;
122
127
  }
123
128
 
124
129
  export declare interface JsonApiStoreConfig {
@@ -139,27 +144,17 @@ export declare interface JsonApiStoreConfig {
139
144
  export declare type JsonApiStoreUseFunction = () => JsonApiStore;
140
145
 
141
146
  /**
142
- * Base class for models
147
+ * Model definition
143
148
  */
144
- export declare class Model {
145
- id: string;
146
- constructor(id: string);
147
- [key: string]: unknown;
148
- }
149
-
150
149
  export declare interface ModelDefinition {
151
150
  /**
152
151
  * The JSON:API type for the model
153
152
  */
154
153
  type: string;
155
154
  /**
156
- * The model constructor
155
+ * Optional relationships for the model
157
156
  */
158
- ctor: typeof Model;
159
- /**
160
- * Relationships for the model
161
- */
162
- rels?: Record<string, Relationship>;
157
+ relationships?: Record<string, Relationship>;
163
158
  }
164
159
 
165
160
  export declare interface PageOption {
@@ -171,8 +166,10 @@ export declare interface PageOption {
171
166
  * Relationship definition
172
167
  */
173
168
  export declare interface Relationship {
174
- ctor: typeof Model;
175
- type: RelationshipType;
169
+ /** The JSON:API type name of the related model */
170
+ type: string;
171
+ /** The relationship type */
172
+ relationshipType: RelationshipType;
176
173
  }
177
174
 
178
175
  export declare enum RelationshipType {
@@ -180,16 +177,6 @@ export declare enum RelationshipType {
180
177
  BelongsTo = 1
181
178
  }
182
179
 
183
- export declare function useJsonApi(config: JsonApiStoreConfig, fetcher?: JsonApiFetcher): {
184
- modelRegistry: Map<typeof Model, string>;
185
- relsRegistry: Map<typeof Model, Record<string, Relationship>>;
186
- findAll: <T extends typeof Model>(ctor: T, options?: FetchOptions, params?: FetchParams) => Promise<{
187
- doc: JsonApiDocument;
188
- records: InstanceType<T>[];
189
- }>;
190
- findRecord: <T extends typeof Model>(ctor: T, id: string, options?: FetchOptions, params?: FetchParams) => Promise<InstanceType<T>>;
191
- findRelated: (record: Model, name: string, options?: FetchOptions, params?: FetchParams) => Promise<JsonApiDocument>;
192
- saveRecord: (record: Model) => Promise<void>;
193
- };
180
+ export declare function useJsonApi(config: JsonApiStoreConfig, fetcher?: JsonApiFetcher): JsonApiStore;
194
181
 
195
182
  export { }
package/dist/lib.js CHANGED
@@ -1,163 +1,175 @@
1
- function O(...i) {
2
- return new URL(i.join("/")).href;
1
+ function b(...o) {
2
+ return new URL(o.join("/")).href;
3
3
  }
4
- async function R(i, t) {
5
- const { headers: r, searchParams: c, method: a, signal: o, body: d } = t, l = `?${c}`, h = i.replace(/(?:\?.*?)?(?=#|$)/, l), y = await fetch(h, {
6
- method: a,
4
+ async function R(o, e) {
5
+ const { headers: r, searchParams: d, method: i, signal: s, body: a } = e, y = `?${d}`, m = o.replace(/(?:\?.*?)?(?=#|$)/, y), w = await fetch(m, {
6
+ method: i,
7
7
  headers: r,
8
- signal: o,
9
- body: d
8
+ signal: s,
9
+ body: a
10
10
  });
11
- if (!y.ok) throw new Error(`HTTP error! status: ${y.status} ${y.statusText}`);
12
- return await y.json();
11
+ if (!w.ok) throw new Error(`HTTP error! status: ${w.status} ${w.statusText}`);
12
+ return await w.json();
13
13
  }
14
- class x {
15
- constructor(t) {
16
- this.endpoint = t;
17
- }
18
- createOptions(t = {}, r = {}, c = !1, a) {
19
- const o = new URLSearchParams(), d = new Headers(t.headers);
20
- d.append("Accept", "application/vnd.api+json"), c && d.append("Content-Type", "application/vnd.api+json");
21
- const l = { searchParams: o, headers: d, body: a };
22
- if (t.fields)
23
- for (const [h, y] of Object.entries(t.fields)) o.append(`fields[${h}]`, y.join(","));
24
- t.page?.size && o.append("page[size]", t.page.size.toString()), t.page?.number && o.append("page[number]", t.page.number.toString()), t.include && o.append("include", t.include.join(",")), t.filter && o.append("filter", t.filter);
25
- for (const [h, y] of Object.entries(r)) o.append(h, y);
26
- return l;
27
- }
28
- async fetchDocument(t, r, c, a) {
29
- const o = [this.endpoint, t];
30
- r && o.push(r);
31
- const d = O(...o);
32
- return await R(d, this.createOptions(c, a));
33
- }
34
- async fetchAll(t, r, c) {
35
- const a = O(this.endpoint, t);
36
- return (await R(a, this.createOptions(r, c))).data;
37
- }
38
- async fetchOne(t, r, c, a) {
39
- const o = O(this.endpoint, t, r);
40
- return (await R(o, this.createOptions(c, a))).data;
41
- }
42
- async fetchHasMany(t, r, c, a, o) {
43
- const d = O(this.endpoint, t, r, c);
44
- return await R(d, this.createOptions(a, o));
45
- }
46
- async fetchBelongsTo(t, r, c, a, o) {
47
- const d = O(this.endpoint, t, r, c);
48
- return await R(d, this.createOptions(a, o));
49
- }
50
- async post(t) {
51
- const r = O(this.endpoint, t.type), a = JSON.stringify({
52
- data: t
53
- }), o = this.createOptions({}, {}, !0, a);
54
- return await R(r, o);
14
+ class k {
15
+ constructor(e) {
16
+ this.endpoint = e;
17
+ }
18
+ createOptions(e = {}, r = {}, d = !1, i) {
19
+ const s = new URLSearchParams(), a = new Headers(e.headers);
20
+ a.append("Accept", "application/vnd.api+json"), d && a.append("Content-Type", "application/vnd.api+json");
21
+ const y = { searchParams: s, headers: a, body: i };
22
+ if (e.fields)
23
+ for (const [m, w] of Object.entries(e.fields)) s.append(`fields[${m}]`, w.join(","));
24
+ e.page?.size && s.append("page[size]", e.page.size.toString()), e.page?.number && s.append("page[number]", e.page.number.toString()), e.include && s.append("include", e.include.join(",")), e.filter && s.append("filter", e.filter);
25
+ for (const [m, w] of Object.entries(r)) s.append(m, w);
26
+ return y;
27
+ }
28
+ async fetchDocument(e, r, d, i) {
29
+ const s = [this.endpoint, e];
30
+ r && s.push(r);
31
+ const a = b(...s);
32
+ return await R(a, this.createOptions(d, i));
33
+ }
34
+ async fetchAll(e, r, d) {
35
+ const i = b(this.endpoint, e);
36
+ return (await R(i, this.createOptions(r, d))).data;
37
+ }
38
+ async fetchOne(e, r, d, i) {
39
+ const s = b(this.endpoint, e, r);
40
+ return (await R(s, this.createOptions(d, i))).data;
41
+ }
42
+ async fetchHasMany(e, r, d, i, s) {
43
+ const a = b(this.endpoint, e, r, d);
44
+ return await R(a, this.createOptions(i, s));
45
+ }
46
+ async fetchBelongsTo(e, r, d, i, s) {
47
+ const a = b(this.endpoint, e, r, d);
48
+ return await R(a, this.createOptions(i, s));
49
+ }
50
+ async post(e) {
51
+ const r = b(this.endpoint, e.type), i = JSON.stringify({
52
+ data: e
53
+ }), s = this.createOptions({}, {}, !0, i);
54
+ return await R(r, s);
55
55
  }
56
56
  }
57
- function F(i) {
58
- return i.replace(/[-][a-z\u00E0-\u00F6\u00F8-\u00FE]/g, (t) => t.slice(1).toUpperCase());
57
+ function H(o) {
58
+ return o.replace(/[-][a-z\u00E0-\u00F6\u00F8-\u00FE]/g, (e) => e.slice(1).toUpperCase());
59
59
  }
60
- class q {
61
- constructor(t) {
62
- this.id = t, this.id = t;
63
- }
60
+ const S = Symbol("jsonApiType");
61
+ function z(o, e) {
62
+ return o[S] = e, o;
64
63
  }
65
- var J = /* @__PURE__ */ ((i) => (i[i.HasMany = 0] = "HasMany", i[i.BelongsTo = 1] = "BelongsTo", i))(J || {});
66
- function I(i, t) {
67
- const r = t ?? new x(i.endpoint), c = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
68
- for (const e of i.modelDefinitions) {
69
- const n = e.ctor;
70
- c.set(n, e.type), a.set(e.type, n), e.rels && o.set(n, e.rels);
71
- }
72
- function d(e) {
73
- return i.kebabCase ? F(e) : e;
74
- }
75
- function l(e, n, f) {
76
- const w = new e(n);
77
- if (f)
78
- for (const [p, u] of Object.entries(f)) u !== void 0 && (w[d(p)] = u);
79
- return w;
80
- }
81
- function h(e) {
82
- const n = c.get(e);
83
- if (!n) throw new Error(`Model ${e.name} not defined`);
84
- return n;
85
- }
86
- function y(e) {
87
- const n = a.get(e);
88
- if (!n) throw new Error(`Model with name ${e} not defined`);
89
- return n;
90
- }
91
- function T(e, n, f) {
92
- function w(s) {
93
- return l(
94
- y(s.type),
95
- s.id,
96
- s.attributes
97
- );
64
+ function A(o) {
65
+ return o[S];
66
+ }
67
+ function j(o, e, r) {
68
+ o[e] = r;
69
+ }
70
+ var B = /* @__PURE__ */ ((o) => (o[o.HasMany = 0] = "HasMany", o[o.BelongsTo = 1] = "BelongsTo", o))(B || {});
71
+ function C(o, e) {
72
+ const r = e ?? new k(o.endpoint), d = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
73
+ for (const t of o.modelDefinitions)
74
+ d.set(t.type, t), t.relationships && i.set(t.type, t.relationships);
75
+ function s(t) {
76
+ return o.kebabCase ? H(t) : t;
77
+ }
78
+ function a(t, c) {
79
+ if (!d.get(t)) throw new Error(`Model type ${t} not defined`);
80
+ const u = c.id ?? crypto.randomUUID(), f = { id: u, ...c };
81
+ if (z(f, t), o.kebabCase) {
82
+ const l = { id: u };
83
+ z(l, t);
84
+ for (const [h, n] of Object.entries(c))
85
+ h !== "id" && n !== void 0 && (l[s(h)] = n);
86
+ return l;
98
87
  }
99
- const p = /* @__PURE__ */ new Map();
100
- if (f) for (const s of f) p.set(s.id, w(s));
101
- const u = n.map((s) => l(e, s.id, s.attributes)), g = /* @__PURE__ */ new Map();
102
- for (const s of u) g.set(s.id, s);
103
- function M(s) {
104
- const D = g.get(s.id) ?? p.get(s.id);
105
- if (!D) throw new Error("Unexpected not found record");
106
- const j = y(s.type);
107
- if (s.relationships)
108
- for (const [b, $] of Object.entries(s.relationships)) {
109
- const v = o.get(j);
110
- if (!v) continue;
111
- const H = d(b), E = v[H];
112
- if (!E) throw new Error(`Relationship ${H} not defined`);
113
- const P = h(E.ctor), k = E.type === 0 ? $.data : [$.data], U = k.filter((m) => m && p.has(m.id) && m.type === P).map((m) => p.get(m.id)), z = k.filter((m) => m && g.has(m.id) && m.type === P).map((m) => g.get(m.id));
114
- z.push(...U), D[H] = E.type === 0 ? z : z[0];
88
+ return f;
89
+ }
90
+ function y(t, c, p) {
91
+ const u = /* @__PURE__ */ new Map();
92
+ if (p)
93
+ for (const n of p) {
94
+ const T = a(n.type, {
95
+ id: n.id,
96
+ ...n.attributes
97
+ });
98
+ u.set(n.id, T);
99
+ }
100
+ const f = c.map(
101
+ (n) => a(t, {
102
+ id: n.id,
103
+ ...n.attributes
104
+ })
105
+ ), l = /* @__PURE__ */ new Map();
106
+ for (const n of f)
107
+ l.set(n.id, n);
108
+ function h(n) {
109
+ const T = l.get(n.id) ?? u.get(n.id);
110
+ if (!T) throw new Error("Unexpected not found record");
111
+ if (!n.relationships) return;
112
+ const O = i.get(n.type);
113
+ if (O)
114
+ for (const [g, E] of Object.entries(n.relationships)) {
115
+ const D = s(g), M = O[D];
116
+ if (!M) continue;
117
+ const P = (M.relationshipType === 0 ? E.data : [E.data]).filter((v) => v && v.type === M.type).map((v) => u.get(v.id) || l.get(v.id)).filter(Boolean);
118
+ j(T, D, M.relationshipType === 0 ? P : P[0]);
115
119
  }
116
120
  }
117
- return f && (n.map(M), f.map(M)), u;
121
+ return p && (c.forEach(h), p.forEach(h)), f;
118
122
  }
119
- async function A(e, n, f) {
120
- const w = h(e), p = await r.fetchDocument(w, void 0, n, f), u = p.data, g = T(e, u, p.included);
121
- return { doc: p, records: g };
123
+ async function m(t, c, p) {
124
+ const u = await r.fetchDocument(t, void 0, c, p), f = u.data, l = y(t, f, u.included);
125
+ return { doc: u, records: l };
122
126
  }
123
- async function B(e, n, f, w) {
124
- const p = h(e), u = await r.fetchDocument(p, n, f, w), g = u.data, s = T(e, [g], u.included)[0];
125
- if (!s) throw new Error(`Record with id ${n} not found`);
126
- return s;
127
+ async function w(t, c, p, u) {
128
+ const f = await r.fetchDocument(t, c, p, u), l = f.data, n = y(t, [l], f.included)[0];
129
+ if (!n) throw new Error(`Record with id ${c} not found`);
130
+ return n;
127
131
  }
128
- async function C(e, n, f, w) {
129
- const p = e.constructor, u = h(p), g = o.get(p);
130
- if (!g) throw new Error(`Model ${p.name} has no relationships`);
131
- const M = g[n];
132
- if (!M) throw new Error(`Has many relationship ${n} not defined`);
133
- if (M.type === 1) {
134
- const b = await r.fetchBelongsTo(u, e.id, n, f, w), $ = b.data, v = l(M.ctor, $.id, $.attributes);
135
- return e[n] = v, b;
132
+ async function $(t, c, p, u) {
133
+ const f = A(t);
134
+ if (!f) throw new Error("Record type not found - ensure records are created via createRecord");
135
+ const l = i.get(f);
136
+ if (!l) throw new Error(`Model ${f} has no relationships`);
137
+ const h = l[c];
138
+ if (!h) throw new Error(`Relationship ${c} not defined`);
139
+ if (h.relationshipType === 1) {
140
+ const g = await r.fetchBelongsTo(f, t.id, c, p, u), E = g.data, D = a(h.type, {
141
+ id: E.id,
142
+ ...E.attributes
143
+ });
144
+ return j(t, c, D), g;
136
145
  }
137
- const s = await r.fetchHasMany(u, e.id, n, f, w), j = (M.type === 0 ? s.data : [s.data]).map((b) => l(M.ctor, b.id, b.attributes));
138
- return e[n] = M.type === 0 ? j : j[0], s;
139
- }
140
- async function S(e) {
141
- const n = h(e.constructor), f = {
142
- id: e.id,
143
- type: n,
144
- attributes: e
146
+ const n = await r.fetchHasMany(f, t.id, c, p, u), O = (h.relationshipType === 0 ? n.data : [n.data]).map((g) => a(h.type, {
147
+ id: g.id,
148
+ ...g.attributes
149
+ }));
150
+ return j(t, c, h.relationshipType === 0 ? O : O[0]), n;
151
+ }
152
+ async function U(t) {
153
+ const c = A(t);
154
+ if (!c) throw new Error("Record type not found - ensure records are created via createRecord");
155
+ const p = {
156
+ id: t.id,
157
+ type: c,
158
+ attributes: t
145
159
  };
146
- await r.post(f);
160
+ await r.post(p);
147
161
  }
148
162
  return {
149
- modelRegistry: c,
150
- relsRegistry: o,
151
- findAll: A,
152
- findRecord: B,
153
- findRelated: C,
154
- saveRecord: S
163
+ findAll: m,
164
+ findRecord: w,
165
+ findRelated: $,
166
+ createRecord: a,
167
+ saveRecord: U
155
168
  };
156
169
  }
157
170
  export {
158
- q as Model,
159
- J as RelationshipType,
160
- F as camel,
161
- I as useJsonApi
171
+ B as RelationshipType,
172
+ H as camel,
173
+ C as useJsonApi
162
174
  };
163
175
  //# sourceMappingURL=lib.js.map