@pylonts/dsl 1.0.6 → 1.1.1

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 (78) hide show
  1. package/README.md +2 -1
  2. package/dist/asset.d.ts +48 -0
  3. package/dist/asset.js +31 -0
  4. package/dist/bases.d.ts +6 -2
  5. package/dist/bases.js +10 -6
  6. package/dist/check-inheritance.js +1 -4
  7. package/dist/curd.d.ts +60 -0
  8. package/dist/curd.js +31 -0
  9. package/dist/db-config.d.ts +8 -0
  10. package/dist/db-config.js +1 -0
  11. package/dist/db.d.ts +52 -0
  12. package/dist/db.js +91 -0
  13. package/dist/dictionary.d.ts +26 -5
  14. package/dist/dictionary.js +21 -8
  15. package/dist/dsl.d.ts +5 -49
  16. package/dist/dsl.js +12 -103
  17. package/dist/dto.d.ts +10 -7
  18. package/dist/dto.js +24 -33
  19. package/dist/enum-driver.d.ts +1 -1
  20. package/dist/enum-driver.js +1 -4
  21. package/dist/flow.d.ts +1 -1
  22. package/dist/flow.js +3 -8
  23. package/dist/import-base.d.ts +15 -0
  24. package/dist/import-base.js +1 -0
  25. package/dist/index.d.ts +21 -17
  26. package/dist/index.js +21 -33
  27. package/dist/mermaid-driver.d.ts +2 -2
  28. package/dist/mermaid-driver.js +2 -6
  29. package/dist/mock.d.ts +30 -0
  30. package/dist/mock.js +18 -0
  31. package/dist/mysql-driver.d.ts +1 -1
  32. package/dist/mysql-driver.js +20 -10
  33. package/dist/page-flow.d.ts +2 -2
  34. package/dist/page-flow.js +2 -6
  35. package/dist/page.d.ts +6 -6
  36. package/dist/page.js +3 -8
  37. package/dist/pattern.js +2 -6
  38. package/dist/patterns/retry.d.ts +1 -1
  39. package/dist/patterns/retry.js +2 -6
  40. package/dist/project.d.ts +18 -13
  41. package/dist/project.js +41 -6
  42. package/dist/prototype.d.ts +1 -1
  43. package/dist/prototype.js +1 -4
  44. package/dist/typebox-driver.d.ts +3 -3
  45. package/dist/typebox-driver.js +24 -26
  46. package/dist/utils.d.ts +2 -0
  47. package/dist/utils.js +5 -4
  48. package/docs/curd.md +111 -0
  49. package/docs/dictionary.md +42 -31
  50. package/docs/driver.md +42 -42
  51. package/docs/dto.md +66 -66
  52. package/docs/enum.md +24 -24
  53. package/docs/project.md +2 -2
  54. package/docs/table.md +50 -15
  55. package/package.json +6 -4
  56. package/src/asset.ts +63 -0
  57. package/src/bases.ts +12 -2
  58. package/src/curd.ts +92 -0
  59. package/src/db-config.ts +8 -0
  60. package/src/db.ts +142 -0
  61. package/src/dictionary.ts +45 -19
  62. package/src/dsl.ts +182 -281
  63. package/src/dto.ts +247 -234
  64. package/src/enum-driver.ts +1 -1
  65. package/src/flow.ts +1 -1
  66. package/src/import-base.ts +15 -0
  67. package/src/index.ts +21 -17
  68. package/src/mermaid-driver.ts +3 -3
  69. package/src/mock.ts +45 -0
  70. package/src/mysql-driver.ts +19 -6
  71. package/src/page-flow.ts +3 -3
  72. package/src/page.ts +7 -7
  73. package/src/patterns/retry.ts +1 -1
  74. package/src/project.ts +90 -54
  75. package/src/prototype.ts +1 -1
  76. package/src/typebox-driver.ts +192 -187
  77. package/src/utils.ts +5 -0
  78. package/src/check-inheritance.ts +0 -86
package/dist/dsl.js CHANGED
@@ -1,130 +1,39 @@
1
- "use strict";
2
1
  // DSL field type definitions.
3
2
  // Shape: { type: <type name>, <extension fields> }
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.TableSchema = void 0;
6
- exports.defineEnum = defineEnum;
7
- exports.stringField = stringField;
8
- exports.textField = textField;
9
- exports.intField = intField;
10
- exports.bigintField = bigintField;
11
- exports.decimalField = decimalField;
12
- exports.booleanField = booleanField;
13
- exports.dateField = dateField;
14
- exports.timeField = timeField;
15
- exports.datetimeField = datetimeField;
16
- exports.jsonField = jsonField;
17
- exports.enumField = enumField;
18
- exports.defineTable = defineTable;
19
- function defineEnum(jsName, valueType, values) {
3
+ export function defineEnum(jsName, valueType, values) {
20
4
  return { jsName, valueType, values };
21
5
  }
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;
64
- function stringField(extra = {}) {
6
+ export function stringField(extra = {}) {
65
7
  return { name: '', type: 'string', jsType: 'string', ...extra };
66
8
  }
67
- function textField(extra = {}) {
9
+ export function textField(extra = {}) {
68
10
  return { name: '', type: 'text', jsType: 'string', ...extra };
69
11
  }
70
- function intField(extra = {}) {
12
+ export function intField(extra = {}) {
71
13
  return { name: '', type: 'integer', jsType: 'number', ...extra };
72
14
  }
73
- function bigintField(extra = {}) {
15
+ export function bigintField(extra = {}) {
74
16
  return { name: '', type: 'bigint', jsType: 'string', ...extra };
75
17
  }
76
- function decimalField(extra) {
18
+ export function decimalField(extra) {
77
19
  return { name: '', type: 'decimal', jsType: 'string', ...extra };
78
20
  }
79
- function booleanField(extra = {}) {
21
+ export function booleanField(extra = {}) {
80
22
  return { name: '', type: 'boolean', jsType: 'boolean', ...extra };
81
23
  }
82
- function dateField(extra = {}) {
24
+ export function dateField(extra = {}) {
83
25
  return { name: '', type: 'date', jsType: 'Date', ...extra };
84
26
  }
85
- function timeField(extra = {}) {
27
+ export function timeField(extra = {}) {
86
28
  return { name: '', type: 'time', jsType: 'string', ...extra };
87
29
  }
88
- function datetimeField(extra = {}) {
30
+ export function datetimeField(extra = {}) {
89
31
  return { name: '', type: 'datetime', jsType: 'Date', ...extra };
90
32
  }
91
- function jsonField(extra = {}) {
33
+ export function jsonField(extra = {}) {
92
34
  return { name: '', type: 'json', jsType: 'object', ...extra };
93
35
  }
94
- function enumField(extra) {
36
+ export function enumField(extra) {
95
37
  const jsType = extra.enum.valueType === 'integer' ? 'number' : 'string';
96
38
  return { name: '', type: 'enum', jsType, ...extra };
97
39
  }
98
- function defineTable(name, schema) {
99
- const table = new TableSchema(name, schema);
100
- for (const key of Object.keys(table.fields)) {
101
- const field = table.fields[key];
102
- if (field.schema && field.schema !== table) {
103
- throw new Error(`field ${key}: belongs to table ${field.schema.name}, cannot reuse in table ${table.name}`);
104
- }
105
- }
106
- for (const key of Object.keys(table.fields)) {
107
- table.fields[key].name = key;
108
- table.fields[key].schema = table;
109
- }
110
- for (const [fkName, fk] of Object.entries(table.foreignKeys ?? {})) {
111
- const refs = Array.isArray(fk.references) ? fk.references : [fk.references];
112
- const fields = Array.isArray(fk.fields) ? fk.fields : [fk.fields];
113
- for (let i = 0; i < refs.length; i++) {
114
- const ref = refs[i];
115
- if (!ref.schema)
116
- throw new Error(`foreign key ${fkName}: references field has no schema`);
117
- if (ref.schema === table)
118
- throw new Error(`foreign key ${fkName}: cannot reference own table ${table.name}`);
119
- const phrase = ref.schema.phrase;
120
- if (!phrase)
121
- throw new Error(`foreign key ${fkName}: referenced table ${ref.schema.name} has no phrase, cannot check field naming`);
122
- const expected = `${phrase.name}_${ref.name}`;
123
- const fkField = fields[i];
124
- if (fkField.name !== expected) {
125
- throw new Error(`foreign key ${fkName}: field must be named ${expected} (phrase ${phrase.name} + ${ref.name}), got ${fkField.name}`);
126
- }
127
- }
128
- }
129
- return table;
130
- }
package/dist/dto.d.ts CHANGED
@@ -1,15 +1,18 @@
1
- import { BaseField, CollectionSchemaBase, Field, SchemaBase, TableSchema } from './dsl';
2
- export type Operator = 'eq' | 'gt' | 'gte' | 'lt' | 'lte' | 'like' | 'ne';
1
+ import { BaseField, CollectionSchemaBase, Field, Operator, SchemaBase } from './dsl.js';
2
+ import { TableSchema } from './db.js';
3
+ import type { ImportBase } from './import-base.js';
4
+ /** Re-export — Operator lives on the DSL level (see dsl.ts). */
5
+ export type { Operator } from './dsl.js';
6
+ /** Re-export — ImportBase lives on its own module (see import-base.ts). */
7
+ export type { ImportBase } from './import-base.js';
8
+ /** Re-export — MockDescriptor lives on its own module (see mock.ts). */
9
+ export type { MockDescriptor } from './mock.js';
3
10
  /**
4
11
  * Reference to an existing TypeBox base schema by its import location.
5
12
  * Serializable metadata: the driver renders `import { name } from 'from'`
6
13
  * and `Type.Intersect([name, ...])` — the runtime schema is never loaded by the DSL.
7
14
  */
8
- export interface ImportRef {
9
- /** Module specifier, e.g. '@pylonts/core' */
10
- from: string;
11
- /** Named export, e.g. 'PageRequest' */
12
- name: string;
15
+ export interface ImportRef extends ImportBase {
13
16
  /**
14
17
  * Generic type arguments for the base schema (e.g. PageResult(OrderRow)).
15
18
  * Two forms, both local DTOs:
package/dist/dto.js CHANGED
@@ -1,16 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DtoMessage = exports.DtoDirection = exports.DtoObjectField = exports.DtoArrayField = exports.DtoField = void 0;
4
- exports.dtoField = dtoField;
5
- exports.dtoArrayField = dtoArrayField;
6
- exports.dtoObjectField = dtoObjectField;
7
- exports.buildInput = buildInput;
8
- exports.buildOutput = buildOutput;
9
- exports.buildQuery = buildQuery;
10
- exports.buildPk = buildPk;
11
- exports.from = from;
12
- const utils_1 = require("./utils");
13
- class DtoField {
1
+ import { toCamelCase } from './utils.js';
2
+ export class DtoField {
14
3
  /** DTO 语义字段名(接口字段名),与 field.name(数据库列名)含义不同。
15
4
  * 构造时未知,由 buildMessage 从 map key 反写。 */
16
5
  name;
@@ -64,28 +53,25 @@ class DtoField {
64
53
  return this.field.optional ?? false;
65
54
  }
66
55
  }
67
- exports.DtoField = DtoField;
68
- class DtoArrayField extends DtoField {
56
+ export class DtoArrayField extends DtoField {
69
57
  /** Element type: inline DtoField or a referenced DtoMessage (rendered by name). */
70
58
  items() {
71
59
  return this.field.items;
72
60
  }
73
61
  }
74
- exports.DtoArrayField = DtoArrayField;
75
- class DtoObjectField extends DtoField {
62
+ export class DtoObjectField extends DtoField {
76
63
  properties() {
77
64
  return this.field.properties;
78
65
  }
79
66
  }
80
- exports.DtoObjectField = DtoObjectField;
81
- var DtoDirection;
67
+ export var DtoDirection;
82
68
  (function (DtoDirection) {
83
69
  DtoDirection["Input"] = "input";
84
70
  DtoDirection["Output"] = "output";
85
71
  DtoDirection["Query"] = "query";
86
72
  DtoDirection["Pk"] = "pk";
87
- })(DtoDirection || (exports.DtoDirection = DtoDirection = {}));
88
- class DtoMessage {
73
+ })(DtoDirection || (DtoDirection = {}));
74
+ export class DtoMessage {
89
75
  type = 'dto';
90
76
  name;
91
77
  description;
@@ -106,16 +92,15 @@ class DtoMessage {
106
92
  return this;
107
93
  }
108
94
  }
109
- exports.DtoMessage = DtoMessage;
110
- function dtoField(field) {
95
+ export function dtoField(field) {
111
96
  return new DtoField(field);
112
97
  }
113
- function dtoArrayField(def) {
98
+ export function dtoArrayField(def) {
114
99
  // Items stay as-is: an inline DtoField is rendered inline, a DtoMessage is
115
100
  // referenced by name (the driver renders Type.Array(<DtoName>)).
116
101
  return new DtoArrayField({ name: '', type: 'array', jsType: 'array', ...def });
117
102
  }
118
- function dtoObjectField(def) {
103
+ export function dtoObjectField(def) {
119
104
  return new DtoObjectField({ name: '', type: 'object', jsType: 'object', ...def });
120
105
  }
121
106
  function buildMessage(name, direction, fields, description) {
@@ -124,6 +109,11 @@ function buildMessage(name, direction, fields, description) {
124
109
  // are created per DTO, never shared).
125
110
  for (const key of Object.keys(message.fields)) {
126
111
  const df = message.fields[key];
112
+ if (!(df instanceof DtoField)) {
113
+ const got = df === null || df === undefined ? String(df) : `${df.constructor.name ?? typeof df}`;
114
+ throw new Error(`[dto] DTO "${name}" field "${key}" must be a DtoField (created with dtoField()/dtoArrayField()/dtoObjectField()), got ${got}. ` +
115
+ `Did you pass enumField(...) directly? Use dtoField(enumField({...})) instead.`);
116
+ }
127
117
  df.name = key;
128
118
  df.schema = message;
129
119
  // Custom (inline) fields are owned by this DTO: write back name + schema.
@@ -136,10 +126,11 @@ function buildMessage(name, direction, fields, description) {
136
126
  }
137
127
  return message;
138
128
  }
139
- function buildInput(name, fields, description) {
129
+ export function buildInput(name, fields, description) {
140
130
  const message = buildMessage(name, DtoDirection.Input, fields, description);
141
131
  // Rule A — set optionality from the DB column rule (skips fields the author
142
- // already set): nullable / default / auto-increment → optional, else required.
132
+ // already set): nullable / default → optional, else required.
133
+ // PK columns are always required.
143
134
  for (const field of Object.values(message.fields)) {
144
135
  if (field.optional !== undefined)
145
136
  continue;
@@ -147,21 +138,21 @@ function buildInput(name, fields, description) {
147
138
  if (f.schema?.type !== 'table')
148
139
  continue;
149
140
  const table = f.schema;
150
- field.optional = f.optional !== false || f.default !== undefined || table.autoIncrement === f;
141
+ field.optional = table.isPk(f) ? false : f.optional !== false || f.default !== undefined;
151
142
  }
152
143
  return message;
153
144
  }
154
- function buildOutput(name, fields, description) {
145
+ export function buildOutput(name, fields, description) {
155
146
  return buildMessage(name, DtoDirection.Output, fields, description);
156
147
  }
157
- function buildQuery(name, fields, description) {
148
+ export function buildQuery(name, fields, description) {
158
149
  const message = buildMessage(name, DtoDirection.Query, fields, description);
159
150
  // Rule B: query/search fields are always optional.
160
151
  for (const field of Object.values(message.fields))
161
152
  field.optional = true;
162
153
  return message;
163
154
  }
164
- function buildPk(name, fields, description) {
155
+ export function buildPk(name, fields, description) {
165
156
  const message = buildMessage(name, DtoDirection.Pk, fields, description);
166
157
  // Rule P: PK locator fields are required, other fields are optional.
167
158
  for (const field of Object.values(message.fields)) {
@@ -174,7 +165,7 @@ function buildPk(name, fields, description) {
174
165
  return message;
175
166
  }
176
167
  /** Pick columns from a built table and wrap them as DTO fields (aligned with dto.from). */
177
- function from(table, fields) {
168
+ export function from(table, fields) {
178
169
  const out = {};
179
170
  for (const field of fields) {
180
171
  if (field.schema !== table) {
@@ -182,7 +173,7 @@ function from(table, fields) {
182
173
  }
183
174
  // DTO field name is camelCase (mer_id → merId); the underlying field.name
184
175
  // stays snake_case (DB column).
185
- out[(0, utils_1.toCamelCase)(field.name)] = dtoField(field);
176
+ out[toCamelCase(field.name)] = dtoField(field);
186
177
  }
187
178
  return out;
188
179
  }
@@ -1,2 +1,2 @@
1
- import { EnumDef } from './dsl';
1
+ import { EnumDef } from './dsl.js';
2
2
  export declare function renderEnum(def: EnumDef): string;
@@ -1,6 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.renderEnum = renderEnum;
4
1
  // Enum driver: renders an EnumDef into a standalone TypeScript enum file.
5
2
  // Shape matches the generated-enum product consumed by the TypeBox driver (Type.Enum):
6
3
  //
@@ -23,7 +20,7 @@ function renderValue(value) {
23
20
  function labelName(jsName) {
24
21
  return `${jsName.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase()}_LABEL`;
25
22
  }
26
- function renderEnum(def) {
23
+ export function renderEnum(def) {
27
24
  const name = def.jsName;
28
25
  const members = def.values.map((v) => ` ${v.symbol} = ${renderValue(v.value)},`);
29
26
  const labels = def.values.map((v) => ` [${name}.${v.symbol}]: ${renderString(v.label)},`);
package/dist/flow.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SchemaBase } from './dsl';
1
+ import { SchemaBase } from './dsl.js';
2
2
  export interface FlowNode extends SchemaBase {
3
3
  /** Optional sub-flow. When present, entering this node runs the sub-flow;
4
4
  * after the sub-flow reaches any terminal node, the outer flow continues
package/dist/flow.js CHANGED
@@ -1,16 +1,11 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.node = node;
4
- exports.edge = edge;
5
- exports.defineFlow = defineFlow;
6
- function node(name, flow, description) {
1
+ export function node(name, flow, description) {
7
2
  return { name, flow, description };
8
3
  }
9
- function edge(start, end, when, description) {
4
+ export function edge(start, end, when, description) {
10
5
  // Auto name for uniformity with SchemaBase; `when` stays the branch marker.
11
6
  return { name: `${start.name}->${end.name}`, start, end, when, description };
12
7
  }
13
- function defineFlow(name, schema) {
8
+ export function defineFlow(name, schema) {
14
9
  const seen = new Set();
15
10
  const nodes = [];
16
11
  for (const e of schema.edges) {
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Reference to a named export from another module, by its import location.
3
+ * Serializable metadata: the driver renders `import { name } from 'from'`.
4
+ * Used for enum types and plain imports that need no generic arguments.
5
+ */
6
+ export interface ImportBase {
7
+ /** Module specifier, e.g. '@pylonts/core' */
8
+ from: string;
9
+ /** Named export, e.g. 'PageRequest' */
10
+ name: string;
11
+ /** Type-only import (`import type`); defaults to a value import. */
12
+ type?: boolean;
13
+ /** Default import (`import X from '...'`) instead of named (`import { X }`). */
14
+ default?: boolean;
15
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,17 +1,21 @@
1
- export * from './dsl';
2
- export * from './dto';
3
- export * from './bases';
4
- export * from './utils';
5
- export * from './project';
6
- export * from './prototype';
7
- export * from './dictionary';
8
- export * from './mysql-driver';
9
- export * from './enum-driver';
10
- export * from './typebox-driver';
11
- export * from './check-inheritance';
12
- export * from './pattern';
13
- export * from './patterns/retry';
14
- export * from './flow';
15
- export * from './page';
16
- export * from './page-flow';
17
- export * from './mermaid-driver';
1
+ export * from './dsl.js';
2
+ export * from './db.js';
3
+ export * from './mock.js';
4
+ export * from './asset.js';
5
+ export * from './dto.js';
6
+ export * from './db-config.js';
7
+ export * from './bases.js';
8
+ export * from './utils.js';
9
+ export * from './project.js';
10
+ export * from './prototype.js';
11
+ export * from './dictionary.js';
12
+ export * from './mysql-driver.js';
13
+ export * from './enum-driver.js';
14
+ export * from './typebox-driver.js';
15
+ export * from './pattern.js';
16
+ export * from './patterns/retry.js';
17
+ export * from './flow.js';
18
+ export * from './page.js';
19
+ export * from './curd.js';
20
+ export * from './page-flow.js';
21
+ export * from './mermaid-driver.js';
package/dist/index.js CHANGED
@@ -1,33 +1,21 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./dsl"), exports);
18
- __exportStar(require("./dto"), exports);
19
- __exportStar(require("./bases"), exports);
20
- __exportStar(require("./utils"), exports);
21
- __exportStar(require("./project"), exports);
22
- __exportStar(require("./prototype"), exports);
23
- __exportStar(require("./dictionary"), exports);
24
- __exportStar(require("./mysql-driver"), exports);
25
- __exportStar(require("./enum-driver"), exports);
26
- __exportStar(require("./typebox-driver"), exports);
27
- __exportStar(require("./check-inheritance"), exports);
28
- __exportStar(require("./pattern"), exports);
29
- __exportStar(require("./patterns/retry"), exports);
30
- __exportStar(require("./flow"), exports);
31
- __exportStar(require("./page"), exports);
32
- __exportStar(require("./page-flow"), exports);
33
- __exportStar(require("./mermaid-driver"), exports);
1
+ export * from './dsl.js';
2
+ export * from './db.js';
3
+ export * from './mock.js';
4
+ export * from './asset.js';
5
+ export * from './dto.js';
6
+ export * from './db-config.js';
7
+ export * from './bases.js';
8
+ export * from './utils.js';
9
+ export * from './project.js';
10
+ export * from './prototype.js';
11
+ export * from './dictionary.js';
12
+ export * from './mysql-driver.js';
13
+ export * from './enum-driver.js';
14
+ export * from './typebox-driver.js';
15
+ export * from './pattern.js';
16
+ export * from './patterns/retry.js';
17
+ export * from './flow.js';
18
+ export * from './page.js';
19
+ export * from './curd.js';
20
+ export * from './page-flow.js';
21
+ export * from './mermaid-driver.js';
@@ -1,4 +1,4 @@
1
- import { FlowSchema } from './flow';
2
- import { PageFlow } from './page-flow';
1
+ import { FlowSchema } from './flow.js';
2
+ import { PageFlow } from './page-flow.js';
3
3
  export declare function renderFlowMermaid(schema: FlowSchema): string;
4
4
  export declare function renderPageFlowMermaid(schema: PageFlow): string;
@@ -1,7 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.renderFlowMermaid = renderFlowMermaid;
4
- exports.renderPageFlowMermaid = renderPageFlowMermaid;
5
1
  // Mermaid driver: converts a FlowSchema into a Mermaid flowchart (TD).
6
2
  // Node ids are hierarchical (n0, n0_0, n0_0_0, ...) so nested sub-flows stay
7
3
  // globally unique. A node with a sub-flow renders as a subgraph block whose
@@ -10,7 +6,7 @@ exports.renderPageFlowMermaid = renderPageFlowMermaid;
10
6
  function escapeLabel(s) {
11
7
  return s.replace(/"/g, '\\"').replace(/\n/g, '<br/>');
12
8
  }
13
- function renderFlowMermaid(schema) {
9
+ export function renderFlowMermaid(schema) {
14
10
  const lines = ['flowchart TD'];
15
11
  const ids = new Map();
16
12
  renderFlow(schema, 'n', lines, ids);
@@ -42,7 +38,7 @@ function renderEdge(e, ids) {
42
38
  }
43
39
  // Page-driven flow renderer: groups pages by their app into swimlane
44
40
  // subgraphs, then renders edges across the whole flow.
45
- function renderPageFlowMermaid(schema) {
41
+ export function renderPageFlowMermaid(schema) {
46
42
  const lines = ['flowchart TD'];
47
43
  const ids = new Map();
48
44
  const byApp = new Map();
package/dist/mock.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Pure-data mock descriptor. Stored on DTO fields, consumed by gen-cli mock
3
+ * or runtime resolveMock. No function references — serializable and gen-readable.
4
+ *
5
+ * @example { fn: 'abc', count: 20 }
6
+ * @example { fn: 'amt', min: 10, max: 500 }
7
+ * @example { fn: 'phone' }
8
+ */
9
+ export interface MockDescriptor {
10
+ fn: string;
11
+ [param: string]: unknown;
12
+ }
13
+ /**
14
+ * Result of a descriptor factory call: pure-data descriptor + lazy generator.
15
+ * generate is non-enumerable — JSON.stringify / spread won't pick it up.
16
+ */
17
+ export interface MockSchema {
18
+ descriptor: MockDescriptor;
19
+ generate: () => unknown;
20
+ }
21
+ type Params = Record<string, unknown>;
22
+ /**
23
+ * Define a mock descriptor factory.
24
+ *
25
+ * @param fn mock function name (for descriptor & dispatch)
26
+ * @param resolve converts descriptor params to a no-arg generator
27
+ * @returns (params?) => { descriptor, generate }
28
+ */
29
+ export declare function defineMock(fn: string, resolve: (d: Params) => () => unknown): (params?: Params) => MockSchema;
30
+ export {};
package/dist/mock.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Define a mock descriptor factory.
3
+ *
4
+ * @param fn mock function name (for descriptor & dispatch)
5
+ * @param resolve converts descriptor params to a no-arg generator
6
+ * @returns (params?) => { descriptor, generate }
7
+ */
8
+ export function defineMock(fn, resolve) {
9
+ return (params) => {
10
+ const d = { fn, ...params };
11
+ const result = { descriptor: d };
12
+ Object.defineProperty(result, 'generate', {
13
+ value: resolve(d),
14
+ enumerable: false,
15
+ });
16
+ return result;
17
+ };
18
+ }
@@ -1,4 +1,4 @@
1
- import { TableSchema } from './dsl';
1
+ import { TableSchema } from './db.js';
2
2
  export interface BuildCreateTableSqlOptions {
3
3
  /** 是否生成外键约束,默认 false(不生成) */
4
4
  generateForeignKeys?: boolean;
@@ -1,6 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildCreateTableSql = buildCreateTableSql;
4
1
  // MySQL driver: converts a TableSchema into a CREATE TABLE statement.
5
2
  function columnType(field) {
6
3
  switch (field.type) {
@@ -31,14 +28,27 @@ function columnType(field) {
31
28
  return 'JSON';
32
29
  }
33
30
  }
31
+ function renderDefault(field) {
32
+ if (field.default === undefined)
33
+ return '';
34
+ // CURRENT_TIMESTAMP is a MySQL function keyword, not a string literal.
35
+ if (field.default === 'CURRENT_TIMESTAMP')
36
+ return ' DEFAULT CURRENT_TIMESTAMP';
37
+ // Numeric columns take a bare literal, not a quoted one.
38
+ if (field.type === 'integer' || field.type === 'bigint' || field.type === 'decimal' || field.type === 'boolean') {
39
+ return ` DEFAULT ${field.default}`;
40
+ }
41
+ return ` DEFAULT '${field.default}'`;
42
+ }
34
43
  function columnDef(field, autoIncrement) {
35
44
  const parts = [field.name, columnType(field)];
36
45
  if (field.optional === false)
37
46
  parts.push('NOT NULL');
38
- if (field.default !== undefined)
39
- parts.push(`DEFAULT '${field.default}'`);
47
+ parts.push(renderDefault(field));
40
48
  if (field === autoIncrement)
41
49
  parts.push('AUTO_INCREMENT');
50
+ if (field.description)
51
+ parts.push(`COMMENT '${field.description.replace(/'/g, "\\'")}'`);
42
52
  return parts.join(' ');
43
53
  }
44
54
  function primaryKeyClause(schema) {
@@ -48,13 +58,13 @@ function primaryKeyClause(schema) {
48
58
  return `PRIMARY KEY (${fields.map((f) => f.name).join(', ')})`;
49
59
  }
50
60
  function indexClause(index) {
51
- const fields = Array.isArray(index.fields) ? index.fields : [index.fields];
61
+ const fields = Array.isArray(index.columns) ? index.columns : [index.columns];
52
62
  const kind = index.unique ? 'UNIQUE KEY' : 'KEY';
53
63
  const name = index.name ?? fields.map((f) => f.name).join('_');
54
64
  return `${kind} ${name} (${fields.map((f) => f.name).join(', ')})`;
55
65
  }
56
66
  function foreignKeyClause(name, fk) {
57
- const fields = Array.isArray(fk.fields) ? fk.fields : [fk.fields];
67
+ const fields = Array.isArray(fk.columns) ? fk.columns : [fk.columns];
58
68
  const refs = Array.isArray(fk.references) ? fk.references : [fk.references];
59
69
  const refTable = refs[0].schema?.name;
60
70
  if (!refTable)
@@ -63,8 +73,8 @@ function foreignKeyClause(name, fk) {
63
73
  const refCols = refs.map((r) => r.name).join(', ');
64
74
  return `CONSTRAINT \`${name}\` FOREIGN KEY (${fkCols}) REFERENCES \`${refTable}\` (${refCols})`;
65
75
  }
66
- function buildCreateTableSql(schema, options = {}) {
67
- const lines = Object.values(schema.fields).map((field) => columnDef(field, schema.autoIncrement));
76
+ export function buildCreateTableSql(schema, options = {}) {
77
+ const lines = Object.values(schema.columns).map((field) => columnDef(field, schema.autoIncrement));
68
78
  const pk = primaryKeyClause(schema);
69
79
  if (pk)
70
80
  lines.push(pk);
@@ -75,5 +85,5 @@ function buildCreateTableSql(schema, options = {}) {
75
85
  lines.push(foreignKeyClause(name, fk));
76
86
  }
77
87
  }
78
- return `CREATE TABLE \`${schema.name}\` (\n ${lines.join(',\n ')}\n);`;
88
+ return `CREATE TABLE IF NOT EXISTS \`${schema.name}\` (\n ${lines.join(',\n ')}\n);`;
79
89
  }
@@ -1,5 +1,5 @@
1
- import { SchemaBase } from './dsl';
2
- import { ActionSchema, Page } from './page';
1
+ import { SchemaBase } from './dsl.js';
2
+ import { ActionSchema, Page } from './page.js';
3
3
  export interface PageEdge extends SchemaBase {
4
4
  /** Trigger action; undefined = default path (success/normal). */
5
5
  when?: ActionSchema;