qubu 0.4.0 → 0.4.2

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.
Files changed (103) hide show
  1. package/dist/{canonical-BbnqavJm.mjs → canonical-BXUguqfo.mjs} +23 -23
  2. package/dist/codegen.d.mts +25 -33
  3. package/dist/codegen.mjs +38 -45
  4. package/dist/column-hqKr7-1I.mjs +620 -0
  5. package/dist/{complete-D5Djh-zo.mjs → complete-WYyVozgK.mjs} +50 -50
  6. package/dist/{complete-types-BavBtv8J.d.mts → complete-types-IjEn5VPN.d.mts} +56 -56
  7. package/dist/core.d.mts +2 -2
  8. package/dist/core.mjs +4 -4
  9. package/dist/ddl.d.mts +12 -12
  10. package/dist/ddl.mjs +13 -14
  11. package/dist/{dialect-b2-Z6uBF.mjs → dialect-wUKrnPMB.mjs} +2 -2
  12. package/dist/diff.d.mts +1 -1
  13. package/dist/diff.mjs +6 -7
  14. package/dist/{index-DH0qV6aS.d.mts → index-1DpA3mUh.d.mts} +20 -20
  15. package/dist/{index-D3ZOwPT-.d.mts → index-CPvfEheG.d.mts} +13 -15
  16. package/dist/index.d.mts +1 -1
  17. package/dist/index.mjs +94 -95
  18. package/dist/introspection.d.mts +8 -8
  19. package/dist/introspection.mjs +29 -30
  20. package/dist/{json-CUZlv4HT.mjs → json-Db7XRD91.mjs} +2 -2
  21. package/dist/migration.d.mts +20 -21
  22. package/dist/migration.mjs +5 -6
  23. package/dist/{mysql-CKEKGnj4.mjs → mysql-B_cYzzX2.mjs} +237 -7
  24. package/dist/mysql.d.mts +2 -2
  25. package/dist/mysql.mjs +3 -3
  26. package/dist/{on-conflict-4MOBl51J.mjs → on-conflict-hfPW0KmQ.mjs} +3 -4
  27. package/dist/postgres.d.mts +5 -5
  28. package/dist/postgres.mjs +6 -6
  29. package/dist/{registry-CXV8u7Pt.mjs → registry-BRMLYwDp.mjs} +26 -29
  30. package/dist/{relational-DuQ9IHSb.mjs → relational-BZ3WDPzC.mjs} +2 -2
  31. package/dist/schema.d.mts +1 -1
  32. package/dist/schema.mjs +5 -6
  33. package/dist/{snapshot-DJpfmxhQ.mjs → snapshot-C-W65HEd.mjs} +5 -5
  34. package/dist/snapshot.d.mts +3 -3
  35. package/dist/snapshot.mjs +5 -7
  36. package/dist/{source-DGO3DRgg.mjs → source-BcS2AsIg.mjs} +6 -8
  37. package/dist/{serialize-CFtYYAdk.mjs → sqlite-Cg0nwYEH.mjs} +326 -12
  38. package/dist/sqlite.d.mts +1 -1
  39. package/dist/sqlite.mjs +2 -2
  40. package/dist/{standard-BTVYKh_F.mjs → standard-DfcZEVOj.mjs} +1 -1
  41. package/dist/{table-D6rcs8SB.mjs → table-Bp5irMSj.mjs} +2 -3
  42. package/dist/{types-Deo_q43Y.d.mts → types-BK1COGZe.d.mts} +1113 -1128
  43. package/dist/{types-g-vVvj1B.mjs → types-JM3FcAnX.mjs} +7 -8
  44. package/dist/{types-CSNJTYaM.d.mts → types-JSZHpUEj.d.mts} +83 -84
  45. package/dist/{value-b6OFZXVS.mjs → value-Bi71Agyf.mjs} +1 -1
  46. package/dist/vite/ambient.d.ts +309 -340
  47. package/dist/vite.d.mts +5 -6
  48. package/dist/vite.mjs +3 -4
  49. package/docs/dialects-and-execution.md +45 -55
  50. package/docs/getting-started.md +4 -4
  51. package/docs/guides/better-auth.md +57 -0
  52. package/docs/guides/compose-queries.md +24 -67
  53. package/docs/guides/drizzle.md +23 -23
  54. package/docs/guides/extensions/dialects.md +4 -4
  55. package/docs/guides/extensions/sources-and-clauses.md +15 -15
  56. package/docs/guides/extensions/typed-expressions.md +13 -17
  57. package/docs/guides/extensions/unsafe-syntax.md +3 -3
  58. package/docs/guides/json.md +7 -7
  59. package/docs/guides/mutations.md +14 -21
  60. package/docs/guides/select/conditions.md +6 -8
  61. package/docs/guides/select/grouping-and-windows.md +4 -15
  62. package/docs/guides/select/ordering-and-pagination.md +6 -19
  63. package/docs/guides/select/overview.md +12 -26
  64. package/docs/guides/sql-templates.md +20 -24
  65. package/docs/guides/vite-plugin.md +9 -13
  66. package/docs/index.md +5 -7
  67. package/docs/query-model/fragments.md +4 -15
  68. package/docs/query-model/result-shapes.md +11 -14
  69. package/docs/query-model/source-scope.md +31 -49
  70. package/docs/reference/mysql-snapshot.md +2 -5
  71. package/docs/reference/postgres-snapshot.md +3 -3
  72. package/docs/reference/sqlite-snapshot.md +2 -5
  73. package/docs/reference/supported-surface.md +26 -26
  74. package/docs/schema/catalog-model.md +2 -5
  75. package/docs/schema/code-generation.md +18 -18
  76. package/docs/schema/columns-and-writes.md +17 -25
  77. package/docs/schema/constraints-and-indexes.md +36 -52
  78. package/docs/schema/ddl-emission.md +6 -6
  79. package/docs/schema/diff.md +5 -5
  80. package/docs/schema/introspection.md +7 -7
  81. package/docs/schema/migration-plans.md +9 -9
  82. package/docs/schema/snapshots.md +3 -3
  83. package/docs/schema/storage-and-schema-sql.md +11 -11
  84. package/docs/schema/tables-and-names.md +11 -14
  85. package/docs/sql-semantic-types.md +10 -10
  86. package/docs/troubleshooting.md +10 -10
  87. package/package.json +21 -33
  88. package/skills/qubu/agents/openai.yaml +3 -3
  89. package/dist/column-D-8OqGuV.mjs +0 -328
  90. package/dist/column-LV7oGQde.mjs +0 -296
  91. package/dist/drizzle-mysql.d.mts +0 -24
  92. package/dist/drizzle-mysql.mjs +0 -72
  93. package/dist/drizzle-postgres.d.mts +0 -24
  94. package/dist/drizzle-postgres.mjs +0 -73
  95. package/dist/drizzle-sqlite.d.mts +0 -57
  96. package/dist/drizzle-sqlite.mjs +0 -108
  97. package/dist/drizzle.d.mts +0 -13
  98. package/dist/drizzle.mjs +0 -2
  99. package/dist/errors-BGCoLe_r.mjs +0 -14
  100. package/dist/postgres-BK2APkKP.mjs +0 -236
  101. package/dist/runtime-Cn_Xgzta.mjs +0 -193
  102. package/dist/sqlite-CrsK0Fza.mjs +0 -320
  103. package/dist/types-DZsueVoI.d.mts +0 -45
@@ -20,45 +20,38 @@ import {
20
20
  text,
21
21
  unique,
22
22
  value,
23
- } from 'qubu'
23
+ } from "qubu"
24
24
 
25
- const accounts = table(
26
- 'accounts',
27
- { id: integer(), slug: text() },
28
- accounts => ({
29
- constraints: {
30
- accountsPrimary: primaryKey(accounts.id),
31
- },
32
- indexes: {
33
- accountsSlug: index([accounts.slug], { unique: true }),
34
- },
35
- })
36
- )
25
+ const accounts = table("accounts", { id: integer(), slug: text() }, (accounts) => ({
26
+ constraints: {
27
+ accountsPrimary: primaryKey(accounts.id),
28
+ },
29
+ indexes: {
30
+ accountsSlug: index([accounts.slug], { unique: true }),
31
+ },
32
+ }))
37
33
 
38
34
  const memberships = table(
39
- 'memberships',
35
+ "memberships",
40
36
  {
41
37
  id: integer(),
42
38
  accountId: integer(),
43
39
  slug: text(),
44
40
  displayName: text(),
45
41
  },
46
- memberships => ({
42
+ (memberships) => ({
47
43
  constraints: {
48
44
  membershipsPrimary: primaryKey(memberships.id),
49
45
  membershipsUnique: unique(memberships.accountId, memberships.slug),
50
- membershipsAccount: foreignKey(
51
- [memberships.accountId],
52
- references(accounts, accounts.id)
53
- ),
54
- membershipsCheck: check(eq(memberships.slug, value('public'))),
46
+ membershipsAccount: foreignKey([memberships.accountId], references(accounts, accounts.id)),
47
+ membershipsCheck: check(eq(memberships.slug, value("public"))),
55
48
  },
56
49
  indexes: {
57
50
  membershipsAccountSlug: index([memberships.accountId, memberships.slug], {
58
51
  unique: true,
59
52
  }),
60
53
  },
61
- })
54
+ }),
62
55
  )
63
56
  ```
64
57
 
@@ -81,21 +74,17 @@ Use `uniqueConstraint()` when the database enforces uniqueness but the rule shou
81
74
  not prove a functional dependency:
82
75
 
83
76
  ```ts
84
- import { table, text, uniqueConstraint } from 'qubu'
85
-
86
- const accounts = table(
87
- 'accounts',
88
- { email: text({ nullable: true }) },
89
- accounts => ({
90
- constraints: {
91
- emailUnique: uniqueConstraint(accounts.email, {
92
- nulls: 'distinct',
93
- physicalName: 'accounts_email_key',
94
- }),
95
- },
96
- indexes: {},
97
- })
98
- )
77
+ import { table, text, uniqueConstraint } from "qubu"
78
+
79
+ const accounts = table("accounts", { email: text({ nullable: true }) }, (accounts) => ({
80
+ constraints: {
81
+ emailUnique: uniqueConstraint(accounts.email, {
82
+ nulls: "distinct",
83
+ physicalName: "accounts_email_key",
84
+ }),
85
+ },
86
+ indexes: {},
87
+ }))
99
88
  ```
100
89
 
101
90
  `nulls: 'distinct'` describes the common rule where multiple NULLs do not
@@ -115,20 +104,15 @@ eligible unique index. Options such as onUpdate, onDelete, match, deferrable,
115
104
  and initially remain metadata:
116
105
 
117
106
  ```ts
118
- const memberships = table(
119
- 'memberships',
120
- { accountId: integer() },
121
- memberships => ({
122
- constraints: {
123
- accountForeign: foreignKey(
124
- [memberships.accountId],
125
- references(accounts, accounts.id),
126
- { onDelete: 'cascade', onUpdate: 'cascade' }
127
- ),
128
- },
129
- indexes: {},
130
- })
131
- )
107
+ const memberships = table("memberships", { accountId: integer() }, (memberships) => ({
108
+ constraints: {
109
+ accountForeign: foreignKey([memberships.accountId], references(accounts, accounts.id), {
110
+ onDelete: "cascade",
111
+ onUpdate: "cascade",
112
+ }),
113
+ },
114
+ indexes: {},
115
+ }))
132
116
  ```
133
117
 
134
118
  Use the preliminary callback table for direct self-references. Wrap the target
@@ -145,12 +129,12 @@ Grouping every column in a declared candidate key lets Qubu select other
145
129
  columns from that source:
146
130
 
147
131
  ```ts
148
- import { count, from, groupBy, select } from 'qubu'
132
+ import { count, from, groupBy, select } from "qubu"
149
133
 
150
134
  const summary = select(
151
135
  { displayName: memberships.displayName, total: count() },
152
136
  from(memberships),
153
- groupBy(memberships.accountId, memberships.slug)
137
+ groupBy(memberships.accountId, memberships.slug),
154
138
  )
155
139
  ```
156
140
 
@@ -8,13 +8,13 @@ migration journal. Preflight runs before rendering, so a blocked or incompatible
8
8
  plan returns diagnostics and no SQL.
9
9
 
10
10
  ```ts
11
- import { emitMigrationPlan } from 'qubu/ddl'
12
- import { postgresSchemaDialect } from 'qubu/snapshot'
11
+ import { emitMigrationPlan } from "qubu/ddl"
12
+ import { postgresSchemaDialect } from "qubu/snapshot"
13
13
 
14
14
  const result = emitMigrationPlan(plan, postgresSchemaDialect)
15
15
  if (!result.ok) {
16
16
  // Review result.diagnostics. result.sql is an empty string.
17
- throw new Error(result.diagnostics.map(item => item.message).join('\n'))
17
+ throw new Error(result.diagnostics.map((item) => item.message).join("\n"))
18
18
  }
19
19
 
20
20
  for (const statement of result.statements) {
@@ -44,9 +44,9 @@ produces `transaction-conflict`; no transaction is opened by the emitter.
44
44
 
45
45
  ```ts
46
46
  const result = emitMigrationPlan(plan, postgresSchemaDialect, {
47
- transaction: 'managed',
48
- lock: 'exclusive',
49
- serverVersion: '16',
47
+ transaction: "managed",
48
+ lock: "exclusive",
49
+ serverVersion: "16",
50
50
  })
51
51
  ```
52
52
 
@@ -8,7 +8,7 @@ It keeps the object kind, namespace, logical ID, physical name, dialect, path,
8
8
  and catalog evidence on every result object.
9
9
 
10
10
  ```ts
11
- import { diffSnapshots } from 'qubu/diff'
11
+ import { diffSnapshots } from "qubu/diff"
12
12
 
13
13
  const result = diffSnapshots(previousSnapshot, currentSnapshot)
14
14
 
@@ -32,10 +32,10 @@ use an ID, a physical name, or an exact path when a nested scope repeats an ID.
32
32
  const result = diffSnapshots(previousSnapshot, currentSnapshot, {
33
33
  renameHints: [
34
34
  {
35
- kind: 'table',
36
- namespace: 'public',
37
- from: 'legacy_accounts',
38
- to: 'accounts',
35
+ kind: "table",
36
+ namespace: "public",
37
+ from: "legacy_accounts",
38
+ to: "accounts",
39
39
  },
40
40
  ],
41
41
  })
@@ -37,10 +37,10 @@ queries, authenticate, or start a transaction. Adapt the driver you already
37
37
  use to `CatalogConnection`:
38
38
 
39
39
  ```ts
40
- import type { CatalogConnection } from 'qubu/introspection'
40
+ import type { CatalogConnection } from "qubu/introspection"
41
41
 
42
42
  const connection: CatalogConnection = {
43
- dialect: 'sqlite',
43
+ dialect: "sqlite",
44
44
  query(statement, options) {
45
45
  // Adapt this call to the driver used by the application.
46
46
  return db.query(statement, options)
@@ -59,16 +59,16 @@ catalog can later support inspection, source generation, or another snapshot
59
59
  format:
60
60
 
61
61
  ```ts
62
- import { mapCatalogToSnapshot, readSqliteCatalog } from 'qubu/introspection'
62
+ import { mapCatalogToSnapshot, readSqliteCatalog } from "qubu/introspection"
63
63
 
64
- const catalog = await readSqliteCatalog(connection, { namespace: 'main' })
64
+ const catalog = await readSqliteCatalog(connection, { namespace: "main" })
65
65
  const result = mapCatalogToSnapshot(catalog, {
66
- namespace: 'main',
67
- mode: 'strict',
66
+ namespace: "main",
67
+ mode: "strict",
68
68
  })
69
69
 
70
70
  if (!result.ok) {
71
- throw new Error(result.diagnostics.map(issue => issue.message).join('\n'))
71
+ throw new Error(result.diagnostics.map((issue) => issue.message).join("\n"))
72
72
  }
73
73
 
74
74
  result.snapshot.tables // canonical Snapshot v1 data
@@ -8,7 +8,7 @@ logical and physical identity evidence, dependency edges, preconditions, safety,
8
8
  lock and transaction requirements, and reversibility markers.
9
9
 
10
10
  ```ts
11
- import { createMigrationPlan } from 'qubu/migration'
11
+ import { createMigrationPlan } from "qubu/migration"
12
12
 
13
13
  const result = createMigrationPlan(diff)
14
14
  if (!result.ok) {
@@ -31,11 +31,11 @@ kind, namespace, and path, and each decision carries a review reason.
31
31
  ```ts
32
32
  const reviewed = createMigrationPlan(diff, {
33
33
  decisions: result.plan.operations
34
- .filter(operation => operation.status === 'decision-required')
35
- .map(operation => ({
34
+ .filter((operation) => operation.status === "decision-required")
35
+ .map((operation) => ({
36
36
  operationId: operation.id,
37
- action: 'allow',
38
- reason: 'Reviewed against the deployment change request',
37
+ action: "allow",
38
+ reason: "Reviewed against the deployment change request",
39
39
  })),
40
40
  })
41
41
  ```
@@ -48,10 +48,10 @@ dialect, safety declaration, reason, reversibility, and dependency position:
48
48
  createMigrationPlan(diff, {
49
49
  customSql: [
50
50
  {
51
- sql: 'ALTER TABLE accounts VALIDATE CONSTRAINT accounts_check',
52
- dialect: { name: 'postgresql', version: 1 },
53
- safety: 'review-required',
54
- reason: 'The dialect emitter does not model this catalog fact yet',
51
+ sql: "ALTER TABLE accounts VALIDATE CONSTRAINT accounts_check",
52
+ dialect: { name: "postgresql", version: 1 },
53
+ safety: "review-required",
54
+ reason: "The dialect emitter does not model this catalog fact yet",
55
55
  reversible: false,
56
56
  position: 3,
57
57
  },
@@ -8,7 +8,7 @@ hashed, checked into source control, and handed to a dialect adapter. Importing
8
8
  the snapshot entrypoint is optional; ordinary query imports do not load it.
9
9
 
10
10
  ```ts
11
- import { createSchemaSnapshot, encodeSchemaSnapshot } from 'qubu/snapshot'
11
+ import { createSchemaSnapshot, encodeSchemaSnapshot } from "qubu/snapshot"
12
12
 
13
13
  const snapshot = createSchemaSnapshot(appSchema)
14
14
  const json = encodeSchemaSnapshot(snapshot)
@@ -29,12 +29,12 @@ expression retains its dialect tag and is rejected when it does not match the
29
29
  selected snapshot dialect.
30
30
 
31
31
  ```ts
32
- import { decodeSchemaSnapshot } from 'qubu/snapshot'
32
+ import { decodeSchemaSnapshot } from "qubu/snapshot"
33
33
 
34
34
  const decoded = decodeSchemaSnapshot(json)
35
35
  if (!decoded.ok) {
36
36
  for (const issue of decoded.diagnostics) {
37
- console.error(issue.path.join('.'), issue.code, issue.message)
37
+ console.error(issue.path.join("."), issue.code, issue.message)
38
38
  }
39
39
  }
40
40
  ```
@@ -33,10 +33,10 @@ Use a dialect-native descriptor when a column needs an exact vendor
33
33
  declaration:
34
34
 
35
35
  ```ts
36
- import { nativeColumn, nativeStorage, table } from 'qubu'
36
+ import { nativeColumn, nativeStorage, table } from "qubu"
37
37
 
38
- const accounts = table('accounts', {
39
- handle: nativeColumn(nativeStorage('postgresql', 'citext COLLATE "C"')),
38
+ const accounts = table("accounts", {
39
+ handle: nativeColumn(nativeStorage("postgresql", 'citext COLLATE "C"')),
40
40
  })
41
41
  ```
42
42
 
@@ -52,12 +52,12 @@ can be rendered for checks, generated columns, indexes, and other declaration
52
52
  metadata:
53
53
 
54
54
  ```ts
55
- import { eq, table, text } from 'qubu'
56
- import { renderSchemaSql } from 'qubu/schema'
55
+ import { eq, table, text } from "qubu"
56
+ import { renderSchemaSql } from "qubu/schema"
57
57
 
58
- const accounts = table('accounts', { status: text() })
58
+ const accounts = table("accounts", { status: text() })
59
59
 
60
- renderSchemaSql(eq(accounts.status, 'active'), { mode: 'check' })
60
+ renderSchemaSql(eq(accounts.status, "active"), { mode: "check" })
61
61
  // ("status" = 'active')
62
62
  ```
63
63
 
@@ -74,13 +74,13 @@ subqueries are rejected in every schema mode.
74
74
  An extension must opt into the schema contract with `defineSchemaExpression()`:
75
75
 
76
76
  ```ts
77
- import { defineSchemaExpression, renderSchemaSql } from 'qubu/schema'
77
+ import { defineSchemaExpression, renderSchemaSql } from "qubu/schema"
78
78
 
79
- const currentDate = defineSchemaExpression('function', context => {
80
- context.append('CURRENT_DATE')
79
+ const currentDate = defineSchemaExpression("function", (context) => {
80
+ context.append("CURRENT_DATE")
81
81
  })
82
82
 
83
- renderSchemaSql(currentDate, { mode: 'default' })
83
+ renderSchemaSql(currentDate, { mode: "default" })
84
84
  ```
85
85
 
86
86
  ## Use raw schema SQL only when necessary
@@ -12,17 +12,17 @@ record keys become logical table IDs and stay stable when a physical SQL name
12
12
  changes:
13
13
 
14
14
  ```ts
15
- import { integer, schema, table, text } from 'qubu'
15
+ import { integer, schema, table, text } from "qubu"
16
16
 
17
- const accounts = table('account_records', {
17
+ const accounts = table("account_records", {
18
18
  id: integer(),
19
19
  email: text(),
20
20
  })
21
- const memberships = table('membership_records', {
21
+ const memberships = table("membership_records", {
22
22
  accountId: integer(),
23
23
  })
24
24
 
25
- const appSchema = schema({ accounts, memberships }, { namespace: 'public' })
25
+ const appSchema = schema({ accounts, memberships }, { namespace: "public" })
26
26
  ```
27
27
 
28
28
  appSchema.registry.accounts.id is "accounts", while the physical table name is
@@ -47,17 +47,14 @@ Write schema keys in camelCase. Qubu converts them to snake_case in SQL, then
47
47
  uses the camelCase keys in the returned row:
48
48
 
49
49
  ```ts
50
- import { from, select, table, timestamp, uuid } from 'qubu'
50
+ import { from, select, table, timestamp, uuid } from "qubu"
51
51
 
52
- const events = table('events', {
52
+ const events = table("events", {
53
53
  userId: uuid(),
54
54
  createdAt: timestamp(),
55
55
  })
56
56
 
57
- const query = select(
58
- { userId: events.userId, createdAt: events.createdAt },
59
- from(events)
60
- )
57
+ const query = select({ userId: events.userId, createdAt: events.createdAt }, from(events))
61
58
  ```
62
59
 
63
60
  The query selects "events"."user_id" and "events"."created_at", then aliases
@@ -76,8 +73,8 @@ Prefer `userId` and `apiKey` when you control the TypeScript name. Use `sqlName`
76
73
  the database name does not follow the convention:
77
74
 
78
75
  ```ts
79
- const events = table('events', {
80
- createdAt: timestamp({ sqlName: 'creation_timestamp' }),
76
+ const events = table("events", {
77
+ createdAt: timestamp({ sqlName: "creation_timestamp" }),
81
78
  })
82
79
  ```
83
80
 
@@ -89,9 +86,9 @@ their projected names stay snake_case. Only the outer result projection uses
89
86
  camelCase aliases. Pass the database relation name explicitly:
90
87
 
91
88
  ```ts
92
- import { table, uuid } from 'qubu'
89
+ import { table, uuid } from "qubu"
93
90
 
94
- const accounts = table('user_accounts', {
91
+ const accounts = table("user_accounts", {
95
92
  id: uuid(),
96
93
  })
97
94
  ```
@@ -43,10 +43,10 @@ Specific result domains are still retained. `lower(textColumn)` produces
43
43
  `SqlText`, while `avg(integerColumn)` produces `SqlDecimal`:
44
44
 
45
45
  ```ts
46
- import { avg, integer, lower, table, text } from 'qubu'
47
- import type { SqlTypeOf } from 'qubu'
46
+ import { avg, integer, lower, table, text } from "qubu"
47
+ import type { SqlTypeOf } from "qubu"
48
48
 
49
- const metrics = table('metrics', {
49
+ const metrics = table("metrics", {
50
50
  label: text(),
51
51
  sampleCount: integer(),
52
52
  })
@@ -72,15 +72,15 @@ semantics. Contextual JavaScript literals remain ergonomic for compatible
72
72
  operators:
73
73
 
74
74
  ```ts
75
- import { asc, eq, inList, like, lower, orderBy, table, uuid } from 'qubu'
75
+ import { asc, eq, inList, like, lower, orderBy, table, uuid } from "qubu"
76
76
 
77
- const records = table('records', { id: uuid() })
77
+ const records = table("records", { id: uuid() })
78
78
 
79
- eq(records.id, '108cb836-20d2-41b2-8c23-f0c94700aa7e') // valid
80
- inList(records.id, ['first-id', 'second-id']) // valid
79
+ eq(records.id, "108cb836-20d2-41b2-8c23-f0c94700aa7e") // valid
80
+ inList(records.id, ["first-id", "second-id"]) // valid
81
81
 
82
82
  lower(records.id) // TypeScript error: SqlUuid is not SqlTextLike
83
- like(records.id, '%uuid%') // TypeScript error: SqlUuid is not SqlTextLike
83
+ like(records.id, "%uuid%") // TypeScript error: SqlUuid is not SqlTextLike
84
84
  orderBy(asc(records.id)) // TypeScript error: SqlUuid is not portably orderable
85
85
  ```
86
86
 
@@ -90,10 +90,10 @@ operation. This contextual typing does not relabel an expression: comparing a
90
90
  the database operation intentionally changes domains:
91
91
 
92
92
  ```ts
93
- import { cast, like, text } from 'qubu'
93
+ import { cast, like, text } from "qubu"
94
94
 
95
95
  const idAsText = cast(records.id, text())
96
- like(idAsText, '108c%')
96
+ like(idAsText, "108c%")
97
97
  ```
98
98
 
99
99
  Built-in definitions carry logical cast targets, so the active dialect can
@@ -12,9 +12,9 @@ Check that the query includes the original source or use the columns exposed by
12
12
  the alias, CTE, or derived table you actually placed in the query:
13
13
 
14
14
  ```ts
15
- import { alias, from, select } from 'qubu'
15
+ import { alias, from, select } from "qubu"
16
16
 
17
- const author = alias(users, 'author')
17
+ const author = alias(users, "author")
18
18
 
19
19
  select({ name: author.name }, from(author))
20
20
  ```
@@ -27,9 +27,9 @@ identity after aliasing.
27
27
  This is the default mutation safety check. Add a source-aware predicate:
28
28
 
29
29
  ```ts
30
- import { deleteFrom, eq, update, where } from 'qubu'
30
+ import { deleteFrom, eq, update, where } from "qubu"
31
31
 
32
- update(users, { name: 'Ada' }, where(eq(users.id, 7)))
32
+ update(users, { name: "Ada" }, where(eq(users.id, 7)))
33
33
  deleteFrom(users, where(eq(users.id, 8)))
34
34
  ```
35
35
 
@@ -43,7 +43,7 @@ A scalar subquery must return one selected field. Reduce the projection before
43
43
  calling `scalar()`:
44
44
 
45
45
  ```ts
46
- import { from, scalar, select } from 'qubu'
46
+ import { from, scalar, select } from "qubu"
47
47
 
48
48
  const idQuery = select({ id: users.id }, from(users))
49
49
  const idExpression = scalar(idQuery)
@@ -58,8 +58,8 @@ Render with the dialect that the adapter expects and inspect both fields of the
58
58
  result:
59
59
 
60
60
  ```ts
61
- import { render } from 'qubu'
62
- import { postgresDialect } from 'qubu/postgres'
61
+ import { render } from "qubu"
62
+ import { postgresDialect } from "qubu/postgres"
63
63
 
64
64
  const statement = render(query, postgresDialect())
65
65
  console.log(statement.text)
@@ -78,7 +78,7 @@ path, and hint before changing the query. The hint names the repair boundary;
78
78
  the path points to the clause or field that needs attention.
79
79
 
80
80
  ```ts
81
- import { QueryValidationError, fetchFirst } from 'qubu'
81
+ import { QueryValidationError, fetchFirst } from "qubu"
82
82
 
83
83
  try {
84
84
  fetchFirst(-1)
@@ -140,10 +140,10 @@ placement. Rendering traverses that normalized statement, so inspect the final
140
140
  `text` and `parameters` together rather than assuming source argument order:
141
141
 
142
142
  ```ts
143
- import { eq, fetchFirst, from, render, select, where } from 'qubu'
143
+ import { eq, fetchFirst, from, render, select, where } from "qubu"
144
144
 
145
145
  const statement = render(
146
- select({ id: users.id }, from(users), where(eq(users.id, 7)), fetchFirst(10))
146
+ select({ id: users.id }, from(users), where(eq(users.id, 7)), fetchFirst(10)),
147
147
  )
148
148
  ```
149
149
 
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "qubu",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/aleclarson/qubu"
7
7
  },
8
- "type": "module",
9
8
  "files": [
10
9
  "dist",
11
10
  "docs",
12
11
  "skills"
13
12
  ],
13
+ "type": "module",
14
14
  "exports": {
15
15
  ".": {
16
16
  "types": "./dist/index.d.mts",
@@ -32,10 +32,6 @@
32
32
  "types": "./dist/diff.d.mts",
33
33
  "import": "./dist/diff.mjs"
34
34
  },
35
- "./drizzle": {
36
- "types": "./dist/drizzle.d.mts",
37
- "import": "./dist/drizzle.mjs"
38
- },
39
35
  "./introspection": {
40
36
  "types": "./dist/introspection.d.mts",
41
37
  "import": "./dist/introspection.mjs"
@@ -69,34 +65,29 @@
69
65
  "import": "./dist/vite.mjs"
70
66
  },
71
67
  "./package.json": "./package.json",
72
- "./drizzle/mysql": {
73
- "types": "./dist/drizzle-mysql.d.mts",
74
- "import": "./dist/drizzle-mysql.mjs"
75
- },
76
- "./drizzle/postgres": {
77
- "types": "./dist/drizzle-postgres.d.mts",
78
- "import": "./dist/drizzle-postgres.mjs"
79
- },
80
- "./drizzle/sqlite": {
81
- "types": "./dist/drizzle-sqlite.d.mts",
82
- "import": "./dist/drizzle-sqlite.mjs"
83
- },
84
68
  "./globals": {
85
69
  "types": "./dist/vite/ambient.d.ts"
86
70
  }
87
71
  },
88
- "prettier": "@alloc/prettier-config",
72
+ "dependencies": {
73
+ "@standard-schema/spec": "^1.0.0"
74
+ },
89
75
  "devDependencies": {
90
76
  "@alloc/prettier-config": "^1.0.0",
77
+ "@electric-sql/pglite": "^0.5.8",
78
+ "@libsql/client": "^0.17.4",
91
79
  "@pg-nano/pg-tmp": "^2.0.3",
80
+ "@stylistic/eslint-plugin": "^6.0.0-beta.6",
92
81
  "@types/bun": "^1.3.0",
93
82
  "@types/node": "^24.6.2",
94
83
  "@types/pg": "^8.23.1",
95
- "drizzle-orm": "1.0.0-rc.4",
96
84
  "lildocs": "^0.1.27",
97
85
  "mysql2": "^3.23.4",
86
+ "oxfmt": "^0.58.0",
87
+ "oxlint": "1.73.0",
98
88
  "pg": "^8.23.0",
99
89
  "picospawn": "^0.3.10",
90
+ "postgres": "^3.4.9",
100
91
  "prettier": "^3.6.2",
101
92
  "qubu": "link:",
102
93
  "radashi": "^12.6.2",
@@ -106,30 +97,27 @@
106
97
  "typescript": "^5.9.3",
107
98
  "vitest": "^3.2.4"
108
99
  },
109
- "dependencies": {
110
- "@standard-schema/spec": "^1.0.0"
111
- },
112
- "peerDependencies": {
113
- "drizzle-orm": "^1.0.0-rc.4"
114
- },
115
- "peerDependenciesMeta": {
116
- "drizzle-orm": {
117
- "optional": true
118
- }
119
- },
100
+ "prettier": "@alloc/prettier-config",
120
101
  "scripts": {
121
102
  "build": "tsdown",
103
+ "build:workspace-packages": "pnpm --recursive --filter './adapters/*' build",
122
104
  "check:package": "node ./scripts/test-package.mjs --check-built",
105
+ "check:workspace-versions": "node ./scripts/set-release-version.mjs --check",
123
106
  "playground": "bun run ./playground/playground.ts",
124
107
  "test": "vitest",
125
- "test:e2e": "vitest --run test/e2e/dialects.test.ts",
108
+ "test:e2e": "vitest --run test/e2e",
126
109
  "test:type-performance": "node ./scripts/test-type-performance.mjs",
127
110
  "diff-check": "vitest --run test/diff.test.ts test/migration.test.ts",
128
111
  "test:bun": "node ./scripts/test-package.mjs --runtime=bun",
129
112
  "test:package": "node ./scripts/test-package.mjs",
113
+ "test:workspace-children": "pnpm --recursive --filter './adapters/*' build && node ./scripts/test-workspace-packages.mjs",
114
+ "test:workspace-packages": "pnpm run test:package && pnpm run test:workspace-children",
130
115
  "test:package:node": "node ./scripts/test-package.mjs --runtime=node",
131
116
  "typecheck": "vitest --typecheck --run",
117
+ "typecheck:workspace-packages": "pnpm --recursive --filter './adapters/*' typecheck",
132
118
  "typecheck:playground": "tsc --project ./playground/tsconfig.json",
133
- "lint": "prettier --check . && npm run typecheck"
119
+ "format": "oxlint --fix && oxfmt",
120
+ "release:version": "node ./scripts/set-release-version.mjs",
121
+ "release:publish": "node ./scripts/publish-workspace.mjs"
134
122
  }
135
123
  }
@@ -1,6 +1,6 @@
1
1
  interface:
2
- display_name: 'Qubu'
3
- short_description: 'Route Qubu work to package docs'
4
- default_prompt: 'Use $qubu to find the smallest canonical Qubu guide for this task.'
2
+ display_name: "Qubu"
3
+ short_description: "Route Qubu work to package docs"
4
+ default_prompt: "Use $qubu to find the smallest canonical Qubu guide for this task."
5
5
  policy:
6
6
  allow_implicit_invocation: true