bun-query-builder 0.1.9 → 0.1.11
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/README.md +489 -0
- package/dist/actions/migrate.d.ts +17 -7
- package/dist/browser.d.ts +290 -0
- package/dist/client.d.ts +5 -3
- package/dist/config.d.ts +20 -1
- package/dist/db.d.ts +20 -1
- package/dist/drivers/dynamodb.d.ts +338 -0
- package/dist/drivers/index.d.ts +27 -1
- package/dist/dynamodb/client.d.ts +178 -0
- package/dist/dynamodb/index.d.ts +156 -0
- package/dist/dynamodb/migration-driver.d.ts +55 -0
- package/dist/dynamodb/migration-tracker.d.ts +22 -0
- package/dist/dynamodb/migrations.d.ts +113 -0
- package/dist/dynamodb/model.d.ts +114 -0
- package/dist/dynamodb-client.d.ts +134 -0
- package/dist/dynamodb-single-table.d.ts +140 -0
- package/dist/dynamodb-tooling-adapter.d.ts +228 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.js +9799 -826
- package/dist/model.d.ts +27 -0
- package/dist/orm.d.ts +172 -0
- package/dist/types.d.ts +18 -1
- package/package.json +18 -5
package/dist/model.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type { BrowserModelDefinition as ModelDefinition };
|
|
2
|
+
/**
|
|
3
|
+
* Define an isomorphic model that works in both server and browser.
|
|
4
|
+
*
|
|
5
|
+
* In the browser, this creates a model that uses fetch() to call your API.
|
|
6
|
+
* On the server, this returns the definition for ORM generation AND provides
|
|
7
|
+
* query methods that work directly with the database.
|
|
8
|
+
*
|
|
9
|
+
* @param definition - The model definition
|
|
10
|
+
* @returns An isomorphic model with query methods
|
|
11
|
+
*/
|
|
12
|
+
export declare function defineModel<const TDef extends BrowserModelDefinition>(definition: TDef): void;
|
|
13
|
+
/**
|
|
14
|
+
* Register models on the global window.StacksBrowser object.
|
|
15
|
+
* Call this in your app's entry point to make models available for STX auto-imports.
|
|
16
|
+
*
|
|
17
|
+
* @param models - Object mapping model names to model instances
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import Trail from './Models/Trail'
|
|
22
|
+
* import Activity from './Models/Activity'
|
|
23
|
+
*
|
|
24
|
+
* registerBrowserModels({ Trail, Activity })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function registerBrowserModels(models: Record<string, unknown>): void;
|
package/dist/orm.d.ts
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { Database } from 'bun:sqlite';
|
|
2
|
+
export type { ModelInstance, ModelQueryBuilder };
|
|
3
|
+
export declare function configureOrm(options: { database?: string | Database; verbose?: boolean }): void;
|
|
4
|
+
export declare function getDatabase(): Database;
|
|
5
|
+
/**
|
|
6
|
+
* Create a model class from a definition with full type inference
|
|
7
|
+
*/
|
|
8
|
+
export declare function createModel<const TDef extends ModelDefinition>(definition: TDef): void;
|
|
9
|
+
export declare function createTableFromModel(definition: ModelDefinition): void;
|
|
10
|
+
export declare function seedModel(definition: ModelDefinition, count?: number, faker?: any): Promise<void>;
|
|
11
|
+
// Attribute definition with explicit type
|
|
12
|
+
export declare interface TypedAttribute<T = unknown> {
|
|
13
|
+
type?: T
|
|
14
|
+
order?: number
|
|
15
|
+
fillable?: boolean
|
|
16
|
+
unique?: boolean
|
|
17
|
+
hidden?: boolean
|
|
18
|
+
guarded?: boolean
|
|
19
|
+
nullable?: boolean
|
|
20
|
+
default?: InferType<T>
|
|
21
|
+
validation?: {
|
|
22
|
+
rule: unknown
|
|
23
|
+
message?: Record<string, string>
|
|
24
|
+
}
|
|
25
|
+
factory?: (faker: unknown) => InferType<T>
|
|
26
|
+
}
|
|
27
|
+
// Base model definition
|
|
28
|
+
export declare interface ModelDefinition {
|
|
29
|
+
name: string
|
|
30
|
+
table: string
|
|
31
|
+
primaryKey?: string
|
|
32
|
+
autoIncrement?: boolean
|
|
33
|
+
connection?: string
|
|
34
|
+
traits?: {
|
|
35
|
+
readonly useUuid?: boolean
|
|
36
|
+
readonly useTimestamps?: boolean
|
|
37
|
+
readonly useSoftDeletes?: boolean
|
|
38
|
+
readonly useSearch?: {
|
|
39
|
+
readonly displayable?: readonly string[]
|
|
40
|
+
readonly searchable?: readonly string[]
|
|
41
|
+
readonly sortable?: readonly string[]
|
|
42
|
+
readonly filterable?: readonly string[]
|
|
43
|
+
}
|
|
44
|
+
readonly useSeeder?: {
|
|
45
|
+
readonly count: number
|
|
46
|
+
}
|
|
47
|
+
readonly useApi?: {
|
|
48
|
+
readonly uri: string
|
|
49
|
+
readonly routes: readonly string[]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
belongsTo?: readonly string[]
|
|
53
|
+
hasMany?: readonly string[]
|
|
54
|
+
hasOne?: readonly string[]
|
|
55
|
+
attributes: {
|
|
56
|
+
readonly [key: string]: TypedAttribute<unknown>
|
|
57
|
+
}
|
|
58
|
+
get?: Record<string, (attributes: Record<string, unknown>) => unknown>
|
|
59
|
+
set?: Record<string, (attributes: Record<string, unknown>) => unknown>
|
|
60
|
+
}
|
|
61
|
+
// Binding helper type for SQL queries
|
|
62
|
+
declare type Bindings = SQLQueryBindings[]
|
|
63
|
+
// Primitive type mappings
|
|
64
|
+
declare type PrimitiveTypeMap = {
|
|
65
|
+
string: string
|
|
66
|
+
number: number
|
|
67
|
+
boolean: boolean
|
|
68
|
+
date: Date
|
|
69
|
+
json: Record<string, unknown>
|
|
70
|
+
}
|
|
71
|
+
// Infer the actual TS type from attribute type definition
|
|
72
|
+
declare type InferType<T> = T extends keyof PrimitiveTypeMap ? PrimitiveTypeMap[T] :
|
|
73
|
+
T extends readonly (infer U)[] ? U :
|
|
74
|
+
T extends (infer U)[] ? U :
|
|
75
|
+
unknown
|
|
76
|
+
// Extract attribute keys from definition
|
|
77
|
+
declare type AttributeKeys<TDef extends ModelDefinition> = keyof TDef['attributes'] & string
|
|
78
|
+
// Infer single attribute type
|
|
79
|
+
declare type InferAttributeType<TAttr> = TAttr extends { type: infer T } ? InferType<T> :
|
|
80
|
+
TAttr extends { factory: (faker: unknown) => infer R } ? R :
|
|
81
|
+
unknown
|
|
82
|
+
// Build the full attributes type from definition
|
|
83
|
+
declare type InferModelAttributes<TDef extends ModelDefinition> = {
|
|
84
|
+
[K in AttributeKeys<TDef>]: InferAttributeType<TDef['attributes'][K]>
|
|
85
|
+
}
|
|
86
|
+
// System fields added by traits
|
|
87
|
+
declare type SystemFields<TDef extends ModelDefinition> = { id: number } &
|
|
88
|
+
(TDef['traits'] extends { useUuid: true } ? { uuid: string } : {}) &
|
|
89
|
+
(TDef['traits'] extends { useTimestamps: true } ? { created_at: string; updated_at: string } : {}) &
|
|
90
|
+
(TDef['traits'] extends { useSoftDeletes: true } ? { deleted_at: string | null } : {})
|
|
91
|
+
// Complete model type
|
|
92
|
+
declare type ModelAttributes<TDef extends ModelDefinition> = InferModelAttributes<TDef> & SystemFields<TDef>
|
|
93
|
+
// All valid column names
|
|
94
|
+
declare type ColumnName<TDef extends ModelDefinition> = | AttributeKeys<TDef>
|
|
95
|
+
| 'id'
|
|
96
|
+
| (TDef['traits'] extends { useUuid: true } ? 'uuid' : never)
|
|
97
|
+
| (TDef['traits'] extends { useTimestamps: true } ? 'created_at' | 'updated_at' : never)
|
|
98
|
+
| (TDef['traits'] extends { useSoftDeletes: true } ? 'deleted_at' : never)
|
|
99
|
+
// Hidden fields
|
|
100
|
+
declare type HiddenKeys<TDef extends ModelDefinition> = {
|
|
101
|
+
[K in AttributeKeys<TDef>]: TDef['attributes'][K] extends { hidden: true } ? K : never
|
|
102
|
+
}[AttributeKeys<TDef>]
|
|
103
|
+
// Fillable fields
|
|
104
|
+
declare type FillableKeys<TDef extends ModelDefinition> = {
|
|
105
|
+
[K in AttributeKeys<TDef>]: TDef['attributes'][K] extends { fillable: true } ? K : never
|
|
106
|
+
}[AttributeKeys<TDef>]
|
|
107
|
+
declare type WhereOperator = '=' | '!=' | '<' | '>' | '<=' | '>=' | 'like' | 'in' | 'not in'
|
|
108
|
+
/**
|
|
109
|
+
* Model instance - represents a single database record
|
|
110
|
+
*/
|
|
111
|
+
declare class ModelInstance<TDef extends ModelDefinition, TSelected extends ColumnName<TDef> = ColumnName<TDef>> {
|
|
112
|
+
private _attributes: Record<string, unknown>;
|
|
113
|
+
private _original: Record<string, unknown>;
|
|
114
|
+
private _definition: TDef;
|
|
115
|
+
private _hasSaved: any;
|
|
116
|
+
constructor(definition: TDef, attributes?: Partial<ModelAttributes<TDef>>);
|
|
117
|
+
get<K extends TSelected>(key: K): K extends keyof ModelAttributes<TDef> ? ModelAttributes<TDef>[K] : never;
|
|
118
|
+
set<K extends AttributeKeys<TDef>>(key: K, value: ModelAttributes<TDef>[K]): void;
|
|
119
|
+
isDirty<K extends AttributeKeys<TDef>>(column?: K): boolean;
|
|
120
|
+
isClean<K extends AttributeKeys<TDef>>(column?: K): boolean;
|
|
121
|
+
getOriginal<K extends AttributeKeys<TDef>>(column: K): ModelAttributes<TDef>[K];
|
|
122
|
+
getChanges(): Partial<InferModelAttributes<TDef>>;
|
|
123
|
+
fill(data: Partial<Pick<InferModelAttributes<TDef>, FillableKeys<TDef>>>): this;
|
|
124
|
+
forceFill(data: Partial<InferModelAttributes<TDef>>): this;
|
|
125
|
+
save(): this;
|
|
126
|
+
update(data: Partial<Pick<InferModelAttributes<TDef>, FillableKeys<TDef>>>): this;
|
|
127
|
+
delete(): boolean;
|
|
128
|
+
refresh(): this;
|
|
129
|
+
toJSON(): Omit<Pick<ModelAttributes<TDef>, TSelected & keyof ModelAttributes<TDef>>, HiddenKeys<TDef>>;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Query builder with precise type narrowing
|
|
133
|
+
*/
|
|
134
|
+
declare class ModelQueryBuilder<TDef extends ModelDefinition, TSelected extends ColumnName<TDef> = ColumnName<TDef>> {
|
|
135
|
+
private _definition: TDef;
|
|
136
|
+
private _wheres: { column: string; operator: WhereOperator; value: unknown; boolean: 'and' | 'or' }[];
|
|
137
|
+
private _orderBy: { column: string; direction: 'asc' | 'desc' }[];
|
|
138
|
+
private _limit?: number;
|
|
139
|
+
private _offset?: number;
|
|
140
|
+
private _select: string[];
|
|
141
|
+
constructor(definition: TDef);
|
|
142
|
+
where<K extends ColumnName<TDef>>(column: K, operatorOrValue: WhereOperator | (K extends keyof ModelAttributes<TDef> ? ModelAttributes<TDef>[K] : unknown), value?: K extends keyof ModelAttributes<TDef> ? ModelAttributes<TDef>[K] : unknown): ModelQueryBuilder<TDef, TSelected>;
|
|
143
|
+
orWhere<K extends ColumnName<TDef>>(column: K, operatorOrValue: WhereOperator | (K extends keyof ModelAttributes<TDef> ? ModelAttributes<TDef>[K] : unknown), value?: K extends keyof ModelAttributes<TDef> ? ModelAttributes<TDef>[K] : unknown): ModelQueryBuilder<TDef, TSelected>;
|
|
144
|
+
whereIn<K extends ColumnName<TDef>>(column: K, values: (K extends keyof ModelAttributes<TDef> ? ModelAttributes<TDef>[K] : unknown)[]): ModelQueryBuilder<TDef, TSelected>;
|
|
145
|
+
whereNotIn<K extends ColumnName<TDef>>(column: K, values: (K extends keyof ModelAttributes<TDef> ? ModelAttributes<TDef>[K] : unknown)[]): ModelQueryBuilder<TDef, TSelected>;
|
|
146
|
+
whereNull<K extends ColumnName<TDef>>(column: K): ModelQueryBuilder<TDef, TSelected>;
|
|
147
|
+
whereNotNull<K extends ColumnName<TDef>>(column: K): ModelQueryBuilder<TDef, TSelected>;
|
|
148
|
+
whereLike<K extends ColumnName<TDef>>(column: K, pattern: string): ModelQueryBuilder<TDef, TSelected>;
|
|
149
|
+
orderBy<K extends ColumnName<TDef>>(column: K, direction?: 'asc' | 'desc'): ModelQueryBuilder<TDef, TSelected>;
|
|
150
|
+
orderByDesc<K extends ColumnName<TDef>>(column: K): ModelQueryBuilder<TDef, TSelected>;
|
|
151
|
+
orderByAsc<K extends ColumnName<TDef>>(column: K): ModelQueryBuilder<TDef, TSelected>;
|
|
152
|
+
limit(count: number): ModelQueryBuilder<TDef, TSelected>;
|
|
153
|
+
take(count: number): ModelQueryBuilder<TDef, TSelected>;
|
|
154
|
+
offset(count: number): ModelQueryBuilder<TDef, TSelected>;
|
|
155
|
+
skip(count: number): ModelQueryBuilder<TDef, TSelected>;
|
|
156
|
+
select<K extends ColumnName<TDef>>(columns: K[]): ModelQueryBuilder<TDef, K>;
|
|
157
|
+
private buildQuery(): { sql: string; params: unknown[] };
|
|
158
|
+
get(): ModelInstance<TDef, TSelected>[];
|
|
159
|
+
first(): ModelInstance<TDef, TSelected> | undefined;
|
|
160
|
+
firstOrFail(): ModelInstance<TDef, TSelected>;
|
|
161
|
+
last(): ModelInstance<TDef, TSelected> | undefined;
|
|
162
|
+
count(): number;
|
|
163
|
+
exists(): boolean;
|
|
164
|
+
paginate(page?: any, perPage?: any): void;
|
|
165
|
+
pluck<K extends ColumnName<TDef>>(column: K): (K extends keyof ModelAttributes<TDef> ? ModelAttributes<TDef>[K] : unknown)[];
|
|
166
|
+
max<K extends AttributeKeys<TDef>>(column: K): number;
|
|
167
|
+
min<K extends AttributeKeys<TDef>>(column: K): number;
|
|
168
|
+
avg<K extends AttributeKeys<TDef>>(column: K): number;
|
|
169
|
+
sum<K extends AttributeKeys<TDef>>(column: K): number;
|
|
170
|
+
delete(): number;
|
|
171
|
+
update(data: Partial<Pick<InferModelAttributes<TDef>, FillableKeys<TDef>>>): number;
|
|
172
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -151,6 +151,21 @@ export declare interface DatabaseConfig {
|
|
|
151
151
|
url?: string
|
|
152
152
|
port: number
|
|
153
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* # `BrowserConfig`
|
|
156
|
+
*
|
|
157
|
+
* Configuration for browser mode that uses fetch() API instead of direct database connections.
|
|
158
|
+
* This enables the query builder to work in browser environments by translating queries to REST API calls.
|
|
159
|
+
*/
|
|
160
|
+
export declare interface BrowserConfig {
|
|
161
|
+
baseUrl: string
|
|
162
|
+
getToken?: () => string | null | Promise<string | null>
|
|
163
|
+
onUnauthorized?: () => void
|
|
164
|
+
headers?: Record<string, string>
|
|
165
|
+
timeout?: number
|
|
166
|
+
transformResponse?: <T>(response: any) => T
|
|
167
|
+
transformRequest?: <T>(data: T) => any
|
|
168
|
+
}
|
|
154
169
|
/**
|
|
155
170
|
* # `QueryBuilderConfig`
|
|
156
171
|
*
|
|
@@ -171,6 +186,7 @@ export declare interface QueryBuilderConfig {
|
|
|
171
186
|
verbose: boolean
|
|
172
187
|
dialect: SupportedDialect
|
|
173
188
|
database: DatabaseConfig
|
|
189
|
+
browser?: BrowserConfig
|
|
174
190
|
timestamps: TimestampConfig
|
|
175
191
|
pagination: PaginationConfig
|
|
176
192
|
aliasing: AliasingConfig
|
|
@@ -230,5 +246,6 @@ export declare interface UnsafeOptions {
|
|
|
230
246
|
* - 'postgres': Uses `RANDOM()`, supports JSON operators (e.g. `@>`), `FOR SHARE`, `FOR UPDATE`, CTEs
|
|
231
247
|
* - 'mysql': Uses `RAND()`, shared locks via `LOCK IN SHARE MODE`
|
|
232
248
|
* - 'sqlite': Lightweight engine; some features are limited or emulated
|
|
249
|
+
* - 'browser': Browser-compatible mode that uses fetch() API calls instead of direct database connections
|
|
233
250
|
*/
|
|
234
|
-
export type SupportedDialect = 'postgres' | 'mysql' | 'sqlite'
|
|
251
|
+
export type SupportedDialect = 'postgres' | 'mysql' | 'sqlite' | 'browser'
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bun-query-builder",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.11",
|
|
5
5
|
"description": "A simple yet performant query builder for TypeScript. Built with Bun.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -21,10 +21,22 @@
|
|
|
21
21
|
],
|
|
22
22
|
"exports": {
|
|
23
23
|
".": {
|
|
24
|
+
"bun": "./src/index.ts",
|
|
24
25
|
"types": "./dist/index.d.ts",
|
|
25
26
|
"import": "./dist/index.js"
|
|
26
27
|
},
|
|
28
|
+
"./browser": {
|
|
29
|
+
"bun": "./src/browser.ts",
|
|
30
|
+
"types": "./dist/browser.d.ts",
|
|
31
|
+
"import": "./dist/browser.js"
|
|
32
|
+
},
|
|
33
|
+
"./dynamodb": {
|
|
34
|
+
"bun": "./src/dynamodb/index.ts",
|
|
35
|
+
"types": "./dist/dynamodb/index.d.ts",
|
|
36
|
+
"import": "./dist/dynamodb/index.js"
|
|
37
|
+
},
|
|
27
38
|
"./*": {
|
|
39
|
+
"bun": "./src/*",
|
|
28
40
|
"import": "./dist/*"
|
|
29
41
|
}
|
|
30
42
|
},
|
|
@@ -58,8 +70,8 @@
|
|
|
58
70
|
"fresh": "bunx rimraf node_modules/ bun.lock && bun i",
|
|
59
71
|
"prepublishOnly": "bun --bun run build && bun run compile:all && bun run zip",
|
|
60
72
|
"test": "bun test",
|
|
61
|
-
"lint": "bunx --bun
|
|
62
|
-
"lint:fix": "bunx --bun
|
|
73
|
+
"lint": "bunx --bun pickier lint .",
|
|
74
|
+
"lint:fix": "bunx --bun pickier lint . --fix",
|
|
63
75
|
"changelog": "bunx logsmith --verbose",
|
|
64
76
|
"changelog:generate": "bunx logsmith --output CHANGELOG.md",
|
|
65
77
|
"release": "bun --bun run changelog:generate && bunx --bun bumpx prompt --recursive",
|
|
@@ -70,7 +82,8 @@
|
|
|
70
82
|
},
|
|
71
83
|
"dependencies": {
|
|
72
84
|
"@stacksjs/clapp": "^0.2.0",
|
|
73
|
-
"@stacksjs/ts-validation": "^0.4.
|
|
85
|
+
"@stacksjs/ts-validation": "^0.4.9",
|
|
86
|
+
"dynamodb-tooling": "^0.3.2",
|
|
74
87
|
"ts-mocker": "^0.1.5"
|
|
75
88
|
},
|
|
76
89
|
"devDependencies": {
|
|
@@ -82,7 +95,7 @@
|
|
|
82
95
|
"git-hooks": {
|
|
83
96
|
"pre-commit": {
|
|
84
97
|
"staged-lint": {
|
|
85
|
-
"*.{js,ts,json,yaml,yml,md}": "bunx --bun
|
|
98
|
+
"*.{js,ts,json,yaml,yml,md}": "bunx --bun pickier lint --fix"
|
|
86
99
|
}
|
|
87
100
|
},
|
|
88
101
|
"commit-msg": "bunx gitlint --edit .git/COMMIT_EDITMSG"
|