appflare 0.2.14 → 0.2.15
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/cli/schema-compiler.ts +104 -8
- package/cli/templates/dashboard/builders/table-routes/helpers.ts +1 -5
- package/cli/templates/handlers/generators/types/query-definitions/schema-and-table-types.ts +23 -19
- package/cli/utils/schema-discovery.ts +1 -1
- package/dist/cli/index.js +179 -175
- package/dist/cli/index.mjs +179 -175
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/schema.ts +19 -2
package/cli/schema-compiler.ts
CHANGED
|
@@ -121,6 +121,8 @@ function ensureInferredReferenceColumn(
|
|
|
121
121
|
fkType?: ColumnType;
|
|
122
122
|
sqlName?: string;
|
|
123
123
|
notNull?: boolean;
|
|
124
|
+
onDelete?: OneRelationDefinition["onDelete"];
|
|
125
|
+
onUpdate?: OneRelationDefinition["onUpdate"];
|
|
124
126
|
},
|
|
125
127
|
inferredType: ColumnType,
|
|
126
128
|
): void {
|
|
@@ -138,7 +140,17 @@ function ensureInferredReferenceColumn(
|
|
|
138
140
|
|
|
139
141
|
table.columns[columnName] = {
|
|
140
142
|
...existing,
|
|
141
|
-
|
|
143
|
+
notNull:
|
|
144
|
+
existing.notNull ??
|
|
145
|
+
(existing.nullable === true ? false : options.notNull),
|
|
146
|
+
nullable:
|
|
147
|
+
existing.nullable ?? (options.notNull === false ? true : undefined),
|
|
148
|
+
references: {
|
|
149
|
+
table: referenceTable,
|
|
150
|
+
column: referenceField,
|
|
151
|
+
onDelete: existing.references?.onDelete ?? options.onDelete,
|
|
152
|
+
onUpdate: existing.references?.onUpdate ?? options.onUpdate,
|
|
153
|
+
},
|
|
142
154
|
};
|
|
143
155
|
return;
|
|
144
156
|
}
|
|
@@ -148,16 +160,66 @@ function ensureInferredReferenceColumn(
|
|
|
148
160
|
type: options.fkType ?? inferredType,
|
|
149
161
|
sqlName: options.sqlName,
|
|
150
162
|
notNull: options.notNull ?? true,
|
|
163
|
+
nullable: options.notNull === false ? true : undefined,
|
|
151
164
|
references: {
|
|
152
165
|
table: referenceTable,
|
|
153
166
|
column: referenceField,
|
|
167
|
+
onDelete: options.onDelete,
|
|
168
|
+
onUpdate: options.onUpdate,
|
|
154
169
|
},
|
|
155
170
|
};
|
|
156
171
|
}
|
|
157
172
|
|
|
173
|
+
function resolveNotNullFromNullableFlags(
|
|
174
|
+
fieldPath: string,
|
|
175
|
+
flags: { notNull?: boolean; nullable?: boolean },
|
|
176
|
+
defaultNotNull: boolean,
|
|
177
|
+
): boolean {
|
|
178
|
+
if (flags.notNull === true && flags.nullable === true) {
|
|
179
|
+
throw new Error(
|
|
180
|
+
`Invalid nullable configuration on '${fieldPath}': cannot set both notNull and nullable to true.`,
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (flags.notNull === true) {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (flags.nullable === true) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (flags.notNull === false) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return defaultNotNull;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function validateNullableFlags(definition: SchemaDefinition): void {
|
|
200
|
+
for (const [tableName, table] of Object.entries(definition.tables)) {
|
|
201
|
+
for (const [columnName, column] of Object.entries(table.columns)) {
|
|
202
|
+
if (column.notNull === true && column.nullable === true) {
|
|
203
|
+
throw new Error(
|
|
204
|
+
`Invalid nullable configuration on '${tableName}.${columnName}': cannot set both notNull and nullable to true.`,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
for (const [relationName, relation] of Object.entries(table.relations)) {
|
|
210
|
+
if (relation.notNull === true && relation.nullable === true) {
|
|
211
|
+
throw new Error(
|
|
212
|
+
`Invalid nullable configuration on '${tableName}.${relationName}': cannot set both notNull and nullable to true.`,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
158
219
|
function normalizeSchemaDefinition(
|
|
159
220
|
definition: SchemaDefinition,
|
|
160
221
|
): SchemaDefinition {
|
|
222
|
+
validateNullableFlags(definition);
|
|
161
223
|
const normalized = cloneSchemaDefinition(definition);
|
|
162
224
|
|
|
163
225
|
for (const [tableName, table] of Object.entries(normalized.tables)) {
|
|
@@ -188,7 +250,13 @@ function normalizeSchemaDefinition(
|
|
|
188
250
|
{
|
|
189
251
|
fkType: relation.fkType,
|
|
190
252
|
sqlName: relation.sqlName,
|
|
191
|
-
notNull:
|
|
253
|
+
notNull: resolveNotNullFromNullableFlags(
|
|
254
|
+
`${tableName}.${relationName}`,
|
|
255
|
+
relation,
|
|
256
|
+
true,
|
|
257
|
+
),
|
|
258
|
+
onDelete: relation.onDelete,
|
|
259
|
+
onUpdate: relation.onUpdate,
|
|
192
260
|
},
|
|
193
261
|
inferredType,
|
|
194
262
|
);
|
|
@@ -225,7 +293,13 @@ function normalizeSchemaDefinition(
|
|
|
225
293
|
{
|
|
226
294
|
fkType: relation.fkType,
|
|
227
295
|
sqlName: relation.sqlName,
|
|
228
|
-
notNull:
|
|
296
|
+
notNull: resolveNotNullFromNullableFlags(
|
|
297
|
+
`${sourceTableName}.${relation.targetTable}`,
|
|
298
|
+
relation,
|
|
299
|
+
true,
|
|
300
|
+
),
|
|
301
|
+
onDelete: relation.onDelete,
|
|
302
|
+
onUpdate: relation.onUpdate,
|
|
229
303
|
},
|
|
230
304
|
inferredType,
|
|
231
305
|
);
|
|
@@ -237,6 +311,7 @@ function normalizeSchemaDefinition(
|
|
|
237
311
|
|
|
238
312
|
function isOptionalInsertColumn(column: ColumnDefinition): boolean {
|
|
239
313
|
return (
|
|
314
|
+
column.primaryKey === true ||
|
|
240
315
|
column.notNull !== true ||
|
|
241
316
|
column.autoIncrement === true ||
|
|
242
317
|
column.sqlDefault !== undefined ||
|
|
@@ -388,6 +463,10 @@ function emitDrizzleSchema(
|
|
|
388
463
|
for (const [fieldName, column] of Object.entries(table.columns)) {
|
|
389
464
|
let expr = drizzleBaseColumn(fieldName, column, strategy);
|
|
390
465
|
|
|
466
|
+
if (column.uuidPrimaryKey) {
|
|
467
|
+
expr += ".$defaultFn(() => crypto.randomUUID())";
|
|
468
|
+
}
|
|
469
|
+
|
|
391
470
|
if (column.primaryKey) {
|
|
392
471
|
expr += column.autoIncrement
|
|
393
472
|
? ".primaryKey({ autoIncrement: true })"
|
|
@@ -402,7 +481,18 @@ function emitDrizzleSchema(
|
|
|
402
481
|
|
|
403
482
|
const reference = resolveColumnReference(fieldName, column, table);
|
|
404
483
|
if (reference) {
|
|
405
|
-
|
|
484
|
+
if (column.references?.onDelete || column.references?.onUpdate) {
|
|
485
|
+
const actions: string[] = [];
|
|
486
|
+
if (column.references.onDelete) {
|
|
487
|
+
actions.push(`onDelete: ${quote(column.references.onDelete)}`);
|
|
488
|
+
}
|
|
489
|
+
if (column.references.onUpdate) {
|
|
490
|
+
actions.push(`onUpdate: ${quote(column.references.onUpdate)}`);
|
|
491
|
+
}
|
|
492
|
+
expr += `.references(() => ${reference.tableName}.${reference.fieldName}, { ${actions.join(", ")} })`;
|
|
493
|
+
} else {
|
|
494
|
+
expr += `.references(() => ${reference.tableName}.${reference.fieldName})`;
|
|
495
|
+
}
|
|
406
496
|
}
|
|
407
497
|
|
|
408
498
|
if (column.unique) {
|
|
@@ -480,6 +570,7 @@ ${relationBlocks.join("\n\n")}
|
|
|
480
570
|
function zodSchemaExpression(
|
|
481
571
|
column: ColumnDefinition,
|
|
482
572
|
optional: boolean,
|
|
573
|
+
nullable: boolean,
|
|
483
574
|
): string {
|
|
484
575
|
let expr = "z.unknown()";
|
|
485
576
|
if (column.type === "int") {
|
|
@@ -499,6 +590,10 @@ function zodSchemaExpression(
|
|
|
499
590
|
expr += ".optional()";
|
|
500
591
|
}
|
|
501
592
|
|
|
593
|
+
if (nullable) {
|
|
594
|
+
expr += ".nullable()";
|
|
595
|
+
}
|
|
596
|
+
|
|
502
597
|
return expr;
|
|
503
598
|
}
|
|
504
599
|
|
|
@@ -512,10 +607,10 @@ function emitZodSchemas(definition: SchemaDefinition): string {
|
|
|
512
607
|
|
|
513
608
|
for (const [fieldName, column] of Object.entries(table.columns)) {
|
|
514
609
|
insertLines.push(
|
|
515
|
-
`\t${fieldName}: ${zodSchemaExpression(column, isOptionalInsertColumn(column))},`,
|
|
610
|
+
`\t${fieldName}: ${zodSchemaExpression(column, isOptionalInsertColumn(column), isNullableSelectColumn(column))},`,
|
|
516
611
|
);
|
|
517
612
|
selectLines.push(
|
|
518
|
-
`\t${fieldName}: ${zodSchemaExpression(column, isNullableSelectColumn(column))},`,
|
|
613
|
+
`\t${fieldName}: ${zodSchemaExpression(column, isNullableSelectColumn(column), isNullableSelectColumn(column))},`,
|
|
519
614
|
);
|
|
520
615
|
}
|
|
521
616
|
|
|
@@ -558,11 +653,12 @@ function emitTypes(definition: SchemaDefinition): string {
|
|
|
558
653
|
|
|
559
654
|
for (const [fieldName, column] of Object.entries(table.columns)) {
|
|
560
655
|
const tsType = toTypeScriptType(column);
|
|
656
|
+
const nullableSuffix = isNullableSelectColumn(column) ? " | null" : "";
|
|
561
657
|
selectFields.push(
|
|
562
|
-
`\t${fieldName}${isNullableSelectColumn(column) ? "?" : ""}: ${tsType};`,
|
|
658
|
+
`\t${fieldName}${isNullableSelectColumn(column) ? "?" : ""}: ${tsType}${nullableSuffix};`,
|
|
563
659
|
);
|
|
564
660
|
insertFields.push(
|
|
565
|
-
`\t${fieldName}${isOptionalInsertColumn(column) ? "?" : ""}: ${tsType};`,
|
|
661
|
+
`\t${fieldName}${isOptionalInsertColumn(column) ? "?" : ""}: ${tsType}${nullableSuffix};`,
|
|
566
662
|
);
|
|
567
663
|
}
|
|
568
664
|
|
|
@@ -8,10 +8,6 @@ export function resolvePrimaryKey(table: DiscoveredTable): string {
|
|
|
8
8
|
);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
function hasColumnDefault(expression: string): boolean {
|
|
12
|
-
return /\.default\s*\(/i.test(expression);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
11
|
export function shouldIncludeCreateField(
|
|
16
12
|
table: DiscoveredTable,
|
|
17
13
|
columnName: string,
|
|
@@ -25,7 +21,7 @@ export function shouldIncludeCreateField(
|
|
|
25
21
|
return false;
|
|
26
22
|
}
|
|
27
23
|
|
|
28
|
-
if (column.primaryKey
|
|
24
|
+
if (column.primaryKey) {
|
|
29
25
|
return false;
|
|
30
26
|
}
|
|
31
27
|
|
|
@@ -38,20 +38,25 @@ type ResolveTableFindManySelection<
|
|
|
38
38
|
(ResolveNativeFindManyWith<TName, TArgs> extends never
|
|
39
39
|
? {}
|
|
40
40
|
: { with: ResolveNativeFindManyWith<TName, TArgs> });
|
|
41
|
+
type TableModel<TName extends TableName> = InferSelectModel<
|
|
42
|
+
(typeof mergedSchema)[TName]
|
|
43
|
+
>;
|
|
41
44
|
type TableFindManyResult<
|
|
42
45
|
TName extends TableName,
|
|
43
46
|
TArgs extends QueryFindManyArgs<TName> | undefined =
|
|
44
47
|
| QueryFindManyArgs<TName>
|
|
45
48
|
| undefined,
|
|
46
|
-
> =
|
|
47
|
-
Array<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
> = TArgs extends undefined
|
|
50
|
+
? Promise<Array<TableModel<TName>>>
|
|
51
|
+
: Promise<
|
|
52
|
+
Array<
|
|
53
|
+
BuildQueryResult<
|
|
54
|
+
SchemaRelations,
|
|
55
|
+
TableRelationConfig<TName>,
|
|
56
|
+
ResolveTableFindManySelection<TName, TArgs>
|
|
57
|
+
>
|
|
58
|
+
>
|
|
59
|
+
>;
|
|
55
60
|
type TableFindFirstArgs<TName extends TableName> = Omit<
|
|
56
61
|
TableFindManyArgs<TName>,
|
|
57
62
|
"limit"
|
|
@@ -80,16 +85,15 @@ type TableFindFirstResult<
|
|
|
80
85
|
TArgs extends QueryFindFirstArgs<TName> | undefined =
|
|
81
86
|
| QueryFindFirstArgs<TName>
|
|
82
87
|
| undefined,
|
|
83
|
-
> =
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
>;
|
|
88
|
+
> = TArgs extends undefined
|
|
89
|
+
? Promise<TableModel<TName> | null>
|
|
90
|
+
: Promise<
|
|
91
|
+
BuildQueryResult<
|
|
92
|
+
SchemaRelations,
|
|
93
|
+
TableRelationConfig<TName>,
|
|
94
|
+
ResolveTableFindFirstSelection<TName, TArgs>
|
|
95
|
+
> | null
|
|
96
|
+
>;
|
|
93
97
|
type TableInsertModel<TName extends TableName> = InferInsertModel<
|
|
94
98
|
(typeof mergedSchema)[TName]
|
|
95
99
|
>;
|
|
@@ -235,7 +235,7 @@ function discoverColumns(rawColumns: string): DiscoveredColumn[] {
|
|
|
235
235
|
const autoIncrement = /autoincrement\s*:\s*true/i.test(expression);
|
|
236
236
|
const hasDefault = /\.default\s*\(/i.test(expression);
|
|
237
237
|
const notNull = /\.notnull\s*\(/i.test(expression);
|
|
238
|
-
const optional = !notNull || hasDefault || autoIncrement;
|
|
238
|
+
const optional = !notNull || hasDefault || autoIncrement || primaryKey;
|
|
239
239
|
|
|
240
240
|
columns.push({
|
|
241
241
|
name: key,
|