@stonyx/orm 0.2.1-beta.87 → 0.2.1-beta.89

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.
package/src/store.ts CHANGED
@@ -30,6 +30,10 @@ interface StoreRecord {
30
30
  [key: string]: unknown;
31
31
  }
32
32
 
33
+ function isStoreRecord(value: unknown): value is StoreRecord {
34
+ return typeof value === 'object' && value !== null && '__data' in value;
35
+ }
36
+
33
37
  export default class Store {
34
38
  static instance: Store | undefined;
35
39
 
@@ -103,7 +107,7 @@ export default class Store {
103
107
  if (!conditions || Object.keys(conditions).length === 0) return records;
104
108
 
105
109
  return records.filter((record: unknown) =>
106
- Object.entries(conditions).every(([key, value]) => (record as StoreRecord).__data[key] === value)
110
+ Object.entries(conditions).every(([key, value]) => isStoreRecord(record) && record.__data[key] === value)
107
111
  );
108
112
  }
109
113
 
@@ -127,7 +131,7 @@ export default class Store {
127
131
  if (!conditions || Object.keys(conditions).length === 0) return records;
128
132
 
129
133
  return records.filter((record: unknown) =>
130
- Object.entries(conditions).every(([key, value]) => (record as StoreRecord).__data[key] === value)
134
+ Object.entries(conditions).every(([key, value]) => isStoreRecord(record) && record.__data[key] === value)
131
135
  );
132
136
  }
133
137
 
@@ -149,7 +153,7 @@ export default class Store {
149
153
  if (Object.keys(conditions).length === 0) return records;
150
154
 
151
155
  return records.filter((record: unknown) =>
152
- Object.entries(conditions).every(([key, value]) => (record as StoreRecord).__data[key] === value)
156
+ Object.entries(conditions).every(([key, value]) => isStoreRecord(record) && record.__data[key] === value)
153
157
  );
154
158
  }
155
159
 
@@ -185,12 +189,13 @@ export default class Store {
185
189
  return;
186
190
  }
187
191
 
188
- const record = modelStore.get(id as string | number) as StoreRecord | undefined;
189
-
190
- if (!record) {
192
+ if (typeof id !== 'string' && typeof id !== 'number') return;
193
+ const raw = modelStore.get(id);
194
+ if (!raw || !isStoreRecord(raw)) {
191
195
  console.warn(`[Store] Cannot unload record: ${model}:${id} not found in store`);
192
196
  return;
193
197
  }
198
+ const record = raw;
194
199
 
195
200
  const { toUnload, visited } = options.includeChildren
196
201
  ? this._buildUnloadQueue(record, options)
@@ -224,7 +229,10 @@ export default class Store {
224
229
  }
225
230
  }
226
231
 
227
- for (const relationshipType of TYPES) (relationships.get(relationshipType) as Map<string, unknown>).delete(model);
232
+ for (const relationshipType of TYPES) {
233
+ const reg = relationships.get(relationshipType);
234
+ if (reg instanceof Map) reg.delete(model);
235
+ }
228
236
  }
229
237
 
230
238
  private _removeFromHasManyArrays(modelName: string, recordId: unknown, visited: Set<string>): void {
@@ -240,7 +248,7 @@ export default class Store {
240
248
  // Don't modify arrays of records being deleted
241
249
  if (visited.has(sourceKey)) continue;
242
250
 
243
- const index = hasManyArray.findIndex(r => r && (r as StoreRecord).id === recordId);
251
+ const index = hasManyArray.findIndex(r => r && isStoreRecord(r) && r.id === recordId);
244
252
  if (index !== -1) hasManyArray.splice(index, 1);
245
253
  }
246
254
  }
@@ -254,17 +262,19 @@ export default class Store {
254
262
  if (!targetModelMap) continue;
255
263
 
256
264
  for (const [sourceRecordId, belongsToRecord] of targetModelMap) {
257
- if (belongsToRecord && (belongsToRecord as StoreRecord).id === recordId) {
265
+ if (belongsToRecord && isStoreRecord(belongsToRecord) && belongsToRecord.id === recordId) {
258
266
  const sourceKey = `${sourceModel}:${sourceRecordId}`;
259
267
 
260
268
  if (visited.has(sourceKey)) continue;
261
269
  targetModelMap.set(sourceRecordId, null);
262
270
 
263
- const sourceRecord = this.get(sourceModel, sourceRecordId as string | number) as StoreRecord | undefined;
264
- if (sourceRecord && sourceRecord.__relationships) {
265
- for (const [key, value] of Object.entries(sourceRecord.__relationships)) {
266
- if (value && (value as StoreRecord).id === recordId) {
267
- sourceRecord.__relationships[key] = null;
271
+ if (typeof sourceRecordId !== 'string' && typeof sourceRecordId !== 'number') continue;
272
+ const sourceRaw = this.get(sourceModel, sourceRecordId);
273
+ if (!sourceRaw || !isStoreRecord(sourceRaw)) continue;
274
+ if (sourceRaw.__relationships) {
275
+ for (const [key, value] of Object.entries(sourceRaw.__relationships)) {
276
+ if (value && isStoreRecord(value) && value.id === recordId) {
277
+ sourceRaw.__relationships[key] = null;
268
278
  }
269
279
  }
270
280
  }
@@ -301,13 +311,13 @@ export default class Store {
301
311
  // hasMany children - always include
302
312
  if (Array.isArray(value)) {
303
313
  for (const childRecord of value) {
304
- if (childRecord) children.push({ childRecord: childRecord as StoreRecord, relationshipKey: key, type: 'hasMany' });
314
+ if (childRecord && isStoreRecord(childRecord)) children.push({ childRecord, relationshipKey: key, type: 'hasMany' });
305
315
  }
306
- } else if (value && !this._isBidirectionalRelationship(
316
+ } else if (value && isStoreRecord(value) && value.__model && !this._isBidirectionalRelationship(
307
317
  record.__model.__name,
308
- (value as StoreRecord).__model.__name
318
+ value.__model.__name
309
319
  )) {
310
- children.push({ childRecord: value as StoreRecord, relationshipKey: key, type: 'belongsTo' });
320
+ children.push({ childRecord: value, relationshipKey: key, type: 'belongsTo' });
311
321
  }
312
322
  }
313
323
 
@@ -332,7 +342,8 @@ export default class Store {
332
342
  }];
333
343
 
334
344
  while (queue.length > 0) {
335
- const item = queue.shift()!;
345
+ const item = queue.shift();
346
+ if (!item) break;
336
347
  const key = `${item.modelName}:${item.recordId}`;
337
348
 
338
349
  if (visited.has(key)) continue;
package/src/utils.ts CHANGED
@@ -1,14 +1,20 @@
1
1
  import { pluralize as basePluralize } from '@stonyx/utils/string';
2
+ import type { OrmRecord } from './types/orm-types.js';
2
3
 
3
4
  export function isDbError(error: unknown): error is { code: string; message: string } {
4
5
  return typeof error === 'object' && error !== null && 'code' in error && typeof (error as Record<string, unknown>).code === 'string' && 'message' in error && typeof (error as Record<string, unknown>).message === 'string';
5
6
  }
6
7
 
8
+ export function isOrmRecord(value: unknown): value is OrmRecord {
9
+ return typeof value === 'object' && value !== null && '__data' in value && '__relationships' in value;
10
+ }
11
+
7
12
  // Wrapper to handle dasherized model names (e.g., "access-link" → "access-links")
8
13
  export function pluralize(word: string): string {
9
14
  if (word.includes('-')) {
10
15
  const parts = word.split('-');
11
- const pluralizedLast = basePluralize(parts.pop()!);
16
+ const last = parts.pop() as string;
17
+ const pluralizedLast = basePluralize(last);
12
18
  return [...parts, pluralizedLast].join('-');
13
19
  }
14
20
 
@@ -137,7 +137,8 @@ export default class ViewResolver {
137
137
  if (!groups.has(key)) {
138
138
  groups.set(key, []);
139
139
  }
140
- groups.get(key)!.push(record);
140
+ const group = groups.get(key);
141
+ if (group) group.push(record);
141
142
  }
142
143
 
143
144
  const results: unknown[] = [];