turbine-orm 0.16.0 → 0.19.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/README.md +180 -12
- package/dist/adapters/cockroachdb.js +4 -2
- package/dist/adapters/index.js +4 -1
- package/dist/adapters/yugabytedb.js +4 -2
- package/dist/cjs/adapters/cockroachdb.js +4 -2
- package/dist/cjs/adapters/index.js +4 -1
- package/dist/cjs/adapters/yugabytedb.js +4 -2
- package/dist/cjs/cli/studio-ui.generated.js +1 -1
- package/dist/cjs/cli/studio.js +35 -73
- package/dist/cjs/client.js +164 -0
- package/dist/cjs/errors.js +35 -5
- package/dist/cjs/generate.js +14 -3
- package/dist/cjs/index.js +10 -2
- package/dist/cjs/introspect.js +81 -0
- package/dist/cjs/nested-write.js +70 -6
- package/dist/cjs/query/builder.js +581 -17
- package/dist/cjs/realtime.js +147 -0
- package/dist/cjs/schema-builder.js +86 -0
- package/dist/cjs/schema.js +10 -0
- package/dist/cjs/typed-sql.js +149 -0
- package/dist/cli/studio-ui.generated.js +1 -1
- package/dist/cli/studio.js +35 -73
- package/dist/client.d.ts +120 -0
- package/dist/client.js +165 -1
- package/dist/errors.js +35 -5
- package/dist/generate.js +14 -3
- package/dist/index.d.ts +4 -2
- package/dist/index.js +5 -1
- package/dist/introspect.js +81 -0
- package/dist/nested-write.js +70 -6
- package/dist/query/builder.d.ts +104 -1
- package/dist/query/builder.js +582 -18
- package/dist/query/index.d.ts +1 -1
- package/dist/query/types.d.ts +126 -2
- package/dist/realtime.d.ts +71 -0
- package/dist/realtime.js +144 -0
- package/dist/schema-builder.d.ts +68 -1
- package/dist/schema-builder.js +85 -0
- package/dist/schema.d.ts +18 -1
- package/dist/schema.js +10 -0
- package/dist/typed-sql.d.ts +101 -0
- package/dist/typed-sql.js +145 -0
- package/package.json +17 -15
package/dist/cjs/nested-write.js
CHANGED
|
@@ -144,17 +144,29 @@ async function executeNestedCreate(ctx, tableName, data, depth = 0, path = []) {
|
|
|
144
144
|
}
|
|
145
145
|
validateOps(relName, ops, false);
|
|
146
146
|
}
|
|
147
|
-
//
|
|
148
|
-
|
|
149
|
-
//
|
|
147
|
+
// belongsTo relations put the foreign key on the PARENT row, so they must be
|
|
148
|
+
// resolved BEFORE the parent is inserted — otherwise a NOT NULL FK column
|
|
149
|
+
// fails on the initial INSERT. We resolve each belongsTo op (create/connect/
|
|
150
|
+
// connectOrCreate) to its referenced row and fold the FK values into the
|
|
151
|
+
// parent's own INSERT.
|
|
152
|
+
const belongsToFks = {};
|
|
153
|
+
for (const [relName, ops] of Object.entries(relations)) {
|
|
154
|
+
const rel = tableMeta.relations[relName];
|
|
155
|
+
if (rel.type === 'belongsTo') {
|
|
156
|
+
Object.assign(belongsToFks, await resolveBelongsToForCreate(ctx, rel, ops, tableName, depth, path, relName));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Insert the parent row (scalars + resolved belongsTo foreign keys)
|
|
160
|
+
const parentRow = (await ctx.tx.table(tableName).create({
|
|
161
|
+
data: { ...scalars, ...belongsToFks },
|
|
162
|
+
}));
|
|
163
|
+
// Process hasMany / hasOne relations — their FK lives on the CHILD, so they
|
|
164
|
+
// need the parent row to exist first.
|
|
150
165
|
for (const [relName, ops] of Object.entries(relations)) {
|
|
151
166
|
const rel = tableMeta.relations[relName];
|
|
152
167
|
if (rel.type === 'hasMany' || rel.type === 'hasOne') {
|
|
153
168
|
await processHasManyCreate(ctx, rel, ops, parentRow, depth, path, relName);
|
|
154
169
|
}
|
|
155
|
-
else if (rel.type === 'belongsTo') {
|
|
156
|
-
await processBelongsToCreate(ctx, rel, ops, parentRow, tableName, depth, path, relName);
|
|
157
|
-
}
|
|
158
170
|
}
|
|
159
171
|
// Build the `with` clause for the final read to return the full tree
|
|
160
172
|
const withClause = {};
|
|
@@ -319,6 +331,58 @@ async function processHasManyCreate(ctx, rel, ops, parentRow, depth, path, relNa
|
|
|
319
331
|
// ---------------------------------------------------------------------------
|
|
320
332
|
// belongsTo create operations
|
|
321
333
|
// ---------------------------------------------------------------------------
|
|
334
|
+
/**
|
|
335
|
+
* Resolve a belongsTo relation's create/connect/connectOrCreate op to the
|
|
336
|
+
* foreign-key value(s) that belong on the PARENT row, returning them keyed by
|
|
337
|
+
* the parent's own field names so they can be merged into the parent INSERT.
|
|
338
|
+
*
|
|
339
|
+
* Used by the create path only. (The update path uses processBelongsToCreate,
|
|
340
|
+
* which UPDATEs the FK after the parent already exists.)
|
|
341
|
+
*/
|
|
342
|
+
async function resolveBelongsToForCreate(ctx, rel, ops, parentTable, depth, path, relName) {
|
|
343
|
+
const fks = (0, schema_js_1.normalizeKeyColumns)(rel.foreignKey);
|
|
344
|
+
const refs = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
|
|
345
|
+
const parentMeta = ctx.schema.tables[parentTable];
|
|
346
|
+
const relatedTable = ctx.schema.tables[rel.to];
|
|
347
|
+
let relatedRow = null;
|
|
348
|
+
if (ops.create !== undefined) {
|
|
349
|
+
const items = toArray(ops.create);
|
|
350
|
+
if (items.length > 0) {
|
|
351
|
+
relatedRow = (await executeNestedCreate(ctx, rel.to, items[0], depth + 1, [...path, relName]));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
else if (ops.connect !== undefined) {
|
|
355
|
+
const items = toArray(ops.connect);
|
|
356
|
+
if (items.length > 0) {
|
|
357
|
+
const target = items[0];
|
|
358
|
+
relatedRow = (await ctx.tx.table(rel.to).findUnique({ where: target }));
|
|
359
|
+
if (!relatedRow) {
|
|
360
|
+
throw new errors_js_1.ValidationError(`[turbine] connect on "${relName}": no ${rel.to} row found matching ${JSON.stringify(target)}.`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
else if (ops.connectOrCreate !== undefined) {
|
|
365
|
+
const items = toArray(ops.connectOrCreate);
|
|
366
|
+
if (items.length > 0) {
|
|
367
|
+
const op = items[0];
|
|
368
|
+
relatedRow = (await ctx.tx.table(rel.to).findUnique({ where: op.where }));
|
|
369
|
+
if (!relatedRow) {
|
|
370
|
+
// For belongsTo the FK lives on the parent, so the related row is
|
|
371
|
+
// created plainly (no FK injection) and we read its reference key.
|
|
372
|
+
relatedRow = (await ctx.tx.table(rel.to).create({ data: op.create }));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
const fkScalars = {};
|
|
377
|
+
if (relatedRow) {
|
|
378
|
+
for (let i = 0; i < fks.length; i++) {
|
|
379
|
+
const fkField = parentMeta.reverseColumnMap[fks[i]] ?? fks[i];
|
|
380
|
+
const refField = relatedTable?.reverseColumnMap[refs[i]] ?? refs[i];
|
|
381
|
+
fkScalars[fkField] = relatedRow[refField];
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return fkScalars;
|
|
385
|
+
}
|
|
322
386
|
async function processBelongsToCreate(ctx, rel, ops, parentRow, parentTable, depth, path, relName) {
|
|
323
387
|
const fks = (0, schema_js_1.normalizeKeyColumns)(rel.foreignKey);
|
|
324
388
|
const refs = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
|