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