@b9g/zen 0.1.4 → 0.1.6
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/CHANGELOG.md +24 -0
- package/README.md +23 -14
- package/package.json +1 -1
- package/src/_chunks/{chunk-2R6FDKLS.js → chunk-BI2NQCYN.js} +1 -1
- package/src/_chunks/{chunk-DKLSJISE.js → chunk-NLI6YKQ6.js} +64 -1
- package/src/_chunks/{chunk-2C6KOX4F.js → chunk-OT6OQQ6S.js} +1 -1
- package/src/_chunks/{ddl-32B7E53E.js → ddl-KUIXILN7.js} +2 -2
- package/src/bun.js +4 -4
- package/src/impl/table.d.ts +110 -5
- package/src/mysql.js +3 -3
- package/src/postgres.js +3 -3
- package/src/sqlite.js +3 -3
- package/src/zen.js +33 -9
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.1.6] - 2026-01-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `table.relations()` method for unified forward and reverse relation navigation
|
|
13
|
+
- `FieldMeta.schema` - raw Zod schema for direct introspection
|
|
14
|
+
- `FieldMeta.db` - raw database metadata from `.db.*()` methods
|
|
15
|
+
- `Relation` type export for typing relation navigators
|
|
16
|
+
- Chained relation navigation: `Users.relations().posts.fields().author.fields().email`
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Validation no longer runs on reads, matching documented behavior (#16)
|
|
21
|
+
|
|
22
|
+
### Deprecated
|
|
23
|
+
|
|
24
|
+
- `FieldMeta.type`, `FieldMeta.required`, and other cooked properties - use `schema` and `db` instead
|
|
25
|
+
|
|
26
|
+
## [0.1.5] - 2025-12-28
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- `ensureTable()`, `ensureView()`, `ensureConstraints()`, `copyColumn()` no longer throw "cannot start a transaction within a transaction" when called inside `upgradeneeded` handler (#12)
|
|
31
|
+
|
|
8
32
|
## [0.1.4] - 2025-12-28
|
|
9
33
|
|
|
10
34
|
### Added
|
package/README.md
CHANGED
|
@@ -110,7 +110,7 @@ const post = await db.get(Posts, posts[0].id);
|
|
|
110
110
|
await db.update(Users, {name: "Alice Smith"}, user.id);
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
## Why
|
|
113
|
+
## Why ZenDB?
|
|
114
114
|
|
|
115
115
|
Zen is the missing link between SQL and typed data. By writing tables with Zod schema, you get idempotent migration helpers, typed CRUD, normalized object references, and many features other database clients cannot provide.
|
|
116
116
|
|
|
@@ -829,19 +829,29 @@ type NewUser = Insert<typeof Users>; // Insert type (respects defaults/.db.auto(
|
|
|
829
829
|
|
|
830
830
|
## Field Metadata
|
|
831
831
|
|
|
832
|
-
Tables expose metadata for form generation:
|
|
832
|
+
Tables expose metadata for introspection and form generation:
|
|
833
833
|
|
|
834
834
|
```typescript
|
|
835
835
|
const fields = Users.fields();
|
|
836
|
-
// {
|
|
837
|
-
// email: { name: "email", type: "email", required: true, unique: true },
|
|
838
|
-
// name: { name: "name", type: "text", required: true, maxLength: 100 },
|
|
839
|
-
// role: { name: "role", type: "select", options: ["user", "admin"], default: "user" },
|
|
840
|
-
// }
|
|
841
836
|
|
|
842
|
-
|
|
837
|
+
// Preferred: raw schema and db metadata
|
|
838
|
+
fields.email.name; // "email"
|
|
839
|
+
fields.email.schema; // ZodString - use Zod APIs (isOptional(), etc.)
|
|
840
|
+
fields.email.db; // FieldDBMeta object
|
|
841
|
+
fields.email.db.unique; // true
|
|
842
|
+
fields.email.db.primaryKey; // undefined
|
|
843
|
+
|
|
844
|
+
const pkName = Users.meta.primary; // "id" (field name)
|
|
843
845
|
const pkFragment = Users.primary; // SQLTemplate: "users"."id"
|
|
844
|
-
const refs = Posts.references
|
|
846
|
+
const refs = Posts.meta.references; // [{fieldName: "authorId", table: Users, as: "author"}]
|
|
847
|
+
|
|
848
|
+
// Relation navigation (forward and reverse)
|
|
849
|
+
Posts.relations().author.table; // Users table
|
|
850
|
+
Posts.relations().author.fields(); // Users field metadata
|
|
851
|
+
Users.relations().posts.table; // Posts table (if reverseAs: "posts" defined)
|
|
852
|
+
|
|
853
|
+
// Chain navigation through relationships
|
|
854
|
+
Users.relations().posts.fields().author.fields().email; // Back to Users.email field
|
|
845
855
|
```
|
|
846
856
|
|
|
847
857
|
## Performance
|
|
@@ -1037,9 +1047,9 @@ import type {
|
|
|
1037
1047
|
CompoundReference, // Compound foreign key reference
|
|
1038
1048
|
|
|
1039
1049
|
// Field types
|
|
1040
|
-
FieldMeta, // Field metadata for
|
|
1041
|
-
FieldType, // Field type enum
|
|
1050
|
+
FieldMeta, // Field metadata for introspection
|
|
1042
1051
|
FieldDBMeta, // Database-specific field metadata
|
|
1052
|
+
Relation, // Relation navigator from table.relations()
|
|
1043
1053
|
|
|
1044
1054
|
// Type inference
|
|
1045
1055
|
Row, // Infer row type from Table (after read)
|
|
@@ -1094,10 +1104,9 @@ Users.primary; // SQLTemplate for primary key column
|
|
|
1094
1104
|
// Metadata
|
|
1095
1105
|
Users.name; // Table name string
|
|
1096
1106
|
Users.schema; // Zod schema
|
|
1097
|
-
Users.meta; // Table metadata (primary, indexes, etc.)
|
|
1098
|
-
Users.primaryKey(); // Primary key field name or null
|
|
1107
|
+
Users.meta; // Table metadata (primary, references, indexes, etc.)
|
|
1099
1108
|
Users.fields(); // Field metadata for form generation
|
|
1100
|
-
Users.
|
|
1109
|
+
Users.relations(); // Forward and reverse relation navigators
|
|
1101
1110
|
|
|
1102
1111
|
// Derived Tables
|
|
1103
1112
|
Users.pick("id", "email"); // PartialTable with subset of fields
|
package/package.json
CHANGED
|
@@ -665,6 +665,25 @@ function extendZod(zodModule) {
|
|
|
665
665
|
extendZod(z);
|
|
666
666
|
var TABLE_MARKER = Symbol.for("@b9g/zen:table");
|
|
667
667
|
var TABLE_META = Symbol.for("@b9g/zen:table-meta");
|
|
668
|
+
var reverseRelationsRegistry = /* @__PURE__ */ new WeakMap();
|
|
669
|
+
function registerReverseRelation(targetTable, reverseName, getSourceTable, sourceTableName, fieldName) {
|
|
670
|
+
let relations = reverseRelationsRegistry.get(targetTable);
|
|
671
|
+
if (!relations) {
|
|
672
|
+
relations = /* @__PURE__ */ new Map();
|
|
673
|
+
reverseRelationsRegistry.set(targetTable, relations);
|
|
674
|
+
}
|
|
675
|
+
if (relations.has(reverseName)) {
|
|
676
|
+
throw new TableDefinitionError(
|
|
677
|
+
`Table "${sourceTableName}": reverse relation "${reverseName}" (from field "${fieldName}") collides with an existing reverse relation on target table "${targetTable.name}". Each reverseAs name must be unique per target table.`,
|
|
678
|
+
sourceTableName,
|
|
679
|
+
fieldName
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
relations.set(reverseName, getSourceTable);
|
|
683
|
+
}
|
|
684
|
+
function getReverseRelations(table2) {
|
|
685
|
+
return reverseRelationsRegistry.get(table2);
|
|
686
|
+
}
|
|
668
687
|
function isTable(value) {
|
|
669
688
|
return value !== null && typeof value === "object" && TABLE_MARKER in value && value[TABLE_MARKER] === true;
|
|
670
689
|
}
|
|
@@ -907,6 +926,15 @@ function table(name, shape, options = {}) {
|
|
|
907
926
|
key
|
|
908
927
|
);
|
|
909
928
|
}
|
|
929
|
+
const targetRefs = getTableMeta(ref.table).references;
|
|
930
|
+
const collidingRef = targetRefs.find((r) => r.as === ref.reverseAs);
|
|
931
|
+
if (collidingRef) {
|
|
932
|
+
throw new TableDefinitionError(
|
|
933
|
+
`Table "${name}": reverse relation "${ref.reverseAs}" (from field "${key}") collides with forward relation "${collidingRef.as}" in target table "${ref.table.name}". Choose a different 'reverseAs' name.`,
|
|
934
|
+
name,
|
|
935
|
+
key
|
|
936
|
+
);
|
|
937
|
+
}
|
|
910
938
|
}
|
|
911
939
|
meta.references.push({
|
|
912
940
|
fieldName: key,
|
|
@@ -942,7 +970,19 @@ function table(name, shape, options = {}) {
|
|
|
942
970
|
meta.fields[key] = dbMeta;
|
|
943
971
|
}
|
|
944
972
|
const schema = z.object(zodShape);
|
|
945
|
-
|
|
973
|
+
const tableObj = createTableObject(name, schema, zodShape, meta, options);
|
|
974
|
+
for (const ref of meta.references) {
|
|
975
|
+
if (ref.reverseAs) {
|
|
976
|
+
registerReverseRelation(
|
|
977
|
+
ref.table,
|
|
978
|
+
ref.reverseAs,
|
|
979
|
+
() => tableObj,
|
|
980
|
+
name,
|
|
981
|
+
ref.fieldName
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
return tableObj;
|
|
946
986
|
}
|
|
947
987
|
function createColsProxy(tableName, zodShape) {
|
|
948
988
|
return new Proxy({}, {
|
|
@@ -1020,6 +1060,25 @@ function createTableObject(name, schema, zodShape, meta, options) {
|
|
|
1020
1060
|
references() {
|
|
1021
1061
|
return meta.references;
|
|
1022
1062
|
},
|
|
1063
|
+
relations() {
|
|
1064
|
+
const result = {};
|
|
1065
|
+
for (const ref of meta.references) {
|
|
1066
|
+
result[ref.as] = {
|
|
1067
|
+
fields: () => ref.table.fields(),
|
|
1068
|
+
table: ref.table
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
const reverseMap = getReverseRelations(table2);
|
|
1072
|
+
if (reverseMap) {
|
|
1073
|
+
for (const [reverseName, getSourceTable] of reverseMap) {
|
|
1074
|
+
result[reverseName] = {
|
|
1075
|
+
fields: () => getSourceTable().fields(),
|
|
1076
|
+
table: getSourceTable()
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
return result;
|
|
1081
|
+
},
|
|
1023
1082
|
deleted() {
|
|
1024
1083
|
const softDeleteField = meta.softDeleteField;
|
|
1025
1084
|
if (!softDeleteField) {
|
|
@@ -1338,7 +1397,11 @@ function extractFieldMeta(name, zodType, dbMeta) {
|
|
|
1338
1397
|
} = unwrapType(zodType);
|
|
1339
1398
|
const { db: _db, ...userMeta } = collectedMeta;
|
|
1340
1399
|
const meta = {
|
|
1400
|
+
// New: raw schema access (preferred)
|
|
1341
1401
|
name,
|
|
1402
|
+
schema: zodType,
|
|
1403
|
+
db: dbMeta,
|
|
1404
|
+
// Deprecated: cooked properties for backwards compatibility
|
|
1342
1405
|
type: "text",
|
|
1343
1406
|
required: !isOptional && !isNullable && !hasDefault,
|
|
1344
1407
|
...userMeta
|
package/src/bun.js
CHANGED
|
@@ -3,15 +3,15 @@ import {
|
|
|
3
3
|
placeholder,
|
|
4
4
|
quoteIdent,
|
|
5
5
|
renderDDL
|
|
6
|
-
} from "./_chunks/chunk-
|
|
6
|
+
} from "./_chunks/chunk-OT6OQQ6S.js";
|
|
7
7
|
import {
|
|
8
8
|
generateDDL,
|
|
9
9
|
generateViewDDL
|
|
10
|
-
} from "./_chunks/chunk-
|
|
10
|
+
} from "./_chunks/chunk-BI2NQCYN.js";
|
|
11
11
|
import {
|
|
12
12
|
getTableMeta,
|
|
13
13
|
resolveSQLBuiltin
|
|
14
|
-
} from "./_chunks/chunk-
|
|
14
|
+
} from "./_chunks/chunk-NLI6YKQ6.js";
|
|
15
15
|
|
|
16
16
|
// src/bun.ts
|
|
17
17
|
import { SQL } from "bun";
|
|
@@ -753,7 +753,7 @@ var BunDriver = class {
|
|
|
753
753
|
return applied;
|
|
754
754
|
}
|
|
755
755
|
async #addColumn(table, fieldName) {
|
|
756
|
-
const { generateColumnDDL } = await import("./_chunks/ddl-
|
|
756
|
+
const { generateColumnDDL } = await import("./_chunks/ddl-KUIXILN7.js");
|
|
757
757
|
const zodType = table.schema.shape[fieldName];
|
|
758
758
|
const fieldMeta = table.meta.fields[fieldName] || {};
|
|
759
759
|
const colTemplate = generateColumnDDL(
|
package/src/impl/table.d.ts
CHANGED
|
@@ -125,46 +125,112 @@ export interface FieldDBMeta {
|
|
|
125
125
|
export declare function extendZod(zodModule: typeof z): void;
|
|
126
126
|
export type FieldType = "text" | "textarea" | "email" | "url" | "tel" | "password" | "number" | "integer" | "checkbox" | "select" | "date" | "datetime" | "time" | "json" | "hidden";
|
|
127
127
|
export interface FieldMeta {
|
|
128
|
+
/** Field name (the key in the schema) */
|
|
128
129
|
name: string;
|
|
130
|
+
/** Raw Zod schema - use Zod APIs for introspection (isOptional(), etc.) */
|
|
131
|
+
schema: z.ZodType;
|
|
132
|
+
/** Raw database metadata from .db.*() methods */
|
|
133
|
+
db: FieldDBMeta;
|
|
134
|
+
/**
|
|
135
|
+
* @deprecated Use `schema` with Zod APIs instead. This form-specific type
|
|
136
|
+
* inference will move to a separate @b9g/forms package.
|
|
137
|
+
*/
|
|
129
138
|
type: FieldType;
|
|
139
|
+
/**
|
|
140
|
+
* @deprecated Use `!schema.isOptional() && !db.autoIncrement && !db.inserted` instead.
|
|
141
|
+
*/
|
|
130
142
|
required: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* @deprecated Use `db.primaryKey` instead.
|
|
145
|
+
*/
|
|
131
146
|
primaryKey?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* @deprecated Use `db.unique` instead.
|
|
149
|
+
*/
|
|
132
150
|
unique?: boolean;
|
|
151
|
+
/**
|
|
152
|
+
* @deprecated Use `db.indexed` instead.
|
|
153
|
+
*/
|
|
133
154
|
indexed?: boolean;
|
|
155
|
+
/**
|
|
156
|
+
* @deprecated Use `db.softDelete` instead.
|
|
157
|
+
*/
|
|
134
158
|
softDelete?: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* @deprecated Use `db.reference` instead.
|
|
161
|
+
*/
|
|
135
162
|
reference?: {
|
|
136
163
|
table: Table;
|
|
137
164
|
field: string;
|
|
138
165
|
as: string;
|
|
139
166
|
onDelete?: "cascade" | "set null" | "restrict";
|
|
140
167
|
};
|
|
168
|
+
/**
|
|
169
|
+
* @deprecated Use `db.encode` instead.
|
|
170
|
+
*/
|
|
141
171
|
encode?: (value: any) => any;
|
|
172
|
+
/**
|
|
173
|
+
* @deprecated Use `db.decode` instead.
|
|
174
|
+
*/
|
|
142
175
|
decode?: (value: any) => any;
|
|
176
|
+
/**
|
|
177
|
+
* @deprecated Use `db.columnType` instead.
|
|
178
|
+
*/
|
|
143
179
|
columnType?: string;
|
|
180
|
+
/**
|
|
181
|
+
* @deprecated Use `db.autoIncrement` instead.
|
|
182
|
+
*/
|
|
144
183
|
autoIncrement?: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* @deprecated Use `db.inserted` instead.
|
|
186
|
+
*/
|
|
145
187
|
inserted?: {
|
|
146
188
|
type: "sql" | "symbol" | "function";
|
|
147
189
|
template?: SQLTemplate;
|
|
148
190
|
symbol?: SQLBuiltin;
|
|
149
191
|
fn?: () => unknown;
|
|
150
192
|
};
|
|
193
|
+
/**
|
|
194
|
+
* @deprecated Use `db.updated` instead.
|
|
195
|
+
*/
|
|
151
196
|
updated?: {
|
|
152
197
|
type: "sql" | "symbol" | "function";
|
|
153
198
|
template?: SQLTemplate;
|
|
154
199
|
symbol?: SQLBuiltin;
|
|
155
200
|
fn?: () => unknown;
|
|
156
201
|
};
|
|
202
|
+
/**
|
|
203
|
+
* @deprecated Use `db.upserted` instead.
|
|
204
|
+
*/
|
|
157
205
|
upserted?: {
|
|
158
206
|
type: "sql" | "symbol" | "function";
|
|
159
207
|
template?: SQLTemplate;
|
|
160
208
|
symbol?: SQLBuiltin;
|
|
161
209
|
fn?: () => unknown;
|
|
162
210
|
};
|
|
211
|
+
/**
|
|
212
|
+
* @deprecated Extract from Zod schema directly.
|
|
213
|
+
*/
|
|
163
214
|
default?: unknown;
|
|
215
|
+
/**
|
|
216
|
+
* @deprecated Extract from Zod schema directly.
|
|
217
|
+
*/
|
|
164
218
|
maxLength?: number;
|
|
219
|
+
/**
|
|
220
|
+
* @deprecated Extract from Zod schema directly.
|
|
221
|
+
*/
|
|
165
222
|
minLength?: number;
|
|
223
|
+
/**
|
|
224
|
+
* @deprecated Extract from Zod schema directly.
|
|
225
|
+
*/
|
|
166
226
|
min?: number;
|
|
227
|
+
/**
|
|
228
|
+
* @deprecated Extract from Zod schema directly.
|
|
229
|
+
*/
|
|
167
230
|
max?: number;
|
|
231
|
+
/**
|
|
232
|
+
* @deprecated Extract from Zod schema directly (for ZodEnum).
|
|
233
|
+
*/
|
|
168
234
|
options?: readonly string[];
|
|
169
235
|
/** Additional user-defined metadata from Zod's .meta() (label, helpText, widget, etc.) */
|
|
170
236
|
[key: string]: unknown;
|
|
@@ -306,12 +372,13 @@ type FilterRefs<PickedShape extends ZodRawShape, OriginalRefs extends Record<str
|
|
|
306
372
|
[Alias in keyof OriginalRefs as Alias extends keyof RowRefs<PickedShape> ? Alias : never]: OriginalRefs[Alias];
|
|
307
373
|
};
|
|
308
374
|
/**
|
|
309
|
-
* A relationship
|
|
375
|
+
* A relationship navigator for traversing table relations.
|
|
376
|
+
* Used for both forward (many-to-one) and reverse (one-to-many) navigation.
|
|
310
377
|
*/
|
|
311
378
|
export interface Relation<TargetTable extends Table<any, any>> {
|
|
312
|
-
/** Navigate to the
|
|
379
|
+
/** Navigate to the related table's fields */
|
|
313
380
|
fields(): ReturnType<TargetTable["fields"]>;
|
|
314
|
-
/** Direct access to the
|
|
381
|
+
/** Direct access to the related table */
|
|
315
382
|
readonly table: TargetTable;
|
|
316
383
|
}
|
|
317
384
|
/**
|
|
@@ -355,9 +422,10 @@ export interface Table<T extends ZodRawShape = ZodRawShape, Refs extends Record<
|
|
|
355
422
|
* Get the primary key field name.
|
|
356
423
|
*
|
|
357
424
|
* @returns The primary key field name, or null if no primary key is defined.
|
|
425
|
+
* @deprecated Use `table.meta.primary` instead.
|
|
358
426
|
*
|
|
359
427
|
* @example
|
|
360
|
-
* const pk = Users.
|
|
428
|
+
* const pk = Users.meta.primary; // "id"
|
|
361
429
|
*/
|
|
362
430
|
primaryKey(): string | null;
|
|
363
431
|
/**
|
|
@@ -368,7 +436,10 @@ export interface Table<T extends ZodRawShape = ZodRawShape, Refs extends Record<
|
|
|
368
436
|
* // → GROUP BY "posts"."id"
|
|
369
437
|
*/
|
|
370
438
|
readonly primary: SQLTemplate | null;
|
|
371
|
-
/**
|
|
439
|
+
/**
|
|
440
|
+
* Get all foreign key references.
|
|
441
|
+
* @deprecated Use `table.meta.references` for raw FK metadata, or `table.relations()` for navigation.
|
|
442
|
+
*/
|
|
372
443
|
references(): ReferenceInfo[];
|
|
373
444
|
/**
|
|
374
445
|
* Generate SQL fragment to check if a row is soft-deleted.
|
|
@@ -518,6 +589,39 @@ export interface Table<T extends ZodRawShape = ZodRawShape, Refs extends Record<
|
|
|
518
589
|
* // → INSERT INTO posts (id, title) VALUES (?, ?), (?, ?)
|
|
519
590
|
*/
|
|
520
591
|
values(rows: Partial<z.infer<ZodObject<T>>>[]): SQLTemplate;
|
|
592
|
+
/**
|
|
593
|
+
* Navigate table relations (both forward and reverse).
|
|
594
|
+
*
|
|
595
|
+
* Returns an object with relation names as keys. Each key provides
|
|
596
|
+
* a `Relation` with `fields()` and `table` properties.
|
|
597
|
+
*
|
|
598
|
+
* - Forward relations come from `as` in `.db.references(Table, "as")`
|
|
599
|
+
* - Reverse relations come from `reverseAs` in `.db.references(Table, "as", { reverseAs: "..." })`
|
|
600
|
+
*
|
|
601
|
+
* @example
|
|
602
|
+
* const Users = table("users", {
|
|
603
|
+
* id: z.string().db.primary(),
|
|
604
|
+
* email: z.string().email(),
|
|
605
|
+
* });
|
|
606
|
+
*
|
|
607
|
+
* const Posts = table("posts", {
|
|
608
|
+
* id: z.string().db.primary(),
|
|
609
|
+
* title: z.string(),
|
|
610
|
+
* authorId: z.string().db.references(Users, "author", { reverseAs: "posts" }),
|
|
611
|
+
* });
|
|
612
|
+
*
|
|
613
|
+
* // Forward relation (many-to-one): Posts -> Users
|
|
614
|
+
* Posts.relations().author.fields().email // Users.email field metadata
|
|
615
|
+
* Posts.relations().author.table // Users table
|
|
616
|
+
*
|
|
617
|
+
* // Reverse relation (one-to-many): Users -> Posts
|
|
618
|
+
* Users.relations().posts.fields().title // Posts.title field metadata
|
|
619
|
+
* Users.relations().posts.table // Posts table
|
|
620
|
+
*
|
|
621
|
+
* // Chain navigation
|
|
622
|
+
* Users.relations().posts.fields().author.fields().email // Back to Users.email
|
|
623
|
+
*/
|
|
624
|
+
relations(): Record<string, Relation<Table<any, any>>>;
|
|
521
625
|
/**
|
|
522
626
|
* Get a view that excludes soft-deleted rows.
|
|
523
627
|
*
|
|
@@ -583,6 +687,7 @@ export interface View<T extends ZodRawShape = ZodRawShape, Refs extends Record<s
|
|
|
583
687
|
/**
|
|
584
688
|
* Get reference metadata for foreign key relationships.
|
|
585
689
|
* Delegates to the base table's references.
|
|
690
|
+
* @deprecated Use `view.baseTable.meta.references` for raw FK metadata, or `view.baseTable.relations()` for navigation.
|
|
586
691
|
*/
|
|
587
692
|
references(): ReferenceInfo[];
|
|
588
693
|
/**
|
package/src/mysql.js
CHANGED
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
import {
|
|
3
3
|
quoteIdent,
|
|
4
4
|
renderDDL
|
|
5
|
-
} from "./_chunks/chunk-
|
|
5
|
+
} from "./_chunks/chunk-OT6OQQ6S.js";
|
|
6
6
|
import {
|
|
7
7
|
generateColumnDDL,
|
|
8
8
|
generateDDL,
|
|
9
9
|
generateViewDDL
|
|
10
|
-
} from "./_chunks/chunk-
|
|
10
|
+
} from "./_chunks/chunk-BI2NQCYN.js";
|
|
11
11
|
import {
|
|
12
12
|
ConstraintPreflightError,
|
|
13
13
|
EnsureError,
|
|
14
14
|
SchemaDriftError,
|
|
15
15
|
getTableMeta,
|
|
16
16
|
resolveSQLBuiltin
|
|
17
|
-
} from "./_chunks/chunk-
|
|
17
|
+
} from "./_chunks/chunk-NLI6YKQ6.js";
|
|
18
18
|
|
|
19
19
|
// src/mysql.ts
|
|
20
20
|
import {
|
package/src/postgres.js
CHANGED
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
import {
|
|
3
3
|
quoteIdent,
|
|
4
4
|
renderDDL
|
|
5
|
-
} from "./_chunks/chunk-
|
|
5
|
+
} from "./_chunks/chunk-OT6OQQ6S.js";
|
|
6
6
|
import {
|
|
7
7
|
generateColumnDDL,
|
|
8
8
|
generateDDL,
|
|
9
9
|
generateViewDDL
|
|
10
|
-
} from "./_chunks/chunk-
|
|
10
|
+
} from "./_chunks/chunk-BI2NQCYN.js";
|
|
11
11
|
import {
|
|
12
12
|
ConstraintPreflightError,
|
|
13
13
|
EnsureError,
|
|
14
14
|
SchemaDriftError,
|
|
15
15
|
getTableMeta,
|
|
16
16
|
resolveSQLBuiltin
|
|
17
|
-
} from "./_chunks/chunk-
|
|
17
|
+
} from "./_chunks/chunk-NLI6YKQ6.js";
|
|
18
18
|
|
|
19
19
|
// src/postgres.ts
|
|
20
20
|
import {
|
package/src/sqlite.js
CHANGED
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
import {
|
|
3
3
|
quoteIdent,
|
|
4
4
|
renderDDL
|
|
5
|
-
} from "./_chunks/chunk-
|
|
5
|
+
} from "./_chunks/chunk-OT6OQQ6S.js";
|
|
6
6
|
import {
|
|
7
7
|
generateColumnDDL,
|
|
8
8
|
generateDDL,
|
|
9
9
|
generateViewDDL
|
|
10
|
-
} from "./_chunks/chunk-
|
|
10
|
+
} from "./_chunks/chunk-BI2NQCYN.js";
|
|
11
11
|
import {
|
|
12
12
|
ConstraintPreflightError,
|
|
13
13
|
EnsureError,
|
|
14
14
|
SchemaDriftError,
|
|
15
15
|
getTableMeta,
|
|
16
16
|
resolveSQLBuiltin
|
|
17
|
-
} from "./_chunks/chunk-
|
|
17
|
+
} from "./_chunks/chunk-NLI6YKQ6.js";
|
|
18
18
|
|
|
19
19
|
// src/sqlite.ts
|
|
20
20
|
import {
|
package/src/zen.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="./zen.d.ts" />
|
|
2
|
-
import "./_chunks/chunk-
|
|
2
|
+
import "./_chunks/chunk-OT6OQQ6S.js";
|
|
3
3
|
import {
|
|
4
4
|
AlreadyExistsError,
|
|
5
5
|
CURRENT_DATE,
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
table,
|
|
40
40
|
validateWithStandardSchema,
|
|
41
41
|
view
|
|
42
|
-
} from "./_chunks/chunk-
|
|
42
|
+
} from "./_chunks/chunk-NLI6YKQ6.js";
|
|
43
43
|
|
|
44
44
|
// src/zen.ts
|
|
45
45
|
import { z as zod } from "zod";
|
|
@@ -87,11 +87,9 @@ function buildEntityMap(rows, tables, driver) {
|
|
|
87
87
|
const key = entityKey(table2.name, pk);
|
|
88
88
|
if (!entities.has(key)) {
|
|
89
89
|
const decoded = decodeData(table2, data, driver);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
);
|
|
94
|
-
entities.set(key, parsed);
|
|
90
|
+
if (decoded) {
|
|
91
|
+
entities.set(key, decoded);
|
|
92
|
+
}
|
|
95
93
|
}
|
|
96
94
|
}
|
|
97
95
|
}
|
|
@@ -1236,6 +1234,7 @@ var Database = class extends EventTarget {
|
|
|
1236
1234
|
#version = 0;
|
|
1237
1235
|
#opened = false;
|
|
1238
1236
|
#tables = [];
|
|
1237
|
+
#inMigrationLock = false;
|
|
1239
1238
|
constructor(driver, options) {
|
|
1240
1239
|
super();
|
|
1241
1240
|
this.#driver = driver;
|
|
@@ -1282,9 +1281,19 @@ var Database = class extends EventTarget {
|
|
|
1282
1281
|
}
|
|
1283
1282
|
};
|
|
1284
1283
|
if (this.#driver.withMigrationLock) {
|
|
1285
|
-
|
|
1284
|
+
this.#inMigrationLock = true;
|
|
1285
|
+
try {
|
|
1286
|
+
await this.#driver.withMigrationLock(runMigration);
|
|
1287
|
+
} finally {
|
|
1288
|
+
this.#inMigrationLock = false;
|
|
1289
|
+
}
|
|
1286
1290
|
} else {
|
|
1287
|
-
|
|
1291
|
+
this.#inMigrationLock = true;
|
|
1292
|
+
try {
|
|
1293
|
+
await this.#driver.transaction(runMigration);
|
|
1294
|
+
} finally {
|
|
1295
|
+
this.#inMigrationLock = false;
|
|
1296
|
+
}
|
|
1288
1297
|
}
|
|
1289
1298
|
this.#version = version;
|
|
1290
1299
|
this.#opened = true;
|
|
@@ -2071,6 +2080,9 @@ var Database = class extends EventTarget {
|
|
|
2071
2080
|
);
|
|
2072
2081
|
}
|
|
2073
2082
|
const doEnsure = () => this.#driver.ensureTable(table2);
|
|
2083
|
+
if (this.#inMigrationLock) {
|
|
2084
|
+
return await doEnsure();
|
|
2085
|
+
}
|
|
2074
2086
|
if (this.#driver.withMigrationLock) {
|
|
2075
2087
|
return await this.#driver.withMigrationLock(doEnsure);
|
|
2076
2088
|
}
|
|
@@ -2094,6 +2106,9 @@ var Database = class extends EventTarget {
|
|
|
2094
2106
|
);
|
|
2095
2107
|
}
|
|
2096
2108
|
const doEnsure = () => this.#driver.ensureView(viewObj);
|
|
2109
|
+
if (this.#inMigrationLock) {
|
|
2110
|
+
return await doEnsure();
|
|
2111
|
+
}
|
|
2097
2112
|
if (this.#driver.withMigrationLock) {
|
|
2098
2113
|
return await this.#driver.withMigrationLock(doEnsure);
|
|
2099
2114
|
}
|
|
@@ -2128,6 +2143,9 @@ var Database = class extends EventTarget {
|
|
|
2128
2143
|
);
|
|
2129
2144
|
}
|
|
2130
2145
|
const doEnsure = () => this.#driver.ensureConstraints(table2);
|
|
2146
|
+
if (this.#inMigrationLock) {
|
|
2147
|
+
return await doEnsure();
|
|
2148
|
+
}
|
|
2131
2149
|
if (this.#driver.withMigrationLock) {
|
|
2132
2150
|
return await this.#driver.withMigrationLock(doEnsure);
|
|
2133
2151
|
}
|
|
@@ -2163,6 +2181,9 @@ var Database = class extends EventTarget {
|
|
|
2163
2181
|
}
|
|
2164
2182
|
if (this.#driver.copyColumn) {
|
|
2165
2183
|
const doCopy2 = () => this.#driver.copyColumn(table2, fromField, toField);
|
|
2184
|
+
if (this.#inMigrationLock) {
|
|
2185
|
+
return await doCopy2();
|
|
2186
|
+
}
|
|
2166
2187
|
if (this.#driver.withMigrationLock) {
|
|
2167
2188
|
return await this.#driver.withMigrationLock(doCopy2);
|
|
2168
2189
|
}
|
|
@@ -2200,6 +2221,9 @@ var Database = class extends EventTarget {
|
|
|
2200
2221
|
);
|
|
2201
2222
|
}
|
|
2202
2223
|
};
|
|
2224
|
+
if (this.#inMigrationLock) {
|
|
2225
|
+
return await doCopy();
|
|
2226
|
+
}
|
|
2203
2227
|
if (this.#driver.withMigrationLock) {
|
|
2204
2228
|
return await this.#driver.withMigrationLock(doCopy);
|
|
2205
2229
|
}
|