@pylonts/dsl 1.1.18 → 1.1.19

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/dist/dto.d.ts CHANGED
@@ -103,6 +103,12 @@ export declare function dtoField(field: Field | DtoArrayFieldDef | DtoObjectFiel
103
103
  export declare function isDtoMessage(v: unknown): v is DtoMessage;
104
104
  /** Structural check — a DtoField wraps a Field in a .field property and has no .type of its own. */
105
105
  export declare function isDtoField(v: unknown): v is DtoField;
106
+ /** TS type of a DtoField in generated code — unwraps the wrapped field
107
+ * (enum → its JS name, date/datetime → string, containers → jsType). */
108
+ export declare function dtoFieldJsType(df: DtoField): string;
109
+ /** Enum JS names referenced by a DtoField, recursing into inline array/object
110
+ * wrappers; DtoMessage item references stop the walk. First-occurrence order. */
111
+ export declare function dtoCollectEnumRefs(df: DtoField, out?: string[]): string[];
106
112
  export declare function dtoArrayField(def: {
107
113
  items: DtoField | DtoMessage;
108
114
  } & Omit<BaseField, 'name'>): DtoArrayField;
package/dist/dto.js CHANGED
@@ -119,6 +119,34 @@ export function isDtoField(v) {
119
119
  return false;
120
120
  return 'field' in v && !('type' in v);
121
121
  }
122
+ /** TS type of a DtoField in generated code — unwraps the wrapped field
123
+ * (enum → its JS name, date/datetime → string, containers → jsType). */
124
+ export function dtoFieldJsType(df) {
125
+ const f = df.field;
126
+ if (f.type === 'enum')
127
+ return f.enum.jsName;
128
+ if (f.type === 'date' || f.type === 'datetime')
129
+ return 'string';
130
+ return f.jsType;
131
+ }
132
+ /** Enum JS names referenced by a DtoField, recursing into inline array/object
133
+ * wrappers; DtoMessage item references stop the walk. First-occurrence order. */
134
+ export function dtoCollectEnumRefs(df, out = []) {
135
+ const f = df.field;
136
+ if (f.type === 'enum') {
137
+ out.push(f.enum.jsName);
138
+ }
139
+ else if (f.type === 'array') {
140
+ const items = f.items;
141
+ if (isDtoField(items))
142
+ dtoCollectEnumRefs(items, out);
143
+ }
144
+ else if (f.type === 'object') {
145
+ for (const child of Object.values(f.properties))
146
+ dtoCollectEnumRefs(child, out);
147
+ }
148
+ return out;
149
+ }
122
150
  export function dtoArrayField(def) {
123
151
  // Items stay as-is: an inline DtoField is rendered inline, a DtoMessage is
124
152
  // referenced by name (the driver renders Type.Array(<DtoName>)).
package/dist/utils.d.ts CHANGED
@@ -1,13 +1,16 @@
1
1
  import type { CollectionSchemaBase, Field, SchemaBase } from './dsl.js';
2
+ import type { DtoField } from './dto.js';
2
3
  import type { FrontAppSchema, ProjectApiSchema } from './project.js';
3
4
  /** A utility method with a full signature. */
4
5
  export interface UtilsMethodSchema extends SchemaBase {
5
6
  type: 'utilsMethod';
6
7
  /** The utility module this method belongs to. */
7
8
  schema: UtilsSchema;
8
- /** Input fields. */
9
- args: Record<string, Field>;
10
- /** Output field. */
9
+ /** Input fields — DtoField wrappers (dtoField(...)); may wrap table columns. */
10
+ args: Record<string, DtoField>;
11
+ /** Output field — a plain inline Field (boolean for checks, decimal for
12
+ * computed amounts, ...). The method output is a fresh value, never a
13
+ * shared table column. */
11
14
  result: Field;
12
15
  }
13
16
  /** Method input for defineUtils: type/schema/name are set by the builder. */
package/dist/utils.js CHANGED
@@ -20,13 +20,23 @@ export function defineUtils(options) {
20
20
  args: method.args,
21
21
  result: method.result,
22
22
  };
23
+ // Args: write back on the DtoField wrapper only (safe: wrappers are
24
+ // created per method via dtoField(), never shared). Inline fields get
25
+ // their underlying Field written back too; fields wrapping table columns
26
+ // (domain rules) keep the shared column instance untouched — its
27
+ // name/schema already point to the table.
23
28
  for (const argKey of Object.keys(methodSchema.args)) {
24
- const field = methodSchema.args[argKey];
25
- field.name = argKey;
26
- field.schema = methodSchema;
29
+ const df = methodSchema.args[argKey];
30
+ df.name = argKey;
31
+ df.schema = schema;
32
+ if (df.field.schema === undefined) {
33
+ df.field.name = argKey;
34
+ df.field.schema = schema;
35
+ }
27
36
  }
37
+ // Result: a plain inline Field — write name/schema back directly.
28
38
  methodSchema.result.name = key;
29
- methodSchema.result.schema = methodSchema;
39
+ methodSchema.result.schema = schema;
30
40
  schema.methods[key] = methodSchema;
31
41
  }
32
42
  return schema;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pylonts/dsl",
3
- "version": "1.1.18",
3
+ "version": "1.1.19",
4
4
  "description": "Schema definition DSL with drivers: MySQL DDL, TS enum, TypeBox schema codegen.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/dto.ts CHANGED
@@ -185,6 +185,30 @@ export function isDtoField(v: unknown): v is DtoField {
185
185
  return 'field' in v && !('type' in v);
186
186
  }
187
187
 
188
+ /** TS type of a DtoField in generated code — unwraps the wrapped field
189
+ * (enum → its JS name, date/datetime → string, containers → jsType). */
190
+ export function dtoFieldJsType(df: DtoField): string {
191
+ const f = df.field;
192
+ if (f.type === 'enum') return f.enum.jsName;
193
+ if (f.type === 'date' || f.type === 'datetime') return 'string';
194
+ return f.jsType;
195
+ }
196
+
197
+ /** Enum JS names referenced by a DtoField, recursing into inline array/object
198
+ * wrappers; DtoMessage item references stop the walk. First-occurrence order. */
199
+ export function dtoCollectEnumRefs(df: DtoField, out: string[] = []): string[] {
200
+ const f = df.field;
201
+ if (f.type === 'enum') {
202
+ out.push(f.enum.jsName);
203
+ } else if (f.type === 'array') {
204
+ const items = f.items;
205
+ if (isDtoField(items)) dtoCollectEnumRefs(items, out);
206
+ } else if (f.type === 'object') {
207
+ for (const child of Object.values(f.properties)) dtoCollectEnumRefs(child, out);
208
+ }
209
+ return out;
210
+ }
211
+
188
212
  export function dtoArrayField(def: { items: DtoField | DtoMessage } & Omit<BaseField, 'name'>): DtoArrayField {
189
213
  // Items stay as-is: an inline DtoField is rendered inline, a DtoMessage is
190
214
  // referenced by name (the driver renders Type.Array(<DtoName>)).
package/src/utils.ts CHANGED
@@ -1,18 +1,26 @@
1
1
  import type { CollectionSchemaBase, Field, SchemaBase } from './dsl.js';
2
+ import type { DtoField } from './dto.js';
2
3
  import type { FrontAppSchema, ProjectApiSchema } from './project.js';
3
4
 
4
5
  // Base utility modules — business-agnostic helpers with full method
5
6
  // signatures (e.g. DateTimeUtils.format). Called at the service layer;
6
7
  // their args/results are own wire types, independent of business schemas.
8
+ // A utils whose name matches a table name is a domain rule module: its
9
+ // methods may wrap table columns via dtoField(table.columns.x) — the DtoField
10
+ // wrapper owns the write-back, so the shared column instance is never
11
+ // mutated (same rule as buildMessage: only inline fields get their
12
+ // underlying Field written back).
7
13
 
8
14
  /** A utility method with a full signature. */
9
15
  export interface UtilsMethodSchema extends SchemaBase {
10
16
  type: 'utilsMethod';
11
17
  /** The utility module this method belongs to. */
12
18
  schema: UtilsSchema;
13
- /** Input fields. */
14
- args: Record<string, Field>;
15
- /** Output field. */
19
+ /** Input fields — DtoField wrappers (dtoField(...)); may wrap table columns. */
20
+ args: Record<string, DtoField>;
21
+ /** Output field — a plain inline Field (boolean for checks, decimal for
22
+ * computed amounts, ...). The method output is a fresh value, never a
23
+ * shared table column. */
16
24
  result: Field;
17
25
  }
18
26
 
@@ -62,13 +70,23 @@ export function defineUtils(options: {
62
70
  args: method.args,
63
71
  result: method.result,
64
72
  };
73
+ // Args: write back on the DtoField wrapper only (safe: wrappers are
74
+ // created per method via dtoField(), never shared). Inline fields get
75
+ // their underlying Field written back too; fields wrapping table columns
76
+ // (domain rules) keep the shared column instance untouched — its
77
+ // name/schema already point to the table.
65
78
  for (const argKey of Object.keys(methodSchema.args)) {
66
- const field = methodSchema.args[argKey] as Field;
67
- field.name = argKey;
68
- field.schema = methodSchema;
79
+ const df = methodSchema.args[argKey] as DtoField;
80
+ df.name = argKey;
81
+ df.schema = schema;
82
+ if (df.field.schema === undefined) {
83
+ df.field.name = argKey;
84
+ df.field.schema = schema;
85
+ }
69
86
  }
87
+ // Result: a plain inline Field — write name/schema back directly.
70
88
  methodSchema.result.name = key;
71
- methodSchema.result.schema = methodSchema;
89
+ methodSchema.result.schema = schema;
72
90
  schema.methods[key] = methodSchema;
73
91
  }
74
92
  return schema;