@pylonts/dsl 1.0.3 → 1.0.5

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.
@@ -0,0 +1,5 @@
1
+ import type { DtoMessage, ImportRef } from './dto';
2
+ /** Paginated query request base — renders `import { PageRequest } from '@pylonts/core'` + Intersect */
3
+ export declare const PageRequest: ImportRef;
4
+ /** Paginated list response base — renders `import { PageResult } from '@pylonts/core'` + `PageResult(<row>)` */
5
+ export declare const PageResult: (row: DtoMessage) => ImportRef;
package/dist/bases.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageResult = exports.PageRequest = void 0;
4
+ // Named base-schema references for common protocol DTOs.
5
+ //
6
+ // These are ImportRef metadata (not re-exports of the actual TypeBox schemas):
7
+ // the DSL stores { from, name } so the generator can emit the import line and
8
+ // the identifier — the runtime schema object itself is never loaded by the DSL.
9
+ //
10
+ // `import { PageRequest } from '@pylonts/dsl'` therefore gives .include() an
11
+ // already-resolved reference — no static analysis or name lookup needed.
12
+ /** Paginated query request base — renders `import { PageRequest } from '@pylonts/core'` + Intersect */
13
+ exports.PageRequest = { from: '@pylonts/core', name: 'PageRequest' };
14
+ /** Paginated list response base — renders `import { PageResult } from '@pylonts/core'` + `PageResult(<row>)` */
15
+ const PageResult = (row) => ({
16
+ from: '@pylonts/core',
17
+ name: 'PageResult',
18
+ args: [row],
19
+ });
20
+ exports.PageResult = PageResult;
@@ -0,0 +1,9 @@
1
+ export interface InheritanceIssue {
2
+ file: string;
3
+ container: string;
4
+ field: string;
5
+ /** e.g. ["t_order.order_no"] or ["t_order.id", "t_merchant.id"] when several inferred tables share the name */
6
+ candidates: string[];
7
+ }
8
+ /** Check one loaded DSL module (its exports) for inheritance gaps. */
9
+ export declare function checkInheritance(mod: Record<string, unknown>, file: string): InheritanceIssue[];
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkInheritance = checkInheritance;
4
+ /** snake_case → camelCase: order_no → orderNo; names without underscores are unchanged */
5
+ function toCamelCase(name) {
6
+ return name.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
7
+ }
8
+ function isDtoMessage(v) {
9
+ if (typeof v !== 'object' || v === null)
10
+ return false;
11
+ const o = v;
12
+ return o.type === 'dto' && typeof o.name === 'string' && typeof o.fields === 'object' && o.fields !== null;
13
+ }
14
+ function collectFields(mod) {
15
+ const out = [];
16
+ for (const [name, v] of Object.entries(mod)) {
17
+ if (isDtoMessage(v)) {
18
+ const container = v;
19
+ for (const [fname, f] of Object.entries(container.fields)) {
20
+ out.push({ name: fname, field: f.field, container: name });
21
+ }
22
+ }
23
+ }
24
+ return out;
25
+ }
26
+ /** Check one loaded DSL module (its exports) for inheritance gaps. */
27
+ function checkInheritance(mod, file) {
28
+ const fields = collectFields(mod);
29
+ if (fields.length === 0)
30
+ return [];
31
+ // Infer the tables this file is about from the referenced fields' schema identity.
32
+ const tables = new Map(); // table -> camelCol -> origCol
33
+ for (const f of fields) {
34
+ const schema = f.field.schema;
35
+ if (schema?.type !== 'table')
36
+ continue;
37
+ const table = schema;
38
+ if (!tables.has(table.name))
39
+ tables.set(table.name, new Map());
40
+ tables.get(table.name).set(toCamelCase(f.name), f.name);
41
+ }
42
+ if (tables.size === 0)
43
+ return [];
44
+ const issues = [];
45
+ for (const f of fields) {
46
+ if (f.field.schema?.type === 'table')
47
+ continue;
48
+ if (f.field.semantic !== undefined || f.field.type === 'enum')
49
+ continue;
50
+ const candidates = [];
51
+ for (const [t, cols] of tables) {
52
+ const orig = cols.get(f.name);
53
+ if (orig !== undefined)
54
+ candidates.push(`${t}.${orig}`);
55
+ }
56
+ if (candidates.length > 0) {
57
+ issues.push({ file, container: f.container, field: f.name, candidates });
58
+ }
59
+ }
60
+ return issues;
61
+ }
package/dist/dsl.d.ts CHANGED
@@ -3,17 +3,23 @@ export interface SchemaBase {
3
3
  name: string;
4
4
  description?: string;
5
5
  }
6
+ /** Field collection schemas (DB table vs DTO message); `type` is the discriminator */
7
+ export interface CollectionSchemaBase extends SchemaBase {
8
+ type: string;
9
+ }
6
10
  export interface BaseField {
7
11
  name: string;
8
12
  /** 显示名称(中文标签) */
9
13
  label?: string;
10
14
  /** 字段描述 */
11
15
  description?: string;
16
+ /** 业务语义码(如 'merchant_name'),驱动 mock 生成等下游消费 */
17
+ semantic?: string;
12
18
  optional?: boolean;
13
19
  readOnly?: boolean;
14
20
  default?: string;
15
21
  /** 所属 schema(db 或 dto) */
16
- schema?: SchemaBase;
22
+ schema?: CollectionSchemaBase;
17
23
  }
18
24
  interface StringField extends BaseField {
19
25
  type: 'string';
@@ -90,7 +96,23 @@ export type ForeignKey = {
90
96
  fields: Field | Field[];
91
97
  references: Field | Field[];
92
98
  };
93
- export interface TableSchema extends SchemaBase {
99
+ export interface TableSchemaOptions {
100
+ description?: string;
101
+ paginated?: boolean;
102
+ actor?: boolean;
103
+ generator?: string;
104
+ autoIncrement?: Field;
105
+ primaryKey?: Field | Field[];
106
+ indexes?: Index[];
107
+ foreignKeys?: Record<string, ForeignKey>;
108
+ /** 引用的实体短语(词典条目):本表归属的实体;关联表等多实体场景不需要 */
109
+ phrase?: DictionaryEntry;
110
+ fields: Record<string, Field>;
111
+ }
112
+ export declare class TableSchema implements CollectionSchemaBase {
113
+ type: string;
114
+ name: string;
115
+ description?: string;
94
116
  /** 分页 */
95
117
  paginated?: boolean;
96
118
  /** 系统操作者(如小程序为 C 端用户,管理端为运营) */
@@ -106,6 +128,9 @@ export interface TableSchema extends SchemaBase {
106
128
  /** 引用的实体短语(词典条目):本表归属的实体;关联表等多实体场景不需要 */
107
129
  phrase?: DictionaryEntry;
108
130
  fields: Record<string, Field>;
131
+ constructor(name: string, options: TableSchemaOptions);
132
+ /** True when the field is part of this table's primary key */
133
+ isPk(fieldRef: Field): boolean;
109
134
  }
110
135
  type FieldExtras<T extends Field> = Omit<T, 'name' | 'type' | 'jsType'>;
111
136
  export declare function stringField(extra?: FieldExtras<StringField>): StringField;
@@ -119,17 +144,5 @@ export declare function timeField(extra?: FieldExtras<TimeField>): TimeField;
119
144
  export declare function datetimeField(extra?: FieldExtras<DateTimeField>): DateTimeField;
120
145
  export declare function jsonField(extra?: FieldExtras<JsonField>): JsonField;
121
146
  export declare function enumField(extra: Omit<EnumField, 'name' | 'type' | 'jsType'>): EnumField;
122
- export declare function defineTable(name: string, schema: {
123
- description?: string;
124
- paginated?: boolean;
125
- actor?: boolean;
126
- generator?: string;
127
- autoIncrement?: Field;
128
- primaryKey?: Field | Field[];
129
- indexes?: Index[];
130
- foreignKeys?: Record<string, ForeignKey>;
131
- /** 引用的实体短语(词典条目) */
132
- phrase?: DictionaryEntry;
133
- fields: Record<string, Field>;
134
- }): TableSchema;
147
+ export declare function defineTable(name: string, schema: TableSchemaOptions): TableSchema;
135
148
  export {};
package/dist/dsl.js CHANGED
@@ -2,6 +2,7 @@
2
2
  // DSL field type definitions.
3
3
  // Shape: { type: <type name>, <extension fields> }
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.TableSchema = void 0;
5
6
  exports.defineEnum = defineEnum;
6
7
  exports.stringField = stringField;
7
8
  exports.textField = textField;
@@ -18,6 +19,48 @@ exports.defineTable = defineTable;
18
19
  function defineEnum(jsName, valueType, values) {
19
20
  return { jsName, valueType, values };
20
21
  }
22
+ class TableSchema {
23
+ type = 'table';
24
+ name;
25
+ description;
26
+ /** 分页 */
27
+ paginated;
28
+ /** 系统操作者(如小程序为 C 端用户,管理端为运营) */
29
+ actor;
30
+ /** id 生成器 */
31
+ generator;
32
+ /** 自增主键字段 */
33
+ autoIncrement;
34
+ primaryKey;
35
+ indexes;
36
+ /** 外键,引用其他表的字段 */
37
+ foreignKeys;
38
+ /** 引用的实体短语(词典条目):本表归属的实体;关联表等多实体场景不需要 */
39
+ phrase;
40
+ fields;
41
+ constructor(name, options) {
42
+ this.name = name;
43
+ this.description = options.description;
44
+ this.paginated = options.paginated;
45
+ this.actor = options.actor;
46
+ this.generator = options.generator;
47
+ this.autoIncrement = options.autoIncrement;
48
+ this.primaryKey = options.primaryKey;
49
+ this.indexes = options.indexes;
50
+ this.foreignKeys = options.foreignKeys;
51
+ this.phrase = options.phrase;
52
+ this.fields = options.fields;
53
+ }
54
+ /** True when the field is part of this table's primary key */
55
+ isPk(fieldRef) {
56
+ if (this.primaryKey === undefined)
57
+ return false;
58
+ return Array.isArray(this.primaryKey)
59
+ ? this.primaryKey.includes(fieldRef)
60
+ : this.primaryKey === fieldRef;
61
+ }
62
+ }
63
+ exports.TableSchema = TableSchema;
21
64
  function stringField(extra = {}) {
22
65
  return { name: '', type: 'string', jsType: 'string', ...extra };
23
66
  }
@@ -53,7 +96,7 @@ function enumField(extra) {
53
96
  return { name: '', type: 'enum', jsType, ...extra };
54
97
  }
55
98
  function defineTable(name, schema) {
56
- const table = { name, ...schema };
99
+ const table = new TableSchema(name, schema);
57
100
  for (const key of Object.keys(table.fields)) {
58
101
  const field = table.fields[key];
59
102
  if (field.schema && field.schema !== table) {
package/dist/dto.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseField, Field, SchemaBase, TableSchema } from './dsl';
1
+ import { BaseField, CollectionSchemaBase, Field, SchemaBase, TableSchema } from './dsl';
2
2
  export type Operator = 'eq' | 'gt' | 'gte' | 'lt' | 'lte' | 'like' | 'ne';
3
3
  /**
4
4
  * Reference to an existing TypeBox base schema by its import location.
@@ -10,16 +10,14 @@ export interface ImportRef {
10
10
  from: string;
11
11
  /** Named export, e.g. 'PageRequest' */
12
12
  name: string;
13
- /** Generic type arguments for the base schema (same-file DTO export names), e.g. PageResult(AdvertRow) */
14
- args?: string[];
13
+ /**
14
+ * Generic type arguments for the base schema (e.g. PageResult(OrderRow)).
15
+ * Two forms, both local DTOs:
16
+ * string — the DTO export name
17
+ * DtoMessage — the DTO instance itself; the driver resolves it to its name
18
+ */
19
+ args?: (string | DtoMessage)[];
15
20
  }
16
- export type DtoExtras = {
17
- pattern?: string;
18
- /** 联合判断是否可选,定义后优先级高于 field.optional */
19
- optional?: boolean;
20
- /** 查询比较操作符(query 方向字段) */
21
- operator?: Operator;
22
- };
23
21
  export type DtoArrayFieldDef = BaseField & {
24
22
  type: 'array';
25
23
  jsType: 'array';
@@ -30,21 +28,31 @@ export type DtoObjectFieldDef = BaseField & {
30
28
  jsType: 'object';
31
29
  properties: Record<string, DtoField>;
32
30
  };
33
- export declare class DtoField {
31
+ export declare class DtoField implements SchemaBase {
34
32
  /** DTO 语义字段名(接口字段名),与 field.name(数据库列名)含义不同。
35
33
  * 构造时未知,由 buildMessage 从 map key 反写。 */
36
34
  name: string;
35
+ /** 字段描述 */
36
+ description?: string;
37
37
  /** 所属 DTO 容器(buildMessage 反写) */
38
38
  schema?: DtoMessage;
39
39
  field: Field | DtoArrayFieldDef | DtoObjectFieldDef;
40
40
  pattern?: string;
41
41
  optional?: boolean;
42
42
  operator?: Operator;
43
- constructor(field: Field | DtoArrayFieldDef | DtoObjectFieldDef, extra?: DtoExtras);
43
+ /** TypeBox default annotation (API contract level); falls back to field.default (DB default) */
44
+ default?: unknown;
45
+ constructor(field: Field | DtoArrayFieldDef | DtoObjectFieldDef);
44
46
  setPattern(value: string): this;
47
+ setDescription(value: string): this;
48
+ getDescription(): string | undefined;
49
+ /** True when this field wraps a DB column (picked via from()); false for inline fields. */
50
+ isColumn(): boolean;
45
51
  setOptional(value: boolean): this;
52
+ /** Set a default value — emitted as a TypeBox schema default annotation */
53
+ setDefault(value: unknown): this;
46
54
  /** 查询比较操作符(query 方向字段)。Rule B: 查询字段恒为可选 */
47
- op(value: Operator): this;
55
+ setOperator(value: Operator): this;
48
56
  /** optional 优先于 field.optional */
49
57
  isOptional(): boolean;
50
58
  }
@@ -56,23 +64,32 @@ export declare class DtoObjectField extends DtoField {
56
64
  field: DtoObjectFieldDef;
57
65
  properties(): Record<string, DtoField>;
58
66
  }
59
- export type DtoDirection = 'input' | 'output' | 'query' | 'pk';
60
- export interface DtoMessage extends SchemaBase {
67
+ export declare enum DtoDirection {
68
+ Input = "input",
69
+ Output = "output",
70
+ Query = "query",
71
+ Pk = "pk"
72
+ }
73
+ export declare class DtoMessage implements CollectionSchemaBase {
74
+ type: string;
75
+ name: string;
76
+ description?: string;
61
77
  /** 方向:输入或输出 */
62
78
  direction: DtoDirection;
63
79
  fields: Record<string, DtoField>;
64
80
  /** TypeBox base schemas to intersect with at generation time (e.g. PageRequest) */
65
- bases?: ImportRef[];
81
+ bases: ImportRef[];
82
+ constructor(name: string, direction: DtoDirection, fields: Record<string, DtoField>, description?: string);
66
83
  /** 引用已存在的 TypeBox base schema,例如 include({ from: '@pylonts/core', name: 'PageRequest' }) */
67
- include(...refs: ImportRef[]): DtoMessage;
84
+ include(...refs: ImportRef[]): this;
68
85
  }
69
- export declare function dtoField(field: Field, extra?: DtoExtras): DtoField;
86
+ export declare function dtoField(field: Field): DtoField;
70
87
  export declare function dtoArrayField(def: {
71
- items: DtoField;
72
- } & Omit<BaseField, 'name'>, extra?: DtoExtras): DtoArrayField;
88
+ items: DtoField | DtoMessage;
89
+ } & Omit<BaseField, 'name'>): DtoArrayField;
73
90
  export declare function dtoObjectField(def: {
74
91
  properties: Record<string, DtoField>;
75
- } & Omit<BaseField, 'name'>, extra?: DtoExtras): DtoObjectField;
92
+ } & Omit<BaseField, 'name'>): DtoObjectField;
76
93
  export declare function buildInput(name: string, fields: Record<string, DtoField>, description?: string): DtoMessage;
77
94
  export declare function buildOutput(name: string, fields: Record<string, DtoField>, description?: string): DtoMessage;
78
95
  export declare function buildQuery(name: string, fields: Record<string, DtoField>, description?: string): DtoMessage;
package/dist/dto.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DtoObjectField = exports.DtoArrayField = exports.DtoField = void 0;
3
+ exports.DtoMessage = exports.DtoDirection = exports.DtoObjectField = exports.DtoArrayField = exports.DtoField = void 0;
4
4
  exports.dtoField = dtoField;
5
5
  exports.dtoArrayField = dtoArrayField;
6
6
  exports.dtoObjectField = dtoObjectField;
@@ -9,35 +9,52 @@ exports.buildOutput = buildOutput;
9
9
  exports.buildQuery = buildQuery;
10
10
  exports.buildPk = buildPk;
11
11
  exports.from = from;
12
+ const utils_1 = require("./utils");
12
13
  class DtoField {
13
14
  /** DTO 语义字段名(接口字段名),与 field.name(数据库列名)含义不同。
14
15
  * 构造时未知,由 buildMessage 从 map key 反写。 */
15
16
  name;
17
+ /** 字段描述 */
18
+ description;
16
19
  /** 所属 DTO 容器(buildMessage 反写) */
17
20
  schema;
18
21
  field;
19
22
  pattern;
20
23
  optional;
21
24
  operator;
22
- constructor(field, extra = {}) {
25
+ /** TypeBox default annotation (API contract level); falls back to field.default (DB default) */
26
+ default;
27
+ constructor(field) {
23
28
  this.name = '';
24
29
  this.field = field;
25
- this.pattern = extra.pattern;
26
- this.optional = extra.optional;
27
- this.operator = extra.operator;
28
30
  }
29
31
  setPattern(value) {
30
32
  this.pattern = value;
31
33
  return this;
32
34
  }
35
+ setDescription(value) {
36
+ this.description = value;
37
+ return this;
38
+ }
39
+ getDescription() {
40
+ return this.description;
41
+ }
42
+ /** True when this field wraps a DB column (picked via from()); false for inline fields. */
43
+ isColumn() {
44
+ return this.field.schema?.type === 'table';
45
+ }
33
46
  setOptional(value) {
34
47
  this.optional = value;
35
48
  return this;
36
49
  }
50
+ /** Set a default value — emitted as a TypeBox schema default annotation */
51
+ setDefault(value) {
52
+ this.default = value;
53
+ return this;
54
+ }
37
55
  /** 查询比较操作符(query 方向字段)。Rule B: 查询字段恒为可选 */
38
- op(value) {
56
+ setOperator(value) {
39
57
  this.operator = value;
40
- this.optional = true;
41
58
  return this;
42
59
  }
43
60
  /** optional 优先于 field.optional */
@@ -60,32 +77,50 @@ class DtoObjectField extends DtoField {
60
77
  }
61
78
  }
62
79
  exports.DtoObjectField = DtoObjectField;
63
- function dtoField(field, extra = {}) {
64
- return new DtoField(field, extra);
80
+ var DtoDirection;
81
+ (function (DtoDirection) {
82
+ DtoDirection["Input"] = "input";
83
+ DtoDirection["Output"] = "output";
84
+ DtoDirection["Query"] = "query";
85
+ DtoDirection["Pk"] = "pk";
86
+ })(DtoDirection || (exports.DtoDirection = DtoDirection = {}));
87
+ class DtoMessage {
88
+ type = 'dto';
89
+ name;
90
+ description;
91
+ /** 方向:输入或输出 */
92
+ direction;
93
+ fields;
94
+ /** TypeBox base schemas to intersect with at generation time (e.g. PageRequest) */
95
+ bases = [];
96
+ constructor(name, direction, fields, description) {
97
+ this.name = name;
98
+ this.direction = direction;
99
+ this.fields = fields;
100
+ this.description = description;
101
+ }
102
+ /** 引用已存在的 TypeBox base schema,例如 include({ from: '@pylonts/core', name: 'PageRequest' }) */
103
+ include(...refs) {
104
+ this.bases.push(...refs);
105
+ return this;
106
+ }
107
+ }
108
+ exports.DtoMessage = DtoMessage;
109
+ function dtoField(field) {
110
+ return new DtoField(field);
65
111
  }
66
- function dtoArrayField(def, extra = {}) {
67
- return new DtoArrayField({ name: '', type: 'array', jsType: 'array', ...def }, extra);
112
+ function dtoArrayField(def) {
113
+ // Reuse an existing DTO as the array element: expand its fields into an object.
114
+ const items = def.items instanceof DtoMessage
115
+ ? new DtoObjectField({ name: '', type: 'object', jsType: 'object', properties: def.items.fields })
116
+ : def.items;
117
+ return new DtoArrayField({ name: '', type: 'array', jsType: 'array', ...def, items });
68
118
  }
69
- function dtoObjectField(def, extra = {}) {
70
- return new DtoObjectField({ name: '', type: 'object', jsType: 'object', ...def }, extra);
119
+ function dtoObjectField(def) {
120
+ return new DtoObjectField({ name: '', type: 'object', jsType: 'object', ...def });
71
121
  }
72
122
  function buildMessage(name, direction, fields, description) {
73
- const message = {
74
- name,
75
- direction,
76
- description,
77
- fields,
78
- bases: [],
79
- include(...refs) {
80
- this.bases.push(...refs);
81
- return this;
82
- },
83
- };
84
- if (direction === 'query') {
85
- // Rule B: query/search fields are always optional.
86
- for (const field of Object.values(message.fields))
87
- field.optional = true;
88
- }
123
+ const message = new DtoMessage(name, direction, fields, description);
89
124
  // Write back the DTO field name from the map key (safe: DtoField instances
90
125
  // are created per DTO, never shared).
91
126
  for (const key of Object.keys(message.fields)) {
@@ -103,16 +138,41 @@ function buildMessage(name, direction, fields, description) {
103
138
  return message;
104
139
  }
105
140
  function buildInput(name, fields, description) {
106
- return buildMessage(name, 'input', fields, description);
141
+ const message = buildMessage(name, DtoDirection.Input, fields, description);
142
+ // Rule A — set optionality from the DB column rule (skips fields the author
143
+ // already set): nullable / default / auto-increment → optional, else required.
144
+ for (const field of Object.values(message.fields)) {
145
+ if (field.optional !== undefined)
146
+ continue;
147
+ const f = field.field;
148
+ if (f.schema?.type !== 'table')
149
+ continue;
150
+ const table = f.schema;
151
+ field.optional = f.optional !== false || f.default !== undefined || table.autoIncrement === f;
152
+ }
153
+ return message;
107
154
  }
108
155
  function buildOutput(name, fields, description) {
109
- return buildMessage(name, 'output', fields, description);
156
+ return buildMessage(name, DtoDirection.Output, fields, description);
110
157
  }
111
158
  function buildQuery(name, fields, description) {
112
- return buildMessage(name, 'query', fields, description);
159
+ const message = buildMessage(name, DtoDirection.Query, fields, description);
160
+ // Rule B: query/search fields are always optional.
161
+ for (const field of Object.values(message.fields))
162
+ field.optional = true;
163
+ return message;
113
164
  }
114
165
  function buildPk(name, fields, description) {
115
- return buildMessage(name, 'pk', fields, description);
166
+ const message = buildMessage(name, DtoDirection.Pk, fields, description);
167
+ // Rule P: PK locator fields are required, other fields are optional.
168
+ for (const field of Object.values(message.fields)) {
169
+ if (field.optional !== undefined)
170
+ continue;
171
+ const f = field.field;
172
+ const table = f.schema;
173
+ field.optional = table !== undefined && table.isPk(f) ? false : true;
174
+ }
175
+ return message;
116
176
  }
117
177
  /** Pick columns from a built table and wrap them as DTO fields (aligned with dto.from). */
118
178
  function from(table, fields) {
@@ -121,7 +181,9 @@ function from(table, fields) {
121
181
  if (field.schema !== table) {
122
182
  throw new Error(`dto.from(${table.name}): field ${field.name} does not belong to this table`);
123
183
  }
124
- out[field.name] = dtoField(field);
184
+ // DTO field name is camelCase (mer_id → merId); the underlying field.name
185
+ // stays snake_case (DB column).
186
+ out[(0, utils_1.toCamelCase)(field.name)] = dtoField(field);
125
187
  }
126
188
  return out;
127
189
  }
package/dist/index.d.ts CHANGED
@@ -1,11 +1,14 @@
1
1
  export * from './dsl';
2
2
  export * from './dto';
3
+ export * from './bases';
4
+ export * from './utils';
3
5
  export * from './project';
4
6
  export * from './prototype';
5
7
  export * from './dictionary';
6
8
  export * from './mysql-driver';
7
9
  export * from './enum-driver';
8
10
  export * from './typebox-driver';
11
+ export * from './check-inheritance';
9
12
  export * from './pattern';
10
13
  export * from './patterns/retry';
11
14
  export * from './flow';
package/dist/index.js CHANGED
@@ -16,12 +16,15 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./dsl"), exports);
18
18
  __exportStar(require("./dto"), exports);
19
+ __exportStar(require("./bases"), exports);
20
+ __exportStar(require("./utils"), exports);
19
21
  __exportStar(require("./project"), exports);
20
22
  __exportStar(require("./prototype"), exports);
21
23
  __exportStar(require("./dictionary"), exports);
22
24
  __exportStar(require("./mysql-driver"), exports);
23
25
  __exportStar(require("./enum-driver"), exports);
24
26
  __exportStar(require("./typebox-driver"), exports);
27
+ __exportStar(require("./check-inheritance"), exports);
25
28
  __exportStar(require("./pattern"), exports);
26
29
  __exportStar(require("./patterns/retry"), exports);
27
30
  __exportStar(require("./flow"), exports);
@@ -47,9 +47,13 @@ function renderPageFlowMermaid(schema) {
47
47
  const ids = new Map();
48
48
  const byApp = new Map();
49
49
  for (const p of schema.pages) {
50
- const list = byApp.get(p.app.name) ?? [];
51
- list.push(p);
52
- byApp.set(p.app.name, list);
50
+ const list = byApp.get(p.app.name);
51
+ if (!list) {
52
+ byApp.set(p.app.name, [p]);
53
+ }
54
+ else {
55
+ list.push(p);
56
+ }
53
57
  }
54
58
  let appIdx = 0;
55
59
  for (const [appName, pages] of byApp) {
@@ -1,5 +1,11 @@
1
1
  import { DtoMessage, ImportRef } from './dto';
2
2
  export type EnumResolver = (enumName: string) => ImportRef | undefined;
3
+ /** Collect all imports needed to render a DTO: include() bases + enum references. */
4
+ export declare function collectDtoImports(schema: DtoMessage, resolver: EnumResolver | undefined, out: Map<string, ImportRef>): void;
5
+ /** Render one DTO export (const + type) — no file header, for file-level generation. */
6
+ export declare function renderDtoExport(schema: DtoMessage, resolver: EnumResolver | undefined): string;
7
+ /** Render the Static type export for a DTO. */
8
+ export declare function renderDtoTypeExport(name: string): string;
3
9
  export declare function renderDtoMessage(schema: DtoMessage, options?: {
4
10
  resolver?: EnumResolver;
5
11
  source?: string;