@stacksjs/orm 0.72.103 → 0.73.1

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.
@@ -84,7 +84,7 @@ export declare function getWritableFields(model: {
84
84
  * columns). The result stays keyed by attribute name — setters, casts and
85
85
  * validation rules all look fields up by that spelling.
86
86
  */
87
- export declare function filterFillable(body: any, fillableFields: string[]): Record<string, any>;
87
+ export declare function filterFillable(body: Record<string, unknown> | null | undefined, fillableFields: string[]): Record<string, unknown>;
88
88
  /**
89
89
  * Normalize JSON-safe values for validators whose in-process type cannot be
90
90
  * represented directly in a request body. `schema.date()` validates a Date
@@ -92,7 +92,7 @@ export declare function filterFillable(body: any, fillableFields: string[]): Rec
92
92
  * stored write payload unchanged and normalize only the value passed to the
93
93
  * validator.
94
94
  */
95
- export declare function normalizeValidationValue(rule: any, value: unknown): unknown;
95
+ export declare function normalizeValidationValue(rule: { name?: unknown } | null | undefined, value: unknown): unknown;
96
96
  /**
97
97
  * Drop attribute keys flagged `hidden: true` from an incoming write body.
98
98
  * Must drop BOTH spellings — accepting the snake spelling in filterFillable
@@ -108,7 +108,7 @@ export declare function dropHiddenInputs(data: Record<string, any>, hiddenFields
108
108
  * `payment_details` on public reads. Response-side mirror of
109
109
  * `dropHiddenInputs`.
110
110
  */
111
- export declare function stripHidden(record: any, hiddenFields: string[]): any;
111
+ export declare function stripHidden<T extends Record<string, unknown>>(record: T | null | undefined, hiddenFields: string[]): T | null | undefined;
112
112
  /**
113
113
  * Build the read-path column allowlist for a model: a map from BOTH the
114
114
  * attribute-name spelling and its snake_case column spelling to the real
@@ -141,7 +141,7 @@ export declare function buildReadColumnMap(attributes: Record<string, unknown> |
141
141
  * ?sort=-rating → ORDER BY rating DESC
142
142
  * ?sort=discountType,name → ORDER BY discount_type ASC, name ASC
143
143
  */
144
- export declare function applySorting(query: any, sortParam: string | null, columns: ReadonlyMap<string, string>): any;
144
+ export declare function applySorting<Q extends { orderBy: (_column: string, _direction: 'asc' | 'desc') => Q }>(query: Q, sortParam: string | null, columns: ReadonlyMap<string, string>): Q;
145
145
  declare function safeJSON(s: string): unknown;
146
146
  declare function safeJSONOrEmpty(_s: string): unknown;
147
147
  /**
@@ -50,7 +50,7 @@ export declare function withoutValidation<T>(fn: () => T | Promise<T>): Promise<
50
50
  * decides for itself how many queries that costs; without it this falls back to
51
51
  * projecting each row, which is what a column-rearranging `shape` wants anyway.
52
52
  */
53
- export declare function projectDocumentsFromTrait(models: any[], config: SearchableTraitConfig): Promise<Record<string, unknown>[]>;
53
+ export declare function projectDocumentsFromTrait(config: SearchableTraitConfig): Promise<Record<string, unknown>[]>;
54
54
  export declare function defineModel<const TDef extends ModelDefinition>(definition: TDef): StacksModelStatic<TDef>;
55
55
  /**
56
56
  * Normalize a ModelInstance (or array of them, or already-plain row) into
@@ -65,7 +65,7 @@ export declare function defineModel<const TDef extends ModelDefinition>(definiti
65
65
  * the latter pattern silently leaks `hidden: true` fields (e.g. license_plate,
66
66
  * vin, password hashes) into responses.
67
67
  */
68
- export declare function toAttrs<T = any>(value: any): T;
68
+ export declare function toAttrs<T = unknown>(value: unknown): T;
69
69
  /**
70
70
  * Thrown when a direct write fails a declared `validation.rule`.
71
71
  *
@@ -164,6 +164,48 @@ export declare interface TraitMethods {
164
164
  * the render layer.
165
165
  */
166
166
  export type CastType = 'string' | 'number' | 'boolean' | 'json' | 'datetime' | 'date' | 'array' | 'integer' | 'float';
167
+ /**
168
+ * Wrap a bun-query-builder ModelInstance in a Proxy that:
169
+ *
170
+ * 1. Forwards attribute reads to `_attributes` so `user.password` /
171
+ * `car.slug` work (instead of returning undefined and silently
172
+ * breaking auth, ownership checks, etc.).
173
+ * 2. Cleans up `{ ...instance }` spreads — only attribute keys appear,
174
+ * not the model's private `_attributes` / `_original` / etc. fields.
175
+ * 3. Keeps every instance method (.update, .save, .toJSON, etc.) bound
176
+ * to the underlying instance.
177
+ *
178
+ * Hidden fields (`hidden: true` attrs) are NOT auto-stripped — call
179
+ * `toAttrs(instance)` or `instance.toJSON()` for that. This proxy is about
180
+ * making direct property access work, not about output sanitization.
181
+ */
182
+ /**
183
+ * A model instance, in the terms this proxy reads it.
184
+ *
185
+ * `wrapModelInstance` is generic over `T extends object`, so nothing inside
186
+ * the handler knew that its target carries `_attributes`, `save`, `isDirty`
187
+ * and the rest - and it reached for them through 31 separate
188
+ * `target` casts. Each one unchecked the whole instance, so a
189
+ * renamed internal (`_attributes` is the one this file is built on) would
190
+ * have gone unnoticed at every single site.
191
+ *
192
+ * Named once, and the target narrowed to it once, so the handler body is
193
+ * checked against the members it genuinely depends on.
194
+ */
195
+ /**
196
+ * The shared model definition, as this handler mutates it.
197
+ *
198
+ * `saveAsync` blanks `def.set` around the inner `save()` so the sync path does
199
+ * not run the setters a second time, then restores it on a `finally`. That
200
+ * assignment is to a `readonly` field, and on an object the comment there
201
+ * already notes is shared across every instance of the model - which the
202
+ * `(target)` reads made invisible at the point of assignment.
203
+ */
204
+ declare type MutableModelDefinition = Omit<ModelDefinition, 'set'> & {
205
+ set?: ModelDefinition['set']
206
+ /** Trait method bags, attached by the trait installers. */
207
+ __traitMethods?: unknown
208
+ }
167
209
  declare type BQBModelAttribute = BQBModelDefinition['attributes'][string];
168
210
  export type StacksModelAttribute = Omit<BQBModelAttribute, 'factory'> & {
169
211
  factory?: (faker: Faker) => unknown
package/dist/index.d.ts CHANGED
@@ -75,8 +75,8 @@ export declare const DeliveryRoute: ReturnType<typeof lazyModel<typeof import('.
75
75
  export declare const DeliveryStop: ReturnType<typeof lazyModel<typeof import('./models/commerce/DeliveryStop').default>>;
76
76
  export declare const Deployment: ReturnType<typeof lazyModel<typeof import('./models/Deployment').default>>;
77
77
  export declare const DigitalDelivery: ReturnType<typeof lazyModel<typeof import('./models/commerce/DigitalDelivery').default>>;
78
- export declare const Driver: ReturnType<typeof lazyModel<typeof import('./models/commerce/Driver').default>>;
79
- export declare const DriverPing: ReturnType<typeof lazyModel<typeof import('./models/commerce/DriverPing').default>>;
78
+ export declare const Courier: ReturnType<typeof lazyModel<typeof import('./models/commerce/Courier').default>>;
79
+ export declare const CourierPing: ReturnType<typeof lazyModel<typeof import('./models/commerce/CourierPing').default>>;
80
80
  export declare const CampaignSend: ReturnType<typeof lazyModel<typeof import('./models/CampaignSend').default>>;
81
81
  export declare const EmailList: ReturnType<typeof lazyModel<typeof import('./models/EmailList').default>>;
82
82
  export declare const EmailListSubscriber: ReturnType<typeof lazyModel<typeof import('./models/EmailListSubscriber').default>>;