@deterministic-code/datasources-cli 0.1.5 → 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.
Files changed (25) hide show
  1. package/node_modules/@deterministic-code/csharp-generators/dist/deterministic-type-converter.js +30 -0
  2. package/node_modules/@deterministic-code/csharp-generators/dist/generate-datasource-types.js +6 -2
  3. package/node_modules/@deterministic-code/csharp-generators/dist/generate-view-types.js +6 -2
  4. package/node_modules/@deterministic-code/csharp-generators/dist/templates/create-backend-app/csharp/App/App.csproj.tmpl +1 -0
  5. package/node_modules/@deterministic-code/csharp-generators/dist/templates/create-datasource-types/type.cs.tmpl +1 -1
  6. package/node_modules/@deterministic-code/csharp-generators/dist/templates/create-view-types/type.cs.tmpl +1 -1
  7. package/node_modules/@deterministic-code/csharp-generators/src/deterministic-type-converter.ts +41 -1
  8. package/node_modules/@deterministic-code/csharp-generators/src/generate-datasource-types.ts +7 -2
  9. package/node_modules/@deterministic-code/csharp-generators/src/generate-view-types.ts +8 -3
  10. package/node_modules/@deterministic-code/csharp-generators/src/templates/create-backend-app/csharp/App/App.csproj.tmpl +1 -0
  11. package/node_modules/@deterministic-code/csharp-generators/src/templates/create-datasource-types/type.cs.tmpl +1 -1
  12. package/node_modules/@deterministic-code/csharp-generators/src/templates/create-view-types/type.cs.tmpl +1 -1
  13. package/node_modules/@deterministic-code/datasources-code-generators/package.json +7 -7
  14. package/node_modules/@deterministic-code/deterministic-specifications-typescript/typescript/parser/parser/specification-parser.ts +7 -4
  15. package/node_modules/@deterministic-code/deterministic-specifications-typescript/typescript/parser/specification.ts +1 -1
  16. package/node_modules/@deterministic-code/deterministic-specifications-typescript/typescript/parser/yaml-node.ts +12 -0
  17. package/node_modules/@deterministic-code/rust-generators/dist/deterministic-type-converter.js +3 -0
  18. package/node_modules/@deterministic-code/rust-generators/dist/generate-view-types.js +1 -1
  19. package/node_modules/@deterministic-code/rust-generators/src/deterministic-type-converter.ts +8 -1
  20. package/node_modules/@deterministic-code/rust-generators/src/generate-view-types.ts +5 -3
  21. package/node_modules/@deterministic-code/typescript-generators/dist/deterministic-type-converter.js +9 -0
  22. package/node_modules/@deterministic-code/typescript-generators/dist/emit-shaped-types.js +7 -3
  23. package/node_modules/@deterministic-code/typescript-generators/src/deterministic-type-converter.ts +19 -1
  24. package/node_modules/@deterministic-code/typescript-generators/src/emit-shaped-types.ts +9 -4
  25. package/package.json +8 -8
@@ -105,8 +105,36 @@ const isCsZero = (specType, expr) => {
105
105
  if (CS_NUMERIC.has(native)) return /^0(\.0+)?$/.test(expr);
106
106
  return false;
107
107
  };
108
+ const CS_VALUE_TYPES = /* @__PURE__ */ new Set([
109
+ "bool",
110
+ "byte",
111
+ "sbyte",
112
+ "short",
113
+ "ushort",
114
+ "int",
115
+ "uint",
116
+ "long",
117
+ "ulong",
118
+ "float",
119
+ "double",
120
+ "decimal",
121
+ "DateTime",
122
+ "Guid"
123
+ ]);
124
+ const isCsValueType = (csType) => {
125
+ const t = csType.endsWith("?") ? csType.slice(0, -1) : csType;
126
+ return CS_VALUE_TYPES.has(t.slice(t.lastIndexOf(".") + 1));
127
+ };
128
+ const collectionDefaultExpr = (field) => {
129
+ if (!field.isArray && field.isMap !== true) return void 0;
130
+ if (field.isNullable && field.defaultValue === null) return void 0;
131
+ return "[]";
132
+ };
108
133
  const nativeDefaultExpr = (specType, field) => {
109
134
  if (field.hasDefault !== true) return void 0;
135
+ if (field.defaultValue === null || Array.isArray(field.defaultValue) || typeof field.defaultValue === "object" && field.defaultValue !== null) {
136
+ return void 0;
137
+ }
110
138
  const expr = defaultValueConverter.convert(
111
139
  specType,
112
140
  String(field.defaultValue)
@@ -116,8 +144,10 @@ const nativeDefaultExpr = (specType, field) => {
116
144
  return isCsZero(specType, expr) ? void 0 : expr;
117
145
  };
118
146
  export {
147
+ collectionDefaultExpr,
119
148
  convertSpecType,
120
149
  defaultValueConverter,
150
+ isCsValueType,
121
151
  nativeDefaultExpr,
122
152
  toNative,
123
153
  typeConverter
@@ -15,7 +15,9 @@ import {
15
15
  withClassParents
16
16
  } from "./common/view-shape.js";
17
17
  import {
18
+ collectionDefaultExpr,
18
19
  convertSpecType,
20
+ isCsValueType,
19
21
  nativeDefaultExpr
20
22
  } from "./deterministic-type-converter.js";
21
23
  import { Emit } from "./emit.js";
@@ -39,10 +41,12 @@ class Generator extends Emit {
39
41
  const { schemaVersion, simpleDoc, descriptionDoc } = this.settings;
40
42
  const parent = classParent(table, "datasource", typesByName);
41
43
  const fields = declaredFields(table, "datasource", typesByName).map((f) => {
42
- const initializer = nativeDefaultExpr(fieldTypeOf(f, typesByName), f);
44
+ const csType = csTypeFor(f, typesByName);
45
+ const initializer = collectionDefaultExpr(f) ?? nativeDefaultExpr(fieldTypeOf(f, typesByName), f);
43
46
  return {
44
47
  ident: this.casing.convertFields(f.name),
45
- csType: csTypeFor(f, typesByName),
48
+ csType,
49
+ required: !f.isNullable && initializer === void 0 && !isCsValueType(csType),
46
50
  hasInitializer: initializer !== void 0,
47
51
  initializer: initializer ?? ""
48
52
  };
@@ -18,7 +18,9 @@ import {
18
18
  typeHasTag
19
19
  } from "./specification-parser.js";
20
20
  import {
21
+ collectionDefaultExpr,
21
22
  convertSpecType,
23
+ isCsValueType,
22
24
  nativeDefaultExpr
23
25
  } from "./deterministic-type-converter.js";
24
26
  import { Emit } from "./emit.js";
@@ -59,10 +61,12 @@ class Generator extends Emit {
59
61
  const isUnion = isUnionLike(view);
60
62
  const parent = classParent(view, "view", typesByName);
61
63
  const fields = declaredFields(view, "view", typesByName).map((f) => {
62
- const initializer = f.kind === "primitive" ? nativeDefaultExpr(fieldTypeOf(f, typesByName), f) : void 0;
64
+ const csType = this.csTypeFor(f, typesByName);
65
+ const initializer = collectionDefaultExpr(f) ?? (f.kind === "primitive" ? nativeDefaultExpr(fieldTypeOf(f, typesByName), f) : void 0);
63
66
  return {
64
67
  ident: this.casing.convertFields(f.name),
65
- csType: this.csTypeFor(f, typesByName),
68
+ csType,
69
+ required: !f.isNullable && initializer === void 0 && !isCsValueType(csType),
66
70
  hasInitializer: initializer !== void 0,
67
71
  initializer: initializer ?? ""
68
72
  };
@@ -6,6 +6,7 @@
6
6
  <AssemblyName>{{PROJECT_NAME}}</AssemblyName>
7
7
  <LangVersion>latest</LangVersion>
8
8
  <Nullable>enable</Nullable>
9
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
9
10
  <ImplicitUsings>enable</ImplicitUsings>
10
11
  <IsPackable>false</IsPackable>
11
12
  <!-- MigrateRunner/ (single-lang) and migrate/ (multi-lang) are sibling projects (see create-migrate-scripts.mjs); both excluded so the app's autoglob doesn't pull in their sources and trip on CS8802 (two top-level Program.cs) plus CS0234/CS0246 for MySqlConnector/Npgsql/Microsoft.Data (those packages are declared in MigrateRunner.csproj, not here). -->
@@ -10,6 +10,6 @@ namespace Backend.Types.Datasource;
10
10
  {{/descriptionDoc}}public class {{className}}{{#hasExtends}} : {{&extendsType}}{{/hasExtends}}
11
11
  {
12
12
  {{#fields}}
13
- public {{csType}} {{ident}} { get; set; }{{#hasInitializer}} = {{&initializer}};{{/hasInitializer}}
13
+ public {{#required}}required {{/required}}{{csType}} {{ident}} { get; set; }{{#hasInitializer}} = {{&initializer}};{{/hasInitializer}}
14
14
  {{/fields}}
15
15
  }
@@ -15,6 +15,6 @@ namespace Backend.Types.View;
15
15
  {{/descriptionDoc}}public class {{className}}{{#hasExtends}} : {{&extendsType}}{{/hasExtends}}
16
16
  {
17
17
  {{#fields}}
18
- public {{&csType}} {{ident}} { get; set; }{{#hasInitializer}} = {{&initializer}};{{/hasInitializer}}
18
+ public {{#required}}required {{/required}}{{&csType}} {{ident}} { get; set; }{{#hasInitializer}} = {{&initializer}};{{/hasInitializer}}
19
19
  {{/fields}}
20
20
  }
@@ -124,16 +124,56 @@ const isCsZero = (specType: string, expr: string): boolean => {
124
124
  return false;
125
125
  };
126
126
 
127
+ const CS_VALUE_TYPES = new Set([
128
+ "bool",
129
+ "byte",
130
+ "sbyte",
131
+ "short",
132
+ "ushort",
133
+ "int",
134
+ "uint",
135
+ "long",
136
+ "ulong",
137
+ "float",
138
+ "double",
139
+ "decimal",
140
+ "DateTime",
141
+ "Guid",
142
+ ]);
143
+
144
+ export const isCsValueType = (csType: string): boolean => {
145
+ const t = csType.endsWith("?") ? csType.slice(0, -1) : csType;
146
+ return CS_VALUE_TYPES.has(t.slice(t.lastIndexOf(".") + 1));
147
+ };
148
+
149
+ export const collectionDefaultExpr = (field: {
150
+ isArray: boolean;
151
+ isMap?: boolean;
152
+ isNullable: boolean;
153
+ defaultValue?: string | number | boolean | null | readonly [] | object;
154
+ }): string | undefined => {
155
+ if (!field.isArray && field.isMap !== true) return undefined;
156
+ if (field.isNullable && field.defaultValue === null) return undefined;
157
+ return "[]";
158
+ };
159
+
127
160
  /** Native initializer, or `undefined` when absent or the language zero. */
128
161
  export const nativeDefaultExpr = (
129
162
  specType: string,
130
163
  field: {
131
164
  hasDefault?: boolean;
132
- defaultValue?: string | number | boolean | null;
165
+ defaultValue?: string | number | boolean | null | readonly [] | object;
133
166
  isNullable: boolean;
134
167
  },
135
168
  ): string | undefined => {
136
169
  if (field.hasDefault !== true) return undefined;
170
+ if (
171
+ field.defaultValue === null ||
172
+ Array.isArray(field.defaultValue) ||
173
+ (typeof field.defaultValue === "object" && field.defaultValue !== null)
174
+ ) {
175
+ return undefined;
176
+ }
137
177
  const expr = defaultValueConverter.convert(
138
178
  specType,
139
179
  String(field.defaultValue),
@@ -19,7 +19,9 @@ import {
19
19
  withClassParents,
20
20
  } from "./common/view-shape.ts";
21
21
  import {
22
+ collectionDefaultExpr,
22
23
  convertSpecType,
24
+ isCsValueType,
23
25
  nativeDefaultExpr,
24
26
  } from "./deterministic-type-converter.ts";
25
27
  import { Emit } from "./emit.ts";
@@ -49,10 +51,13 @@ class Generator extends Emit {
49
51
  const { schemaVersion, simpleDoc, descriptionDoc } = this.settings;
50
52
  const parent = classParent(table, "datasource", typesByName);
51
53
  const fields = declaredFields(table, "datasource", typesByName).map((f) => {
52
- const initializer = nativeDefaultExpr(fieldTypeOf(f, typesByName), f);
54
+ const csType = csTypeFor(f, typesByName);
55
+ const initializer =
56
+ collectionDefaultExpr(f) ?? nativeDefaultExpr(fieldTypeOf(f, typesByName), f);
53
57
  return {
54
58
  ident: this.casing.convertFields(f.name),
55
- csType: csTypeFor(f, typesByName),
59
+ csType,
60
+ required: !f.isNullable && initializer === undefined && !isCsValueType(csType),
56
61
  hasInitializer: initializer !== undefined,
57
62
  initializer: initializer ?? "",
58
63
  };
@@ -22,7 +22,9 @@ import {
22
22
  type TypeField,
23
23
  } from "./specification-parser.ts";
24
24
  import {
25
+ collectionDefaultExpr,
25
26
  convertSpecType,
27
+ isCsValueType,
26
28
  nativeDefaultExpr,
27
29
  } from "./deterministic-type-converter.ts";
28
30
  import { Emit } from "./emit.ts";
@@ -75,13 +77,16 @@ class Generator extends Emit {
75
77
  const isUnion = isUnionLike(view);
76
78
  const parent = classParent(view, "view", typesByName);
77
79
  const fields = declaredFields(view, "view", typesByName).map((f) => {
80
+ const csType = this.csTypeFor(f, typesByName);
78
81
  const initializer =
79
- f.kind === "primitive"
82
+ collectionDefaultExpr(f) ??
83
+ (f.kind === "primitive"
80
84
  ? nativeDefaultExpr(fieldTypeOf(f, typesByName), f)
81
- : undefined;
85
+ : undefined);
82
86
  return {
83
87
  ident: this.casing.convertFields(f.name),
84
- csType: this.csTypeFor(f, typesByName),
88
+ csType,
89
+ required: !f.isNullable && initializer === undefined && !isCsValueType(csType),
85
90
  hasInitializer: initializer !== undefined,
86
91
  initializer: initializer ?? "",
87
92
  };
@@ -6,6 +6,7 @@
6
6
  <AssemblyName>{{PROJECT_NAME}}</AssemblyName>
7
7
  <LangVersion>latest</LangVersion>
8
8
  <Nullable>enable</Nullable>
9
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
9
10
  <ImplicitUsings>enable</ImplicitUsings>
10
11
  <IsPackable>false</IsPackable>
11
12
  <!-- MigrateRunner/ (single-lang) and migrate/ (multi-lang) are sibling projects (see create-migrate-scripts.mjs); both excluded so the app's autoglob doesn't pull in their sources and trip on CS8802 (two top-level Program.cs) plus CS0234/CS0246 for MySqlConnector/Npgsql/Microsoft.Data (those packages are declared in MigrateRunner.csproj, not here). -->
@@ -10,6 +10,6 @@ namespace Backend.Types.Datasource;
10
10
  {{/descriptionDoc}}public class {{className}}{{#hasExtends}} : {{&extendsType}}{{/hasExtends}}
11
11
  {
12
12
  {{#fields}}
13
- public {{csType}} {{ident}} { get; set; }{{#hasInitializer}} = {{&initializer}};{{/hasInitializer}}
13
+ public {{#required}}required {{/required}}{{csType}} {{ident}} { get; set; }{{#hasInitializer}} = {{&initializer}};{{/hasInitializer}}
14
14
  {{/fields}}
15
15
  }
@@ -15,6 +15,6 @@ namespace Backend.Types.View;
15
15
  {{/descriptionDoc}}public class {{className}}{{#hasExtends}} : {{&extendsType}}{{/hasExtends}}
16
16
  {
17
17
  {{#fields}}
18
- public {{&csType}} {{ident}} { get; set; }{{#hasInitializer}} = {{&initializer}};{{/hasInitializer}}
18
+ public {{#required}}required {{/required}}{{&csType}} {{ident}} { get; set; }{{#hasInitializer}} = {{&initializer}};{{/hasInitializer}}
19
19
  {{/fields}}
20
20
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deterministic-code/datasources-code-generators",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dist/generateSql.js",
@@ -10,12 +10,12 @@
10
10
  "./sql/dialect-converters": "./dist/sql/dialect-converters.js"
11
11
  },
12
12
  "dependencies": {
13
- "@deterministic-code/datasources": "^0.1.5",
14
- "@deterministic-code/datasources-mysql": "^0.1.5",
15
- "@deterministic-code/datasources-oracle": "^0.1.5",
16
- "@deterministic-code/datasources-postgres": "^0.1.5",
17
- "@deterministic-code/datasources-sqlite": "^0.1.5",
18
- "@deterministic-code/datasources-sqlserver": "^0.1.5",
13
+ "@deterministic-code/datasources": "^0.1.6",
14
+ "@deterministic-code/datasources-mysql": "^0.1.6",
15
+ "@deterministic-code/datasources-oracle": "^0.1.6",
16
+ "@deterministic-code/datasources-postgres": "^0.1.6",
17
+ "@deterministic-code/datasources-sqlite": "^0.1.6",
18
+ "@deterministic-code/datasources-sqlserver": "^0.1.6",
19
19
  "@deterministic-code/deterministic-generators-common": "0.1.0",
20
20
  "@deterministic-code/generators-common": "0.0.1",
21
21
  "pluralize": "^8.0.0",
@@ -178,7 +178,7 @@ class Parser {
178
178
  }
179
179
 
180
180
  async parse(
181
- settings: Record<string, string>,
181
+ _settings: Record<string, string>,
182
182
  opts?: { serviceClassName?: (entity: string) => string },
183
183
  ): Promise<IDeterministic> {
184
184
  const reader = this.#reader;
@@ -284,6 +284,7 @@ class Parser {
284
284
  const references = referencesOf(node);
285
285
  const size = sizeOf(node);
286
286
  const minSize = node.finiteInt("min_size");
287
+ const collectionDefault = parsed.isArray ? [] : parsed.isMap ? {} : undefined;
287
288
  return {
288
289
  name,
289
290
  type: rawType,
@@ -297,8 +298,10 @@ class Parser {
297
298
  ...(minSize !== undefined ? { minSize } : {}),
298
299
  ...(references !== undefined ? { references } : {}),
299
300
  ...(node.has("default_value")
300
- ? { hasDefault: true, defaultValue: node.literal("default_value") }
301
- : {}),
301
+ ? { hasDefault: true, defaultValue: node.fieldDefault("default_value") }
302
+ : collectionDefault !== undefined
303
+ ? { hasDefault: true, defaultValue: collectionDefault }
304
+ : {}),
302
305
  };
303
306
  }
304
307
 
@@ -837,7 +840,7 @@ class Parser {
837
840
 
838
841
  #extractCustomRoutes(
839
842
  root: YamlNode,
840
- dsByName: Map<string, DatasourceTable>,
843
+ _dsByName: Map<string, DatasourceTable>,
841
844
  typeByName: Map<string, Type>,
842
845
  ): CustomRouteEntry[] {
843
846
  const customs: CustomRouteEntry[] = [];
@@ -21,7 +21,7 @@ export type TypeField = {
21
21
  minSize?: number;
22
22
  references?: string | [string, string];
23
23
  hasDefault?: boolean;
24
- defaultValue?: string | number | boolean | null;
24
+ defaultValue?: string | number | boolean | null | object;
25
25
  };
26
26
 
27
27
  /** Primary label. `inherit` may also carry `union` — those members compose. */
@@ -3,6 +3,7 @@ import { parse } from "yaml";
3
3
  type YamlLiteral = string | number | boolean | null;
4
4
  type YamlMap = { readonly [key: string]: YamlValue };
5
5
  type YamlValue = YamlLiteral | YamlValue[] | YamlMap;
6
+ type FieldDefault = YamlLiteral | YamlValue[] | YamlMap;
6
7
  type Named = { name: string; node: YamlNode };
7
8
 
8
9
  const isMap = (v: YamlValue | undefined): v is YamlMap =>
@@ -16,12 +17,21 @@ const isFiniteNumber = (v: YamlValue | undefined): v is number =>
16
17
  const isFiniteInt = (v: YamlValue | undefined): v is number =>
17
18
  isFiniteNumber(v) && Number.isInteger(v);
18
19
 
20
+ const isEmptyList = (v: YamlValue | undefined): v is YamlValue[] =>
21
+ Array.isArray(v) && v.length === 0;
22
+
23
+ const isEmptyMap = (v: YamlValue | undefined): v is YamlMap =>
24
+ isMap(v) && Object.keys(v).length === 0;
25
+
19
26
  const isLiteral = (v: YamlValue | undefined): v is YamlLiteral =>
20
27
  v === null ||
21
28
  typeof v === "string" ||
22
29
  typeof v === "number" ||
23
30
  typeof v === "boolean";
24
31
 
32
+ const isFieldDefault = (v: YamlValue | undefined): v is FieldDefault =>
33
+ isLiteral(v) || isEmptyList(v) || isEmptyMap(v);
34
+
25
35
  /** Typed cursor over a YAML value. Missing keys are empty nodes, not throws. */
26
36
  export type YamlNode = {
27
37
  readonly value: YamlValue | undefined;
@@ -34,6 +44,7 @@ export type YamlNode = {
34
44
  finiteNumber: (key: string) => number | undefined;
35
45
  finiteInt: (key: string) => number | undefined;
36
46
  literal: (key: string) => YamlLiteral | undefined;
47
+ fieldDefault: (key: string) => FieldDefault | undefined;
37
48
  strings: (key: string) => string[];
38
49
  items: () => YamlNode[];
39
50
  namedItems: () => Named[];
@@ -66,6 +77,7 @@ const yamlNode = (value: YamlValue | undefined, path = "$"): YamlNode => {
66
77
  finiteNumber: pick(isFiniteNumber),
67
78
  finiteInt: pick(isFiniteInt),
68
79
  literal: pick(isLiteral),
80
+ fieldDefault: pick(isFieldDefault),
69
81
  strings: (key) => {
70
82
  const v = at(key);
71
83
  return Array.isArray(v) ? v.filter(isString) : [];
@@ -101,6 +101,9 @@ const convertSpecType = toNative;
101
101
  const isRustZeroExpr = (expr) => expr === "false" || expr === "0" || expr === "0.0" || expr === "String::new()" || expr === 'String::from("")' || expr === "vec![]" || expr === "None";
102
102
  const rustSpecDefaultExpr = (specType, field) => {
103
103
  if (field.hasDefault !== true) return void 0;
104
+ if (field.defaultValue === null || Array.isArray(field.defaultValue) || typeof field.defaultValue === "object" && field.defaultValue !== null) {
105
+ return void 0;
106
+ }
104
107
  const expr = defaultValueConverter.convert(
105
108
  specType,
106
109
  String(field.defaultValue)
@@ -68,7 +68,7 @@ class Generator extends Emit {
68
68
  }
69
69
  fieldToken(field) {
70
70
  const rustType = this.rustTypeFor(field);
71
- const specExpr = field.kind === "primitive" ? rustSpecDefaultExpr(fieldTypeOf(field, this.typesByName), field) : void 0;
71
+ const specExpr = field.isArray || field.isMap === true ? void 0 : field.kind === "primitive" ? rustSpecDefaultExpr(fieldTypeOf(field, this.typesByName), field) : void 0;
72
72
  return {
73
73
  ident: this.casing.convertFields(field.name),
74
74
  rustType,
@@ -130,11 +130,18 @@ export const rustSpecDefaultExpr = (
130
130
  specType: string,
131
131
  field: {
132
132
  hasDefault?: boolean;
133
- defaultValue?: string | number | boolean | null;
133
+ defaultValue?: string | number | boolean | null | readonly [] | object;
134
134
  isNullable: boolean;
135
135
  },
136
136
  ): string | undefined => {
137
137
  if (field.hasDefault !== true) return undefined;
138
+ if (
139
+ field.defaultValue === null ||
140
+ Array.isArray(field.defaultValue) ||
141
+ (typeof field.defaultValue === "object" && field.defaultValue !== null)
142
+ ) {
143
+ return undefined;
144
+ }
138
145
  const expr = defaultValueConverter.convert(
139
146
  specType,
140
147
  String(field.defaultValue),
@@ -83,9 +83,11 @@ class Generator extends Emit {
83
83
  private fieldToken(field: TypeField) {
84
84
  const rustType = this.rustTypeFor(field);
85
85
  const specExpr =
86
- field.kind === "primitive"
87
- ? rustSpecDefaultExpr(fieldTypeOf(field, this.typesByName), field)
88
- : undefined;
86
+ field.isArray || field.isMap === true
87
+ ? undefined
88
+ : field.kind === "primitive"
89
+ ? rustSpecDefaultExpr(fieldTypeOf(field, this.typesByName), field)
90
+ : undefined;
89
91
  return {
90
92
  ident: this.casing.convertFields(field.name),
91
93
  rustType,
@@ -92,8 +92,16 @@ const defaultValueConverter = new DeterministicDefaultValueConverter({
92
92
  });
93
93
  const toNative = (specType) => typeConverter.convert(specType);
94
94
  const isTsZeroExpr = (expr) => expr === "false" || expr === "0" || expr === '""';
95
+ const collectionDefaultExpr = (field) => {
96
+ if (!field.isArray && field.isMap !== true) return void 0;
97
+ if (field.isNullable && field.defaultValue === null) return void 0;
98
+ return field.isMap === true ? "{}" : "[]";
99
+ };
95
100
  const nativeDefaultExpr = (specType, field) => {
96
101
  if (field.hasDefault !== true) return void 0;
102
+ if (field.defaultValue === null || Array.isArray(field.defaultValue) || typeof field.defaultValue === "object" && field.defaultValue !== null) {
103
+ return void 0;
104
+ }
97
105
  const expr = defaultValueConverter.convert(
98
106
  specType,
99
107
  String(field.defaultValue)
@@ -103,6 +111,7 @@ const nativeDefaultExpr = (specType, field) => {
103
111
  return isTsZeroExpr(expr) ? void 0 : expr;
104
112
  };
105
113
  export {
114
+ collectionDefaultExpr,
106
115
  defaultValueConverter,
107
116
  nativeDefaultExpr,
108
117
  toNative,
@@ -17,7 +17,11 @@ import {
17
17
  import {
18
18
  DeterministicParser
19
19
  } from "@deterministic-code/deterministic-generators-common/parser";
20
- import { nativeDefaultExpr, toNative } from "./deterministic-type-converter.js";
20
+ import {
21
+ collectionDefaultExpr,
22
+ nativeDefaultExpr,
23
+ toNative
24
+ } from "./deterministic-type-converter.js";
21
25
  import { fieldRefKind, fieldsBeyondParent, isAlias } from "./common/view-shape.js";
22
26
  import { bag, Emit } from "./emit.js";
23
27
  import {
@@ -277,14 +281,14 @@ class Generator extends Emit {
277
281
  const parent = flatten ? void 0 : this.extendsType(type, aliasByClass);
278
282
  const fields = this.emitFields(type, expanded, flatten);
279
283
  const fieldTokens = fields.map((f) => {
280
- const initializer = f.kind === "primitive" ? nativeDefaultExpr(fieldTypeOf(f, this.typesByName), f) : void 0;
284
+ const initializer = collectionDefaultExpr(f) ?? (f.kind === "primitive" ? nativeDefaultExpr(fieldTypeOf(f, this.typesByName), f) : void 0);
281
285
  return {
282
286
  ident: this.casing.fieldIdent(f.name),
283
287
  tsType: this.fieldTs(f, aliasByClass),
284
288
  nullable: f.isNullable,
285
289
  hasInitializer: isClass && initializer !== void 0,
286
290
  initializer: initializer ?? "",
287
- definite: isClass && initializer === void 0
291
+ definite: isClass && initializer === void 0 && !f.isNullable
288
292
  };
289
293
  });
290
294
  const refs = this.refs(type, expanded, flatten);
@@ -114,16 +114,34 @@ export const toNative = (specType: string): string =>
114
114
  const isTsZeroExpr = (expr: string): boolean =>
115
115
  expr === "false" || expr === "0" || expr === '""';
116
116
 
117
+ export const collectionDefaultExpr = (field: {
118
+ isArray: boolean;
119
+ isMap?: boolean;
120
+ isNullable: boolean;
121
+ defaultValue?: string | number | boolean | null | readonly [] | object;
122
+ }): string | undefined => {
123
+ if (!field.isArray && field.isMap !== true) return undefined;
124
+ if (field.isNullable && field.defaultValue === null) return undefined;
125
+ return field.isMap === true ? "{}" : "[]";
126
+ };
127
+
117
128
  /** Native initializer, or `undefined` when absent or the language zero. */
118
129
  export const nativeDefaultExpr = (
119
130
  specType: string,
120
131
  field: {
121
132
  hasDefault?: boolean;
122
- defaultValue?: string | number | boolean | null;
133
+ defaultValue?: string | number | boolean | null | readonly [] | object;
123
134
  isNullable: boolean;
124
135
  },
125
136
  ): string | undefined => {
126
137
  if (field.hasDefault !== true) return undefined;
138
+ if (
139
+ field.defaultValue === null ||
140
+ Array.isArray(field.defaultValue) ||
141
+ (typeof field.defaultValue === "object" && field.defaultValue !== null)
142
+ ) {
143
+ return undefined;
144
+ }
127
145
  const expr = defaultValueConverter.convert(
128
146
  specType,
129
147
  String(field.defaultValue),
@@ -21,7 +21,11 @@ import {
21
21
  type Type,
22
22
  type TypeField,
23
23
  } from "@deterministic-code/deterministic-generators-common/parser";
24
- import { nativeDefaultExpr, toNative } from "./deterministic-type-converter.ts";
24
+ import {
25
+ collectionDefaultExpr,
26
+ nativeDefaultExpr,
27
+ toNative,
28
+ } from "./deterministic-type-converter.ts";
25
29
  import { fieldRefKind, fieldsBeyondParent, isAlias } from "./common/view-shape.ts";
26
30
  import { bag, Emit } from "./emit.ts";
27
31
  import {
@@ -457,16 +461,17 @@ class Generator extends Emit {
457
461
  const fields = this.emitFields(type, expanded, flatten);
458
462
  const fieldTokens = fields.map((f) => {
459
463
  const initializer =
460
- f.kind === "primitive"
464
+ collectionDefaultExpr(f) ??
465
+ (f.kind === "primitive"
461
466
  ? nativeDefaultExpr(fieldTypeOf(f, this.typesByName), f)
462
- : undefined;
467
+ : undefined);
463
468
  return {
464
469
  ident: this.casing.fieldIdent(f.name),
465
470
  tsType: this.fieldTs(f, aliasByClass),
466
471
  nullable: f.isNullable,
467
472
  hasInitializer: isClass && initializer !== undefined,
468
473
  initializer: initializer ?? "",
469
- definite: isClass && initializer === undefined,
474
+ definite: isClass && initializer === undefined && !f.isNullable,
470
475
  };
471
476
  });
472
477
  const refs = this.refs(type, expanded, flatten);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deterministic-code/datasources-cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "datasources": "./bin/datasources.mjs"
@@ -13,7 +13,7 @@
13
13
  "access": "public"
14
14
  },
15
15
  "dependencies": {
16
- "@deterministic-code/datasources-code-generators": "0.1.5",
16
+ "@deterministic-code/datasources-code-generators": "0.1.6",
17
17
  "@deterministic-code/generators-common": "0.0.1",
18
18
  "@deterministic-code/deterministic-generators-common": "0.1.0",
19
19
  "@deterministic-code/typescript-generators": "0.0.1",
@@ -21,12 +21,12 @@
21
21
  "@deterministic-code/rust-generators": "0.0.1",
22
22
  "@deterministic-code/generators-openapi": "0.0.1",
23
23
  "@deterministic-code/patch-merger": "0.1.0",
24
- "@deterministic-code/datasources": "^0.1.5",
25
- "@deterministic-code/datasources-sqlite": "^0.1.5",
26
- "@deterministic-code/datasources-mysql": "^0.1.5",
27
- "@deterministic-code/datasources-postgres": "^0.1.5",
28
- "@deterministic-code/datasources-sqlserver": "^0.1.5",
29
- "@deterministic-code/datasources-oracle": "^0.1.5",
24
+ "@deterministic-code/datasources": "^0.1.6",
25
+ "@deterministic-code/datasources-sqlite": "^0.1.6",
26
+ "@deterministic-code/datasources-mysql": "^0.1.6",
27
+ "@deterministic-code/datasources-postgres": "^0.1.6",
28
+ "@deterministic-code/datasources-sqlserver": "^0.1.6",
29
+ "@deterministic-code/datasources-oracle": "^0.1.6",
30
30
  "@inquirer/prompts": "^7.8.0",
31
31
  "yaml": "^2.6.0",
32
32
  "mustache": "^4.2.0",