@stacksjs/orm 0.70.45 → 0.70.53

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.
@@ -0,0 +1,225 @@
1
+ /**
2
+ * True when the error is a unique-constraint violation, across SQLite,
3
+ * MySQL, and Postgres:
4
+ *
5
+ * - SQLite: `SQLITE_CONSTRAINT_UNIQUE` / `SQLITE_CONSTRAINT`
6
+ * - MySQL: `errno: 1062` (ER_DUP_ENTRY)
7
+ * - Postgres: `code: '23505'` (unique_violation)
8
+ * - Generic fallback: message text match — covers wrapped errors from drivers
9
+ * that lose the structured code.
10
+ *
11
+ * Lives here (cycle-free `@stacksjs/orm`) rather than in `@stacksjs/auth`
12
+ * because every framework write path needs it: auto-CRUD routes, commerce/cms
13
+ * write functions, and `@stacksjs/auth`'s `register()` (which re-exports this
14
+ * via './rbac-store-bqb' for back-compat). `@stacksjs/database` is NOT a valid
15
+ * home — its drivers statically import `@stacksjs/orm`, so orm routes importing
16
+ * from database would create a package cycle.
17
+ *
18
+ * Exported for direct unit testing and for callers that map duplicates to
19
+ * their own error (e.g. `register()`'s 409) instead of swallowing them.
20
+ */
21
+ export declare function isUniqueViolation(err: unknown): boolean;
22
+ /**
23
+ * Classify a write-path error into an HTTP status + JSON body for the
24
+ * auto-CRUD store/update handlers. Three branches, in priority order:
25
+ *
26
+ * 1. HttpError-like (an Error carrying an integer `status` in 400-599) —
27
+ * preserve its status, message and optional `details`. Duck-typed rather
28
+ * than `instanceof HttpError` so this helper stays inline-copyable into the
29
+ * canonical generated routes file without importing @stacksjs/error-handling.
30
+ * Covers the 400/413/422 throws from getRequestBody / validation.
31
+ * 2. Unique-constraint violation — 409 with a clean `${Model} already exists`
32
+ * message (NO raw driver text, which would leak column names in prod).
33
+ * 3. Anything else — the unchanged 500 contract, including `detail: String(err)`.
34
+ */
35
+ export declare function mapWriteError(err: unknown, modelName: string, op: 'create' | 'update'): { status: number, body: Record<string, unknown> };
36
+ /**
37
+ * Attribute names in model definitions may be camelCase; the migration
38
+ * drivers (database/src/drivers/{sqlite,mysql,postgres}.ts) snake_case them
39
+ * into column names. Write payload keys must be mapped the same way, LAST on
40
+ * the write path — fillable filtering, validation, set-hooks and casts are
41
+ * all keyed by attribute name. Output-identical to @stacksjs/strings
42
+ * snakeCase for word-shaped attribute names (locked in by tests).
43
+ */
44
+ export declare function toSnakeCase(s: string): string;
45
+ /** Map every key of a write payload to its snake_case column spelling. */
46
+ export declare function toSnakeCaseKeys(data: Record<string, any>): Record<string, any>;
47
+ /**
48
+ * Filter a request body down to fillable fields. Accepts BOTH the
49
+ * attribute-name spelling and its snake_case column spelling on input, so
50
+ * read-modify-write round-trips work (GET responses expose snake_case
51
+ * columns). The result stays keyed by attribute name — setters, casts and
52
+ * validation rules all look fields up by that spelling.
53
+ */
54
+ export declare function filterFillable(body: any, fillableFields: string[]): Record<string, any>;
55
+ /**
56
+ * Drop attribute keys flagged `hidden: true` from an incoming write body.
57
+ * Must drop BOTH spellings — accepting the snake spelling in filterFillable
58
+ * without this would let `payment_intent_id` sneak past a camelCase hidden
59
+ * marker.
60
+ */
61
+ export declare function dropHiddenInputs(data: Record<string, any>, hiddenFields: string[]): Record<string, any>;
62
+ /**
63
+ * Strip attribute keys flagged `hidden: true` from an outgoing response
64
+ * record. Must drop BOTH spellings — DB rows come back keyed by snake_case
65
+ * column names, so deleting only the attribute-name spelling lets a
66
+ * camelCase hidden attribute (Transaction's `paymentDetails`) leak as
67
+ * `payment_details` on public reads. Response-side mirror of
68
+ * `dropHiddenInputs`.
69
+ */
70
+ export declare function stripHidden(record: any, hiddenFields: string[]): any;
71
+ /**
72
+ * Build the read-path column allowlist for a model: a map from BOTH the
73
+ * attribute-name spelling and its snake_case column spelling to the real
74
+ * snake_case column. One map serves `?sort=` and `?<column>=` filters.
75
+ *
76
+ * Why a map and not a set: attribute names may be camelCase
77
+ * (`discountType`) while DB columns are always snake_case (the migration
78
+ * drivers snake_case them — same contract as `toSnakeCaseKeys` on the
79
+ * write path). A set keyed by attribute spelling let `?sort=discountType`
80
+ * through to `orderBy('discountType')` (ghost column → 500) while
81
+ * REJECTING the real column spelling `discount_type`. The map accepts
82
+ * either spelling and always emits the column spelling.
83
+ *
84
+ * Hidden attributes are removed under BOTH spellings — sorting or
85
+ * equality-filtering on a hidden column (`?two_factor_secret=x`) is a
86
+ * blind-enumeration oracle even though the value never appears in the
87
+ * response body.
88
+ */
89
+ export declare function buildReadColumnMap(attributes: Record<string, unknown> | null | undefined, hiddenFields: string[]): Map<string, string>;
90
+ /**
91
+ * Apply a `?sort=` parameter to a query builder chain. Comma-separated
92
+ * tokens, each optionally `-` prefixed for descending. Tokens are resolved
93
+ * through the `columns` allowlist map (see `buildReadColumnMap`) so either
94
+ * spelling of a declared, non-hidden attribute works and everything else —
95
+ * unknown names, hidden attributes, non-word tokens — is silently skipped
96
+ * (the existing contract, matching the filter loop).
97
+ *
98
+ * Examples:
99
+ * ?sort=name → ORDER BY name ASC
100
+ * ?sort=-rating → ORDER BY rating DESC
101
+ * ?sort=discountType,name → ORDER BY discount_type ASC, name ASC
102
+ */
103
+ export declare function applySorting(query: any, sortParam: string | null, columns: ReadonlyMap<string, string>): any;
104
+ /**
105
+ * Apply a model's `casts` to a record, in either direction:
106
+ * - `'get'` — DB shape → JS-typed values (read responses)
107
+ * - `'set'` — input → DB shape (write payloads)
108
+ *
109
+ * Casts are declared keyed by attribute name (possibly camelCase:
110
+ * `instantBook: 'boolean'`) but DB rows come back keyed by snake_case
111
+ * column names (`instant_book`) — so each cast is applied under BOTH
112
+ * spellings, whichever is present. A record keyed by attribute names
113
+ * (the write path) behaves exactly as before; a snake-keyed DB row (the
114
+ * read path) now gets its casts instead of leaking raw SQLite `"1"`s.
115
+ */
116
+ export declare function applyCasts(record: Record<string, any> | null | undefined, casts: Record<string, string | { get: (v: unknown) => unknown, set: (v: unknown) => unknown }> | null | undefined, direction: 'get' | 'set'): any;
117
+ /**
118
+ * Resolve middleware lists for a model's `useApi` trait value (which may be
119
+ * `true` or `{ uri, routes, middleware }`).
120
+ *
121
+ * Secure-by-default: mutating routes (store/update/destroy) get `auth`
122
+ * unless the model explicitly declares `useApi.middleware` — an explicit
123
+ * `middleware: []` is a deliberate opt-out and is honored (with a startup
124
+ * warning at the call site). Read routes stay public unless declared.
125
+ */
126
+ export declare function resolveApiMiddleware(useApi: unknown): { read: string[], write: string[], declared: boolean };
127
+ /**
128
+ * Resolve `?page=` / `?per_page=` for the index route into a clamped,
129
+ * NaN-safe `{ page, perPage, offset }`.
130
+ *
131
+ * - `page` is clamped to `>= 1` (a `?page=0` / negative would otherwise
132
+ * produce a negative OFFSET), defaulting to 1 on missing/NaN.
133
+ * - `perPage` defaults to {@link INDEX_DEFAULT_PER_PAGE}, is clamped to
134
+ * `>= 1`, and capped at {@link INDEX_MAX_PER_PAGE}.
135
+ */
136
+ export declare function resolveIndexPageArgs(params: URLSearchParams): { page: number, perPage: number, offset: number };
137
+ /**
138
+ * Build the index pagination `meta`. `hasMore` is the source of truth for
139
+ * "is there a next page" (derived by the route from a `LIMIT perPage + 1`
140
+ * probe fetch), so `next_page_url` stays consistent whether or not a total
141
+ * was counted. When `total` is known, `last_page` uses the
142
+ * `Math.max(1, ceil(total / perPage))` floor from the Paginator interface.
143
+ */
144
+ export declare function buildIndexMeta(url: URL, page: number, perPage: number, rowCount: number, hasMore: boolean, total?: number): IndexPageMeta;
145
+ /**
146
+ * Flat Laravel paginator shape for the index response top level. Same values
147
+ * as {@link buildIndexMeta} but keyed `current_page` (not `page`) so a
148
+ * generated-endpoint list response deep-equals a `Model.paginate()` envelope.
149
+ * The `page` -> `current_page` rename is the only delta; the value math lives
150
+ * solely in `buildIndexMeta`.
151
+ */
152
+ export declare function buildIndexPaginator(url: URL, page: number, perPage: number, rowCount: number, hasMore: boolean, total?: number): IndexPaginator;
153
+ /**
154
+ * Columns every auto-CRUD table carries regardless of declared attributes.
155
+ * Members of the read allowlist (sort/filter) alongside the model's own
156
+ * attribute names.
157
+ * @defaultValue `['id', 'uuid', 'created_at', 'updated_at', 'deleted_at']`
158
+ */
159
+ export declare const SYSTEM_COLUMNS: string[];
160
+ /**
161
+ * Built-in cast resolvers — kept in sync with @stacksjs/orm/define-model.
162
+ * A duplicate here is the simplest way to keep auto-CRUD parity with the
163
+ * model-driven path without introducing a circular import.
164
+ */
165
+ export declare const AUTO_CRUD_CASTERS: {
166
+ string: { get: (v) => unknown; set: (v) => unknown };
167
+ number: { get: (v) => unknown; set: (v) => unknown };
168
+ integer: { get: (v) => unknown; set: (v) => unknown };
169
+ float: { get: (v) => unknown; set: (v) => unknown };
170
+ boolean: { get: (v) => unknown; set: (v) => unknown };
171
+ json: { get: (v) => unknown; set: (v) => unknown };
172
+ datetime: { get: (v) => unknown; set: (v) => unknown };
173
+ date: { get: (v) => unknown; set: (v) => unknown };
174
+ array: { get: (v) => unknown; set: (v) => unknown }
175
+ };
176
+ // Default page size for the auto-CRUD index route. Matches the
177
+ // request-aware Model.paginate() / resolvePageArgs default (15) so the
178
+ // REST list endpoint and the in-process paginator agree out of the box.
179
+ export declare const INDEX_DEFAULT_PER_PAGE: 15;
180
+ // Upper bound on ?per_page= so a single request can't ask for an
181
+ // unbounded page and exhaust memory.
182
+ export declare const INDEX_MAX_PER_PAGE: 100;
183
+ /**
184
+ * Pagination `meta` for the auto-CRUD index envelope (`{ data, meta }`).
185
+ *
186
+ * Always carries `page` / `per_page` / `from` / `to` / `has_more_pages`
187
+ * plus `prev_page_url` / `next_page_url`. `total` / `last_page` and the
188
+ * `first_page_url` / `last_page_url` are added only when a total is known
189
+ * (`?with_count=true`).
190
+ */
191
+ export declare interface IndexPageMeta {
192
+ page: number
193
+ per_page: number
194
+ from: number | null
195
+ to: number | null
196
+ has_more_pages: boolean
197
+ prev_page_url: string | null
198
+ next_page_url: string | null
199
+ total?: number
200
+ last_page?: number
201
+ first_page_url?: string
202
+ last_page_url?: string
203
+ }
204
+ /**
205
+ * Flat Laravel paginator shape lifted to the index response top level.
206
+ * Mirrors {@link IndexPageMeta} minus `data`/`path` (the route spreads this
207
+ * alongside its own `data`), but keys the current page as `current_page`
208
+ * instead of `page` so a generated-endpoint list response deep-equals a
209
+ * `Model.paginate()` envelope. `total` / `last_page` / `first_page_url` /
210
+ * `last_page_url` stay gated on `total` (`?with_count=true`), matching
211
+ * {@link SimplePaginator} when absent.
212
+ */
213
+ export declare interface IndexPaginator {
214
+ current_page: number
215
+ per_page: number
216
+ from: number | null
217
+ to: number | null
218
+ has_more_pages: boolean
219
+ prev_page_url: string | null
220
+ next_page_url: string | null
221
+ total?: number
222
+ last_page?: number
223
+ first_page_url?: string
224
+ last_page_url?: string
225
+ }
@@ -1,4 +1,3 @@
1
- import type { InferRelationNames } from 'bun-query-builder';
2
1
  import { createBillableMethods } from './traits/billable';
3
2
  import { createCategorizableMethods } from './traits/categorizable';
4
3
  import { createCommentableMethods } from './traits/commentable';
@@ -6,8 +5,22 @@ import { createLikeableMethods } from './traits/likeable';
6
5
  import { createSoftDeleteMethods } from './traits/soft-deletes';
7
6
  import { createTaggableMethods } from './traits/taggable';
8
7
  import { createTwoFactorMethods } from './traits/two-factor';
8
+ import type { InferRelationNames } from '@stacksjs/query-builder';
9
9
  // Re-export types from bun-query-builder for convenience
10
- export type { ModelDefinition, InferRelationNames, ModelAttributes, InferModelAttributes, SystemFields, ColumnName, AttributeKeys, FillableKeys, HiddenKeys, ModelInstance, ModelQueryBuilder } from 'bun-query-builder';
10
+ export type { ModelDefinition, InferRelationNames, ModelAttributes, InferModelAttributes, SystemFields, ColumnName, AttributeKeys, FillableKeys, HiddenKeys, ModelInstance, ModelQueryBuilder } from '@stacksjs/query-builder';
11
+ /**
12
+ * Run a callback with model lifecycle events suppressed for its entire
13
+ * (synchronous + async) duration. Any nested awaits inside the callback
14
+ * inherit the suppression via the AsyncLocalStorage propagation.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * await User.withoutEvents(async () => {
19
+ * for (const row of importedRows) await User.create(row) // no events fire
20
+ * })
21
+ * ```
22
+ */
23
+ export declare function withoutEvents<T>(fn: () => T | Promise<T>): Promise<T>;
11
24
  /**
12
25
  * Stacks-enhanced model definition.
13
26
  *
@@ -81,7 +94,7 @@ declare interface StacksModelDefinition {
81
94
  primaryKey?: string
82
95
  autoIncrement?: boolean
83
96
  traits?: Record<string, unknown>
84
- indexes?: Array<{ name: string, columns: string[] }>
97
+ indexes?: Array<{ name: string, columns: string[], unique?: boolean, where?: string }>
85
98
  casts?: Record<string, CastType | CasterInterface>
86
99
  attributes: {
87
100
  [key: string]: {
@@ -102,6 +115,27 @@ export declare interface TraitMethods {
102
115
  }
103
116
  /**
104
117
  * Built-in cast types for model attributes.
118
+ *
119
+ * ### Timezone contract (stacksjs/stacks#1876 O-5, D-5)
120
+ *
121
+ * `datetime` and `date` casts persist values in **UTC** regardless of
122
+ * which driver is connected. The `set` direction uses
123
+ * `Date.toISOString()`, which always emits `Z`-suffixed UTC. The
124
+ * `get` direction parses the stored string back into a JavaScript
125
+ * `Date`, which represents an instant on the universal timeline —
126
+ * timezone presentation is the caller's responsibility (typically via
127
+ * `Intl.DateTimeFormat` at the render layer, or a Temporal-API
128
+ * adapter).
129
+ *
130
+ * **Why UTC-only:** Per-driver behavior diverges sharply on
131
+ * timezone-aware columns. PostgreSQL has `timestamptz` (timezone-
132
+ * aware); MySQL stores `TIMESTAMP` as UTC but presents in the
133
+ * session timezone; SQLite has no timezone concept at all and stores
134
+ * ISO strings verbatim. The ORM normalizes them to a single
135
+ * convention (UTC on the wire) so multi-driver apps behave the same
136
+ * across environments. Apps that need original-timezone preservation
137
+ * should store the user's TZ as a separate column and convert at
138
+ * the render layer.
105
139
  */
106
140
  export type CastType = 'string' | 'number' | 'boolean' | 'json' | 'datetime' | 'date' | 'array' | 'integer' | 'float';
107
141
  declare type ModelDefinition = StacksModelDefinition;
@@ -114,3 +148,25 @@ export declare class ModelNotFoundError extends Error {
114
148
  readonly id: number | string | undefined;
115
149
  constructor(model: string, id?: number | string);
116
150
  }
151
+ /**
152
+ * Thrown when a write payload (`Model.create` / `Model.update` /
153
+ * `firstOrCreate` / `updateOrCreate`) contains an attribute the model
154
+ * forbids from mass assignment. There are two reasons this fires:
155
+ *
156
+ * • `guarded` — the attribute is explicitly marked `guarded: true`.
157
+ * • `not-fillable` — the model is in *allowlist* mode (at least one
158
+ * attribute has `fillable: true`) and the write payload contains a
159
+ * non-allowlisted field.
160
+ *
161
+ * The check exists to stop unfiltered request payloads from landing
162
+ * directly in the DB. If you genuinely need to write a normally-protected
163
+ * column, use the `force*` escape hatches (`Model.forceCreate(...)`,
164
+ * `Model.forceUpdate(id, ...)`) — those bypass the check by design and
165
+ * make the bypass auditable in code review.
166
+ */
167
+ export declare class MassAssignmentException extends Error {
168
+ readonly model: string;
169
+ readonly attribute: string;
170
+ readonly reason: 'guarded' | 'not-fillable';
171
+ constructor(model: string, attribute: string, reason: 'guarded' | 'not-fillable');
172
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Walk userland + framework-default models, return the rendered
3
+ * `database/types.d.ts` content plus a structured per-table summary
4
+ * the CLI can render.
5
+ */
6
+ export declare function buildDatabaseSchema(options?: GenerateSchemaOptions): Promise<GenerateSchemaResult>;
7
+ /**
8
+ * Pure renderer — for tests that don't want to round-trip through the
9
+ * model loader.
10
+ */
11
+ export declare function renderDatabaseTypeFile(tables: Array<{ table: string, columns: Record<string, string> }>): string;
12
+ export declare interface GenerateSchemaOptions {
13
+ modelsDir?: string
14
+ defaultsDir?: string
15
+ outFile?: string
16
+ dryRun?: boolean
17
+ }
18
+ export declare interface GenerateSchemaResult {
19
+ outFile: string
20
+ tables: Array<{ table: string, model: string, columns: Record<string, string> }>
21
+ errors: Array<{ file: string, error: string }>
22
+ content: string
23
+ }
@@ -3,6 +3,9 @@ export type { PrunableOptions } from './utils/prunable';
3
3
  export type { AuditHelpers } from './traits/audit';
4
4
  // Re-export soft-delete option types so user code can `satisfies SoftDeleteOptions`.
5
5
  export type { SoftDeleteOptions, SoftDeleteHelpers } from './traits/soft-deletes';
6
+ export type { GenerateSchemaOptions, GenerateSchemaResult } from './generate-database-schema';
7
+ export type { CursorPaginator, Paginator, SimplePaginator } from './paginator';
8
+ export type { ResolvedPageArgs } from './paginator-request';
6
9
  // Re-export type utilities from bun-query-builder so consumers can infer
7
10
  // model types directly from defineModel() definitions
8
11
  export type {
@@ -11,71 +14,120 @@ export type {
11
14
  InferRelationNames,
12
15
  InferTableName,
13
16
  ModelDefinition,
14
- } from 'bun-query-builder';
15
- export declare const User: unknown;
16
- // Same lazy-export pattern for the two queue framework models. The CLI
17
- // commands `buddy queue:status`, `queue:failed`, `queue:flush`,
18
- // `queue:inspect`, `queue:monitor`, `queue:clear` import them as
19
- // `import { Job, FailedJob } from '@stacksjs/orm'`. Prefer the userland
20
- // publication (`app/Models/Job.ts`, dropped in by `buddy publish:model
21
- // Job`) so projects that customize the queue model — renamed columns,
22
- // extra observers, custom traits — see their version.
23
- export declare const Job: unknown;
24
- export declare const FailedJob: unknown;
25
- export declare const Activity: unknown;
26
- export declare const Author: unknown;
27
- export declare const Campaign: unknown;
28
- export declare const Cart: unknown;
29
- export declare const CartItem: unknown;
30
- export declare const Category: unknown;
31
- export declare const Comment: unknown;
32
- export declare const Coupon: unknown;
33
- export declare const Customer: unknown;
34
- export declare const DeliveryRoute: unknown;
35
- export declare const Deployment: unknown;
36
- export declare const DigitalDelivery: unknown;
37
- export declare const Driver: unknown;
38
- export declare const CampaignSend: unknown;
39
- export declare const EmailList: unknown;
40
- export declare const EmailListSubscriber: unknown;
41
- export declare const ErrorModel: unknown;
42
- export declare const GiftCard: unknown;
43
- export declare const LicenseKey: unknown;
44
- export declare const Log: unknown;
45
- export declare const LoyaltyPoint: unknown;
46
- export declare const LoyaltyReward: unknown;
47
- export declare const Manufacturer: unknown;
48
- export declare const Notification: unknown;
49
- export declare const Order: unknown;
50
- export declare const OrderItem: unknown;
51
- export declare const Page: unknown;
52
- export declare const Payment: unknown;
53
- export declare const PaymentMethod: unknown;
54
- export declare const PaymentProduct: unknown;
55
- export declare const PaymentTransaction: unknown;
56
- export declare const Post: unknown;
57
- export declare const PrintDevice: unknown;
58
- export declare const Product: unknown;
59
- export declare const ProductUnit: unknown;
60
- export declare const ProductVariant: unknown;
61
- export declare const Receipt: unknown;
62
- export declare const Release: unknown;
63
- export declare const Request: unknown;
64
- export declare const Review: unknown;
65
- export declare const ShippingMethod: unknown;
66
- export declare const ShippingRate: unknown;
67
- export declare const ShippingZone: unknown;
68
- export declare const SocialPost: unknown;
69
- export declare const Subscriber: unknown;
70
- export declare const SubscriberEmail: unknown;
71
- export declare const Subscription: unknown;
72
- export declare const Tag: unknown;
73
- export declare const TaxRate: unknown;
74
- export declare const Team: unknown;
75
- export declare const Transaction: unknown;
76
- export declare const WaitlistProduct: unknown;
77
- export declare const WaitlistRestaurant: unknown;
78
- export declare const Websocket: unknown;
17
+ } from '@stacksjs/query-builder';
18
+ /**
19
+ * Resolves once all framework-default models have been loaded into the
20
+ * lazy-export proxies. Server bootstrap code that wants to ensure model
21
+ * exports are populated before serving the first request should
22
+ * `await ormReady` early. Per-request code doesn't need to — by the
23
+ * time any HTTP handler runs, the microtask queue has long drained.
24
+ */
25
+ export declare const ormReady: Promise<void>;
26
+ export declare const User: any;
27
+ // Queue framework models. The CLI commands `buddy queue:status`,
28
+ // `queue:failed`, `queue:flush`, `queue:inspect`, `queue:monitor`,
29
+ // `queue:clear` import them as `import { Job, FailedJob } from
30
+ // '@stacksjs/orm'`. Prefer the userland publication
31
+ // (`app/Models/Job.ts`, dropped in by `buddy publish:model Job`) so
32
+ // projects that customize the queue model see their version.
33
+ //
34
+ // Gated on the 'queue' feature flag — projects that don't run a queue
35
+ // (most marketing sites, plain CMS apps) leave it off and skip the
36
+ // defineModel pipeline for these two entirely. The lazyModel proxy
37
+ // returns `undefined` for unloaded models, and the CLI queue commands
38
+ // can check `await ormReady; if (!Job) throw …` to surface a clear
39
+ // "run ./buddy queue:install" error.
40
+ export declare const Job: any;
41
+ export declare const FailedJob: any;
42
+ export declare const Activity: any;
43
+ export declare const Author: any;
44
+ export declare const Campaign: any;
45
+ export declare const Cart: any;
46
+ export declare const CartItem: any;
47
+ export declare const Category: any;
48
+ export declare const Comment: any;
49
+ export declare const Coupon: any;
50
+ export declare const Customer: any;
51
+ export declare const DeliveryRoute: any;
52
+ export declare const Deployment: any;
53
+ export declare const DigitalDelivery: any;
54
+ export declare const Driver: any;
55
+ export declare const CampaignSend: any;
56
+ export declare const EmailList: any;
57
+ export declare const EmailListSubscriber: any;
58
+ export declare const ErrorModel: any;
59
+ export declare const GiftCard: any;
60
+ export declare const LicenseKey: any;
61
+ export declare const Log: any;
62
+ export declare const LoyaltyPoint: any;
63
+ export declare const LoyaltyReward: any;
64
+ export declare const Manufacturer: any;
65
+ export declare const Notification: any;
66
+ export declare const Order: any;
67
+ export declare const OrderItem: any;
68
+ export declare const Page: any;
69
+ export declare const Payment: any;
70
+ export declare const PaymentMethod: any;
71
+ export declare const PaymentProduct: any;
72
+ export declare const PaymentTransaction: any;
73
+ export declare const Post: any;
74
+ export declare const PrintDevice: any;
75
+ export declare const Product: any;
76
+ export declare const ProductUnit: any;
77
+ export declare const ProductVariant: any;
78
+ export declare const Receipt: any;
79
+ export declare const Release: any;
80
+ export declare const Request: any;
81
+ export declare const Review: any;
82
+ export declare const ShippingMethod: any;
83
+ export declare const ShippingRate: any;
84
+ export declare const ShippingZone: any;
85
+ export declare const SocialPost: any;
86
+ export declare const Subscriber: any;
87
+ export declare const SubscriberEmail: any;
88
+ export declare const Subscription: any;
89
+ export declare const Tag: any;
90
+ export declare const TaxRate: any;
91
+ export declare const Team: any;
92
+ export declare const Transaction: any;
93
+ export declare const WaitlistProduct: any;
94
+ export declare const WaitlistRestaurant: any;
95
+ export declare const Websocket: any;
96
+ /**
97
+ * Framework-default User row shape. Matches the attributes declared on
98
+ * `storage/framework/defaults/app/Models/User.ts` plus the system
99
+ * fields contributed by `useUuid` / `useTimestamps` / `useAuth` traits.
100
+ *
101
+ * For project-specific narrowing, prefer `ModelRow<typeof User>` so
102
+ * any added attributes flow through automatically.
103
+ */
104
+ export declare interface UserModel {
105
+ id: number
106
+ uuid: string
107
+ name: string
108
+ email: string
109
+ password: string
110
+ avatar?: string | null
111
+ email_verified_at?: string | null
112
+ two_factor_secret?: string | null
113
+ public_key?: string | null
114
+ created_at: string
115
+ updated_at: string | null
116
+ [key: string]: unknown
117
+ }
118
+ /**
119
+ * Framework-default insertable User shape — fillable attributes from
120
+ * the default User model, all optional (DB-side defaults can fill in
121
+ * the rest). For project-specific narrowing, prefer
122
+ * `NewModelData<typeof User>`.
123
+ */
124
+ export declare interface NewUser {
125
+ name?: string
126
+ email?: string
127
+ password?: string
128
+ avatar?: string | null
129
+ [key: string]: unknown
130
+ }
79
131
  /** Row type for the polymorphic categories table (categorizable trait). */
80
132
  export declare interface CategorizableTable {
81
133
  id?: number
@@ -121,22 +173,6 @@ export declare interface TaggableTable {
121
173
  created_at?: string
122
174
  updated_at?: string
123
175
  }
124
- // The following type utilities are referenced by the framework but are not
125
- // yet exported by the installed `bun-query-builder` version. Until upstream
126
- // catches up we ship structural stubs so consumer code still type-checks.
127
- // These intentionally fall back to `any` to avoid spurious narrowing errors;
128
- // once `bun-query-builder` exports the real shapes, remove these stubs.
129
- export type InferFillableAttributes<_M> = any;
130
- export type InferNumericColumns<_M> = string;
131
- export type InferColumnNames<_M> = string;
132
- export type ModelRow<_M> = any;
133
- export type ModelRowLoose<_M> = any;
134
- export type ModelCreateData<_M> = any;
135
- export type ModelCreateDataLoose<_M> = any;
136
- /** User model row type — inferred from the User model definition. */
137
- export type UserModel = ModelRowLoose<unknown>;
138
- /** Data required to create a new User — inferred fillable attributes. */
139
- export type NewUser = ModelCreateDataLoose<unknown>;
140
176
  export * from './utils/prunable';
141
177
  export {
142
178
  collectEncryptedAttributes,
@@ -147,6 +183,12 @@ export {
147
183
  // Audit trait public API: setAuditUser is the queue/cron escape hatch for
148
184
  // attributing audit rows to a user when there's no current HTTP request.
149
185
  export { setAuditUser, createAuditMethods } from './traits/audit';
186
+ // Shared write-error classifiers (stacksjs/stacks#1957). Named exports only —
187
+ // `export *` would collide with the snakeCase helpers also exported from
188
+ // './auto-crud' via other barrels. `isUniqueViolation` is re-exported by
189
+ // `@stacksjs/auth`'s './rbac-store-bqb' for back-compat; `mapWriteError`
190
+ // powers the auto-CRUD store/update 409 mapping.
191
+ export { isUniqueViolation, mapWriteError } from './auto-crud';
150
192
  export * from './batch-loader';
151
193
  export * from './db';
152
194
  export * from './subquery';
@@ -155,3 +197,23 @@ export * from './model-types';
155
197
  export * from './types';
156
198
  export * from './utils';
157
199
  export * from './define-model';
200
+ // Codegen for `database/types.d.ts` — augments
201
+ // `@stacksjs/database`'s `DatabaseSchema` so `db.selectFrom(...)` gets
202
+ // table-name autocomplete (stacksjs/stacks#1923).
203
+ export { buildDatabaseSchema, renderDatabaseTypeFile } from './generate-database-schema';
204
+ // Canonical paginator shapes + adapters (stacksjs/stacks#1905 P1).
205
+ export {
206
+ isCursorPaginator,
207
+ isPaginator,
208
+ isSimplePaginator,
209
+ toCursorPaginator,
210
+ toPaginator,
211
+ toSimplePaginator,
212
+ } from './paginator';
213
+ // Request-aware pagination helpers (stacksjs/stacks#1906 P2 + #1907 P3).
214
+ export {
215
+ enrichPaginatorUrls,
216
+ parseCursor,
217
+ resolveCursorArgs,
218
+ resolvePageArgs,
219
+ } from './paginator-request';