appflare 0.2.13 → 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.
@@ -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
- references: { table: referenceTable, column: referenceField },
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: relation.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: relation.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
- expr += `.references(() => ${reference.tableName}.${reference.fieldName})`;
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 && hasColumnDefault(column.expression)) {
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
- > = Promise<
47
- Array<
48
- BuildQueryResult<
49
- SchemaRelations,
50
- TableRelationConfig<TName>,
51
- ResolveTableFindManySelection<TName, TArgs>
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
- > = Promise<
84
- BuildQueryResult<
85
- SchemaRelations,
86
- TableRelationConfig<TName>,
87
- ResolveTableFindFirstSelection<TName, TArgs>
88
- > | null
89
- >;
90
- type TableModel<TName extends TableName> = InferSelectModel<
91
- (typeof mergedSchema)[TName]
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,