@stacksjs/orm 0.70.368 → 0.70.370
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/dist/batch-loader.d.ts +5 -1
- package/dist/define-model.d.ts +52 -15
- package/dist/index.d.ts +3 -0
- package/dist/index.js +13 -13
- package/dist/model-types.d.ts +113 -20
- package/dist/subquery.d.ts +6 -6
- package/dist/transaction.d.ts +2 -2
- package/package.json +7 -6
package/dist/model-types.d.ts
CHANGED
|
@@ -1,17 +1,106 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MODEL_DEFINITION } from './define-model';
|
|
2
|
+
import type { Validator } from '@stacksjs/validation';
|
|
2
3
|
/**
|
|
3
4
|
* Extract the raw ModelDefinition from a defineModel() return value.
|
|
4
5
|
* Uses the getDefinition() accessor that defineModel() provides.
|
|
5
6
|
*/
|
|
6
|
-
export type Def<T> = T extends {
|
|
7
|
+
export type Def<T> = T extends { readonly [MODEL_DEFINITION]: infer TDefinition }
|
|
8
|
+
? TDefinition
|
|
9
|
+
: T extends { getDefinition: () => infer TDefinition }
|
|
10
|
+
? TDefinition
|
|
11
|
+
: never;
|
|
7
12
|
/**
|
|
8
13
|
* Extract foreign key columns from belongsTo relations.
|
|
9
14
|
* e.g., belongsTo: ['Customer', 'Coupon'] → { customer_id: number, coupon_id: number }
|
|
10
15
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
?
|
|
14
|
-
: {}
|
|
16
|
+
declare type SnakeCase<S extends string> = S extends `${infer TFirst}${infer TRest}`
|
|
17
|
+
? TFirst extends Lowercase<TFirst>
|
|
18
|
+
? `${TFirst}${SnakeCase<TRest>}`
|
|
19
|
+
: `_${Lowercase<TFirst>}${SnakeCase<TRest>}`
|
|
20
|
+
: S;
|
|
21
|
+
declare type BelongsToForeignKeyOf<TEntry> = TEntry extends string
|
|
22
|
+
? `${SnakeCase<Uncapitalize<TEntry>>}_id`
|
|
23
|
+
: TEntry extends { readonly foreignKey: infer TForeignKey extends string }
|
|
24
|
+
? TForeignKey
|
|
25
|
+
: TEntry extends { readonly model: infer TModel extends string }
|
|
26
|
+
? `${SnakeCase<Uncapitalize<TModel>>}_id`
|
|
27
|
+
: never;
|
|
28
|
+
declare type BelongsToForeignKeyNames<TDef> = TDef extends { readonly belongsTo: infer TRelations }
|
|
29
|
+
? TRelations extends readonly (infer TEntry)[]
|
|
30
|
+
? BelongsToForeignKeyOf<TEntry>
|
|
31
|
+
: TRelations extends Readonly<Record<string, infer TEntry>>
|
|
32
|
+
? BelongsToForeignKeyOf<TEntry>
|
|
33
|
+
: never
|
|
34
|
+
: never;
|
|
35
|
+
export type BelongsToForeignKeys<TDef> = {
|
|
36
|
+
[TKey in BelongsToForeignKeyNames<TDef>]: number
|
|
37
|
+
}
|
|
38
|
+
declare type DefinitionAttributes<TDef> = TDef extends { readonly attributes: infer TAttributes }
|
|
39
|
+
? TAttributes
|
|
40
|
+
: never;
|
|
41
|
+
declare type AttributeKeys<TDef> = keyof DefinitionAttributes<TDef> & string;
|
|
42
|
+
declare type PrimitiveType<TType> = TType extends 'string'
|
|
43
|
+
? string
|
|
44
|
+
: TType extends 'number' ? number
|
|
45
|
+
: TType extends 'boolean' ? boolean
|
|
46
|
+
: TType extends 'date' ? Date
|
|
47
|
+
: TType extends 'json' ? Record<string, unknown>
|
|
48
|
+
: TType extends readonly (infer TValue)[] ? TValue
|
|
49
|
+
: TType extends Validator<infer TValue> ? TValue
|
|
50
|
+
: unknown;
|
|
51
|
+
declare type WidenDefault<TValue> = TValue extends string
|
|
52
|
+
? string
|
|
53
|
+
: TValue extends number ? number
|
|
54
|
+
: TValue extends boolean ? boolean
|
|
55
|
+
: TValue;
|
|
56
|
+
declare type AttributeValue<TAttribute> = TAttribute extends { readonly type: infer TType }
|
|
57
|
+
? PrimitiveType<TType>
|
|
58
|
+
: TAttribute extends { readonly factory: (...args: never[]) => infer TValue } ? TValue
|
|
59
|
+
: TAttribute extends { readonly validation: { readonly rule: infer TRule } }
|
|
60
|
+
? TRule extends Validator<infer TValue> ? TValue : unknown
|
|
61
|
+
: TAttribute extends { readonly default: infer TDefault } ? WidenDefault<TDefault>
|
|
62
|
+
: unknown;
|
|
63
|
+
declare type DeclaredAttributes<TDef> = {
|
|
64
|
+
[TKey in AttributeKeys<TDef>]: DefinitionAttributes<TDef>[TKey] extends { readonly nullable: true }
|
|
65
|
+
? AttributeValue<DefinitionAttributes<TDef>[TKey]> | null
|
|
66
|
+
: AttributeValue<DefinitionAttributes<TDef>[TKey]>
|
|
67
|
+
}
|
|
68
|
+
declare type SnakeCaseAttributes<TDef> = {
|
|
69
|
+
[TKey in AttributeKeys<TDef> as SnakeCase<TKey>]: DeclaredAttributes<TDef>[TKey]
|
|
70
|
+
}
|
|
71
|
+
declare type PrimaryKey<TDef> = TDef extends { readonly primaryKey: infer TKey extends string } ? TKey : 'id';
|
|
72
|
+
declare type TraitFields<TDef> = { [TKey in PrimaryKey<TDef>]: number }
|
|
73
|
+
& (TDef extends { readonly traits: { readonly useUuid: true } } ? { uuid: string } : {})
|
|
74
|
+
& (TDef extends { readonly traits: { readonly useTimestamps: true } } ? {
|
|
75
|
+
created_at: string
|
|
76
|
+
updated_at: string | null
|
|
77
|
+
} : {})
|
|
78
|
+
& (TDef extends { readonly traits: { readonly timestampable: true | object } } ? {
|
|
79
|
+
created_at: string
|
|
80
|
+
updated_at: string | null
|
|
81
|
+
} : {})
|
|
82
|
+
& (TDef extends { readonly traits: { readonly useSoftDeletes: true } } ? { deleted_at: string | null } : {})
|
|
83
|
+
& (TDef extends { readonly traits: { readonly softDeletable: true | object } } ? { deleted_at: string | null } : {})
|
|
84
|
+
& (TDef extends { readonly traits: { readonly useAuth: true | object } } ? {
|
|
85
|
+
two_factor_secret: string | null
|
|
86
|
+
public_key: string | null
|
|
87
|
+
} : {})
|
|
88
|
+
& (TDef extends { readonly traits: { readonly billable: true } } ? { stripe_id: string | null } : {});
|
|
89
|
+
declare type InferredModelRow<TDef> = DeclaredAttributes<TDef>
|
|
90
|
+
& SnakeCaseAttributes<TDef>
|
|
91
|
+
& Omit<TraitFields<TDef>, AttributeKeys<TDef> | SnakeCase<AttributeKeys<TDef>>>
|
|
92
|
+
& Omit<BelongsToForeignKeys<TDef>, AttributeKeys<TDef> | SnakeCase<AttributeKeys<TDef>>>;
|
|
93
|
+
declare type FillableKeys<TDef> = {
|
|
94
|
+
[TKey in AttributeKeys<TDef>]: DefinitionAttributes<TDef>[TKey] extends { readonly fillable: true }
|
|
95
|
+
? TKey
|
|
96
|
+
: never
|
|
97
|
+
}[AttributeKeys<TDef>];
|
|
98
|
+
declare type OptionalFillableKeys<TDef> = {
|
|
99
|
+
[TKey in FillableKeys<TDef>]: DefinitionAttributes<TDef>[TKey] extends
|
|
100
|
+
{ readonly nullable: true } | { readonly default: unknown }
|
|
101
|
+
? TKey
|
|
102
|
+
: never
|
|
103
|
+
}[FillableKeys<TDef>];
|
|
15
104
|
/**
|
|
16
105
|
* Full database row type: model attributes + system fields (id, uuid, timestamps) + FK columns.
|
|
17
106
|
*
|
|
@@ -20,7 +109,7 @@ export type BelongsToForeignKeys<TDef> = TDef extends { readonly belongsTo: read
|
|
|
20
109
|
* import type Post from '../models/Post'
|
|
21
110
|
* type PostJsonResponse = ModelRow<typeof Post>
|
|
22
111
|
*/
|
|
23
|
-
export type ModelRow<T> =
|
|
112
|
+
export type ModelRow<T> = InferredModelRow<Def<T>>;
|
|
24
113
|
/**
|
|
25
114
|
* Same as {@link ModelRow} but with every field optional. Useful for
|
|
26
115
|
* partial-projection reads (`select('id', 'name')`) and test fixtures
|
|
@@ -35,7 +124,7 @@ export type ModelRowLoose<T> = Partial<ModelRow<T>>;
|
|
|
35
124
|
* import type Post from '../models/Post'
|
|
36
125
|
* type NewPost = NewModelData<typeof Post>
|
|
37
126
|
*/
|
|
38
|
-
export type NewModelData<T> = Partial<
|
|
127
|
+
export type NewModelData<T> = Partial<ModelRow<T>>;
|
|
39
128
|
/**
|
|
40
129
|
* Strict insertable shape: only attributes marked `fillable: true` in
|
|
41
130
|
* the model definition (plus belongsTo foreign keys), partial because
|
|
@@ -45,7 +134,7 @@ export type NewModelData<T> = Partial<QueryInferAttributes<T> & BelongsToForeign
|
|
|
45
134
|
* can't pass non-fillable fields to `create()` / `insert()`.
|
|
46
135
|
* {@link NewModelData} is the looser sibling that allows any attribute.
|
|
47
136
|
*/
|
|
48
|
-
export type ModelCreateData<T> = Partial<
|
|
137
|
+
export type ModelCreateData<T> = Partial<InferFillableAttributes<T> & BelongsToForeignKeys<Def<T>>>;
|
|
49
138
|
/** Loose variant of {@link ModelCreateData} — same shape as {@link NewModelData}, aliased for naming-parity with the row types. */
|
|
50
139
|
export type ModelCreateDataLoose<T> = NewModelData<T>;
|
|
51
140
|
/**
|
|
@@ -56,23 +145,23 @@ export type ModelCreateDataLoose<T> = NewModelData<T>;
|
|
|
56
145
|
* import type Post from '../models/Post'
|
|
57
146
|
* type PostUpdate = UpdateModelData<typeof Post>
|
|
58
147
|
*/
|
|
59
|
-
export type UpdateModelData<T> = Partial<
|
|
60
|
-
/**
|
|
61
|
-
* Just the attribute records flagged `fillable: true` — useful for
|
|
62
|
-
* code-generators and any helper that needs the typed shape of a
|
|
63
|
-
* model's fillable-attribute config (e.g., admin form schemas).
|
|
64
|
-
*/
|
|
148
|
+
export type UpdateModelData<T> = Partial<ModelRow<T>>;
|
|
149
|
+
/** Attribute values accepted by mass-assignment writes. */
|
|
65
150
|
export type InferFillableAttributes<T> = {
|
|
66
|
-
[
|
|
67
|
-
|
|
68
|
-
|
|
151
|
+
[TKey in Exclude<FillableKeys<Def<T>>, OptionalFillableKeys<Def<T>>>]: DeclaredAttributes<Def<T>>[TKey]
|
|
152
|
+
} & {
|
|
153
|
+
[TKey in OptionalFillableKeys<Def<T>>]?: DeclaredAttributes<Def<T>>[TKey]
|
|
69
154
|
}
|
|
70
155
|
/**
|
|
71
156
|
* Every valid column name for the model (attributes + system fields
|
|
72
157
|
* added by traits like `id`, `uuid`, `created_at`). Useful for
|
|
73
158
|
* constraining query builders that accept a `column` parameter.
|
|
74
159
|
*/
|
|
75
|
-
export type InferColumnNames<T> =
|
|
160
|
+
export type InferColumnNames<T> = AttributeKeys<Def<T>>
|
|
161
|
+
| SnakeCase<AttributeKeys<Def<T>>>
|
|
162
|
+
| PrimaryKey<Def<T>>
|
|
163
|
+
| BelongsToForeignKeyNames<Def<T>>
|
|
164
|
+
| keyof TraitFields<Def<T>>;
|
|
76
165
|
/**
|
|
77
166
|
* Attribute keys whose `type` is declared as `'number'` in the model
|
|
78
167
|
* definition. Used to constrain aggregate methods (`sum`, `avg`,
|
|
@@ -84,4 +173,8 @@ export type InferColumnNames<T> = QueryInferColumnNames<T>;
|
|
|
84
173
|
* `AttributeKeys<Def<T>>` here. Tighten by declaring `type: 'number'`
|
|
85
174
|
* on the attribute spec when narrowing matters.
|
|
86
175
|
*/
|
|
87
|
-
export type InferNumericColumns<T> =
|
|
176
|
+
export type InferNumericColumns<T> = {
|
|
177
|
+
[TKey in AttributeKeys<Def<T>>]: AttributeValue<DefinitionAttributes<Def<T>>[TKey]> extends number
|
|
178
|
+
? TKey
|
|
179
|
+
: never
|
|
180
|
+
}[AttributeKeys<Def<T>>];
|
package/dist/subquery.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare interface WhereCondition<T, V =
|
|
1
|
+
declare interface WhereCondition<T, V = unknown> {
|
|
2
2
|
type: 'and' | 'or'
|
|
3
3
|
method: 'where' | 'whereIn' | 'whereNull' | 'whereNotNull' | 'whereBetween' | 'whereExists'
|
|
4
4
|
column: keyof T
|
|
@@ -10,13 +10,13 @@ declare interface WhereCondition<T, V = any> {
|
|
|
10
10
|
}
|
|
11
11
|
export type Operator = '=' | '<' | '>' | '<=' | '>=' | '<>' | '!=' | 'like' | 'not like' | 'in' | 'not in' | 'between' | 'not between' | 'is' | 'is not';
|
|
12
12
|
export declare class SubqueryBuilder<T> {
|
|
13
|
-
where<
|
|
14
|
-
orWhere<
|
|
15
|
-
whereIn<
|
|
16
|
-
whereNotIn<
|
|
13
|
+
where<TKey extends keyof T>(column: TKey, ...args: [T[TKey]] | [Operator, T[TKey]]): void;
|
|
14
|
+
orWhere<TKey extends keyof T>(column: TKey, ...args: [T[TKey]] | [Operator, T[TKey]]): void;
|
|
15
|
+
whereIn<TKey extends keyof T>(column: TKey, values: T[TKey][]): void;
|
|
16
|
+
whereNotIn<TKey extends keyof T>(column: TKey, values: T[TKey][]): void;
|
|
17
17
|
whereNull(column: keyof T): void;
|
|
18
18
|
whereNotNull(column: keyof T): void;
|
|
19
|
-
whereBetween<
|
|
19
|
+
whereBetween<TKey extends keyof T>(column: TKey, range: [T[TKey], T[TKey]]): void;
|
|
20
20
|
whereExists(callback: (query: SubqueryBuilder<T>) => void): void;
|
|
21
21
|
getConditions(): WhereCondition<T>[];
|
|
22
22
|
}
|
package/dist/transaction.d.ts
CHANGED
|
@@ -50,12 +50,12 @@ export declare function savepoint<T>(callback: (sp: TransactionHandle) => Promis
|
|
|
50
50
|
* const user = await createUserWithProfile('Alice', 'Hello world')
|
|
51
51
|
* ```
|
|
52
52
|
*/
|
|
53
|
-
export declare function transactional<TArgs extends
|
|
53
|
+
export declare function transactional<TArgs extends unknown[], R>(fn: (tx: TransactionHandle, ...args: TArgs) => Promise<R>, options?: TransactionOptions): (...args: TArgs) => Promise<R>;
|
|
54
54
|
export declare interface TransactionOptions {
|
|
55
55
|
retries?: number
|
|
56
56
|
isolation?: 'read committed' | 'repeatable read' | 'serializable'
|
|
57
57
|
readOnly?: boolean
|
|
58
|
-
onRollback?: (error:
|
|
58
|
+
onRollback?: (error: unknown) => void
|
|
59
59
|
afterRollback?: () => void
|
|
60
60
|
}
|
|
61
61
|
/**
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/orm",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.70.
|
|
5
|
+
"version": "0.70.370",
|
|
6
6
|
"description": "The Stacks ORM integration",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -59,16 +59,17 @@
|
|
|
59
59
|
"scripts": {
|
|
60
60
|
"build": "bun build.ts",
|
|
61
61
|
"typecheck": "bun tsc --noEmit",
|
|
62
|
+
"typecheck:inference": "bun run build && (cd ../faker && bun run build) && (cd ../query-builder && bun run build) && (cd ../types && bun run build) && (cd ../validation && bun run build) && bun tsc -p tsconfig.type-tests.json",
|
|
62
63
|
"prepublishOnly": "bun run build"
|
|
63
64
|
},
|
|
64
65
|
"dependencies": {
|
|
65
|
-
"@stacksjs/ts-validation": "^0.5.
|
|
66
|
-
"bun-query-builder": "^0.2.
|
|
66
|
+
"@stacksjs/ts-validation": "^0.5.3",
|
|
67
|
+
"bun-query-builder": "^0.2.28"
|
|
67
68
|
},
|
|
68
69
|
"devDependencies": {
|
|
69
|
-
"@stacksjs/config": "0.70.
|
|
70
|
+
"@stacksjs/config": "0.70.370",
|
|
70
71
|
"better-dx": "^0.2.17",
|
|
71
|
-
"@stacksjs/query-builder": "0.70.
|
|
72
|
-
"@stacksjs/types": "0.70.
|
|
72
|
+
"@stacksjs/query-builder": "0.70.370",
|
|
73
|
+
"@stacksjs/types": "0.70.370"
|
|
73
74
|
}
|
|
74
75
|
}
|