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

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.
@@ -122,7 +122,7 @@ export default class PostgresDB {
122
122
  const pending = files.filter(f => !applied.includes(f));
123
123
 
124
124
  if (pending.length > 0) {
125
- this.deps.log.db!(`${pending.length} pending migration(s) found.`);
125
+ this.deps.log.db?.(`${pending.length} pending migration(s) found.`);
126
126
 
127
127
  const shouldApply = await this.deps.confirm(`${pending.length} pending migration(s) found. Apply now?`);
128
128
 
@@ -132,13 +132,13 @@ export default class PostgresDB {
132
132
  const { up } = this.deps.parseMigrationFile(content);
133
133
 
134
134
  await this.deps.applyMigration(this.requirePool(), filename, up, this.pgConfig.migrationsTable as string | undefined);
135
- this.deps.log.db!(`Applied migration: ${filename}`);
135
+ this.deps.log.db?.(`Applied migration: ${filename}`);
136
136
  }
137
137
 
138
138
  // Reload records after applying migrations
139
139
  await this.loadMemoryRecords();
140
140
  } else {
141
- this.deps.log.warn!('Skipping pending migrations. Schema may be outdated.');
141
+ this.deps.log.warn?.('Skipping pending migrations. Schema may be outdated.');
142
142
  }
143
143
  } else if (files.length === 0) {
144
144
  const schemas = this.deps.introspectModels();
@@ -156,11 +156,11 @@ export default class PostgresDB {
156
156
  if (result) {
157
157
  const { up } = this.deps.parseMigrationFile(result.content);
158
158
  await this.deps.applyMigration(this.requirePool(), result.filename, up, this.pgConfig.migrationsTable as string | undefined);
159
- this.deps.log.db!(`Applied migration: ${result.filename}`);
159
+ this.deps.log.db?.(`Applied migration: ${result.filename}`);
160
160
  await this.loadMemoryRecords();
161
161
  }
162
162
  } else {
163
- this.deps.log.warn!('Skipping initial migration. Tables may not exist.');
163
+ this.deps.log.warn?.('Skipping initial migration. Tables may not exist.');
164
164
  }
165
165
  }
166
166
  }
@@ -173,8 +173,8 @@ export default class PostgresDB {
173
173
  const drift = this.deps.detectSchemaDrift(schemas, snapshot as Parameters<typeof detectSchemaDrift>[1]);
174
174
 
175
175
  if (drift.hasChanges) {
176
- this.deps.log.warn!('Schema drift detected: models have changed since the last migration.');
177
- this.deps.log.warn!('Run `stonyx db:generate-migration` to create a new migration.');
176
+ this.deps.log.warn?.('Schema drift detected: models have changed since the last migration.');
177
+ this.deps.log.warn?.('Run `stonyx db:generate-migration` to create a new migration.');
178
178
  }
179
179
  }
180
180
  }
@@ -200,7 +200,7 @@ export default class PostgresDB {
200
200
  for (const modelName of order) {
201
201
  const { modelClass } = Orm.instance.getRecordClasses(modelName) as { modelClass: { memory?: boolean } };
202
202
  if (modelClass?.memory === false) {
203
- this.deps.log.db!(`Skipping memory load for '${modelName}' (memory: false)`);
203
+ this.deps.log.db?.(`Skipping memory load for '${modelName}' (memory: false)`);
204
204
  continue;
205
205
  }
206
206
 
@@ -217,7 +217,7 @@ export default class PostgresDB {
217
217
  } catch (error) {
218
218
  // 42P01 = undefined_table (PG equivalent of ER_NO_SUCH_TABLE)
219
219
  if (isDbError(error) && error.code === '42P01') {
220
- this.deps.log.db!(`Table '${schema.table}' does not exist yet. Skipping load for '${modelName}'.`);
220
+ this.deps.log.db?.(`Table '${schema.table}' does not exist yet. Skipping load for '${modelName}'.`);
221
221
  continue;
222
222
  }
223
223
 
@@ -231,7 +231,7 @@ export default class PostgresDB {
231
231
  for (const [viewName, viewSchema] of Object.entries(viewSchemas)) {
232
232
  const { modelClass: viewClass } = Orm.instance.getRecordClasses(viewName) as { modelClass: { memory?: boolean } };
233
233
  if (viewClass?.memory !== true) {
234
- this.deps.log.db!(`Skipping memory load for view '${viewName}' (memory: false)`);
234
+ this.deps.log.db?.(`Skipping memory load for view '${viewName}' (memory: false)`);
235
235
  continue;
236
236
  }
237
237
 
@@ -256,7 +256,7 @@ export default class PostgresDB {
256
256
  }
257
257
  } catch (error) {
258
258
  if (isDbError(error) && error.code === '42P01') {
259
- this.deps.log.db!(`View '${viewSchema.viewName}' does not exist yet. Skipping load for '${viewName}'.`);
259
+ this.deps.log.db?.(`View '${viewSchema.viewName}' does not exist yet. Skipping load for '${viewName}'.`);
260
260
  continue;
261
261
  }
262
262
  throw error;
@@ -345,13 +345,14 @@ export default class PostgresDB {
345
345
 
346
346
  if (!schema) return [];
347
347
 
348
- const { sql, values } = this.deps.buildSelect(schema.table, conditions);
348
+ const resolvedSchema = schema;
349
+ const { sql, values } = this.deps.buildSelect(resolvedSchema.table, conditions);
349
350
 
350
351
  try {
351
352
  const result = await this.requirePool().query(sql, values);
352
353
 
353
354
  const records = result.rows.map(row => {
354
- const rawData = this._rowToRawData(row, schema!);
355
+ const rawData = this._rowToRawData(row, resolvedSchema);
355
356
  return this.deps.createRecord(modelName, rawData, { isDbRecord: true, serialize: false, transform: false }) as unknown as OrmRecord;
356
357
  });
357
358
 
@@ -93,9 +93,10 @@ export function introspectModels(): Record<string, ModelSchema> {
93
93
 
94
94
  // Build foreign keys from belongsTo relationships
95
95
  for (const [relName, targetModelName] of Object.entries(relationships.belongsTo)) {
96
+ if (!targetModelName) continue;
96
97
  const fkColumn = `${relName}_id`;
97
98
  foreignKeys[fkColumn] = {
98
- references: sanitizeTableName(getPluralName(targetModelName!)),
99
+ references: sanitizeTableName(getPluralName(targetModelName)),
99
100
  column: 'id',
100
101
  };
101
102
  }
@@ -189,7 +190,7 @@ export function getTopologicalOrder(schemas: Record<string, ModelSchema>): strin
189
190
 
190
191
  // Visit dependencies (belongsTo targets) first
191
192
  for (const targetModelName of Object.values(schema.relationships.belongsTo)) {
192
- visit(targetModelName!);
193
+ if (targetModelName) visit(targetModelName);
193
194
  }
194
195
 
195
196
  order.push(name);
@@ -233,11 +234,13 @@ export function introspectViews(): Record<string, ViewSchema> {
233
234
 
234
235
  if (relInfo?.type === 'belongsTo') {
235
236
  relationships.belongsTo[key] = relInfo.modelName;
236
- const fkColumn = `${key}_id`;
237
- foreignKeys[fkColumn] = {
238
- references: sanitizeTableName(getPluralName(relInfo.modelName!)),
239
- column: 'id',
240
- };
237
+ if (relInfo.modelName) {
238
+ const fkColumn = `${key}_id`;
239
+ foreignKeys[fkColumn] = {
240
+ references: sanitizeTableName(getPluralName(relInfo.modelName)),
241
+ column: 'id',
242
+ };
243
+ }
241
244
  } else if (relInfo?.type === 'hasMany') {
242
245
  relationships.hasMany[key] = relInfo.modelName;
243
246
  } else if (property instanceof ModelProperty) {
@@ -13,11 +13,12 @@ export function getRelationships(type: string, sourceModel: string, targetModel:
13
13
  // create relationship map for this type of it doesn't already exist
14
14
  if (!allRelationships.has(sourceModel)) allRelationships.set(sourceModel, new Map());
15
15
 
16
- const modelRelationship = allRelationships.get(sourceModel)!;
16
+ const modelRelationship = allRelationships.get(sourceModel) as Map<string, Map<unknown, unknown>> | undefined;
17
+ if (!modelRelationship) return undefined;
17
18
 
18
19
  if (!modelRelationship.has(targetModel)) modelRelationship.set(targetModel, new Map());
19
20
 
20
- const relationship = modelRelationship.get(targetModel)!;
21
+ const relationship = modelRelationship.get(targetModel) as Map<unknown, unknown> | undefined;
21
22
 
22
23
  // TODO: Determine whether already having id should be handled differently
23
24
  //if (relationship.has(relationshipId)) return;
@@ -14,7 +14,7 @@ interface AccessInstance {
14
14
  }
15
15
 
16
16
  export default async function(route: string, accessPath: string, metaRoute: boolean): Promise<void> {
17
- let accessFiles: Record<string, (request: unknown) => unknown> | null = {};
17
+ const accessFiles: Record<string, (request: unknown) => unknown> = {};
18
18
 
19
19
  try {
20
20
  await forEachFileImport(accessPath, (accessClass: unknown) => {
@@ -31,14 +31,14 @@ export default async function(route: string, accessPath: string, metaRoute: bool
31
31
  for (const model of models === '*' ? availableModels : models) {
32
32
  if (model === dbKey) continue;
33
33
  if (!store.data.has(model)) throw new Error(`Unable to define access for Invalid Model "${model}". Model does not exist`);
34
- if (accessFiles![model]) throw new Error(`Access for model "${model}" has already been defined by another access class.`);
34
+ if (accessFiles[model]) throw new Error(`Access for model "${model}" has already been defined by another access class.`);
35
35
 
36
- accessFiles![model] = accessInstance.access;
36
+ accessFiles[model] = accessInstance.access;
37
37
  }
38
38
  });
39
39
  } catch (error) {
40
- log.error!(error instanceof Error ? error.message : String(error));
41
- log.warn!('You must define a valid access configuration file in order to access ORM generated REST endpoints.');
40
+ log.error?.(error instanceof Error ? error.message : String(error));
41
+ log.warn?.('You must define a valid access configuration file in order to access ORM generated REST endpoints.');
42
42
  }
43
43
 
44
44
  await waitForModule('rest-server');
@@ -47,7 +47,7 @@ export default async function(route: string, accessPath: string, metaRoute: bool
47
47
  const name = route === '/' ? 'index' : (route[0] === '/' ? route.slice(1) : route);
48
48
 
49
49
  // Configure endpoints for models and views with access configuration
50
- for (const [model, access] of Object.entries(accessFiles!)) {
50
+ for (const [model, access] of Object.entries(accessFiles)) {
51
51
  const pluralizedModel = getPluralName(model);
52
52
  const modelName = name === 'index' ? pluralizedModel : `${name}/${pluralizedModel}`;
53
53
  RestServer.instance.mountRoute(OrmRequest, { name: modelName, options: { model, access } });
@@ -55,11 +55,8 @@ export default async function(route: string, accessPath: string, metaRoute: bool
55
55
 
56
56
  // Mount the meta route when metaRoute config is enabled
57
57
  if (metaRoute) {
58
- log.warn!('SECURITY RISK! - Meta route is enabled via metaRoute config. This feature is intended for development purposes only!');
58
+ log.warn?.('SECURITY RISK! - Meta route is enabled via metaRoute config. This feature is intended for development purposes only!');
59
59
 
60
60
  RestServer.instance.mountRoute(MetaRequest, { name });
61
61
  }
62
-
63
- // Cleanup references
64
- accessFiles = null;
65
62
  }
package/src/store.ts CHANGED
@@ -332,7 +332,8 @@ export default class Store {
332
332
  }];
333
333
 
334
334
  while (queue.length > 0) {
335
- const item = queue.shift()!;
335
+ const item = queue.shift();
336
+ if (!item) break;
336
337
  const key = `${item.modelName}:${item.recordId}`;
337
338
 
338
339
  if (visited.has(key)) continue;
package/src/utils.ts CHANGED
@@ -8,7 +8,8 @@ export function isDbError(error: unknown): error is { code: string; message: str
8
8
  export function pluralize(word: string): string {
9
9
  if (word.includes('-')) {
10
10
  const parts = word.split('-');
11
- const pluralizedLast = basePluralize(parts.pop()!);
11
+ const last = parts.pop() as string;
12
+ const pluralizedLast = basePluralize(last);
12
13
  return [...parts, pluralizedLast].join('-');
13
14
  }
14
15
 
@@ -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[] = [];