@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.
- package/README.md +2 -1
- package/dist/asset.d.ts +48 -0
- package/dist/asset.js +31 -0
- package/dist/bases.d.ts +6 -2
- package/dist/bases.js +10 -6
- package/dist/check-inheritance.js +1 -4
- package/dist/curd.d.ts +60 -0
- package/dist/curd.js +31 -0
- package/dist/db-config.d.ts +8 -0
- package/dist/db-config.js +1 -0
- package/dist/db.d.ts +52 -0
- package/dist/db.js +91 -0
- package/dist/dictionary.d.ts +26 -5
- package/dist/dictionary.js +21 -8
- package/dist/dsl.d.ts +5 -49
- package/dist/dsl.js +12 -103
- package/dist/dto.d.ts +10 -7
- package/dist/dto.js +24 -33
- package/dist/enum-driver.d.ts +1 -1
- package/dist/enum-driver.js +1 -4
- package/dist/flow.d.ts +1 -1
- package/dist/flow.js +3 -8
- package/dist/import-base.d.ts +15 -0
- package/dist/import-base.js +1 -0
- package/dist/index.d.ts +21 -17
- package/dist/index.js +21 -33
- package/dist/mermaid-driver.d.ts +2 -2
- package/dist/mermaid-driver.js +2 -6
- package/dist/mock.d.ts +30 -0
- package/dist/mock.js +18 -0
- package/dist/mysql-driver.d.ts +1 -1
- package/dist/mysql-driver.js +20 -10
- package/dist/page-flow.d.ts +2 -2
- package/dist/page-flow.js +2 -6
- package/dist/page.d.ts +6 -6
- package/dist/page.js +3 -8
- package/dist/pattern.js +2 -6
- package/dist/patterns/retry.d.ts +1 -1
- package/dist/patterns/retry.js +2 -6
- package/dist/project.d.ts +18 -13
- package/dist/project.js +41 -6
- package/dist/prototype.d.ts +1 -1
- package/dist/prototype.js +1 -4
- package/dist/typebox-driver.d.ts +3 -3
- package/dist/typebox-driver.js +24 -26
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +5 -4
- package/docs/curd.md +111 -0
- package/docs/dictionary.md +42 -31
- package/docs/driver.md +42 -42
- package/docs/dto.md +66 -66
- package/docs/enum.md +24 -24
- package/docs/project.md +2 -2
- package/docs/table.md +50 -15
- package/package.json +6 -4
- package/src/asset.ts +63 -0
- package/src/bases.ts +12 -2
- package/src/curd.ts +92 -0
- package/src/db-config.ts +8 -0
- package/src/db.ts +142 -0
- package/src/dictionary.ts +45 -19
- package/src/dsl.ts +182 -281
- package/src/dto.ts +247 -234
- package/src/enum-driver.ts +1 -1
- package/src/flow.ts +1 -1
- package/src/import-base.ts +15 -0
- package/src/index.ts +21 -17
- package/src/mermaid-driver.ts +3 -3
- package/src/mock.ts +45 -0
- package/src/mysql-driver.ts +19 -6
- package/src/page-flow.ts +3 -3
- package/src/page.ts +7 -7
- package/src/patterns/retry.ts +1 -1
- package/src/project.ts +90 -54
- package/src/prototype.ts +1 -1
- package/src/typebox-driver.ts +192 -187
- package/src/utils.ts +5 -0
- 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
|
-
|
|
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
|
-
|
|
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,
|
|
2
|
-
|
|
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
|
-
|
|
2
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 || (
|
|
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
|
-
|
|
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
|
|
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
|
|
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[
|
|
176
|
+
out[toCamelCase(field.name)] = dtoField(field);
|
|
186
177
|
}
|
|
187
178
|
return out;
|
|
188
179
|
}
|
package/dist/enum-driver.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { EnumDef } from './dsl';
|
|
1
|
+
import { EnumDef } from './dsl.js';
|
|
2
2
|
export declare function renderEnum(def: EnumDef): string;
|
package/dist/enum-driver.js
CHANGED
|
@@ -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
|
-
|
|
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 './
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
10
|
-
export * from './
|
|
11
|
-
export * from './
|
|
12
|
-
export * from './
|
|
13
|
-
export * from './
|
|
14
|
-
export * from './
|
|
15
|
-
export * from './
|
|
16
|
-
export * from './
|
|
17
|
-
export * from './
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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';
|
package/dist/mermaid-driver.d.ts
CHANGED
|
@@ -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;
|
package/dist/mermaid-driver.js
CHANGED
|
@@ -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
|
+
}
|
package/dist/mysql-driver.d.ts
CHANGED
package/dist/mysql-driver.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
}
|
package/dist/page-flow.d.ts
CHANGED
|
@@ -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;
|