yayson 4.1.0 → 4.3.0

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 +43 -0
  2. package/build/legacy.cjs +27 -23
  3. package/build/legacy.d.cts +35 -7
  4. package/build/legacy.d.cts.map +1 -1
  5. package/build/legacy.d.mts +35 -7
  6. package/build/legacy.d.mts.map +1 -1
  7. package/build/legacy.mjs +27 -23
  8. package/build/legacy.mjs.map +1 -1
  9. package/build/{symbols-nFs99aEX.cjs → symbols-B--FS78o.cjs} +3 -0
  10. package/build/{symbols-DSjKJ8vh.mjs → symbols-BfU4k1el.mjs} +4 -1
  11. package/build/symbols-BfU4k1el.mjs.map +1 -0
  12. package/build/{types-NiKV-lj-.d.cts → types-KZiF6x7A.d.mts} +14 -2
  13. package/build/types-KZiF6x7A.d.mts.map +1 -0
  14. package/build/{types-Do2flKZX.d.mts → types-iC38_iCI.d.cts} +14 -2
  15. package/build/types-iC38_iCI.d.cts.map +1 -0
  16. package/build/utils.cjs +1 -1
  17. package/build/utils.d.cts +1 -1
  18. package/build/utils.d.mts +1 -1
  19. package/build/utils.mjs +1 -1
  20. package/build/{yayson-l2JKseMH.cjs → yayson-B51EJfRP.cjs} +97 -27
  21. package/build/{yayson-3UYKq2H5.d.cts → yayson-BvwMr4Ad.d.mts} +6 -4
  22. package/build/yayson-BvwMr4Ad.d.mts.map +1 -0
  23. package/build/{yayson-Ce5uGpgU.d.mts → yayson-DTMLeA5k.d.cts} +6 -4
  24. package/build/yayson-DTMLeA5k.d.cts.map +1 -0
  25. package/build/{yayson-CwZg5FNt.mjs → yayson-RzT9zsdx.mjs} +81 -29
  26. package/build/yayson-RzT9zsdx.mjs.map +1 -0
  27. package/build/yayson.cjs +1 -1
  28. package/build/yayson.d.cts +2 -2
  29. package/build/yayson.d.mts +2 -2
  30. package/build/yayson.mjs +1 -1
  31. package/package.json +1 -1
  32. package/skill/yayson/SKILL.md +20 -0
  33. package/skill/yayson/references/api.md +27 -2
  34. package/build/symbols-DSjKJ8vh.mjs.map +0 -1
  35. package/build/types-Do2flKZX.d.mts.map +0 -1
  36. package/build/types-NiKV-lj-.d.cts.map +0 -1
  37. package/build/yayson-3UYKq2H5.d.cts.map +0 -1
  38. package/build/yayson-Ce5uGpgU.d.mts.map +0 -1
  39. package/build/yayson-CwZg5FNt.mjs.map +0 -1
package/README.md CHANGED
@@ -81,6 +81,49 @@ class BikePresenter extends Presenter {
81
81
  }
82
82
  ```
83
83
 
84
+ ### Declaring cardinality and optional relationships
85
+
86
+ By default a missing relationship renders as `data: null`. This isn't valid JSON:API for to-many relationships (the spec requires `[]`) and can mislead clients when a relationship simply wasn't loaded. Use the config form to declare cardinality and optional semantics:
87
+
88
+ ```javascript
89
+ class BikePresenter extends Presenter {
90
+ static type = 'bikes'
91
+
92
+ relationships() {
93
+ return {
94
+ wheels: { presenter: WheelPresenter, hasMany: true },
95
+ manufacturer: { presenter: ManufacturerPresenter, optional: true },
96
+ accessories: { presenter: AccessoryPresenter, hasMany: true, optional: true },
97
+ }
98
+ }
99
+ }
100
+
101
+ BikePresenter.render({ id: 1 })
102
+ ```
103
+
104
+ This produces:
105
+
106
+ ```javascript
107
+ {
108
+ data: {
109
+ id: '1',
110
+ type: 'bikes',
111
+ attributes: {},
112
+ relationships: {
113
+ wheels: { data: [] } // hasMany + no data → empty array, not null
114
+ // manufacturer and accessories omitted entirely — they weren't loaded
115
+ }
116
+ }
117
+ }
118
+ ```
119
+
120
+ - **`hasMany: true`** — declares a to-many relationship. Empty or missing data renders as `data: []` instead of `data: null`.
121
+ - **`optional: true`** — when the relationship key is absent from the instance, the relationship is omitted from the output (or rendered with just `links` if `links()` configures one for that key). An explicit `null` on the instance still renders as `data: null` — `optional` distinguishes "not loaded" from "explicitly empty".
122
+
123
+ In `payload()` output, `optional` omission is disabled (a write request asserts state, so dropping a relationship would be misleading), but `hasMany` still applies so a client can correctly clear a to-many with `data: []`.
124
+
125
+ The bare-class form (`relationships() { return { wheels: WheelPresenter } }`) is unchanged.
126
+
84
127
  ### Filtering attributes with fields
85
128
 
86
129
  Use the static `fields` property to limit which attributes are included in the output:
package/build/legacy.cjs CHANGED
@@ -1,5 +1,5 @@
1
- const require_symbols = require('./symbols-nFs99aEX.cjs');
2
- const require_yayson = require('./yayson-l2JKseMH.cjs');
1
+ const require_symbols = require('./symbols-B--FS78o.cjs');
2
+ const require_yayson = require('./yayson-B51EJfRP.cjs');
3
3
 
4
4
  //#region src/yayson/legacy-presenter.ts
5
5
  function hasId$1(value) {
@@ -39,9 +39,9 @@ function createLegacyPresenter(Presenter) {
39
39
  const result = [];
40
40
  if (!relationships) return result;
41
41
  for (const key in relationships) {
42
- const factory = relationships[key];
43
- if (!factory) throw new Error(`Presenter for ${key} in ${this.constructor.type} is not defined`);
44
- const presenter = new factory(scope);
42
+ const entry = relationships[key];
43
+ if (!entry) throw new Error(`Presenter for ${key} in ${this.constructor.type} is not defined`);
44
+ const presenter = new (typeof entry === "function" ? entry : entry.presenter)(scope);
45
45
  const data = this.constructor.adapter.get(instance, key);
46
46
  if (data != null) presenter.toJSON(data, { defaultPlural: true });
47
47
  const type = scope[this.pluralType()] != null ? this.pluralType() : this.constructor.type;
@@ -122,19 +122,20 @@ var LegacyStore = class LegacyStore {
122
122
  validationErrors;
123
123
  models;
124
124
  constructor(options) {
125
- this.types = options?.types || {};
125
+ this.types = require_yayson.safeObject();
126
+ Object.assign(this.types, options?.types);
126
127
  this.schemas = options?.schemas;
127
128
  this.strict = options?.strict ?? false;
128
129
  this.records = [];
129
- this.relations = {};
130
+ this.relations = require_yayson.safeObject();
130
131
  this.validationErrors = [];
131
- this.models = {};
132
+ this.models = require_yayson.safeObject();
132
133
  }
133
134
  reset() {
134
135
  this.records = [];
135
- this.relations = {};
136
+ this.relations = require_yayson.safeObject();
136
137
  this.validationErrors = [];
137
- this.models = {};
138
+ this.models = require_yayson.safeObject();
138
139
  }
139
140
  #createStub(type, id) {
140
141
  const stub = { id };
@@ -144,7 +145,8 @@ var LegacyStore = class LegacyStore {
144
145
  #resolveRelationships(model, type, resolver) {
145
146
  const relations = this.relations[type];
146
147
  if (!relations) return;
147
- for (const attribute in relations) {
148
+ for (const attribute of Object.keys(relations)) {
149
+ if (require_yayson.isUnsafeKey(attribute)) continue;
148
150
  const relationType = relations[attribute];
149
151
  const value = model[attribute];
150
152
  if (Array.isArray(value)) model[attribute] = value.filter((id) => id != null).map((id) => resolver(relationType, String(id)));
@@ -161,18 +163,19 @@ var LegacyStore = class LegacyStore {
161
163
  if (rec.data.links != null) model[require_symbols.LINKS] = rec.data.links;
162
164
  if (models && hasId(model)) {
163
165
  const idStr = String(model.id);
164
- if (!models[type]) models[type] = {};
166
+ if (!models[type]) models[type] = require_yayson.safeObject();
165
167
  models[type][idStr] = model;
166
168
  }
167
169
  const resolver = (relationType, id) => {
168
- return this.#findModel(relationType, id, models ?? {}) ?? this.#createStub(relationType, id);
170
+ return this.#findModel(relationType, id, models ?? require_yayson.safeObject()) ?? this.#createStub(relationType, id);
169
171
  };
170
172
  this.#resolveRelationships(model, type, resolver);
171
173
  return model;
172
174
  }
173
- toModel(rec, type, models) {
175
+ toModel(rec, type, modelsArg) {
174
176
  const idStr = String(rec.data.id);
175
- if (!models[type]) models[type] = {};
177
+ const models = require_yayson.safeCache(modelsArg);
178
+ if (!models[type]) models[type] = require_yayson.safeObject();
176
179
  if (models[type][idStr]) return models[type][idStr];
177
180
  const result = this.#createModel(rec, type, { models });
178
181
  if (!hasId(result)) throw new Error(`Expected model of type ${type} to have an id`);
@@ -195,13 +198,14 @@ var LegacyStore = class LegacyStore {
195
198
  return model;
196
199
  }
197
200
  setupRelations(links) {
198
- for (const key in links) {
201
+ for (const key of Object.keys(links)) {
199
202
  const value = links[key];
200
203
  const parts = key.split(".");
201
204
  const typeRaw = parts[0];
202
205
  const attribute = parts[1];
206
+ if (require_yayson.isUnsafeKey(attribute)) continue;
203
207
  const type = this.types[typeRaw] || typeRaw;
204
- if (!this.relations[type]) this.relations[type] = {};
208
+ if (!this.relations[type]) this.relations[type] = require_yayson.safeObject();
205
209
  this.relations[type][attribute] = this.types[value.type] || value.type;
206
210
  }
207
211
  }
@@ -222,7 +226,7 @@ var LegacyStore = class LegacyStore {
222
226
  build(data) {
223
227
  if (data.links) this.setupRelations(data.links);
224
228
  let name;
225
- for (const key in data) if (key !== "meta" && key !== "links") {
229
+ for (const key of Object.keys(data)) if (key !== "meta" && key !== "links") {
226
230
  name = key;
227
231
  break;
228
232
  }
@@ -248,14 +252,14 @@ var LegacyStore = class LegacyStore {
248
252
  return model;
249
253
  }
250
254
  find(type, id, models) {
251
- return this.#findModel(type, String(id), models ?? this.models);
255
+ return this.#findModel(type, String(id), require_yayson.safeCache(models ?? this.models));
252
256
  }
253
257
  findAll(type, models) {
254
- const modelsObj = models ?? this.models;
258
+ const modelsObj = require_yayson.safeCache(models ?? this.models);
255
259
  const recs = this.findRecords(type);
256
260
  if (recs.length === 0) return [];
257
261
  recs.forEach((rec) => {
258
- if (!modelsObj[type]) modelsObj[type] = {};
262
+ if (!modelsObj[type]) modelsObj[type] = require_yayson.safeObject();
259
263
  return this.toModel(rec, type, modelsObj);
260
264
  });
261
265
  return Object.values(modelsObj[type] || {});
@@ -274,10 +278,10 @@ var LegacyStore = class LegacyStore {
274
278
  }
275
279
  syncAll(data) {
276
280
  this.validationErrors = [];
277
- this.models = {};
281
+ this.models = require_yayson.safeObject();
278
282
  if (data.links) this.setupRelations(data.links);
279
283
  const syncedRecords = [];
280
- for (const name in data) {
284
+ for (const name of Object.keys(data)) {
281
285
  if (name === "meta" || name === "links") continue;
282
286
  const value = data[name];
283
287
  const type = this.types[name] || name;
@@ -1,5 +1,5 @@
1
- import { E as ModelLike, T as Adapter, _ as StoreResult, a as JsonApiRelationship, c as LegacyPresenterOptions, d as SchemaRegistry, f as StoreModel, i as JsonApiLinks, l as LegacyStoreOptions, m as StoreModels, n as JsonApiDocument, o as JsonApiRelationships, p as StoreModelWithOptionalId, r as JsonApiLink, s as JsonApiResource, t as InferModelType, u as PresenterOptions, v as ValidationError } from "./types-NiKV-lj-.cjs";
2
- import { i as Presenter, r as yayson$1, t as YaysonOptions } from "./yayson-3UYKq2H5.cjs";
1
+ import { D as ModelLike, E as Adapter, a as JsonApiRelationship, c as LegacyPresenterOptions, d as RelationshipConfig, f as SchemaRegistry, h as StoreModels, i as JsonApiLinks, l as LegacyStoreOptions, m as StoreModelWithOptionalId, n as JsonApiDocument, o as JsonApiRelationships, p as StoreModel, r as JsonApiLink, s as JsonApiResource, t as InferModelType, u as PresenterOptions, v as StoreResult, y as ValidationError } from "./types-iC38_iCI.cjs";
2
+ import { i as Presenter, r as yayson$1, t as YaysonOptions } from "./yayson-DTMLeA5k.cjs";
3
3
 
4
4
  //#region src/yayson/legacy-presenter.d.ts
5
5
  interface LegacyJsonApiDocument extends JsonApiDocument {
@@ -25,10 +25,12 @@ declare function createLegacyPresenter(Presenter: Presenter): {
25
25
  id(instance: ModelLike): string | undefined;
26
26
  selfLinks(_instance: ModelLike): JsonApiLink | string | undefined;
27
27
  links(_instance?: ModelLike): JsonApiLinks | undefined;
28
- relationships(): Record<string, /*elided*/any>;
28
+ relationships(): Record<string, /*elided*/any | RelationshipConfig< /*elided*/any>>;
29
29
  attributes(instance: ModelLike | null): Record<string, unknown>;
30
30
  includeRelationships(scope: JsonApiDocument, instance: ModelLike): unknown[];
31
- buildRelationships(instance: ModelLike | null): JsonApiRelationships | null;
31
+ buildRelationships(instance: ModelLike | null, options?: {
32
+ payload?: boolean;
33
+ }): JsonApiRelationships | null;
32
34
  buildSelfLink(instance: ModelLike): JsonApiLink | undefined;
33
35
  toJSON(instanceOrCollection: ModelLike | ModelLike[] | null | undefined, options?: PresenterOptions): JsonApiDocument;
34
36
  payload(instance: ModelLike, options?: PresenterOptions): JsonApiDocument;
@@ -40,8 +42,34 @@ declare function createLegacyPresenter(Presenter: Presenter): {
40
42
  toJSON(instanceOrCollection: ModelLike | ModelLike[] | null, options?: PresenterOptions): JsonApiDocument;
41
43
  render(instanceOrCollection: ModelLike | ModelLike[] | null, options?: PresenterOptions): JsonApiDocument;
42
44
  payload(instance: ModelLike, options?: PresenterOptions): JsonApiDocument;
43
- }>;
44
- buildRelationships(instance: ModelLike | null): JsonApiRelationships | null;
45
+ } | RelationshipConfig<{
46
+ new (scope?: JsonApiDocument): {
47
+ constructor: /*elided*/any;
48
+ scope: JsonApiDocument;
49
+ id(instance: ModelLike): string | undefined;
50
+ selfLinks(_instance: ModelLike): JsonApiLink | string | undefined;
51
+ links(_instance?: ModelLike): JsonApiLinks | undefined;
52
+ relationships(): Record<string, /*elided*/any | RelationshipConfig< /*elided*/any>>;
53
+ attributes(instance: ModelLike | null): Record<string, unknown>;
54
+ includeRelationships(scope: JsonApiDocument, instance: ModelLike): unknown[];
55
+ buildRelationships(instance: ModelLike | null, options?: {
56
+ payload?: boolean;
57
+ }): JsonApiRelationships | null;
58
+ buildSelfLink(instance: ModelLike): JsonApiLink | undefined;
59
+ toJSON(instanceOrCollection: ModelLike | ModelLike[] | null | undefined, options?: PresenterOptions): JsonApiDocument;
60
+ payload(instance: ModelLike, options?: PresenterOptions): JsonApiDocument;
61
+ render(instanceOrCollection: ModelLike | ModelLike[] | null, options?: PresenterOptions): JsonApiDocument;
62
+ };
63
+ adapter: typeof Adapter;
64
+ type: string;
65
+ fields?: string[];
66
+ toJSON(instanceOrCollection: ModelLike | ModelLike[] | null, options?: PresenterOptions): JsonApiDocument;
67
+ render(instanceOrCollection: ModelLike | ModelLike[] | null, options?: PresenterOptions): JsonApiDocument;
68
+ payload(instance: ModelLike, options?: PresenterOptions): JsonApiDocument;
69
+ }>>;
70
+ buildRelationships(instance: ModelLike | null, options?: {
71
+ payload?: boolean;
72
+ }): JsonApiRelationships | null;
45
73
  buildSelfLink(instance: ModelLike): JsonApiLink | undefined;
46
74
  };
47
75
  type: string;
@@ -84,7 +112,7 @@ declare class LegacyStore<S extends SchemaRegistry = SchemaRegistry> {
84
112
  models: StoreModels;
85
113
  constructor(options?: LegacyStoreOptions<S>);
86
114
  reset(): void;
87
- toModel(rec: LegacyStoreRecordType, type: string, models: StoreModels): StoreModel;
115
+ toModel(rec: LegacyStoreRecordType, type: string, modelsArg: StoreModels): StoreModel;
88
116
  setupRelations(links: LegacyLinks): void;
89
117
  findRecord(type: string, id: string): LegacyStoreRecordType | undefined;
90
118
  findRecords(type: string): LegacyStoreRecordType[];
@@ -1 +1 @@
1
- {"version":3,"file":"legacy.d.cts","names":[],"sources":["../../../../../../yayson/legacy-presenter.ts","../../../../../../yayson/legacy-store.ts","../../../../../../legacy.ts"],"mappings":"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"}
1
+ {"version":3,"file":"legacy.d.cts","names":[],"sources":["../../../../../../yayson/legacy-presenter.ts","../../../../../../yayson/legacy-store.ts","../../../../../../legacy.ts"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { E as ModelLike, T as Adapter, _ as StoreResult, a as JsonApiRelationship, c as LegacyPresenterOptions, d as SchemaRegistry, f as StoreModel, i as JsonApiLinks, l as LegacyStoreOptions, m as StoreModels, n as JsonApiDocument, o as JsonApiRelationships, p as StoreModelWithOptionalId, r as JsonApiLink, s as JsonApiResource, t as InferModelType, u as PresenterOptions, v as ValidationError } from "./types-Do2flKZX.mjs";
2
- import { i as Presenter, r as yayson$1, t as YaysonOptions } from "./yayson-Ce5uGpgU.mjs";
1
+ import { D as ModelLike, E as Adapter, a as JsonApiRelationship, c as LegacyPresenterOptions, d as RelationshipConfig, f as SchemaRegistry, h as StoreModels, i as JsonApiLinks, l as LegacyStoreOptions, m as StoreModelWithOptionalId, n as JsonApiDocument, o as JsonApiRelationships, p as StoreModel, r as JsonApiLink, s as JsonApiResource, t as InferModelType, u as PresenterOptions, v as StoreResult, y as ValidationError } from "./types-KZiF6x7A.mjs";
2
+ import { i as Presenter, r as yayson$1, t as YaysonOptions } from "./yayson-BvwMr4Ad.mjs";
3
3
 
4
4
  //#region src/yayson/legacy-presenter.d.ts
5
5
  interface LegacyJsonApiDocument extends JsonApiDocument {
@@ -25,10 +25,12 @@ declare function createLegacyPresenter(Presenter: Presenter): {
25
25
  id(instance: ModelLike): string | undefined;
26
26
  selfLinks(_instance: ModelLike): JsonApiLink | string | undefined;
27
27
  links(_instance?: ModelLike): JsonApiLinks | undefined;
28
- relationships(): Record<string, /*elided*/any>;
28
+ relationships(): Record<string, /*elided*/any | RelationshipConfig< /*elided*/any>>;
29
29
  attributes(instance: ModelLike | null): Record<string, unknown>;
30
30
  includeRelationships(scope: JsonApiDocument, instance: ModelLike): unknown[];
31
- buildRelationships(instance: ModelLike | null): JsonApiRelationships | null;
31
+ buildRelationships(instance: ModelLike | null, options?: {
32
+ payload?: boolean;
33
+ }): JsonApiRelationships | null;
32
34
  buildSelfLink(instance: ModelLike): JsonApiLink | undefined;
33
35
  toJSON(instanceOrCollection: ModelLike | ModelLike[] | null | undefined, options?: PresenterOptions): JsonApiDocument;
34
36
  payload(instance: ModelLike, options?: PresenterOptions): JsonApiDocument;
@@ -40,8 +42,34 @@ declare function createLegacyPresenter(Presenter: Presenter): {
40
42
  toJSON(instanceOrCollection: ModelLike | ModelLike[] | null, options?: PresenterOptions): JsonApiDocument;
41
43
  render(instanceOrCollection: ModelLike | ModelLike[] | null, options?: PresenterOptions): JsonApiDocument;
42
44
  payload(instance: ModelLike, options?: PresenterOptions): JsonApiDocument;
43
- }>;
44
- buildRelationships(instance: ModelLike | null): JsonApiRelationships | null;
45
+ } | RelationshipConfig<{
46
+ new (scope?: JsonApiDocument): {
47
+ constructor: /*elided*/any;
48
+ scope: JsonApiDocument;
49
+ id(instance: ModelLike): string | undefined;
50
+ selfLinks(_instance: ModelLike): JsonApiLink | string | undefined;
51
+ links(_instance?: ModelLike): JsonApiLinks | undefined;
52
+ relationships(): Record<string, /*elided*/any | RelationshipConfig< /*elided*/any>>;
53
+ attributes(instance: ModelLike | null): Record<string, unknown>;
54
+ includeRelationships(scope: JsonApiDocument, instance: ModelLike): unknown[];
55
+ buildRelationships(instance: ModelLike | null, options?: {
56
+ payload?: boolean;
57
+ }): JsonApiRelationships | null;
58
+ buildSelfLink(instance: ModelLike): JsonApiLink | undefined;
59
+ toJSON(instanceOrCollection: ModelLike | ModelLike[] | null | undefined, options?: PresenterOptions): JsonApiDocument;
60
+ payload(instance: ModelLike, options?: PresenterOptions): JsonApiDocument;
61
+ render(instanceOrCollection: ModelLike | ModelLike[] | null, options?: PresenterOptions): JsonApiDocument;
62
+ };
63
+ adapter: typeof Adapter;
64
+ type: string;
65
+ fields?: string[];
66
+ toJSON(instanceOrCollection: ModelLike | ModelLike[] | null, options?: PresenterOptions): JsonApiDocument;
67
+ render(instanceOrCollection: ModelLike | ModelLike[] | null, options?: PresenterOptions): JsonApiDocument;
68
+ payload(instance: ModelLike, options?: PresenterOptions): JsonApiDocument;
69
+ }>>;
70
+ buildRelationships(instance: ModelLike | null, options?: {
71
+ payload?: boolean;
72
+ }): JsonApiRelationships | null;
45
73
  buildSelfLink(instance: ModelLike): JsonApiLink | undefined;
46
74
  };
47
75
  type: string;
@@ -84,7 +112,7 @@ declare class LegacyStore<S extends SchemaRegistry = SchemaRegistry> {
84
112
  models: StoreModels;
85
113
  constructor(options?: LegacyStoreOptions<S>);
86
114
  reset(): void;
87
- toModel(rec: LegacyStoreRecordType, type: string, models: StoreModels): StoreModel;
115
+ toModel(rec: LegacyStoreRecordType, type: string, modelsArg: StoreModels): StoreModel;
88
116
  setupRelations(links: LegacyLinks): void;
89
117
  findRecord(type: string, id: string): LegacyStoreRecordType | undefined;
90
118
  findRecords(type: string): LegacyStoreRecordType[];
@@ -1 +1 @@
1
- {"version":3,"file":"legacy.d.mts","names":[],"sources":["../../../../../../yayson/legacy-presenter.ts","../../../../../../yayson/legacy-store.ts","../../../../../../legacy.ts"],"mappings":"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"}
1
+ {"version":3,"file":"legacy.d.mts","names":[],"sources":["../../../../../../yayson/legacy-presenter.ts","../../../../../../yayson/legacy-store.ts","../../../../../../legacy.ts"],"mappings":"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"}
package/build/legacy.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { a as TYPE, n as META, t as LINKS } from "./symbols-DSjKJ8vh.mjs";
2
- import { n as validate, r as filterByFields, t as yayson_default } from "./yayson-CwZg5FNt.mjs";
1
+ import { a as TYPE, n as META, t as LINKS } from "./symbols-BfU4k1el.mjs";
2
+ import { a as validate, i as safeObject, n as isUnsafeKey, o as filterByFields, r as safeCache, t as yayson_default } from "./yayson-RzT9zsdx.mjs";
3
3
 
4
4
  //#region src/yayson/legacy-presenter.ts
5
5
  function hasId$1(value) {
@@ -39,9 +39,9 @@ function createLegacyPresenter(Presenter) {
39
39
  const result = [];
40
40
  if (!relationships) return result;
41
41
  for (const key in relationships) {
42
- const factory = relationships[key];
43
- if (!factory) throw new Error(`Presenter for ${key} in ${this.constructor.type} is not defined`);
44
- const presenter = new factory(scope);
42
+ const entry = relationships[key];
43
+ if (!entry) throw new Error(`Presenter for ${key} in ${this.constructor.type} is not defined`);
44
+ const presenter = new (typeof entry === "function" ? entry : entry.presenter)(scope);
45
45
  const data = this.constructor.adapter.get(instance, key);
46
46
  if (data != null) presenter.toJSON(data, { defaultPlural: true });
47
47
  const type = scope[this.pluralType()] != null ? this.pluralType() : this.constructor.type;
@@ -122,19 +122,20 @@ var LegacyStore = class LegacyStore {
122
122
  validationErrors;
123
123
  models;
124
124
  constructor(options) {
125
- this.types = options?.types || {};
125
+ this.types = safeObject();
126
+ Object.assign(this.types, options?.types);
126
127
  this.schemas = options?.schemas;
127
128
  this.strict = options?.strict ?? false;
128
129
  this.records = [];
129
- this.relations = {};
130
+ this.relations = safeObject();
130
131
  this.validationErrors = [];
131
- this.models = {};
132
+ this.models = safeObject();
132
133
  }
133
134
  reset() {
134
135
  this.records = [];
135
- this.relations = {};
136
+ this.relations = safeObject();
136
137
  this.validationErrors = [];
137
- this.models = {};
138
+ this.models = safeObject();
138
139
  }
139
140
  #createStub(type, id) {
140
141
  const stub = { id };
@@ -144,7 +145,8 @@ var LegacyStore = class LegacyStore {
144
145
  #resolveRelationships(model, type, resolver) {
145
146
  const relations = this.relations[type];
146
147
  if (!relations) return;
147
- for (const attribute in relations) {
148
+ for (const attribute of Object.keys(relations)) {
149
+ if (isUnsafeKey(attribute)) continue;
148
150
  const relationType = relations[attribute];
149
151
  const value = model[attribute];
150
152
  if (Array.isArray(value)) model[attribute] = value.filter((id) => id != null).map((id) => resolver(relationType, String(id)));
@@ -161,18 +163,19 @@ var LegacyStore = class LegacyStore {
161
163
  if (rec.data.links != null) model[LINKS] = rec.data.links;
162
164
  if (models && hasId(model)) {
163
165
  const idStr = String(model.id);
164
- if (!models[type]) models[type] = {};
166
+ if (!models[type]) models[type] = safeObject();
165
167
  models[type][idStr] = model;
166
168
  }
167
169
  const resolver = (relationType, id) => {
168
- return this.#findModel(relationType, id, models ?? {}) ?? this.#createStub(relationType, id);
170
+ return this.#findModel(relationType, id, models ?? safeObject()) ?? this.#createStub(relationType, id);
169
171
  };
170
172
  this.#resolveRelationships(model, type, resolver);
171
173
  return model;
172
174
  }
173
- toModel(rec, type, models) {
175
+ toModel(rec, type, modelsArg) {
174
176
  const idStr = String(rec.data.id);
175
- if (!models[type]) models[type] = {};
177
+ const models = safeCache(modelsArg);
178
+ if (!models[type]) models[type] = safeObject();
176
179
  if (models[type][idStr]) return models[type][idStr];
177
180
  const result = this.#createModel(rec, type, { models });
178
181
  if (!hasId(result)) throw new Error(`Expected model of type ${type} to have an id`);
@@ -195,13 +198,14 @@ var LegacyStore = class LegacyStore {
195
198
  return model;
196
199
  }
197
200
  setupRelations(links) {
198
- for (const key in links) {
201
+ for (const key of Object.keys(links)) {
199
202
  const value = links[key];
200
203
  const parts = key.split(".");
201
204
  const typeRaw = parts[0];
202
205
  const attribute = parts[1];
206
+ if (isUnsafeKey(attribute)) continue;
203
207
  const type = this.types[typeRaw] || typeRaw;
204
- if (!this.relations[type]) this.relations[type] = {};
208
+ if (!this.relations[type]) this.relations[type] = safeObject();
205
209
  this.relations[type][attribute] = this.types[value.type] || value.type;
206
210
  }
207
211
  }
@@ -222,7 +226,7 @@ var LegacyStore = class LegacyStore {
222
226
  build(data) {
223
227
  if (data.links) this.setupRelations(data.links);
224
228
  let name;
225
- for (const key in data) if (key !== "meta" && key !== "links") {
229
+ for (const key of Object.keys(data)) if (key !== "meta" && key !== "links") {
226
230
  name = key;
227
231
  break;
228
232
  }
@@ -248,14 +252,14 @@ var LegacyStore = class LegacyStore {
248
252
  return model;
249
253
  }
250
254
  find(type, id, models) {
251
- return this.#findModel(type, String(id), models ?? this.models);
255
+ return this.#findModel(type, String(id), safeCache(models ?? this.models));
252
256
  }
253
257
  findAll(type, models) {
254
- const modelsObj = models ?? this.models;
258
+ const modelsObj = safeCache(models ?? this.models);
255
259
  const recs = this.findRecords(type);
256
260
  if (recs.length === 0) return [];
257
261
  recs.forEach((rec) => {
258
- if (!modelsObj[type]) modelsObj[type] = {};
262
+ if (!modelsObj[type]) modelsObj[type] = safeObject();
259
263
  return this.toModel(rec, type, modelsObj);
260
264
  });
261
265
  return Object.values(modelsObj[type] || {});
@@ -274,10 +278,10 @@ var LegacyStore = class LegacyStore {
274
278
  }
275
279
  syncAll(data) {
276
280
  this.validationErrors = [];
277
- this.models = {};
281
+ this.models = safeObject();
278
282
  if (data.links) this.setupRelations(data.links);
279
283
  const syncedRecords = [];
280
- for (const name in data) {
284
+ for (const name of Object.keys(data)) {
281
285
  if (name === "meta" || name === "links") continue;
282
286
  const value = data[name];
283
287
  const type = this.types[name] || name;
@@ -1 +1 @@
1
- {"version":3,"file":"legacy.mjs","names":["hasId","#findModel","#createStub","#resolveRelationships","#createModel","result","yaysonFactory"],"sources":["../src/yayson/legacy-presenter.ts","../src/yayson/legacy-store.ts","../src/legacy.ts"],"sourcesContent":["import type { ModelLike } from './adapter.js'\nimport type { Presenter } from './presenter.js'\nimport type { JsonApiDocument, JsonApiLinks, LegacyPresenterOptions } from './types.js'\nimport { filterByFields } from './utils.js'\n\nfunction hasId(value: unknown): value is { id: unknown } {\n return typeof value === 'object' && value !== null && 'id' in value\n}\n\ninterface LegacyJsonApiDocument extends JsonApiDocument {\n [key: string]: unknown\n}\n\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -- Return type is inferred from class\nexport default function createLegacyPresenter(Presenter: Presenter) {\n return class LegacyPresenter extends Presenter {\n declare ['constructor']: typeof LegacyPresenter\n declare scope: LegacyJsonApiDocument\n\n static type = 'object'\n static plural?: string\n static fields?: string[]\n\n constructor(scope?: JsonApiDocument) {\n // LegacyPresenter doesn't use the 'data' property, so pass an empty scope\n const emptyScope: JsonApiDocument = { data: null }\n super(scope || emptyScope)\n // Remove the 'data' property that the parent constructor adds\n if (!scope) {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Need Partial to allow delete\n delete (this.scope as Partial<JsonApiDocument>).data\n }\n }\n\n pluralType(): string {\n return this.constructor.plural || this.constructor.type + 's'\n }\n\n attributes(instance: ModelLike | null): Record<string, unknown> {\n if (!instance) {\n return {}\n }\n const attributes = { ...this.constructor.adapter.get(instance) }\n const relationships = this.relationships()\n if (relationships) {\n for (const key in relationships) {\n let id: unknown\n const data = attributes[key]\n if (data == null) {\n id = attributes[key + 'Id']\n if (id != null) {\n attributes[key] = id\n }\n } else if (Array.isArray(data)) {\n attributes[key] = data.map((obj: unknown) => (hasId(obj) ? obj.id : obj))\n } else if (hasId(data)) {\n attributes[key] = data.id\n }\n }\n }\n\n // Include relationship keys in allowed fields (so users don't need to list them twice)\n const relationshipKeys = relationships ? Object.keys(relationships) : []\n const allowedFields = this.constructor.fields ? [...this.constructor.fields, ...relationshipKeys] : undefined\n\n return filterByFields(attributes, allowedFields)\n }\n\n includeRelationships(scope: LegacyJsonApiDocument, instance: ModelLike): unknown[] {\n if (!scope.links) {\n scope.links = {}\n }\n const relationships = this.relationships()\n const result: unknown[] = []\n\n if (!relationships) {\n return result\n }\n\n for (const key in relationships) {\n const factory = relationships[key]\n if (!factory) throw new Error(`Presenter for ${key} in ${this.constructor.type} is not defined`)\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Factory returns PresenterInstance, we know it's LegacyPresenter\n const presenter = new factory(scope) as LegacyPresenter\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- unknown from adapter.get\n const data = this.constructor.adapter.get(instance, key) as ModelLike | ModelLike[] | null\n if (data != null) {\n presenter.toJSON(data, { defaultPlural: true })\n }\n\n const type = scope[this.pluralType()] != null ? this.pluralType() : this.constructor.type\n const presenterType = presenter.constructor.type\n const keyName = scope[presenter.pluralType()] != null ? presenter.pluralType() : presenterType\n const link = { type: keyName }\n if (scope.links) {\n scope.links[`${type}.${key}`] = link\n }\n result.push(link)\n }\n return result\n }\n\n toJSON(\n instanceOrCollection: ModelLike | ModelLike[] | null | undefined,\n options?: LegacyPresenterOptions,\n ): LegacyJsonApiDocument {\n const opts = options ?? {}\n if (!this.scope.links) {\n this.scope.links = {}\n }\n if (Array.isArray(instanceOrCollection)) {\n const collection = instanceOrCollection\n const type = this.pluralType()\n if (!this.scope[type]) {\n this.scope[type] = []\n }\n collection.forEach((instance: ModelLike) => {\n return this.toJSON(instance)\n })\n } else {\n let links: JsonApiLinks | undefined\n const instance = instanceOrCollection\n let added = true\n const attrs = instance ? this.attributes(instance) : null\n if ((links = this.links())) {\n if (attrs) {\n attrs.links = links\n }\n }\n // If eg x.image already exists\n if (this.scope[this.constructor.type] && !this.scope[this.pluralType()]) {\n const existingValue = this.scope[this.constructor.type]\n if (attrs && hasId(existingValue) && existingValue.id !== attrs.id) {\n this.scope[this.pluralType()] = [this.scope[this.constructor.type]]\n delete this.scope[this.constructor.type]\n const pluralArray = this.scope[this.pluralType()]\n if (Array.isArray(pluralArray)) {\n pluralArray.push(attrs)\n }\n } else {\n added = false\n }\n\n // If eg x.images already exists\n } else if (this.scope[this.pluralType()]) {\n const existing = this.scope[this.pluralType()]\n if (Array.isArray(existing)) {\n if (attrs && !existing.some((i) => hasId(i) && i.id === attrs.id)) {\n existing.push(attrs)\n } else {\n added = false\n }\n }\n } else if (opts.defaultPlural) {\n this.scope[this.pluralType()] = attrs ? [attrs] : []\n } else {\n this.scope[this.constructor.type] = attrs\n }\n\n if (added && instance) {\n this.includeRelationships(this.scope, instance)\n }\n }\n return this.scope\n }\n\n payload(instance: ModelLike): LegacyJsonApiDocument {\n if (Array.isArray(instance)) {\n throw new Error('payload() expects a single resource, not an array')\n }\n if (instance == null) {\n throw new Error('payload() requires a resource, got null')\n }\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Legacy payload intentionally omits `data`\n return { [this.constructor.type]: this.attributes(instance) } as LegacyJsonApiDocument\n }\n\n render(instanceOrCollection: ModelLike | ModelLike[] | null): LegacyJsonApiDocument {\n return this.toJSON(instanceOrCollection)\n }\n\n static toJSON(\n instanceOrCollection: ModelLike | ModelLike[] | null,\n options?: LegacyPresenterOptions,\n ): LegacyJsonApiDocument {\n return new this().toJSON(instanceOrCollection, options)\n }\n\n static render(\n instanceOrCollection: ModelLike | ModelLike[] | null,\n _options?: LegacyPresenterOptions,\n ): LegacyJsonApiDocument {\n return new this().render(instanceOrCollection)\n }\n\n static payload(instance: ModelLike): LegacyJsonApiDocument {\n return new this().payload(instance)\n }\n }\n}\n","import type {\n StoreModel,\n StoreModelWithOptionalId,\n StoreModels,\n StoreResult,\n SchemaRegistry,\n ValidationError,\n InferModelType,\n LegacyStoreOptions,\n} from './types.js'\nimport { TYPE, LINKS, META } from './symbols.js'\nimport { validate } from './schema.js'\n\ninterface LegacyStoreRecordType {\n type: string\n data: Record<string, unknown> & {\n id?: string | number\n meta?: Record<string, unknown>\n links?: Record<string, unknown>\n }\n}\n\ninterface LegacyLinks {\n [key: string]: {\n type: string\n }\n}\n\ntype LegacyDataValue = Record<string, unknown> | Array<Record<string, unknown>>\n\nexport interface LegacyData {\n links?: LegacyLinks\n meta?: Record<string, unknown>\n [key: string]: LegacyDataValue | LegacyLinks | Record<string, unknown> | undefined\n}\n\nfunction hasId<T extends StoreModelWithOptionalId>(model: T): model is T & { id: string | number } {\n return model.id != null\n}\n\nexport default class LegacyStore<S extends SchemaRegistry = SchemaRegistry> {\n types: Record<string, string>\n records: LegacyStoreRecordType[]\n relations: Record<string, Record<string, string>>\n schemas?: S\n strict: boolean\n validationErrors: ValidationError[]\n models: StoreModels\n\n constructor(options?: LegacyStoreOptions<S>) {\n this.types = options?.types || {}\n this.schemas = options?.schemas\n this.strict = options?.strict ?? false\n this.records = []\n this.relations = {}\n this.validationErrors = []\n this.models = {}\n }\n\n reset(): void {\n this.records = []\n this.relations = {}\n this.validationErrors = []\n this.models = {}\n }\n\n #createStub(type: string, id: string): StoreModel {\n const stub: StoreModel = { id }\n stub[TYPE] = type\n return stub\n }\n\n #resolveRelationships(\n model: StoreModel | StoreModelWithOptionalId,\n type: string,\n resolver: (relationType: string, id: string) => StoreModel,\n ): void {\n const relations = this.relations[type]\n if (!relations) return\n\n for (const attribute in relations) {\n const relationType = relations[attribute]!\n const value = model[attribute]\n if (Array.isArray(value)) {\n model[attribute] = value\n .filter((id: unknown) => id != null)\n .map((id: unknown) => resolver(relationType, String(id)))\n } else if (value != null) {\n model[attribute] = resolver(relationType, String(value))\n } else {\n model[attribute] = null\n }\n }\n }\n\n #createModel(rec: LegacyStoreRecordType, type: string, options?: { models?: StoreModels }): StoreModelWithOptionalId {\n const models = options?.models\n\n const model: StoreModelWithOptionalId = { ...rec.data }\n if (rec.data.id != null) {\n model.id = rec.data.id\n }\n model[TYPE] = type\n if (rec.data.meta != null) {\n model[META] = rec.data.meta\n }\n if (rec.data.links != null) {\n model[LINKS] = rec.data.links\n }\n\n if (models && hasId(model)) {\n const idStr = String(model.id)\n if (!models[type]) {\n models[type] = {}\n }\n models[type]![idStr] = model\n }\n\n const resolver = (relationType: string, id: string): StoreModel => {\n return this.#findModel(relationType, id, models ?? {}) ?? this.#createStub(relationType, id)\n }\n this.#resolveRelationships(model, type, resolver)\n\n return model\n }\n\n toModel(rec: LegacyStoreRecordType, type: string, models: StoreModels): StoreModel {\n const idStr = String(rec.data.id)\n\n if (!models[type]) {\n models[type] = {}\n }\n\n if (models[type]![idStr]) {\n return models[type]![idStr]!\n }\n\n const result = this.#createModel(rec, type, { models })\n if (!hasId(result)) {\n throw new Error(`Expected model of type ${type} to have an id`)\n }\n const model = result\n\n if (this.schemas && this.schemas[type]) {\n const schema = this.schemas[type]\n const result = validate(schema, model, this.strict)\n\n if (!result.valid) {\n this.validationErrors.push({\n type,\n id: idStr,\n error: result.error,\n })\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Schema validation returns unknown, cast to StoreModel after validation\n const validatedModel = result.data as StoreModel\n\n // Preserve symbol keys from original model (schema validation may not preserve them)\n validatedModel[TYPE] = model[TYPE]\n validatedModel[LINKS] = model[LINKS]\n validatedModel[META] = model[META]\n\n models[type]![idStr] = validatedModel\n return validatedModel\n }\n\n return model\n }\n\n setupRelations(links: LegacyLinks): void {\n for (const key in links) {\n const value = links[key]!\n const parts = key.split('.')\n const typeRaw = parts[0]!\n const attribute = parts[1]!\n const type = this.types[typeRaw] || typeRaw\n if (!this.relations[type]) {\n this.relations[type] = {}\n }\n this.relations[type]![attribute] = this.types[value.type] || value.type\n }\n }\n\n findRecord(type: string, id: string): LegacyStoreRecordType | undefined {\n return this.records.find((r) => r.type === type && String(r.data.id) === id)\n }\n\n findRecords(type: string): LegacyStoreRecordType[] {\n return this.records.filter((r) => r.type === type)\n }\n\n #findModel(type: string, id: string, models: StoreModels): StoreModel | null {\n const rec = this.findRecord(type, id)\n if (rec == null) {\n return null\n }\n return models[type]?.[id] ?? this.toModel(rec, type, models)\n }\n\n static build(data: LegacyData): StoreModelWithOptionalId {\n return new LegacyStore().build(data)\n }\n\n build(data: LegacyData): StoreModelWithOptionalId {\n if (data.links) {\n this.setupRelations(data.links)\n }\n\n let name: string | undefined\n for (const key in data) {\n if (key !== 'meta' && key !== 'links') {\n name = key\n break\n }\n }\n\n if (name == null) {\n throw new Error('build() expects a single resource, not an array')\n }\n\n const value = data[name]\n if (value == null || Array.isArray(value)) {\n throw new Error('build() expects a single resource, not an array')\n }\n\n const type = this.types[name] || name\n return this.#createModel({ type, data: value }, type)\n }\n\n /** @deprecated Use retrieve() instead. */\n retrive<T extends string>(type: T, data: LegacyData): InferModelType<S, T> | null {\n return this.retrieve(type, data)\n }\n\n retrieve<T extends string>(type: T, data: LegacyData): InferModelType<S, T> | null {\n const synced = this.syncAll(data)\n const normalizedType = this.types[type] || type\n const model = synced.find((m) => m[TYPE] === normalizedType)\n if (!model) return null\n if (synced[META]) {\n model[META] = synced[META]\n }\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Enable type inference from type parameter\n return model as InferModelType<S, T>\n }\n\n find<T extends string>(type: T, id: string | number, models?: StoreModels): InferModelType<S, T> | null {\n const result = this.#findModel(type, String(id), models ?? this.models)\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Type inference: maps string literal type parameter to schema type\n return result as InferModelType<S, T> | null\n }\n\n findAll<T extends string>(type: T, models?: StoreModels): InferModelType<S, T>[] {\n const modelsObj = models ?? this.models\n const recs = this.findRecords(type)\n if (recs.length === 0) {\n return []\n }\n recs.forEach((rec) => {\n if (!modelsObj[type]) {\n modelsObj[type] = {}\n }\n return this.toModel(rec, type, modelsObj)\n })\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Type inference: maps string literal type parameter to schema type\n return Object.values(modelsObj[type] || {}) as InferModelType<S, T>[]\n }\n\n remove(type: string, id?: string | number): void {\n const normalizedType = this.types[type] || type\n\n const removeOne = (record: LegacyStoreRecordType): void => {\n const index = this.records.indexOf(record)\n if (!(index < 0)) {\n this.records.splice(index, 1)\n }\n }\n\n if (id != null) {\n const idStr = String(id)\n const record = this.findRecord(normalizedType, idStr)\n if (record) {\n removeOne(record)\n }\n } else {\n const records = this.findRecords(normalizedType)\n records.forEach(removeOne)\n }\n }\n\n syncAll(data: LegacyData): StoreResult {\n // Clear validation errors and models cache from previous sync\n this.validationErrors = []\n this.models = {}\n\n if (data.links) {\n this.setupRelations(data.links)\n }\n\n const syncedRecords: LegacyStoreRecordType[] = []\n\n for (const name in data) {\n if (name === 'meta' || name === 'links') {\n continue\n }\n\n const value = data[name]!\n const type = this.types[name] || name\n\n const add = (d: Record<string, unknown>): void => {\n this.remove(type, String(d.id))\n const rec: LegacyStoreRecordType = { type, data: d }\n this.records.push(rec)\n syncedRecords.push(rec)\n }\n\n if (Array.isArray(value)) {\n value.forEach(add)\n } else if (typeof value === 'object' && value !== null) {\n add(value)\n }\n }\n\n for (const rec of syncedRecords) {\n this.toModel(rec, rec.type, this.models)\n }\n\n const result: StoreResult = syncedRecords.map((rec) => this.models[rec.type]![String(rec.data.id)]!)\n if (data.meta != null) {\n result[META] = data.meta\n }\n return result\n }\n\n sync(data: LegacyData): StoreModel | StoreResult {\n const result = this.syncAll(data)\n if (result.length === 1) {\n const model = result[0]\n if (result[META]) {\n model[META] = result[META]\n }\n return model\n }\n return result\n }\n\n retrieveAll<T extends string>(type: T, data: LegacyData): StoreResult<InferModelType<S, T>> {\n const normalizedType = this.types[type] || type\n const synced = this.syncAll(data)\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Enable type inference from type parameter\n const result: StoreResult<InferModelType<S, T>> = synced.filter(\n (model) => model[TYPE] === normalizedType,\n ) as StoreResult<InferModelType<S, T>>\n result[META] = synced[META]\n return result\n }\n}\n","import yaysonFactory from './yayson.js'\nimport createLegacyPresenter from './yayson/legacy-presenter.js'\nimport LegacyStore from './yayson/legacy-store.js'\nimport type { LegacyData } from './yayson/legacy-store.js'\nimport Adapter from './yayson/adapter.js'\nimport type {\n JsonApiDocument,\n JsonApiLink,\n JsonApiLinks,\n JsonApiRelationship,\n JsonApiRelationships,\n JsonApiResource,\n} from './yayson/types.js'\nimport type { YaysonOptions } from './yayson.js'\n\nexport type {\n Adapter,\n JsonApiDocument,\n JsonApiLink,\n JsonApiLinks,\n JsonApiRelationship,\n JsonApiRelationships,\n JsonApiResource,\n LegacyData,\n}\n\ninterface LegacyYaysonResult {\n Store: typeof LegacyStore\n Presenter: ReturnType<typeof createLegacyPresenter>\n Adapter: ReturnType<typeof yaysonFactory>['Adapter']\n}\n\nexport default function yayson(options?: YaysonOptions): LegacyYaysonResult {\n const { Presenter, Adapter } = yaysonFactory(options)\n return {\n Store: LegacyStore,\n Presenter: createLegacyPresenter(Presenter),\n Adapter,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"legacy.mjs","names":["hasId","#findModel","#createStub","#resolveRelationships","#createModel","result","yaysonFactory"],"sources":["../src/yayson/legacy-presenter.ts","../src/yayson/legacy-store.ts","../src/legacy.ts"],"sourcesContent":["import type { ModelLike } from './adapter.js'\nimport type { Presenter } from './presenter.js'\nimport type { JsonApiDocument, JsonApiLinks, LegacyPresenterOptions } from './types.js'\nimport { filterByFields } from './utils.js'\n\nfunction hasId(value: unknown): value is { id: unknown } {\n return typeof value === 'object' && value !== null && 'id' in value\n}\n\ninterface LegacyJsonApiDocument extends JsonApiDocument {\n [key: string]: unknown\n}\n\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -- Return type is inferred from class\nexport default function createLegacyPresenter(Presenter: Presenter) {\n return class LegacyPresenter extends Presenter {\n declare ['constructor']: typeof LegacyPresenter\n declare scope: LegacyJsonApiDocument\n\n static type = 'object'\n static plural?: string\n static fields?: string[]\n\n constructor(scope?: JsonApiDocument) {\n // LegacyPresenter doesn't use the 'data' property, so pass an empty scope\n const emptyScope: JsonApiDocument = { data: null }\n super(scope || emptyScope)\n // Remove the 'data' property that the parent constructor adds\n if (!scope) {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Need Partial to allow delete\n delete (this.scope as Partial<JsonApiDocument>).data\n }\n }\n\n pluralType(): string {\n return this.constructor.plural || this.constructor.type + 's'\n }\n\n attributes(instance: ModelLike | null): Record<string, unknown> {\n if (!instance) {\n return {}\n }\n const attributes = { ...this.constructor.adapter.get(instance) }\n const relationships = this.relationships()\n if (relationships) {\n for (const key in relationships) {\n let id: unknown\n const data = attributes[key]\n if (data == null) {\n id = attributes[key + 'Id']\n if (id != null) {\n attributes[key] = id\n }\n } else if (Array.isArray(data)) {\n attributes[key] = data.map((obj: unknown) => (hasId(obj) ? obj.id : obj))\n } else if (hasId(data)) {\n attributes[key] = data.id\n }\n }\n }\n\n // Include relationship keys in allowed fields (so users don't need to list them twice)\n const relationshipKeys = relationships ? Object.keys(relationships) : []\n const allowedFields = this.constructor.fields ? [...this.constructor.fields, ...relationshipKeys] : undefined\n\n return filterByFields(attributes, allowedFields)\n }\n\n includeRelationships(scope: LegacyJsonApiDocument, instance: ModelLike): unknown[] {\n if (!scope.links) {\n scope.links = {}\n }\n const relationships = this.relationships()\n const result: unknown[] = []\n\n if (!relationships) {\n return result\n }\n\n for (const key in relationships) {\n const entry = relationships[key]\n if (!entry) throw new Error(`Presenter for ${key} in ${this.constructor.type} is not defined`)\n const factory = typeof entry === 'function' ? entry : entry.presenter\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Factory returns PresenterInstance, we know it's LegacyPresenter\n const presenter = new factory(scope) as LegacyPresenter\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- unknown from adapter.get\n const data = this.constructor.adapter.get(instance, key) as ModelLike | ModelLike[] | null\n if (data != null) {\n presenter.toJSON(data, { defaultPlural: true })\n }\n\n const type = scope[this.pluralType()] != null ? this.pluralType() : this.constructor.type\n const presenterType = presenter.constructor.type\n const keyName = scope[presenter.pluralType()] != null ? presenter.pluralType() : presenterType\n const link = { type: keyName }\n if (scope.links) {\n scope.links[`${type}.${key}`] = link\n }\n result.push(link)\n }\n return result\n }\n\n toJSON(\n instanceOrCollection: ModelLike | ModelLike[] | null | undefined,\n options?: LegacyPresenterOptions,\n ): LegacyJsonApiDocument {\n const opts = options ?? {}\n if (!this.scope.links) {\n this.scope.links = {}\n }\n if (Array.isArray(instanceOrCollection)) {\n const collection = instanceOrCollection\n const type = this.pluralType()\n if (!this.scope[type]) {\n this.scope[type] = []\n }\n collection.forEach((instance: ModelLike) => {\n return this.toJSON(instance)\n })\n } else {\n let links: JsonApiLinks | undefined\n const instance = instanceOrCollection\n let added = true\n const attrs = instance ? this.attributes(instance) : null\n if ((links = this.links())) {\n if (attrs) {\n attrs.links = links\n }\n }\n // If eg x.image already exists\n if (this.scope[this.constructor.type] && !this.scope[this.pluralType()]) {\n const existingValue = this.scope[this.constructor.type]\n if (attrs && hasId(existingValue) && existingValue.id !== attrs.id) {\n this.scope[this.pluralType()] = [this.scope[this.constructor.type]]\n delete this.scope[this.constructor.type]\n const pluralArray = this.scope[this.pluralType()]\n if (Array.isArray(pluralArray)) {\n pluralArray.push(attrs)\n }\n } else {\n added = false\n }\n\n // If eg x.images already exists\n } else if (this.scope[this.pluralType()]) {\n const existing = this.scope[this.pluralType()]\n if (Array.isArray(existing)) {\n if (attrs && !existing.some((i) => hasId(i) && i.id === attrs.id)) {\n existing.push(attrs)\n } else {\n added = false\n }\n }\n } else if (opts.defaultPlural) {\n this.scope[this.pluralType()] = attrs ? [attrs] : []\n } else {\n this.scope[this.constructor.type] = attrs\n }\n\n if (added && instance) {\n this.includeRelationships(this.scope, instance)\n }\n }\n return this.scope\n }\n\n payload(instance: ModelLike): LegacyJsonApiDocument {\n if (Array.isArray(instance)) {\n throw new Error('payload() expects a single resource, not an array')\n }\n if (instance == null) {\n throw new Error('payload() requires a resource, got null')\n }\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Legacy payload intentionally omits `data`\n return { [this.constructor.type]: this.attributes(instance) } as LegacyJsonApiDocument\n }\n\n render(instanceOrCollection: ModelLike | ModelLike[] | null): LegacyJsonApiDocument {\n return this.toJSON(instanceOrCollection)\n }\n\n static toJSON(\n instanceOrCollection: ModelLike | ModelLike[] | null,\n options?: LegacyPresenterOptions,\n ): LegacyJsonApiDocument {\n return new this().toJSON(instanceOrCollection, options)\n }\n\n static render(\n instanceOrCollection: ModelLike | ModelLike[] | null,\n _options?: LegacyPresenterOptions,\n ): LegacyJsonApiDocument {\n return new this().render(instanceOrCollection)\n }\n\n static payload(instance: ModelLike): LegacyJsonApiDocument {\n return new this().payload(instance)\n }\n }\n}\n","import type {\n StoreModel,\n StoreModelWithOptionalId,\n StoreModels,\n StoreResult,\n SchemaRegistry,\n ValidationError,\n InferModelType,\n LegacyStoreOptions,\n} from './types.js'\nimport { TYPE, LINKS, META } from './symbols.js'\nimport { validate } from './schema.js'\nimport { safeObject, safeCache, isUnsafeKey } from './safe.js'\n\ninterface LegacyStoreRecordType {\n type: string\n data: Record<string, unknown> & {\n id?: string | number\n meta?: Record<string, unknown>\n links?: Record<string, unknown>\n }\n}\n\ninterface LegacyLinks {\n [key: string]: {\n type: string\n }\n}\n\ntype LegacyDataValue = Record<string, unknown> | Array<Record<string, unknown>>\n\nexport interface LegacyData {\n links?: LegacyLinks\n meta?: Record<string, unknown>\n [key: string]: LegacyDataValue | LegacyLinks | Record<string, unknown> | undefined\n}\n\nfunction hasId<T extends StoreModelWithOptionalId>(model: T): model is T & { id: string | number } {\n return model.id != null\n}\n\nexport default class LegacyStore<S extends SchemaRegistry = SchemaRegistry> {\n types: Record<string, string>\n records: LegacyStoreRecordType[]\n relations: Record<string, Record<string, string>>\n schemas?: S\n strict: boolean\n validationErrors: ValidationError[]\n models: StoreModels\n\n constructor(options?: LegacyStoreOptions<S>) {\n // Null-prototype: read with untrusted `name`/`type` values, so \"__proto__\"\n // must not resolve to Object.prototype.\n this.types = safeObject<Record<string, string>>()\n Object.assign(this.types, options?.types)\n this.schemas = options?.schemas\n this.strict = options?.strict ?? false\n this.records = []\n this.relations = safeObject<Record<string, Record<string, string>>>()\n this.validationErrors = []\n this.models = safeObject<StoreModels>()\n }\n\n reset(): void {\n this.records = []\n this.relations = safeObject<Record<string, Record<string, string>>>()\n this.validationErrors = []\n this.models = safeObject<StoreModels>()\n }\n\n #createStub(type: string, id: string): StoreModel {\n const stub: StoreModel = { id }\n stub[TYPE] = type\n return stub\n }\n\n #resolveRelationships(\n model: StoreModel | StoreModelWithOptionalId,\n type: string,\n resolver: (relationType: string, id: string) => StoreModel,\n ): void {\n const relations = this.relations[type]\n if (!relations) return\n\n for (const attribute of Object.keys(relations)) {\n if (isUnsafeKey(attribute)) {\n continue\n }\n const relationType = relations[attribute]!\n const value = model[attribute]\n if (Array.isArray(value)) {\n model[attribute] = value\n .filter((id: unknown) => id != null)\n .map((id: unknown) => resolver(relationType, String(id)))\n } else if (value != null) {\n model[attribute] = resolver(relationType, String(value))\n } else {\n model[attribute] = null\n }\n }\n }\n\n #createModel(rec: LegacyStoreRecordType, type: string, options?: { models?: StoreModels }): StoreModelWithOptionalId {\n const models = options?.models\n\n const model: StoreModelWithOptionalId = { ...rec.data }\n if (rec.data.id != null) {\n model.id = rec.data.id\n }\n model[TYPE] = type\n if (rec.data.meta != null) {\n model[META] = rec.data.meta\n }\n if (rec.data.links != null) {\n model[LINKS] = rec.data.links\n }\n\n if (models && hasId(model)) {\n const idStr = String(model.id)\n if (!models[type]) {\n models[type] = safeObject<StoreModels[string]>()\n }\n models[type]![idStr] = model\n }\n\n const resolver = (relationType: string, id: string): StoreModel => {\n return (\n this.#findModel(relationType, id, models ?? safeObject<StoreModels>()) ?? this.#createStub(relationType, id)\n )\n }\n this.#resolveRelationships(model, type, resolver)\n\n return model\n }\n\n toModel(rec: LegacyStoreRecordType, type: string, modelsArg: StoreModels): StoreModel {\n const idStr = String(rec.data.id)\n const models = safeCache(modelsArg)\n\n if (!models[type]) {\n models[type] = safeObject<StoreModels[string]>()\n }\n\n if (models[type]![idStr]) {\n return models[type]![idStr]!\n }\n\n const result = this.#createModel(rec, type, { models })\n if (!hasId(result)) {\n throw new Error(`Expected model of type ${type} to have an id`)\n }\n const model = result\n\n if (this.schemas && this.schemas[type]) {\n const schema = this.schemas[type]\n const result = validate(schema, model, this.strict)\n\n if (!result.valid) {\n this.validationErrors.push({\n type,\n id: idStr,\n error: result.error,\n })\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Schema validation returns unknown, cast to StoreModel after validation\n const validatedModel = result.data as StoreModel\n\n // Preserve symbol keys from original model (schema validation may not preserve them)\n validatedModel[TYPE] = model[TYPE]\n validatedModel[LINKS] = model[LINKS]\n validatedModel[META] = model[META]\n\n models[type]![idStr] = validatedModel\n return validatedModel\n }\n\n return model\n }\n\n setupRelations(links: LegacyLinks): void {\n for (const key of Object.keys(links)) {\n const value = links[key]!\n const parts = key.split('.')\n const typeRaw = parts[0]!\n const attribute = parts[1]!\n if (isUnsafeKey(attribute)) {\n continue\n }\n const type = this.types[typeRaw] || typeRaw\n if (!this.relations[type]) {\n this.relations[type] = safeObject<Record<string, string>>()\n }\n this.relations[type]![attribute] = this.types[value.type] || value.type\n }\n }\n\n findRecord(type: string, id: string): LegacyStoreRecordType | undefined {\n return this.records.find((r) => r.type === type && String(r.data.id) === id)\n }\n\n findRecords(type: string): LegacyStoreRecordType[] {\n return this.records.filter((r) => r.type === type)\n }\n\n #findModel(type: string, id: string, models: StoreModels): StoreModel | null {\n const rec = this.findRecord(type, id)\n if (rec == null) {\n return null\n }\n return models[type]?.[id] ?? this.toModel(rec, type, models)\n }\n\n static build(data: LegacyData): StoreModelWithOptionalId {\n return new LegacyStore().build(data)\n }\n\n build(data: LegacyData): StoreModelWithOptionalId {\n if (data.links) {\n this.setupRelations(data.links)\n }\n\n let name: string | undefined\n for (const key of Object.keys(data)) {\n if (key !== 'meta' && key !== 'links') {\n name = key\n break\n }\n }\n\n if (name == null) {\n throw new Error('build() expects a single resource, not an array')\n }\n\n const value = data[name]\n if (value == null || Array.isArray(value)) {\n throw new Error('build() expects a single resource, not an array')\n }\n\n const type = this.types[name] || name\n return this.#createModel({ type, data: value }, type)\n }\n\n /** @deprecated Use retrieve() instead. */\n retrive<T extends string>(type: T, data: LegacyData): InferModelType<S, T> | null {\n return this.retrieve(type, data)\n }\n\n retrieve<T extends string>(type: T, data: LegacyData): InferModelType<S, T> | null {\n const synced = this.syncAll(data)\n const normalizedType = this.types[type] || type\n const model = synced.find((m) => m[TYPE] === normalizedType)\n if (!model) return null\n if (synced[META]) {\n model[META] = synced[META]\n }\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Enable type inference from type parameter\n return model as InferModelType<S, T>\n }\n\n find<T extends string>(type: T, id: string | number, models?: StoreModels): InferModelType<S, T> | null {\n const result = this.#findModel(type, String(id), safeCache(models ?? this.models))\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Type inference: maps string literal type parameter to schema type\n return result as InferModelType<S, T> | null\n }\n\n findAll<T extends string>(type: T, models?: StoreModels): InferModelType<S, T>[] {\n const modelsObj = safeCache(models ?? this.models)\n const recs = this.findRecords(type)\n if (recs.length === 0) {\n return []\n }\n recs.forEach((rec) => {\n if (!modelsObj[type]) {\n modelsObj[type] = safeObject<StoreModels[string]>()\n }\n return this.toModel(rec, type, modelsObj)\n })\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Type inference: maps string literal type parameter to schema type\n return Object.values(modelsObj[type] || {}) as InferModelType<S, T>[]\n }\n\n remove(type: string, id?: string | number): void {\n const normalizedType = this.types[type] || type\n\n const removeOne = (record: LegacyStoreRecordType): void => {\n const index = this.records.indexOf(record)\n if (!(index < 0)) {\n this.records.splice(index, 1)\n }\n }\n\n if (id != null) {\n const idStr = String(id)\n const record = this.findRecord(normalizedType, idStr)\n if (record) {\n removeOne(record)\n }\n } else {\n const records = this.findRecords(normalizedType)\n records.forEach(removeOne)\n }\n }\n\n syncAll(data: LegacyData): StoreResult {\n // Clear validation errors and models cache from previous sync\n this.validationErrors = []\n this.models = safeObject<StoreModels>()\n\n if (data.links) {\n this.setupRelations(data.links)\n }\n\n const syncedRecords: LegacyStoreRecordType[] = []\n\n for (const name of Object.keys(data)) {\n if (name === 'meta' || name === 'links') {\n continue\n }\n\n const value = data[name]!\n const type = this.types[name] || name\n\n const add = (d: Record<string, unknown>): void => {\n this.remove(type, String(d.id))\n const rec: LegacyStoreRecordType = { type, data: d }\n this.records.push(rec)\n syncedRecords.push(rec)\n }\n\n if (Array.isArray(value)) {\n value.forEach(add)\n } else if (typeof value === 'object' && value !== null) {\n add(value)\n }\n }\n\n for (const rec of syncedRecords) {\n this.toModel(rec, rec.type, this.models)\n }\n\n const result: StoreResult = syncedRecords.map((rec) => this.models[rec.type]![String(rec.data.id)]!)\n if (data.meta != null) {\n result[META] = data.meta\n }\n return result\n }\n\n sync(data: LegacyData): StoreModel | StoreResult {\n const result = this.syncAll(data)\n if (result.length === 1) {\n const model = result[0]\n if (result[META]) {\n model[META] = result[META]\n }\n return model\n }\n return result\n }\n\n retrieveAll<T extends string>(type: T, data: LegacyData): StoreResult<InferModelType<S, T>> {\n const normalizedType = this.types[type] || type\n const synced = this.syncAll(data)\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Enable type inference from type parameter\n const result: StoreResult<InferModelType<S, T>> = synced.filter(\n (model) => model[TYPE] === normalizedType,\n ) as StoreResult<InferModelType<S, T>>\n result[META] = synced[META]\n return result\n }\n}\n","import yaysonFactory from './yayson.js'\nimport createLegacyPresenter from './yayson/legacy-presenter.js'\nimport LegacyStore from './yayson/legacy-store.js'\nimport type { LegacyData } from './yayson/legacy-store.js'\nimport Adapter from './yayson/adapter.js'\nimport type {\n JsonApiDocument,\n JsonApiLink,\n JsonApiLinks,\n JsonApiRelationship,\n JsonApiRelationships,\n JsonApiResource,\n} from './yayson/types.js'\nimport type { YaysonOptions } from './yayson.js'\n\nexport type {\n Adapter,\n JsonApiDocument,\n JsonApiLink,\n JsonApiLinks,\n JsonApiRelationship,\n JsonApiRelationships,\n JsonApiResource,\n LegacyData,\n}\n\ninterface LegacyYaysonResult {\n Store: typeof LegacyStore\n Presenter: ReturnType<typeof createLegacyPresenter>\n Adapter: ReturnType<typeof yaysonFactory>['Adapter']\n}\n\nexport default function yayson(options?: YaysonOptions): LegacyYaysonResult {\n const { Presenter, Adapter } = yaysonFactory(options)\n return {\n Store: LegacyStore,\n Presenter: createLegacyPresenter(Presenter),\n Adapter,\n }\n}\n"],"mappings":"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"}
@@ -11,6 +11,9 @@ var Adapter = class {
11
11
  if (id == null) return;
12
12
  return `${id}`;
13
13
  }
14
+ static has(model, key) {
15
+ return key in model;
16
+ }
14
17
  };
15
18
  var adapter_default = Adapter;
16
19