@happyvertical/smrt-core 0.38.19 → 0.38.21

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/AGENTS.md CHANGED
@@ -51,6 +51,14 @@ await collection.list({
51
51
  });
52
52
  ```
53
53
 
54
+ Projection primitive (#1902): pass `select: ['id', 'title', 'tenantId']` to
55
+ `list()` when an admin/list workflow needs compact rows. `select` uses SMRT
56
+ field names, maps them to DB columns internally, and returns plain objects keyed
57
+ by the same SMRT field names without hydrating `SmrtObject` instances. It
58
+ composes with `where`, `orderBy`, `limit`, and `offset`; `beforeList`
59
+ interceptors still run. It is for column-backed fields only and cannot combine
60
+ with `include`/relationship eager loading.
61
+
54
62
  **WHERE operators**: `=`, `>`, `<`, `>=`, `<=`, `!=`, `in`, `not in`, `like`, `is null`, `is not null`. Arrays auto-detect `IN`. Dot notation for JSON paths: `metadata.userId`.
55
63
 
56
64
  STI child collections auto-filter by `_meta_type`.
@@ -51,20 +51,72 @@ export type SmrtCreateInput<T extends SmrtObject> = Partial<Omit<{
51
51
  * `convertWhereKeys()` handles field and operator checking.
52
52
  */
53
53
  export type SmrtWhereClause<T extends SmrtObject> = Record<string, unknown>;
54
+ type SmrtModelData<T extends SmrtObject> = Omit<{
55
+ [K in keyof T as T[K] extends (...args: never[]) => unknown ? never : K]: T[K];
56
+ }, SmrtInternalKeys>;
57
+ /**
58
+ * Logical field names accepted by `collection.list({ select })`.
59
+ *
60
+ * `select` is intentionally a column-backed projection primitive: callers pass
61
+ * SMRT field names such as `parentId`, and the collection maps them to database
62
+ * columns such as `parent_id` while returning rows keyed by the original SMRT
63
+ * field names.
64
+ */
65
+ export type SmrtSelectField<T extends SmrtObject> = Extract<keyof SmrtModelData<T>, string> | 'id' | 'slug' | 'context' | 'created_at' | 'updated_at' | '_meta_type';
66
+ type SmrtCoreSelectedFieldData = {
67
+ id: string | null | undefined;
68
+ slug: string | null | undefined;
69
+ context: string;
70
+ created_at: Date | null | undefined;
71
+ updated_at: Date | null | undefined;
72
+ _meta_type: string;
73
+ };
74
+ /**
75
+ * Plain row shape returned by `collection.list({ select })`.
76
+ */
77
+ export type SmrtSelectedRow<T extends SmrtObject, Select extends readonly SmrtSelectField<T>[]> = {
78
+ [Field in Select[number]]: Field extends keyof SmrtCoreSelectedFieldData ? SmrtCoreSelectedFieldData[Field] : Field extends keyof SmrtModelData<T> ? SmrtModelData<T>[Field] : unknown;
79
+ };
80
+ export interface SmrtListOptions<ModelType extends SmrtObject> {
81
+ where?: SmrtWhereClause<ModelType>;
82
+ offset?: number;
83
+ limit?: number;
84
+ orderBy?: string | string[];
85
+ /**
86
+ * Column-backed field projection. When present, `list()` returns plain rows
87
+ * instead of hydrated model instances.
88
+ */
89
+ select?: readonly SmrtSelectField<ModelType>[];
90
+ /**
91
+ * Relationships to eagerly load. Only supported for hydrated list() calls.
92
+ */
93
+ include?: string[];
94
+ /**
95
+ * Opt-in read-through cache for this call (issue #1498).
96
+ */
97
+ cache?: CollectionCacheConfig | false;
98
+ }
54
99
  /**
55
100
  * Minimal runtime shape of a field definition as consumed by the collection's
56
101
  * query/hydration helpers (`getFieldsSync()`, `convertWhereKeys()`,
57
102
  * `formatDataJs()`). These come from `fieldsFromClass()` /
58
103
  * `ObjectRegistry.getFields()` and only a few members are read here: `type`
59
- * (for `formatDataJs` value coercion) and the `sensitive` markers (for the
60
- * `@field({ sensitive: true })` WHERE guard, #1540). The index signature keeps
61
- * the bag open for the other registry-attached members without forcing `any`.
104
+ * (for `formatDataJs` value coercion) and the field-level access markers. The
105
+ * index signature keeps the bag open for the other registry-attached members
106
+ * without forcing `any`.
62
107
  */
63
108
  interface CollectionFieldDefinition {
64
109
  type?: string;
110
+ primaryKey?: boolean;
111
+ transient?: boolean;
65
112
  sensitive?: boolean;
113
+ readPermission?: string;
66
114
  _meta?: {
67
115
  sensitive?: boolean;
116
+ readPermission?: string;
117
+ transient?: boolean;
118
+ primaryKey?: boolean;
119
+ __smrtSystemField?: boolean;
68
120
  } & Record<string, unknown>;
69
121
  [key: string]: unknown;
70
122
  }
@@ -139,6 +191,16 @@ export declare class SmrtCollection<ModelType extends SmrtObject> extends SmrtCl
139
191
  * ```
140
192
  */
141
193
  private convertWhereKeys;
194
+ private toDbColumnName;
195
+ private assertSafeProjectionFieldName;
196
+ private quoteProjectionIdentifier;
197
+ private isSensitiveFieldDefinition;
198
+ private getReadPermissionFieldDefinition;
199
+ private collectSensitiveFieldNames;
200
+ private hasCustomPrimaryKey;
201
+ private isOmittedCustomPrimaryKeySystemField;
202
+ private resolveProjectionSelect;
203
+ private formatProjectionRow;
142
204
  /**
143
205
  * Gets the class constructor for items in this collection
144
206
  */
@@ -299,7 +361,7 @@ export declare class SmrtCollection<ModelType extends SmrtObject> extends SmrtCl
299
361
  * The cache key is the final SQL + bound parameters — computed after
300
362
  * interceptors (tenancy filters) and STI discriminators are applied, so
301
363
  * differently-scoped queries can never share an entry. Cached values are
302
- * raw rows; hydration and read interceptors still run on every call.
364
+ * raw rows; callers still run their normal post-query formatting path.
303
365
  */
304
366
  private queryRowsWithCache;
305
367
  /**
@@ -351,6 +413,7 @@ export declare class SmrtCollection<ModelType extends SmrtObject> extends SmrtCl
351
413
  * @param options.offset - Number of records to skip
352
414
  * @param options.limit - Maximum number of records to return
353
415
  * @param options.orderBy - Field(s) to order results by, with optional direction
416
+ * @param options.select - Column-backed fields to return as plain rows without hydrating model instances
354
417
  *
355
418
  * @example
356
419
  * ```typescript
@@ -377,46 +440,24 @@ export declare class SmrtCollection<ModelType extends SmrtObject> extends SmrtCl
377
440
  * 'last_login <': lastMonth
378
441
  * }
379
442
  * });
443
+ *
444
+ * // Fetch compact page-key rows without constructing full objects
445
+ * await collection.list({
446
+ * select: ['id', 'title', 'accountId'],
447
+ * where: { status: 'open' },
448
+ * orderBy: 'created_at DESC',
449
+ * limit: 50,
450
+ * });
380
451
  * ```
381
452
  *
382
- * @returns Promise resolving to an array of model instances
453
+ * @returns Promise resolving to an array of model instances, or plain selected rows when `select` is present
383
454
  */
384
- list(options?: {
385
- where?: SmrtWhereClause<ModelType>;
386
- offset?: number;
387
- limit?: number;
388
- orderBy?: string | string[];
389
- /**
390
- * Relationships to eagerly load (avoids N+1 query problem)
391
- * @example
392
- * ```typescript
393
- * // Load orders with their customers pre-loaded
394
- * const orders = await orderCollection.list({
395
- * include: ['customerId']
396
- * });
397
- * // Access customer without additional query
398
- * orders[0].getRelated('customerId');
399
- * ```
400
- */
401
- include?: string[];
402
- /**
403
- * Opt-in read-through cache for this call (issue #1498).
404
- *
405
- * Pass `{ ttl }` (milliseconds) to memoize the result rows keyed by
406
- * the final query shape. Mutations through SMRT invalidate the
407
- * table's entries automatically. Pass `false` to force a fresh read
408
- * when the model opted in via `@smrt({ cache })`. Defaults to the
409
- * model-level config; uncached when neither is set.
410
- *
411
- * @example
412
- * ```typescript
413
- * const published = await resumes.list({
414
- * where: { status: 'published' },
415
- * cache: { ttl: 60_000 },
416
- * });
417
- * ```
418
- */
419
- cache?: CollectionCacheConfig | false;
455
+ list<const Select extends readonly SmrtSelectField<ModelType>[]>(options: SmrtListOptions<ModelType> & {
456
+ select: Select;
457
+ include?: never;
458
+ }): Promise<SmrtSelectedRow<ModelType, Select>[]>;
459
+ list(options?: Omit<SmrtListOptions<ModelType>, 'select'> & {
460
+ select?: undefined;
420
461
  }): Promise<ModelType[]>;
421
462
  /**
422
463
  * Eagerly load relationships for a collection of instances
@@ -1 +1 @@
1
- {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"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"}
@@ -116,18 +116,7 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
116
116
  ];
117
117
  const fields = this.getFieldsSync();
118
118
  const validFieldNames = new Set(Object.keys(fields).map((f) => toSnakeCase(f)));
119
- const sensitiveFieldNames = /* @__PURE__ */ new Set();
120
- const collectSensitive = (fieldMap) => {
121
- const entries = fieldMap instanceof Map ? fieldMap.entries() : Object.entries(fieldMap);
122
- for (const [fieldName, rawDef] of entries) {
123
- const def = rawDef;
124
- if (def && (def.sensitive === true || def._meta?.sensitive === true)) {
125
- sensitiveFieldNames.add(toSnakeCase(fieldName));
126
- sensitiveFieldNames.add(fieldName);
127
- }
128
- }
129
- };
130
- collectSensitive(fields);
119
+ const sensitiveFieldNames = this.collectSensitiveFieldNames(fields);
131
120
  validFieldNames.add("id");
132
121
  validFieldNames.add("slug");
133
122
  validFieldNames.add("context");
@@ -145,10 +134,10 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
145
134
  if (ancestorName === "SmrtObject" || ancestorName === "SmrtClass" || ancestorName === itemQualifiedName || ancestorName === itemClassName) continue;
146
135
  const ancestorFields = ObjectRegistry.getFields(ancestorName);
147
136
  for (const fieldName of ancestorFields.keys()) validFieldNames.add(toSnakeCase(fieldName));
148
- collectSensitive(ancestorFields);
137
+ this.collectSensitiveFieldNames(ancestorFields, sensitiveFieldNames);
149
138
  }
150
139
  const stiBase = ObjectRegistry.getSTIBase(itemQualifiedName);
151
- if (stiBase) for (const descendant of ObjectRegistry.getDescendants(stiBase)) collectSensitive(ObjectRegistry.getFields(descendant));
140
+ if (stiBase) for (const descendant of ObjectRegistry.getDescendants(stiBase)) this.collectSensitiveFieldNames(ObjectRegistry.getFields(descendant), sensitiveFieldNames);
152
141
  }
153
142
  const skipFieldValidation = !(Object.keys(fields).length > 0);
154
143
  const converted = {};
@@ -177,6 +166,88 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
177
166
  }
178
167
  return converted;
179
168
  }
169
+ toDbColumnName(fieldName) {
170
+ return fieldName.startsWith("_") ? `_${toSnakeCase(fieldName.slice(1))}` : toSnakeCase(fieldName);
171
+ }
172
+ assertSafeProjectionFieldName(fieldName) {
173
+ if (fieldName === "__proto__" || fieldName === "constructor" || fieldName === "prototype") throw new Error(`Invalid select field: '${fieldName}'. Prototype pollution attempts are not allowed.`);
174
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(fieldName)) throw new Error(`Invalid select field: '${fieldName}'. Field names must be identifiers (letters, digits, underscore).`);
175
+ }
176
+ quoteProjectionIdentifier(identifier) {
177
+ this.assertSafeProjectionFieldName(identifier);
178
+ return `"${identifier.replace(/"/g, "\"\"")}"`;
179
+ }
180
+ isSensitiveFieldDefinition(fieldDef) {
181
+ return fieldDef?.sensitive === true || fieldDef?._meta?.sensitive === true;
182
+ }
183
+ getReadPermissionFieldDefinition(fieldDef) {
184
+ if (typeof fieldDef?.readPermission === "string") return fieldDef.readPermission;
185
+ if (typeof fieldDef?._meta?.readPermission === "string") return fieldDef._meta.readPermission;
186
+ }
187
+ collectSensitiveFieldNames(fieldMap, target = /* @__PURE__ */ new Set()) {
188
+ const entries = fieldMap instanceof Map ? fieldMap.entries() : Object.entries(fieldMap);
189
+ for (const [fieldName, fieldDef] of entries) if (this.isSensitiveFieldDefinition(fieldDef)) {
190
+ target.add(toSnakeCase(fieldName));
191
+ target.add(fieldName);
192
+ }
193
+ return target;
194
+ }
195
+ hasCustomPrimaryKey(fields) {
196
+ return Object.values(fields).some((fieldDef) => fieldDef.primaryKey === true || fieldDef._meta?.primaryKey === true);
197
+ }
198
+ isOmittedCustomPrimaryKeySystemField(fieldName, hasCustomPrimaryKey, explicitFieldNames) {
199
+ return hasCustomPrimaryKey && !explicitFieldNames.has(fieldName) && (fieldName === "id" || fieldName === "slug" || fieldName === "context");
200
+ }
201
+ resolveProjectionSelect(select, fields, isSTI) {
202
+ if (!Array.isArray(select)) throw new Error("Invalid select option: expected an array of field names.");
203
+ if (select.length === 0) throw new Error("Invalid select option: at least one field name is required.");
204
+ const customPrimaryKey = this.hasCustomPrimaryKey(fields);
205
+ const itemClassName = this.getResolvedItemClassName();
206
+ const itemQualifiedName = this.getResolvedItemQualifiedName();
207
+ const schema = ObjectRegistry.getSchema(itemQualifiedName) ?? ObjectRegistry.getSchema(itemClassName);
208
+ const schemaColumnNames = schema?.columns ? new Set(Object.keys(schema.columns)) : void 0;
209
+ const registeredFields = ObjectRegistry.getFields(itemQualifiedName);
210
+ const explicitFields = registeredFields.size > 0 ? registeredFields : ObjectRegistry.getFields(itemClassName);
211
+ const explicitFieldNames = new Set(explicitFields.keys());
212
+ const validFieldNames = /* @__PURE__ */ new Set();
213
+ for (const [fieldName, fieldDef] of Object.entries(fields)) {
214
+ if (this.isOmittedCustomPrimaryKeySystemField(fieldName, customPrimaryKey, explicitFieldNames)) continue;
215
+ const columnName = this.toDbColumnName(fieldName);
216
+ if (schemaColumnNames && !schemaColumnNames.has(columnName)) continue;
217
+ validFieldNames.add(fieldName);
218
+ }
219
+ if (isSTI && (!schemaColumnNames || schemaColumnNames.has("_meta_type"))) validFieldNames.add("_meta_type");
220
+ const seen = /* @__PURE__ */ new Set();
221
+ const outputFields = [];
222
+ const selectExpressions = [];
223
+ for (const fieldName of select) {
224
+ if (typeof fieldName !== "string") throw new Error(`Invalid select field: expected a string field name, got ${typeof fieldName}.`);
225
+ this.assertSafeProjectionFieldName(fieldName);
226
+ if (seen.has(fieldName)) throw new Error(`Invalid select field: '${fieldName}' was requested more than once.`);
227
+ seen.add(fieldName);
228
+ if (!validFieldNames.has(fieldName)) throw new Error(`Invalid select field: '${fieldName}'. Field does not exist on ${itemClassName}. Valid fields: ${Array.from(validFieldNames).sort().join(", ")}`);
229
+ const fieldDef = fields[fieldName];
230
+ const fieldType = fieldDef?.type;
231
+ if (this.isSensitiveFieldDefinition(fieldDef)) throw new Error(`Invalid select field: '${fieldName}' is sensitive and cannot be projected by collection.list({ select }).`);
232
+ const readPermission = this.getReadPermissionFieldDefinition(fieldDef);
233
+ if (readPermission) throw new Error(`Invalid select field: '${fieldName}' is gated by readPermission '${readPermission}' and cannot be projected by collection.list({ select }).`);
234
+ const isTransient = fieldDef?.transient === true || fieldDef?._meta?.transient === true;
235
+ if (fieldType === "meta" || isTransient || fieldType === "oneToMany" || fieldType === "manyToMany") throw new Error(`Invalid select field: '${fieldName}' is not a column-backed field on ${itemClassName}.`);
236
+ const columnName = this.toDbColumnName(fieldName);
237
+ selectExpressions.push(`${this.quoteProjectionIdentifier(columnName)} AS ${this.quoteProjectionIdentifier(fieldName)}`);
238
+ outputFields.push(fieldName);
239
+ }
240
+ return {
241
+ sql: selectExpressions.join(", "),
242
+ outputFields
243
+ };
244
+ }
245
+ formatProjectionRow(row, fields, outputFields) {
246
+ const formattedData = this.withHydratedCoreFields(formatDataJs(row, fields));
247
+ const projected = {};
248
+ for (const fieldName of outputFields) projected[fieldName] = formattedData[fieldName];
249
+ return projected;
250
+ }
180
251
  /**
181
252
  * Gets the class constructor for items in this collection
182
253
  */
@@ -412,7 +483,7 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
412
483
  * The cache key is the final SQL + bound parameters — computed after
413
484
  * interceptors (tenancy filters) and STI discriminators are applied, so
414
485
  * differently-scoped queries can never share an entry. Cached values are
415
- * raw rows; hydration and read interceptors still run on every call.
486
+ * raw rows; callers still run their normal post-query formatting path.
416
487
  */
417
488
  async queryRowsWithCache(sql, params, cacheConfig) {
418
489
  if (!cacheConfig) return (await this.db.query(sql, ...params)).rows;
@@ -492,52 +563,13 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
492
563
  const instance = await this.hydrateResultRow(rows[0], fields, isSTI);
493
564
  return await GlobalInterceptors.executeAfterGet(itemClassName, instance, interceptorContext);
494
565
  }
495
- /**
496
- * Lists records from the collection with flexible filtering options
497
- *
498
- * @param options - Query options object
499
- * @param options.where - Record of conditions to filter results. Each key can include an operator
500
- * separated by a space (e.g., 'price >', 'name like'). Default operator is '='.
501
- * @param options.offset - Number of records to skip
502
- * @param options.limit - Maximum number of records to return
503
- * @param options.orderBy - Field(s) to order results by, with optional direction
504
- *
505
- * @example
506
- * ```typescript
507
- * // Find active products priced between $100-$200
508
- * await collection.list({
509
- * where: {
510
- * 'price >': 100,
511
- * 'price <=': 200,
512
- * 'status': 'active', // equals operator is default
513
- * 'category in': ['A', 'B', 'C'], // IN operator for arrays
514
- * 'name like': '%shirt%', // LIKE for pattern matching
515
- * 'deleted_at !=': null // exclude deleted items
516
- * },
517
- * limit: 10,
518
- * offset: 0
519
- * });
520
- *
521
- * // Find users matching pattern but not in specific roles
522
- * await users.list({
523
- * where: {
524
- * 'email like': '%@company.com',
525
- * 'active': true,
526
- * 'role in': ['guest', 'blocked'],
527
- * 'last_login <': lastMonth
528
- * }
529
- * });
530
- * ```
531
- *
532
- * @returns Promise resolving to an array of model instances
533
- */
534
566
  async list(options = {}) {
535
567
  await this.ensureStorageReady();
536
568
  const itemClassName = this.getResolvedItemClassName();
537
569
  const itemQualifiedName = this.getResolvedItemQualifiedName();
538
570
  const interceptorContext = createInterceptorContext(itemClassName, "list", this.constructor.name);
539
571
  const interceptedOptions = await GlobalInterceptors.executeBeforeList(itemClassName, options, interceptorContext) ?? options ?? {};
540
- let { where, offset, limit, orderBy } = interceptedOptions;
572
+ let { where, offset, limit, orderBy, select } = interceptedOptions;
541
573
  const isSTI = ObjectRegistry.getTableStrategy(itemQualifiedName) === "sti";
542
574
  if (isSTI) {
543
575
  const stiBase = ObjectRegistry.getSTIBase(itemQualifiedName);
@@ -548,6 +580,9 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
548
580
  }
549
581
  where = resolveMetaTypeInWhere(where);
550
582
  const { sql: whereSql, values: whereValues } = buildWhere(this.convertWhereKeys(where || {}));
583
+ const fields = this.getFieldsSync();
584
+ const projection = select !== void 0 ? this.resolveProjectionSelect(select, fields, isSTI) : void 0;
585
+ if (projection && interceptedOptions.include && interceptedOptions.include.length > 0) throw new Error("collection.list({ select }) returns plain projection rows and cannot eager-load relationships. Remove include or omit select.");
551
586
  let orderBySql = "";
552
587
  if (orderBy) {
553
588
  orderBySql = " ORDER BY ";
@@ -570,10 +605,10 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
570
605
  limitOffsetSql += ` OFFSET $${paramIndex++}`;
571
606
  limitOffsetValues.push(offset);
572
607
  }
573
- const sql = `SELECT * FROM ${this.tableName} ${whereSql} ${orderBySql} ${limitOffsetSql}`;
608
+ const sql = `SELECT ${projection ? projection.sql : "*"} FROM ${this.tableName} ${whereSql} ${orderBySql} ${limitOffsetSql}`;
574
609
  const params = [...whereValues, ...limitOffsetValues];
575
610
  const rows = await this.queryRowsWithCache(sql, params, this.resolveReadCacheConfig(interceptedOptions.cache));
576
- const fields = this.getFieldsSync();
611
+ if (projection) return rows.map((item) => this.formatProjectionRow(item, fields, projection.outputFields));
577
612
  const instances = await Promise.all(rows.map((item) => this.hydrateResultRow(item, fields, isSTI)));
578
613
  if (interceptedOptions.include && interceptedOptions.include.length > 0) await this.eagerLoadRelationships(instances, interceptedOptions.include);
579
614
  return await GlobalInterceptors.executeAfterList(itemClassName, instances, interceptorContext);