@dudousxd/nestjs-codegen 0.23.0 → 0.24.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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @dudousxd/nestjs-codegen
2
2
 
3
+ ## 0.24.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c8d7eec: A mapped column's two declared types can disagree, so both are now emitted.
8
+
9
+ **If you upgraded to 0.23.0, you were affected** wherever an entity declares a mapped column — `@Property({ columnType: 'date', type: DateType }) x?: Opt<string>`, or a DECIMAL read back as a string. Those fields kept being emitted, but with the wrong kind, so every union a client derives from it rejected them: `.lt('serviceEndDate', …)` stopped compiling on a column that had been orderable all along.
10
+
11
+ The cause was the brand unwrapping itself. `classifyFieldType` consults the column decorator ONLY when the TS type resolves to `unknown` — so before 0.23.0 an `Opt<string>` fell through to `columnType: 'date'` and classified `date`, correctly and by accident. Making the TS side resolve meant the decorator was never reached.
12
+
13
+ The fix is not to pick a winner, because both are true and each is needed for a different question. `kind` now carries what the COLUMN is — the semantics an operator set derives from — and a new optional `valueKind` carries what the VALUE is, when they differ. A DATE column read back as `'YYYY-MM-DD'` emits `kind: 'date'` and `valueKind: 'string'`.
14
+
15
+ Collapsing them loses one or the other. Answer `string` and the field stops accepting the ordering and range operators the column supports. Answer `date` and the emitted type promises a `Date` the value never holds — which a type-preserving wire format like superjson then contradicts at runtime, since it faithfully transports the string that is actually there. That second failure predates 0.23.0 and is fixed here too: these columns used to emit as `Date` while carrying a string.
16
+
17
+ `valueKind` is absent when the two agree, which is the overwhelming majority of columns, so nothing changes for them.
18
+
19
+ Also teaches the decorator reader `columnType` (MikroORM's raw DDL slot) alongside `type`, and a mapped-type class (`type: DateType`) alongside a keyword string. It read neither, which is why the conflict was invisible from that side.
20
+
3
21
  ## 0.23.0
4
22
 
5
23
  ### Minor Changes
package/dist/cli/main.cjs CHANGED
@@ -1503,12 +1503,19 @@ function classifyFromColumnDecorator(prop, sourceFile, project) {
1503
1503
  return { kind: "string" };
1504
1504
  }
1505
1505
  }
1506
- const typeProp = arg.getProperty("type");
1507
- if (typeProp && import_ts_morph4.Node.isPropertyAssignment(typeProp)) {
1506
+ for (const key of ["columnType", "type"]) {
1507
+ const typeProp = arg.getProperty(key);
1508
+ if (!typeProp || !import_ts_morph4.Node.isPropertyAssignment(typeProp)) continue;
1508
1509
  const init = typeProp.getInitializer();
1509
- if (init && import_ts_morph4.Node.isStringLiteral(init)) {
1510
+ if (!init) continue;
1511
+ if (import_ts_morph4.Node.isStringLiteral(init)) {
1510
1512
  const kind = classifyTypeKeyword(init.getLiteralValue());
1511
1513
  if (kind) return { kind };
1514
+ continue;
1515
+ }
1516
+ if (import_ts_morph4.Node.isIdentifier(init)) {
1517
+ const kind = classifyTypeKeyword(init.getText());
1518
+ if (kind) return { kind };
1512
1519
  }
1513
1520
  }
1514
1521
  }
@@ -1520,12 +1527,18 @@ function classifyFromColumnDecorator(prop, sourceFile, project) {
1520
1527
  function classifyFieldType(prop, sourceFile, project) {
1521
1528
  let nullable = prop.hasQuestionToken();
1522
1529
  const typeNode = prop.getTypeNode();
1530
+ const fromDecorator = classifyFromColumnDecorator(prop, sourceFile, project);
1523
1531
  if (typeNode) {
1524
1532
  const r = classifyTypeNode(typeNode, sourceFile, project);
1525
1533
  if (r.nullable) nullable = true;
1526
- if (r.kind !== "unknown") return markNullable(r, nullable);
1534
+ if (r.kind !== "unknown") {
1535
+ const conflicts = fromDecorator !== null && fromDecorator.kind !== "unknown" && fromDecorator.kind !== r.kind;
1536
+ if (conflicts) {
1537
+ return markNullable({ ...fromDecorator, valueKind: r.kind }, nullable);
1538
+ }
1539
+ return markNullable(r, nullable);
1540
+ }
1527
1541
  }
1528
- const fromDecorator = classifyFromColumnDecorator(prop, sourceFile, project);
1529
1542
  if (fromDecorator) {
1530
1543
  return markNullable(fromDecorator, nullable || fromDecorator.nullable === true);
1531
1544
  }
@@ -1533,6 +1546,7 @@ function classifyFieldType(prop, sourceFile, project) {
1533
1546
  }
1534
1547
  function toFilterFieldType(name, r) {
1535
1548
  const ft = { name, kind: r.kind };
1549
+ if (r.valueKind && r.valueKind !== r.kind) ft.valueKind = r.valueKind;
1536
1550
  if (r.enumValues && r.enumValues.length > 0) ft.enumValues = r.enumValues;
1537
1551
  if (r.nullable) ft.nullable = true;
1538
1552
  if (r.numericEnum) ft.numericEnum = true;
@@ -3338,7 +3352,7 @@ function kindToTs(kind, enumValues, numericEnum) {
3338
3352
  }
3339
3353
  function emitFieldTypesLiteral(fts) {
3340
3354
  const entries = fts.map((f) => {
3341
- let t = f.typeRef ? f.typeRef.name : kindToTs(f.kind, f.enumValues, f.numericEnum);
3355
+ let t = f.typeRef ? f.typeRef.name : kindToTs(f.valueKind ?? f.kind, f.enumValues, f.numericEnum);
3342
3356
  if (f.nullable) t = `${t} | null`;
3343
3357
  return `${JSON.stringify(f.name)}: ${t}`;
3344
3358
  });
@@ -5259,7 +5273,7 @@ async function watch(config, onChange, options = {}) {
5259
5273
  }
5260
5274
 
5261
5275
  // src/index.ts
5262
- var VERSION = "0.23.0";
5276
+ var VERSION = "0.24.0";
5263
5277
 
5264
5278
  // src/cli/codegen.ts
5265
5279
  async function runCodegen(opts = {}) {