@bakery-framework/orm 2.4.1 → 2.5.0-alpha.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bakery-framework/orm",
3
- "version": "2.4.1",
3
+ "version": "2.5.0-alpha.0",
4
4
  "description": "Bakery database layer: adapters, query builder, schema sync and backup.",
5
5
  "keywords": [
6
6
  "bakery",
@@ -56,6 +56,6 @@
56
56
  "bun": ">=1.4.0"
57
57
  },
58
58
  "dependencies": {
59
- "@bakery-framework/core": "^2.4.1"
59
+ "@bakery-framework/core": "^2.5.0-alpha.0"
60
60
  }
61
61
  }
@@ -360,7 +360,9 @@ export function createExecutor(
360
360
  } = {},
361
361
  ): SQLAdapter.Executor {
362
362
  const bind = options.bind ?? refuseArrays(driver)
363
- const bound = <F extends SQLAdapter.Executor['all'] | SQLAdapter.Executor['run']>(
363
+ const bound = <
364
+ F extends SQLAdapter.Executor['all'] | SQLAdapter.Executor['run'],
365
+ >(
364
366
  fn: F,
365
367
  ): F =>
366
368
  (async (sqlText: string, params: unknown[] = []) =>
@@ -1527,7 +1529,6 @@ function parseCSVValue(val: any, type?: string): any {
1527
1529
  return parseCSVValueFallback(trimmed)
1528
1530
  }
1529
1531
 
1530
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: csv
1531
1532
  function parseCSVRows(csv: string): string[][] {
1532
1533
  const result: string[][] = []
1533
1534
  let row: string[] = []
@@ -243,7 +243,9 @@ export class SQLiteAdapter extends SQLAdapter {
243
243
 
244
244
  const fell = await this.sql.unsafe('PRAGMA journal_mode = DELETE;')
245
245
  const mode = Array.isArray(fell)
246
- ? String((fell[0] as { journal_mode?: unknown })?.journal_mode ?? 'unknown')
246
+ ? String(
247
+ (fell[0] as { journal_mode?: unknown })?.journal_mode ?? 'unknown',
248
+ )
247
249
  : 'unknown'
248
250
  MESSAGES.JOURNAL_WAL_REFUSED({
249
251
  file: filename,
@@ -268,9 +270,7 @@ export class SQLiteAdapter extends SQLAdapter {
268
270
  */
269
271
  override async schemaFingerprint(): Promise<string | null> {
270
272
  const row = (await this.query('PRAGMA schema_version').get()) as
271
- | { schema_version?: number }
272
- | null
273
- | undefined
273
+ { schema_version?: number } | null | undefined
274
274
  const version = row?.schema_version
275
275
  if (typeof version !== 'number') return null
276
276
  return `sqlite:${this.filename ?? ''}:${version}`
package/src/field.ts CHANGED
@@ -52,10 +52,7 @@ type ArrayElement =
52
52
 
53
53
  /** What Bun returns for one element of an array of `E`. */
54
54
  type ElementOf<E extends ArrayElement> = E extends
55
- | 'integer'
56
- | 'smallint'
57
- | 'real'
58
- | 'double precision'
55
+ 'integer' | 'smallint' | 'real' | 'double precision'
59
56
  ? number
60
57
  : E extends 'boolean'
61
58
  ? boolean
@@ -379,7 +376,10 @@ export const Field = {
379
376
  element: E,
380
377
  options: { nullable?: true; optional?: true } = {},
381
378
  ) => {
382
- const def: Record<string, unknown> = { type: 'sql', sqlType: `${element}[]` }
379
+ const def: Record<string, unknown> = {
380
+ type: 'sql',
381
+ sqlType: `${element}[]`,
382
+ }
383
383
  if (options.nullable) def.nullable = true
384
384
  return def
385
385
  }) as {
@@ -492,8 +492,7 @@ export const Field = {
492
492
  // The options object, when present, is the only non-column argument.
493
493
  const actions =
494
494
  (args.find(a => a && !isColumnValue(a)) as
495
- | ForeignKeyActions
496
- | undefined) ?? {}
495
+ ForeignKeyActions | undefined) ?? {}
497
496
 
498
497
  if (!targets.length)
499
498
  throws(
package/src/index.ts CHANGED
@@ -61,9 +61,5 @@ export type {
61
61
  ExtractViews,
62
62
  TableDef,
63
63
  } from './schema-util'
64
- export {
65
- col,
66
- dateNow,
67
- old,
68
- } from './schema-util'
64
+ export { col, dateNow, old } from './schema-util'
69
65
  export { DB, Mutation }
@@ -33,8 +33,7 @@ const MIGRATION_NAME = /^(\d+)_[A-Za-z0-9._-]+\.sql$/
33
33
  const NO_TRANSACTION = /^--\s*bakery:\s*no-transaction\s*$/i
34
34
 
35
35
  export type ReadResult =
36
- | { ok: true; files: MigrationFile[] }
37
- | { ok: false; problems: string[] }
36
+ { ok: true; files: MigrationFile[] } | { ok: false; problems: string[] }
38
37
 
39
38
  /**
40
39
  * Every migration in `dir`, in the order they run.
package/src/orm/index.ts CHANGED
@@ -11,11 +11,11 @@
11
11
  * initializing, and the whole ORM dies with
12
12
  * `TypeError: undefined is not an object (evaluating 'Mutation.Insert')`.
13
13
  *
14
- * Biome's `organizeImports` sorts these alphabetically and puts `./mutation`
15
- * first. The compiler cannot see the breakage, because the types are fine
16
- * either way. Hence the suppression.
14
+ * Sorting these imports alphabetically, as Biome's `organizeImports` did while
15
+ * the repo ran Biome, puts `./mutation` first. The compiler cannot see the
16
+ * breakage, because the types are fine either way, so no import sorter may
17
+ * run on this file.
17
18
  */
18
- // biome-ignore-all assist/source/organizeImports: cycle. See above
19
19
  import { DB } from './query'
20
20
  import { Mutation } from './mutation'
21
21
 
@@ -63,9 +63,8 @@ export namespace Mutation {
63
63
  : string
64
64
 
65
65
  export type QualifiedColumnTarget<T extends Tables> = T extends keyof DBSchema
66
- ?
67
- | `${Extract<T, string>}.${Extract<keyof DBSchema[T], string>}`
68
- | ColumnTarget<T>
66
+ ? | `${Extract<T, string>}.${Extract<keyof DBSchema[T], string>}`
67
+ | ColumnTarget<T>
69
68
  : string
70
69
 
71
70
  /**
package/src/orm/query.ts CHANGED
@@ -2,7 +2,19 @@ import { Case } from '@bakery-framework/core/utils'
2
2
  import { throws } from '@bakery-framework/core/utils/common'
3
3
  import { getActiveDb, txStorage } from '../connection'
4
4
  import type { AppDBSchema as DBSchema } from '../schema-registry'
5
- import { ColumnRef as schemaColumnRef, OperatorRef as schemaOperatorRef, SQLFunctionRef as schemaSQLFunctionRef, SQL_FUNCTIONS, WindowRef as schemaWindowRef, col as schemaCol, evalOperands, isSafeIdentifier, nullComparison, qId, qRaw } from '../schema-util'
5
+ import {
6
+ ColumnRef as schemaColumnRef,
7
+ OperatorRef as schemaOperatorRef,
8
+ SQLFunctionRef as schemaSQLFunctionRef,
9
+ SQL_FUNCTIONS,
10
+ WindowRef as schemaWindowRef,
11
+ col as schemaCol,
12
+ evalOperands,
13
+ isSafeIdentifier,
14
+ nullComparison,
15
+ qId,
16
+ qRaw,
17
+ } from '../schema-util'
6
18
  import { Mutation } from './mutation'
7
19
  import { ArrayValue } from '../array-value'
8
20
 
@@ -128,7 +140,9 @@ export namespace DB {
128
140
  * so every call site got this answer anyway: it only misled the reader.
129
141
  */
130
142
  export type AllTableColumns = {
131
- [T in keyof DBSchema]: `${T & string}.${Extract<keyof DBSchema[T] & string, string>}`
143
+ [
144
+ T in keyof DBSchema
145
+ ]: `${T & string}.${Extract<keyof DBSchema[T] & string, string>}`
132
146
  }[keyof DBSchema]
133
147
 
134
148
  export type WhereValue<C extends string> =
@@ -143,10 +157,7 @@ export namespace DB {
143
157
  | null
144
158
 
145
159
  export type WhereColumn<S extends TableSchemas, J extends string> =
146
- | ColumnString<S, J>
147
- | SQLFunctionRef<ColumnString<S, J>>
148
- | QBRaw
149
- | QBObject
160
+ ColumnString<S, J> | SQLFunctionRef<ColumnString<S, J>> | QBRaw | QBObject
150
161
 
151
162
  export type ResolveColumnString<
152
163
  S,
@@ -610,8 +621,11 @@ export namespace DB {
610
621
  C extends `${infer Table}.${infer _Col}` ? Table : C
611
622
 
612
623
  // Stage Interfaces for Method Ordering
613
- export interface IQBTable<S extends TableSchemas, J extends string, P = any>
614
- extends QBObject<P> {
624
+ export interface IQBTable<
625
+ S extends TableSchemas,
626
+ J extends string,
627
+ P = any,
628
+ > extends QBObject<P> {
615
629
  join<R extends AllTableColumns, A extends string | undefined = undefined>(
616
630
  leftCol: ColumnString<S, J>,
617
631
  rightCol: R,
@@ -690,7 +704,9 @@ export namespace DB {
690
704
  select<
691
705
  C extends SelectColumns<S, J>,
692
706
  P2 extends TakeSelectValues<S, C> = TakeSelectValues<S, C>,
693
- >(columns: C): IQBSelect<S, J, P2>
707
+ >(
708
+ columns: C,
709
+ ): IQBSelect<S, J, P2>
694
710
  selectAll<A extends Extract<J, string>>(
695
711
  alias?: A,
696
712
  ): IQBSelect<
@@ -721,8 +737,11 @@ export namespace DB {
721
737
  ): IQBLimit<S, J, P>
722
738
  }
723
739
 
724
- export interface IQBWhere<S extends TableSchemas, J extends string, P = any>
725
- extends QBObject<P> {
740
+ export interface IQBWhere<
741
+ S extends TableSchemas,
742
+ J extends string,
743
+ P = any,
744
+ > extends QBObject<P> {
726
745
  and(
727
746
  column: WhereColumn<S, J>,
728
747
  valueOrRef?: WhereValue<ColumnString<S, J>>,
@@ -736,7 +755,9 @@ export namespace DB {
736
755
  select<
737
756
  C extends SelectColumns<S, J>,
738
757
  P2 extends TakeSelectValues<S, C> = TakeSelectValues<S, C>,
739
- >(columns: C): IQBSelect<S, J, P2>
758
+ >(
759
+ columns: C,
760
+ ): IQBSelect<S, J, P2>
740
761
  selectAll<A extends Extract<J, string>>(
741
762
  alias?: A,
742
763
  ): IQBSelect<
@@ -761,12 +782,17 @@ export namespace DB {
761
782
  ): IQBLimit<S, J, P>
762
783
  }
763
784
 
764
- export interface IQBGroupBy<S extends TableSchemas, J extends string, P = any>
765
- extends QBObject<P> {
785
+ export interface IQBGroupBy<
786
+ S extends TableSchemas,
787
+ J extends string,
788
+ P = any,
789
+ > extends QBObject<P> {
766
790
  select<
767
791
  C extends SelectColumns<S, J>,
768
792
  P2 extends TakeSelectValues<S, C> = TakeSelectValues<S, C>,
769
- >(columns: C): IQBSelect<S, J, P2>
793
+ >(
794
+ columns: C,
795
+ ): IQBSelect<S, J, P2>
770
796
  selectAll<A extends Extract<J, string>>(
771
797
  alias?: A,
772
798
  ): IQBSelect<
@@ -789,8 +815,11 @@ export namespace DB {
789
815
  distinct(): this
790
816
  }
791
817
 
792
- export interface IQBHaving<S extends TableSchemas, J extends string, P = any>
793
- extends QBObject<P> {
818
+ export interface IQBHaving<
819
+ S extends TableSchemas,
820
+ J extends string,
821
+ P = any,
822
+ > extends QBObject<P> {
794
823
  andHaving(
795
824
  column: WhereColumn<S, J>,
796
825
  valueOrRef?: WhereValue<ColumnString<S, J>>,
@@ -816,8 +845,11 @@ export namespace DB {
816
845
  ): IQBLimit<S, J, P>
817
846
  }
818
847
 
819
- export interface IQBSelect<S extends TableSchemas, J extends string, P = any>
820
- extends QBObject<P> {
848
+ export interface IQBSelect<
849
+ S extends TableSchemas,
850
+ J extends string,
851
+ P = any,
852
+ > extends QBObject<P> {
821
853
  /**
822
854
  * Grouping after selecting, which always worked at runtime (clauses are
823
855
  * assembled at `parse()`, so call order is irrelevant), and was simply
@@ -829,7 +861,9 @@ export namespace DB {
829
861
  select<
830
862
  C extends SelectColumns<S, J>,
831
863
  P2 extends TakeSelectValues<S, C> = TakeSelectValues<S, C>,
832
- >(columns: C): IQBSelect<S, J, P & P2>
864
+ >(
865
+ columns: C,
866
+ ): IQBSelect<S, J, P & P2>
833
867
  selectAll<A extends Extract<J, string>>(
834
868
  alias?: A,
835
869
  ): IQBSelect<
@@ -877,8 +911,11 @@ export namespace DB {
877
911
  ): IQBLimit<S, J, P>
878
912
  }
879
913
 
880
- export interface IQBOrderBy<S extends TableSchemas, J extends string, P = any>
881
- extends QBObject<P> {
914
+ export interface IQBOrderBy<
915
+ S extends TableSchemas,
916
+ J extends string,
917
+ P = any,
918
+ > extends QBObject<P> {
882
919
  orderBy(
883
920
  colStr: keyof P | ColumnString<S, J>,
884
921
  direction?: 'ASC' | 'DESC',
@@ -896,8 +933,11 @@ export namespace DB {
896
933
  ): IQBLimit<S, J, P>
897
934
  }
898
935
 
899
- export interface IQBLimit<S extends TableSchemas, J extends string, P = any>
900
- extends QBObject<P> {
936
+ export interface IQBLimit<
937
+ S extends TableSchemas,
938
+ J extends string,
939
+ P = any,
940
+ > extends QBObject<P> {
901
941
  /** `SELECT DISTINCT`. See the runtime method for the semantics. */
902
942
  distinct(): this
903
943
  limit(count: number, offset?: number): IQBLimit<S, J, P>
@@ -1120,10 +1160,10 @@ export namespace DB {
1120
1160
  }
1121
1161
 
1122
1162
  export class QB<
1123
- S extends TableSchemas = DBSchema,
1124
- J extends string = never,
1125
- P = any,
1126
- >
1163
+ S extends TableSchemas = DBSchema,
1164
+ J extends string = never,
1165
+ P = any,
1166
+ >
1127
1167
  extends QBObject<P>
1128
1168
  implements
1129
1169
  IQBTable<S, J, P>,
@@ -1504,7 +1544,6 @@ export namespace DB {
1504
1544
  // The numbered sections below are the statement grammar. Parameter push order
1505
1545
  // is load-bearing (Postgres renumbers `?` to `$n` left to right), so the
1506
1546
  // sequence is the correctness condition, not incidental.
1507
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: SQL assembler, one section per clause, in emission order
1508
1547
  parse(): { sql: string; params: any[] } {
1509
1548
  const params: any[] = []
1510
1549
 
@@ -41,11 +41,10 @@ import type { MapOf } from '@bakery-framework/core/types'
41
41
  // app's `declare module '@bakery-framework/orm/schema-registry'` into
42
42
  // `TS2300: Duplicate identifier` and the whole schema registry stops working.
43
43
  //
44
- // Biome's `noBannedTypes` proposes exactly that rewrite and calls it a safe
45
- // fix. That rule is off repo-wide now, but `noEmptyInterface` reaches the same
46
- // construct and offers the same fix, so the suppression stays. The compiler is
47
- // the real guard: change this line and `apps/starter` fails to typecheck.
48
- // biome-ignore lint/suspicious/noEmptyInterface: must stay mergeable, above
44
+ // Linters propose exactly that rewrite and call it a safe fix: Biome's
45
+ // `noBannedTypes` and `noEmptyInterface` both did while the repo ran Biome.
46
+ // The compiler is the real guard: change this line and `apps/starter` fails
47
+ // to typecheck.
49
48
  export interface SchemaRegistry {}
50
49
 
51
50
  type Registered = SchemaRegistry extends { schema: infer S } ? S : never
@@ -281,7 +281,6 @@ export class OperatorRef<R = any> {
281
281
 
282
282
  // Convention 8 makes this the single writer of SQL identifiers, so the arms
283
283
  // belong together: splitting by operand kind spreads that responsibility.
284
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: recursive operand evaluator, one arm per operand shape
285
284
  export function evalOperands(
286
285
  where: unknown,
287
286
  params: unknown[],
@@ -269,7 +269,6 @@ export class SchemaBuilder {
269
269
  * and are not introspected, so the database cannot tell us an enum from a
270
270
  * `VARCHAR`, and guessing would silently invent a constraint.
271
271
  */
272
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: decision table: column constraints to a Field.* call
273
272
  private static asFieldCall(
274
273
  cons: any,
275
274
  def: string | undefined,
@@ -14,7 +14,7 @@ import { buildSyncPlan, calculateIndexDiff, logPlannedChanges } from './plan'
14
14
  import type * as SyncTypes from './types'
15
15
 
16
16
  // prettier-ignore
17
- export const syncMsgs = {
17
+ const syncMsgs = {
18
18
  GEN_TYPES: 'I Generating types...',
19
19
  // Counted rather than silently dropped: a composite key is not a property of
20
20
  // one column, so the generator cannot spell it, but a reader who is not told
@@ -210,20 +210,20 @@ export class SyncEngine {
210
210
  // lands in `tablesToDrop`, which is still dangerous.
211
211
  const isDangerous = Boolean(
212
212
  plan.tablesToDrop.length ||
213
- plan.tablesToRename.length ||
214
- plan.columnsToDrop.length ||
215
- plan.columnsToRename.length ||
216
- plan.tablesToRebuild.size ||
217
- indexesToDrop.size,
213
+ plan.tablesToRename.length ||
214
+ plan.columnsToDrop.length ||
215
+ plan.columnsToRename.length ||
216
+ plan.tablesToRebuild.size ||
217
+ indexesToDrop.size,
218
218
  )
219
219
 
220
220
  const hasChanges = Boolean(
221
221
  isDangerous ||
222
- plan.unmappedTsTables.size ||
223
- plan.columnsToAdd.length ||
224
- plan.viewsToUpdate.length ||
225
- indexesToDrop.size ||
226
- indexesToAdd.size,
222
+ plan.unmappedTsTables.size ||
223
+ plan.columnsToAdd.length ||
224
+ plan.viewsToUpdate.length ||
225
+ indexesToDrop.size ||
226
+ indexesToAdd.size,
227
227
  )
228
228
 
229
229
  return { isDangerous, hasChanges }
@@ -378,8 +378,7 @@ export function hasOldWrappers(constraints: SyncTypes.DBConstraints) {
378
378
  // `undefined`, which is what this check wants, so the narrowing is
379
379
  // deliberate rather than a lie, and the emitted code is unchanged.
380
380
  const cols = Object.values(tObj) as (
381
- | SyncTypes.ColumnConstraint
382
- | undefined
381
+ SyncTypes.ColumnConstraint | undefined
383
382
  )[]
384
383
  return cols.some(c => c?._oldColumn || c?._transform)
385
384
  })
package/src/sync/load.ts CHANGED
@@ -156,7 +156,8 @@ async function readSchema(
156
156
  const [error, module] = await importFresh(entry)
157
157
  // Still read as no schema, which `loadSchema` relies on for a broken folder
158
158
  // entry, but no longer in silence: this is the only place the cause exists.
159
- if (error) MESSAGES.SCHEMA_IMPORT_FAILED({ file: entry, error: error.message })
159
+ if (error)
160
+ MESSAGES.SCHEMA_IMPORT_FAILED({ file: entry, error: error.message })
160
161
  if (error || !module) return emptyAt(targetPath)
161
162
 
162
163
  if (layout === 'folder') {
package/src/sync/types.ts CHANGED
@@ -89,11 +89,7 @@ export interface IndexConstraint {
89
89
  * against `c` and drop-and-recreate the key on every sync.
90
90
  */
91
91
  export type ForeignKeyAction =
92
- | 'NO ACTION'
93
- | 'RESTRICT'
94
- | 'CASCADE'
95
- | 'SET NULL'
96
- | 'SET DEFAULT'
92
+ 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT'
97
93
 
98
94
  /**
99
95
  * A foreign key as the database reports it.