@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.
- package/LICENSE.md +21 -0
- package/dist/index.js +27 -133
- package/dist/src/auto-crud.d.ts +225 -0
- package/dist/src/define-model.d.ts +59 -3
- package/dist/src/generate-database-schema.d.ts +23 -0
- package/dist/src/index.d.ts +143 -81
- package/dist/src/model-types.d.ts +53 -4
- package/dist/src/paginator-request.d.ts +68 -0
- package/dist/src/paginator.d.ts +99 -0
- package/dist/src/traits/audit.d.ts +22 -5
- package/dist/src/traits/billable.d.ts +36 -0
- package/dist/src/traits/categorizable.d.ts +4 -0
- package/dist/src/types.d.ts +9 -5
- package/dist/src/utils.d.ts +1 -1
- package/package.json +11 -7
|
@@ -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 '
|
|
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
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -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 '
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
export declare const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
export declare const
|
|
38
|
-
export declare const
|
|
39
|
-
export declare const
|
|
40
|
-
export declare const
|
|
41
|
-
export declare const
|
|
42
|
-
export declare const
|
|
43
|
-
export declare const
|
|
44
|
-
export declare const
|
|
45
|
-
export declare const
|
|
46
|
-
export declare const
|
|
47
|
-
export declare const
|
|
48
|
-
export declare const
|
|
49
|
-
export declare const
|
|
50
|
-
export declare const
|
|
51
|
-
export declare const
|
|
52
|
-
export declare const
|
|
53
|
-
export declare const
|
|
54
|
-
export declare const
|
|
55
|
-
export declare const
|
|
56
|
-
export declare const
|
|
57
|
-
export declare const
|
|
58
|
-
export declare const
|
|
59
|
-
export declare const
|
|
60
|
-
export declare const
|
|
61
|
-
export declare const
|
|
62
|
-
export declare const
|
|
63
|
-
export declare const
|
|
64
|
-
export declare const
|
|
65
|
-
export declare const
|
|
66
|
-
export declare const
|
|
67
|
-
export declare const
|
|
68
|
-
export declare const
|
|
69
|
-
export declare const
|
|
70
|
-
export declare const
|
|
71
|
-
export declare const
|
|
72
|
-
export declare const
|
|
73
|
-
export declare const
|
|
74
|
-
export declare const
|
|
75
|
-
export declare const
|
|
76
|
-
export declare const
|
|
77
|
-
export declare const
|
|
78
|
-
export declare const
|
|
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';
|