bun-query-builder 0.1.10 → 0.1.12

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,288 @@
1
+ import type { BrowserConfig } from './types';
2
+ import type { Faker } from 'ts-mocker';
3
+ export type { BrowserModelInstance, BrowserModelQueryBuilder };
4
+ /**
5
+ * Configure the browser query client
6
+ */
7
+ export declare function configureBrowser(config: Partial<BrowserConfig>): void;
8
+ /**
9
+ * Get the current browser configuration
10
+ */
11
+ export declare function getBrowserConfig(): BrowserConfig;
12
+ /**
13
+ * Check if we're in a browser environment
14
+ */
15
+ export declare function isBrowser(): boolean;
16
+ /**
17
+ * Create a browser query builder for a table
18
+ */
19
+ export declare function browserQuery<T = any>(table: string): BrowserQueryBuilder<T>;
20
+ /**
21
+ * Shorthand for common tables - creates a factory function
22
+ */
23
+ export declare function createBrowserDb<Tables extends Record<string, any>>(): {
24
+ [K in keyof Tables]: () => BrowserQueryBuilder<Tables[K]>
25
+ };
26
+ /**
27
+ * Create a browser model from a definition with full type inference
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const roles = ['admin', 'user', 'moderator'] as const
32
+ *
33
+ * const User = createBrowserModel({
34
+ * name: 'User',
35
+ * table: 'users',
36
+ * traits: {
37
+ * useTimestamps: true,
38
+ * useApi: { uri: 'users' }
39
+ * },
40
+ * attributes: {
41
+ * name: { fillable: true, factory: () => 'John' },
42
+ * email: { fillable: true, factory: () => 'john@example.com' },
43
+ * role: { fillable: true, factory: (): typeof roles[number] => 'user' },
44
+ * }
45
+ * } as const)
46
+ *
47
+ * // Full type inference:
48
+ * const user = await User.find(1)
49
+ * user?.get('role') // type: 'admin' | 'user' | 'moderator'
50
+ *
51
+ * const roles = await User.pluck('role')
52
+ * // type: ('admin' | 'user' | 'moderator')[]
53
+ * ```
54
+ */
55
+ export declare function createBrowserModel<const TDef extends BrowserModelDefinition>(definition: TDef): void;
56
+ /**
57
+ * Auth helpers for browser
58
+ */
59
+ export declare const browserAuth: {
60
+ /**
61
+ * Login and store token
62
+ */
63
+ async login(credentials: { email: string, password: string }): () => unknown;
64
+ /**
65
+ * Register a new user
66
+ */
67
+ async register(data: { name: string, email: string, password: string }): () => unknown;
68
+ /**
69
+ * Logout and clear token
70
+ */
71
+ async logout(): unknown;
72
+ /**
73
+ * Get current authenticated user
74
+ */
75
+ async user(): unknown;
76
+ /**
77
+ * Check if user is authenticated
78
+ */
79
+ async check(): unknown;
80
+ /**
81
+ * Get the current token
82
+ */
83
+ getToken: unknown
84
+ };
85
+ // Attribute definition with explicit type
86
+ export declare interface BrowserTypedAttribute<T = unknown> {
87
+ type?: T
88
+ order?: number
89
+ fillable?: boolean
90
+ unique?: boolean
91
+ hidden?: boolean
92
+ guarded?: boolean
93
+ nullable?: boolean
94
+ default?: InferType<T>
95
+ validation?: {
96
+ rule: unknown
97
+ message?: Record<string, string>
98
+ }
99
+ factory?: (faker: Faker) => InferType<T>
100
+ }
101
+ // Base model definition for browser
102
+ export declare interface BrowserModelDefinition {
103
+ name: string
104
+ table: string
105
+ primaryKey?: string
106
+ traits?: {
107
+ readonly useUuid?: boolean
108
+ readonly useTimestamps?: boolean
109
+ readonly useSoftDeletes?: boolean
110
+ readonly useApi?: {
111
+ readonly uri: string
112
+ readonly routes?: readonly string[]
113
+ }
114
+ }
115
+ attributes: {
116
+ readonly [key: string]: BrowserTypedAttribute<unknown>
117
+ }
118
+ }
119
+ declare interface QueryState {
120
+ table: string
121
+ wheres: WhereClause[]
122
+ orderBy: OrderByClause[]
123
+ limitValue?: number
124
+ offsetValue?: number
125
+ selectColumns: string[]
126
+ withRelations: string[]
127
+ }
128
+ // Primitive type mappings
129
+ declare type PrimitiveTypeMap = {
130
+ string: string
131
+ number: number
132
+ boolean: boolean
133
+ date: Date
134
+ json: Record<string, unknown>
135
+ }
136
+ // Infer the actual TS type from attribute type definition
137
+ declare type InferType<T> = T extends keyof PrimitiveTypeMap ? PrimitiveTypeMap[T] :
138
+ T extends readonly (infer U)[] ? U :
139
+ T extends (infer U)[] ? U :
140
+ unknown
141
+ // Extract attribute keys from definition
142
+ declare type BrowserAttributeKeys<TDef extends BrowserModelDefinition> = keyof TDef['attributes'] & string
143
+ // Infer single attribute type
144
+ declare type InferBrowserAttributeType<TAttr> = TAttr extends { type: infer T } ? InferType<T> :
145
+ TAttr extends { factory: (faker: unknown) => infer R } ? R :
146
+ unknown
147
+ // Build the full attributes type from definition
148
+ declare type InferBrowserModelAttributes<TDef extends BrowserModelDefinition> = {
149
+ [K in BrowserAttributeKeys<TDef>]: InferBrowserAttributeType<TDef['attributes'][K]>
150
+ }
151
+ // System fields added by traits
152
+ declare type BrowserSystemFields<TDef extends BrowserModelDefinition> = { id: number } &
153
+ (TDef['traits'] extends { useUuid: true } ? { uuid: string } : {}) &
154
+ (TDef['traits'] extends { useTimestamps: true } ? { created_at: string; updated_at: string } : {}) &
155
+ (TDef['traits'] extends { useSoftDeletes: true } ? { deleted_at: string | null } : {})
156
+ // Complete model type
157
+ declare type BrowserModelAttributes<TDef extends BrowserModelDefinition> = InferBrowserModelAttributes<TDef> & BrowserSystemFields<TDef>
158
+ // All valid column names
159
+ declare type BrowserColumnName<TDef extends BrowserModelDefinition> = | BrowserAttributeKeys<TDef>
160
+ | 'id'
161
+ | (TDef['traits'] extends { useUuid: true } ? 'uuid' : never)
162
+ | (TDef['traits'] extends { useTimestamps: true } ? 'created_at' | 'updated_at' : never)
163
+ | (TDef['traits'] extends { useSoftDeletes: true } ? 'deleted_at' : never)
164
+ // Hidden fields
165
+ declare type BrowserHiddenKeys<TDef extends BrowserModelDefinition> = {
166
+ [K in BrowserAttributeKeys<TDef>]: TDef['attributes'][K] extends { hidden: true } ? K : never
167
+ }[BrowserAttributeKeys<TDef>]
168
+ // Fillable fields
169
+ declare type BrowserFillableKeys<TDef extends BrowserModelDefinition> = {
170
+ [K in BrowserAttributeKeys<TDef>]: TDef['attributes'][K] extends { fillable: true } ? K : never
171
+ }[BrowserAttributeKeys<TDef>]
172
+ // Types for query building
173
+ export type WhereOperator = '=' | '!=' | '<' | '>' | '<=' | '>=' | 'like' | 'in' | 'not in' | 'is' | 'is not'
174
+ /**
175
+ * Custom error class for browser query errors
176
+ */
177
+ export declare class BrowserQueryError extends Error {
178
+ status: number;
179
+ constructor(message: string, status: number);
180
+ }
181
+ /**
182
+ * Browser Query Builder
183
+ * Fluent API that builds queries and executes them via fetch
184
+ */
185
+ export declare class BrowserQueryBuilder<T = any> {
186
+ private state: QueryState;
187
+ constructor(table: string);
188
+ select(columns: string[]): this;
189
+ where(column: string, operatorOrValue: WhereOperator | any, value?: any): this;
190
+ orWhere(column: string, operatorOrValue: WhereOperator | any, value?: any): this;
191
+ andWhere(column: string, operatorOrValue: WhereOperator | any, value?: any): this;
192
+ whereNull(column: string): this;
193
+ whereNotNull(column: string): this;
194
+ whereIn(column: string, values: any[]): this;
195
+ whereNotIn(column: string, values: any[]): this;
196
+ orderBy(column: string, direction?: 'asc' | 'desc'): this;
197
+ orderByDesc(column: string): this;
198
+ latest(column?: string): this;
199
+ oldest(column?: string): this;
200
+ limit(count: number): this;
201
+ offset(count: number): this;
202
+ skip(count: number): this;
203
+ take(count: number): this;
204
+ with(relations: string[]): this;
205
+ private buildQueryParams(): URLSearchParams;
206
+ private buildUrl(path?: string | number): string;
207
+ get(): Promise<T[]>;
208
+ first(): Promise<T | null>;
209
+ firstOrFail(): Promise<T>;
210
+ find(id: number | string): Promise<T | null>;
211
+ findOrFail(id: number | string): Promise<T>;
212
+ count(): Promise<number>;
213
+ exists(): Promise<boolean>;
214
+ create(data: Partial<T>): Promise<T>;
215
+ insert(data: Partial<T>): Promise<T>;
216
+ update(id: number | string, data: Partial<T>): Promise<T>;
217
+ delete(id: number | string): Promise<boolean>;
218
+ destroy(id: number | string): Promise<boolean>;
219
+ paginate(page?: number, perPage?: number): Promise<{
220
+ data: T[]
221
+ total: number
222
+ page: number
223
+ perPage: number
224
+ lastPage: number
225
+ }>;
226
+ toState(): QueryState;
227
+ }
228
+ /**
229
+ * Browser Model Instance - represents a single record with type-safe access
230
+ */
231
+ declare class BrowserModelInstance<TDef extends BrowserModelDefinition, TSelected extends BrowserColumnName<TDef> = BrowserColumnName<TDef>> {
232
+ private _attributes: Record<string, unknown>;
233
+ private _definition: TDef;
234
+ constructor(definition: TDef, attributes?: Partial<BrowserModelAttributes<TDef>>);
235
+ get<K extends TSelected>(key: K): K extends keyof BrowserModelAttributes<TDef> ? BrowserModelAttributes<TDef>[K] : never;
236
+ set<K extends BrowserAttributeKeys<TDef>>(key: K, value: BrowserModelAttributes<TDef>[K]): void;
237
+ toJSON(): Omit<Pick<BrowserModelAttributes<TDef>, TSelected & keyof BrowserModelAttributes<TDef>>, BrowserHiddenKeys<TDef>>;
238
+ }
239
+ /**
240
+ * Typed Browser Query Builder with precise type narrowing
241
+ */
242
+ declare class BrowserModelQueryBuilder<TDef extends BrowserModelDefinition, TSelected extends BrowserColumnName<TDef> = BrowserColumnName<TDef>> {
243
+ private _definition: TDef;
244
+ private _wheres: { column: string; operator: WhereOperator; value: unknown; boolean: 'and' | 'or' }[];
245
+ private _orderBy: { column: string; direction: 'asc' | 'desc' }[];
246
+ private _limit?: number;
247
+ private _offset?: number;
248
+ private _select: string[];
249
+ private _withRelations: string[];
250
+ constructor(definition: TDef);
251
+ private getTablePath(): string;
252
+ where<K extends BrowserColumnName<TDef>>(column: K, operatorOrValue: WhereOperator | (K extends keyof BrowserModelAttributes<TDef> ? BrowserModelAttributes<TDef>[K] : unknown), value?: K extends keyof BrowserModelAttributes<TDef> ? BrowserModelAttributes<TDef>[K] : unknown): BrowserModelQueryBuilder<TDef, TSelected>;
253
+ orWhere<K extends BrowserColumnName<TDef>>(column: K, operatorOrValue: WhereOperator | (K extends keyof BrowserModelAttributes<TDef> ? BrowserModelAttributes<TDef>[K] : unknown), value?: K extends keyof BrowserModelAttributes<TDef> ? BrowserModelAttributes<TDef>[K] : unknown): BrowserModelQueryBuilder<TDef, TSelected>;
254
+ whereIn<K extends BrowserColumnName<TDef>>(column: K, values: (K extends keyof BrowserModelAttributes<TDef> ? BrowserModelAttributes<TDef>[K] : unknown)[]): BrowserModelQueryBuilder<TDef, TSelected>;
255
+ whereNotIn<K extends BrowserColumnName<TDef>>(column: K, values: (K extends keyof BrowserModelAttributes<TDef> ? BrowserModelAttributes<TDef>[K] : unknown)[]): BrowserModelQueryBuilder<TDef, TSelected>;
256
+ whereNull<K extends BrowserColumnName<TDef>>(column: K): BrowserModelQueryBuilder<TDef, TSelected>;
257
+ whereNotNull<K extends BrowserColumnName<TDef>>(column: K): BrowserModelQueryBuilder<TDef, TSelected>;
258
+ whereLike<K extends BrowserColumnName<TDef>>(column: K, pattern: string): BrowserModelQueryBuilder<TDef, TSelected>;
259
+ orderBy<K extends BrowserColumnName<TDef>>(column: K, direction?: 'asc' | 'desc'): BrowserModelQueryBuilder<TDef, TSelected>;
260
+ orderByDesc<K extends BrowserColumnName<TDef>>(column: K): BrowserModelQueryBuilder<TDef, TSelected>;
261
+ orderByAsc<K extends BrowserColumnName<TDef>>(column: K): BrowserModelQueryBuilder<TDef, TSelected>;
262
+ limit(count: number): BrowserModelQueryBuilder<TDef, TSelected>;
263
+ take(count: number): BrowserModelQueryBuilder<TDef, TSelected>;
264
+ offset(count: number): BrowserModelQueryBuilder<TDef, TSelected>;
265
+ skip(count: number): BrowserModelQueryBuilder<TDef, TSelected>;
266
+ select<K extends BrowserColumnName<TDef>>(columns: K[]): BrowserModelQueryBuilder<TDef, K>;
267
+ with(relations: string[]): BrowserModelQueryBuilder<TDef, TSelected>;
268
+ latest(column?: BrowserColumnName<TDef>): BrowserModelQueryBuilder<TDef, TSelected>;
269
+ oldest(column?: BrowserColumnName<TDef>): BrowserModelQueryBuilder<TDef, TSelected>;
270
+ private buildQueryParams(): URLSearchParams;
271
+ private buildUrl(path?: string | number): string;
272
+ get(): Promise<BrowserModelInstance<TDef, TSelected>[]>;
273
+ first(): Promise<BrowserModelInstance<TDef, TSelected> | null>;
274
+ firstOrFail(): Promise<BrowserModelInstance<TDef, TSelected>>;
275
+ find(id: number | string): Promise<BrowserModelInstance<TDef, TSelected> | null>;
276
+ findOrFail(id: number | string): Promise<BrowserModelInstance<TDef, TSelected>>;
277
+ count(): Promise<number>;
278
+ exists(): Promise<boolean>;
279
+ pluck<K extends BrowserColumnName<TDef>>(column: K): Promise<(K extends keyof BrowserModelAttributes<TDef> ? BrowserModelAttributes<TDef>[K] : unknown)[]>;
280
+ paginate(page?: any, perPage?: any): Promise<{
281
+ data: BrowserModelInstance<TDef, TSelected>[]
282
+ total: number
283
+ page: number
284
+ perPage: number
285
+ lastPage: number
286
+ }>;
287
+ }
288
+ export default browserQuery;
package/dist/client.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { config } from './config';
2
+ import { resetConnection } from './db';
2
3
  import type { DatabaseSchema } from './schema';
3
4
  import type { SchemaMeta } from './meta';
4
5
  export declare function createQueryBuilder<DB extends DatabaseSchema<any>>(state?: Partial<InternalState>): QueryBuilder<DB>;
@@ -168,6 +169,7 @@ export declare interface BaseSelectQueryBuilder<DB extends DatabaseSchema<any>,
168
169
  toSQL: () => string
169
170
  execute: () => Promise<SelectedRow<DB, TTable, TSelected>[]>
170
171
  executeTakeFirst: () => Promise<SelectedRow<DB, TTable, TSelected> | undefined>
172
+ executeTakeFirstOrThrow: () => Promise<SelectedRow<DB, TTable, TSelected>>
171
173
  get: () => Promise<SelectedRow<DB, TTable, TSelected>[]>
172
174
  first: () => Promise<SelectedRow<DB, TTable, TSelected> | undefined>
173
175
  firstOrFail: () => Promise<SelectedRow<DB, TTable, TSelected>>
@@ -202,21 +204,28 @@ export declare interface InsertQueryBuilder<DB extends DatabaseSchema<any>, TTab
202
204
  returning: <K extends keyof DB[TTable]['columns'] & string>(...cols: K[]) => SelectQueryBuilder<DB, TTable, Pick<DB[TTable]['columns'], K>>
203
205
  toSQL: () => string
204
206
  execute: () => Promise<number | DB[TTable]['columns'] | DB[TTable]['columns'][]>
207
+ returningAll: () => SelectQueryBuilder<DB, TTable, DB[TTable]['columns']>
208
+ executeTakeFirst: () => Promise<DB[TTable]['columns'] | undefined>
209
+ executeTakeFirstOrThrow: () => Promise<DB[TTable]['columns']>
205
210
  }
206
211
  export declare interface UpdateQueryBuilder<DB extends DatabaseSchema<any>, TTable extends keyof DB & string> {
207
212
  set: (values: Partial<DB[TTable]['columns']>) => UpdateQueryBuilder<DB, TTable>
208
- where: (expr: WhereExpression<DB[TTable]['columns']>) => UpdateQueryBuilder<DB, TTable>
213
+ where: (expr: WhereExpression<DB[TTable]['columns']> | string, op?: WhereOperator, value?: any) => UpdateQueryBuilder<DB, TTable>
209
214
  returning: <K extends keyof DB[TTable]['columns'] & string>(...cols: K[]) => SelectQueryBuilder<DB, TTable, Pick<DB[TTable]['columns'], K>>
210
215
  toSQL: () => string
211
216
  execute: () => Promise<number>
212
- executeTakeFirst?: () => Promise<{ numUpdatedRows?: number }>
217
+ returningAll: () => SelectQueryBuilder<DB, TTable, DB[TTable]['columns']>
218
+ executeTakeFirst: () => Promise<{ numUpdatedRows?: number }>
219
+ executeTakeFirstOrThrow: () => Promise<{ numUpdatedRows: number }>
213
220
  }
214
221
  export declare interface DeleteQueryBuilder<DB extends DatabaseSchema<any>, TTable extends keyof DB & string> {
215
- where: (expr: WhereExpression<DB[TTable]['columns']>) => DeleteQueryBuilder<DB, TTable>
222
+ where: (expr: WhereExpression<DB[TTable]['columns']> | string, op?: WhereOperator, value?: any) => DeleteQueryBuilder<DB, TTable>
216
223
  returning: <K extends keyof DB[TTable]['columns'] & string>(...cols: K[]) => SelectQueryBuilder<DB, TTable, Pick<DB[TTable]['columns'], K>>
217
224
  toSQL: () => string
218
225
  execute: () => Promise<number>
219
- executeTakeFirst?: () => Promise<{ numDeletedRows?: number }>
226
+ returningAll: () => SelectQueryBuilder<DB, TTable, DB[TTable]['columns']>
227
+ executeTakeFirst: () => Promise<{ numDeletedRows?: number }>
228
+ executeTakeFirstOrThrow: () => Promise<{ numDeletedRows: number }>
220
229
  }
221
230
  export declare interface TableQueryBuilder<DB extends DatabaseSchema<any>, TTable extends keyof DB & string> {
222
231
  insert: (data: Partial<DB[TTable]['columns']> | Partial<DB[TTable]['columns']>[]) => InsertQueryBuilder<DB, TTable>
@@ -486,4 +495,5 @@ declare class QueryCache {
486
495
  set(key: string, data: any, ttlMs: number): void;
487
496
  clear(): void;
488
497
  setMaxSize(size: number): void;
489
- }
498
+ }
499
+ export { resetConnection };
package/dist/config.d.ts CHANGED
@@ -1,4 +1,22 @@
1
1
  import type { QueryBuilderConfig } from './types';
2
+ /**
3
+ * Get the placeholder format for the current dialect.
4
+ * PostgreSQL uses $1, $2, $3... while MySQL and SQLite use ?
5
+ */
6
+ export declare function getPlaceholder(index: number): string;
7
+ /**
8
+ * Generate placeholders for an array of values.
9
+ * PostgreSQL: $1, $2, $3
10
+ * MySQL/SQLite: ?, ?, ?
11
+ */
12
+ export declare function getPlaceholders(count: number, startIndex?: any): string;
13
+ export declare function getConfig(): Promise<QueryBuilderConfig>;
14
+ /**
15
+ * Programmatically set/override the query builder configuration.
16
+ * This is useful when you want to configure bun-query-builder from
17
+ * your application code rather than using a config file.
18
+ */
19
+ export declare function setConfig(userConfig: Partial<QueryBuilderConfig>): void;
2
20
  export declare const defaultConfig: QueryBuilderConfig;
3
- // eslint-disable-next-line antfu/no-top-level-await
21
+ // For backwards compatibility - synchronous access with default fallback
4
22
  export declare const config: QueryBuilderConfig;
package/dist/db.d.ts CHANGED
@@ -1,11 +1,30 @@
1
1
  import { SQL } from 'bun';
2
+ import { Database } from 'bun:sqlite';
2
3
  /**
3
4
  * Returns a Bun SQL instance configured for the current dialect and database settings.
5
+ * For SQLite, uses bun:sqlite directly for better compiled binary support.
4
6
  * Handles connection errors gracefully by falling back to in-memory SQLite.
5
7
  */
6
8
  export declare function getBunSql(): SQL;
7
9
  export declare function getOrCreateBunSql(forceNew?: any): SQL;
10
+ /**
11
+ * Resets the cached database connection.
12
+ * Call this after changing config via setConfig() to ensure the new config is used.
13
+ */
14
+ export declare function resetConnection(): void;
8
15
  // Wrapper that catches "Connection closed" errors and retries with a fresh connection
9
16
  export declare function withFreshConnection<T>(fn: (sql: SQL) => Promise<T>): Promise<T>;
10
- export declare const bunSql: unknown;
17
+ // Export a lazy proxy - no connection is made until first use
18
+ export declare const bunSql: SQL;
19
+ /**
20
+ * SQLite wrapper that provides a SQL-like tagged template literal interface
21
+ * using bun:sqlite's Database class for better compiled binary support.
22
+ */
23
+ declare class SQLiteWrapper {
24
+ private db: Database;
25
+ constructor(filename: string);
26
+ query(sql: string, params?: any[]): any[];
27
+ run(sql: string, params?: any[]): any;
28
+ close(): void;
29
+ }
11
30
  export { SQL } from 'bun';