bun-query-builder 0.2.25 → 0.2.27

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/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { QueryBuilderConfig, SupportedDialect } from './types';
1
+ import type { QueryBuilderConfig, QueryBuilderOptions, SupportedDialect } from './types';
2
2
  /**
3
3
  * Whether a dialect belongs to the MySQL wire-protocol family (MySQL itself,
4
4
  * SingleStore, or Vitess). These share `?` placeholders, backtick identifier
@@ -9,6 +9,54 @@ import type { QueryBuilderConfig, SupportedDialect } from './types';
9
9
  * `SingleStoreDriver` / `VitessDriver`) diverges.
10
10
  */
11
11
  export declare function isMysqlLike(dialect?: SupportedDialect): boolean;
12
+ /**
13
+ * Recursively merge `source` over `target`, returning a NEW object. Neither
14
+ * argument is mutated.
15
+ *
16
+ * The semantics below are load-bearing — each is pinned by a test or by a
17
+ * documented promise, so do not "simplify" them:
18
+ *
19
+ * - ARRAYS REPLACE. They do not concatenate or union. `SqliteConfig.pragmas`
20
+ * says so in its own doc comment, and `sqlite-bootstrap-pragmas.test.ts`
21
+ * asserts it by checking that `foreign_keys` is still 0 after an override
22
+ * that omits it — concatenation would flip that to 1.
23
+ * `transactionDefaults.sqlStates` is the same shape: a user narrowing
24
+ * retries to `['40002']` must stop retrying on `40001`, not keep it.
25
+ *
26
+ * - FUNCTIONS REPLACE. `isPlainObject` rejects them, so `QueryHooks` members
27
+ * and `BrowserConfig.getToken` / `transformResponse` stay opaque leaves. We
28
+ * never recurse into a function's own enumerable properties.
29
+ *
30
+ * - AN EXPLICIT `undefined` ASSIGNS; AN ABSENT KEY DOES NOT. The rule is
31
+ * PRESENCE, not value — `Object.keys(source)` contains a key written as
32
+ * `undefined` and does not contain one that was never written. Not a style
33
+ * choice: `resolve-dialect.test.ts` calls `setConfig({ dialect: undefined })`
34
+ * and expects `resolveDialect()` to fall back to `'postgres'`, and
35
+ * `sqlite-bootstrap-pragmas.test.ts` uses `sqlite: undefined` as the restore
36
+ * that un-does a pragma override for the rest of a shared-process run.
37
+ * Skipping `undefined` breaks both, and now that `hooks` deep-merges, an
38
+ * explicit `undefined` is also the only way to REMOVE a hook.
39
+ *
40
+ * - `null` ASSIGNS and is never recursed into. No field in
41
+ * `QueryBuilderConfig` is nullable, so a `null` arriving here is a caller
42
+ * mistake; assigning it surfaces that at the read site instead of hiding it.
43
+ *
44
+ * Arrays are copied by REFERENCE, being leaves — `config.transactionDefaults
45
+ * .sqlStates` is the same array as `defaultConfig`'s until something replaces
46
+ * it. Nothing in `src/` mutates a config array in place (the only read is an
47
+ * `.includes`), and cloning on every merge is not worth paying for that.
48
+ *
49
+ * `seen` is the chain of source objects currently being merged, so a source
50
+ * that points back at one of its own ancestors is treated as a leaf instead of
51
+ * recursed into. An embedding framework's config slice — the case this type
52
+ * exists to serve — routinely carries a parent back-pointer, and it typechecks
53
+ * fine because an optional field of an interface can be that interface. Without
54
+ * the guard that input spins for seconds, allocates gigabytes and dies with a
55
+ * stack overflow. It is a DEPTH chain, pushed and popped around the recursion,
56
+ * not a global set: the same object legitimately appearing under two different
57
+ * keys must merge both times, and a global set would silently drop the second.
58
+ */
59
+ declare function mergeObject(target: Record<string, unknown>, source: Record<string, unknown>, seen?: Set<object>): Record<string, unknown>;
12
60
  /**
13
61
  * The dialect a command should operate on.
14
62
  *
@@ -62,12 +110,64 @@ export declare function getPlaceholders(count: number, startIndex?: number): str
62
110
  *
63
111
  * So the loaded object is applied with those keys filtered out — an explicit API
64
112
  * call is a stronger signal than a file that may not know the embedder exists.
113
+ * The filter is per top-level section; see `configState` for why per-leaf is
114
+ * the wrong granularity.
65
115
  *
66
116
  * Note the load MUST pass `defaultConfig`: bunfig derives the environment
67
117
  * variable names it recognises (`QUERY_BUILDER_*`) from the shape of the
68
118
  * defaults, so passing an empty object silently drops env-var support.
69
119
  */
70
120
  export declare function getConfig(): Promise<QueryBuilderConfig>;
71
- export declare function setConfig(userConfig: Partial<QueryBuilderConfig>): void;
121
+ export declare function setConfig(userConfig: QueryBuilderOptions): void;
122
+ /**
123
+ * Identity helper for a typed `query-builder.config.ts`.
124
+ *
125
+ * It exists so that writing a config file requires no decision about which
126
+ * type to annotate with — which is what stacksjs/bun-query-builder#1062 was
127
+ * actually about. The only config type this package exported was
128
+ * `QueryBuilderConfig`, the RESOLVED shape with every field required, and the
129
+ * docs told people to import it, so downstream apps annotated their config
130
+ * file with a type demanding `migrationDir`, `snapshotDir`, `features`,
131
+ * `aliasing` and nine other sections they had no opinion about. Every field
132
+ * added here afterwards was a downstream build break.
133
+ *
134
+ * `defineConfig` takes `QueryBuilderOptions`, so nothing is ever required, and
135
+ * returns its argument unchanged — there is no runtime behavior here, only the
136
+ * type and the editor completion that comes with it.
137
+ *
138
+ * ```ts
139
+ * // query-builder.config.ts
140
+ * import { defineConfig } from 'bun-query-builder'
141
+ *
142
+ * export default defineConfig({
143
+ * dialect: 'postgres',
144
+ * database: { database: 'my_app' },
145
+ * })
146
+ * ```
147
+ */
148
+ export declare function defineConfig(userConfig: QueryBuilderOptions): QueryBuilderOptions;
72
149
  export declare const defaultConfig: QueryBuilderConfig;
150
+ // The single, process-wide config object — stored on a `globalThis` symbol so
151
+ // that EVERY copy of this module shares one object, even if Bun's bundler
152
+ // inlines `config.ts` more than once. Previously this was an `export let` that
153
+ // `setConfig` mutated in place: it worked, but relied on the bundler keeping a
154
+ // never-reassigned live binding as a single shared binding, and the build had
155
+ // to regex-patch the emitted `__esm(init_config)` wrapper to keep readers and
156
+ // writers on the same binding. A `globalThis`-keyed `export const` removes both
157
+ // hazards — there is no module-local binding to split or rename, and `const`
158
+ // makes the "never reassign config" rule unenforceable-to-break.
159
+ //
160
+ // Notes:
161
+ // - `??=` so the first-evaluated copy wins and the rest reuse it.
162
+ // - `Symbol.for` is a process-global registry key (shared across copies). It
163
+ // is also shared across package versions in one process — that's the intended
164
+ // hardening; pin a versioned key if you ever need per-version isolation.
165
+ // - Synchronous + no top-level await here, so `bun --compile` is unaffected.
166
+ // - Seeded through `mergeObject`, not `{ ...defaultConfig }`. A shallow spread
167
+ // left `config.debug === defaultConfig.debug`, so the direct writes this
168
+ // package makes to the live config — `config.debug.captureText = true` in
169
+ // `actions/sql.ts` and `computeSqlText()` — were reaching into the exported
170
+ // DEFAULTS and permanently changing them. `mergeObject` clones every plain
171
+ // object node, which closes that.
172
+ declare const CONFIG_SINGLETON_KEY: symbol;
73
173
  export declare const config: QueryBuilderConfig;
package/dist/db.d.ts CHANGED
@@ -60,6 +60,11 @@ export declare function resetConnection(): void;
60
60
  export declare function setSqlInstance(sql: SQL): void;
61
61
  // Wrapper that catches "Connection closed" errors and retries with a fresh connection
62
62
  export declare function withFreshConnection<T>(fn: (sql: SQL) => Promise<T>): Promise<T>;
63
+ /**
64
+ * Lazy SQL connection proxy - connection is only created when first accessed.
65
+ * This allows setConfig() to be called before any database connection is made.
66
+ */
67
+ declare function createLazyBunSql(): SQL;
63
68
  // Export a lazy proxy - no connection is made until first use
64
69
  export declare const bunSql: SQL;
65
70
  /**
package/dist/model.d.ts CHANGED
@@ -79,7 +79,7 @@ export declare function registerModel<TModel>(name: string, model: TModel): TMod
79
79
  * @param definition - The model definition
80
80
  * @returns An isomorphic model with query methods
81
81
  */
82
- export declare function defineModel<const TDef extends BrowserModelDefinition>(definition: TDef): void;
82
+ export declare function defineModel<const TDef extends BrowserModelDefinition>(definition: TDef): unknown;
83
83
  /**
84
84
  * Register models on the global window.StacksBrowser object.
85
85
  * Call this in your app's entry point to make models available for STX auto-imports.
package/dist/orm.d.ts CHANGED
@@ -228,7 +228,8 @@ declare type PrimitiveTypeMap = {
228
228
  declare type InferType<T> = T extends keyof PrimitiveTypeMap ? PrimitiveTypeMap[T] :
229
229
  T extends readonly (infer U)[] ? U :
230
230
  T extends (infer U)[] ? U :
231
- T extends { validate: (value: infer U) => any } ? U :
231
+ T extends { validate: (value: infer U) => unknown } ? U :
232
+ T extends { test: (value: infer U) => unknown } ? U :
232
233
  unknown;
233
234
  // Extract attribute keys from definition
234
235
  declare type AttributeKeys<TDef extends ModelDefinition> = keyof TDef['attributes'] & string;
@@ -358,9 +359,9 @@ declare type FillableAttributes<TDef extends ModelDefinition> = Partial<Pick<
358
359
  ModelAttributes<TDef>,
359
360
  FillableKeys<TDef> | SnakeCase<FillableKeys<TDef>> | BelongsToKeys<TDef>
360
361
  >>;
361
- // Numeric attribute columns — constrains aggregate methods (sum, avg, etc.)
362
+ // Numeric attribute columns - constrains aggregate methods (sum, avg, etc.)
362
363
  declare type NumericColumns<TDef extends ModelDefinition> = {
363
- [K in AttributeKeys<TDef>]: TDef['attributes'][K] extends { type: 'number' } ? K : never
364
+ [K in AttributeKeys<TDef>]: InferAttributeType<TDef['attributes'][K]> extends number ? K : never
364
365
  }[AttributeKeys<TDef>];
365
366
  /**
366
367
  * Relation names of one relation declaration. Array form lowercases the
package/dist/schema.d.ts CHANGED
@@ -62,7 +62,7 @@ export declare interface Attribute {
62
62
  fillable?: boolean
63
63
  guarded?: boolean
64
64
  foreignKey?: boolean | ForeignKeyConfig
65
- factory?: (faker: Faker) => any
65
+ factory?: (faker: Faker) => unknown
66
66
  validation: {
67
67
  rule: ValidationType
68
68
  message?: ValidatorMessage