@pylonts/dsl 1.1.5 → 1.1.11
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 +4 -0
- package/dist/action.d.ts +32 -0
- package/dist/action.js +14 -0
- package/dist/aggregate.d.ts +38 -0
- package/dist/aggregate.js +46 -0
- package/dist/business-flow.d.ts +9 -0
- package/dist/business-flow.js +72 -0
- package/dist/controller.d.ts +35 -0
- package/dist/controller.js +17 -0
- package/dist/convert.d.ts +37 -7
- package/dist/convert.js +23 -2
- package/dist/curd.d.ts +7 -12
- package/dist/curd.js +10 -1
- package/dist/dao.d.ts +140 -3
- package/dist/dao.js +307 -2
- package/dist/db.d.ts +6 -0
- package/dist/db.js +13 -0
- package/dist/domain-event.d.ts +48 -0
- package/dist/domain-event.js +24 -0
- package/dist/dsl.d.ts +32 -2
- package/dist/dsl.js +13 -0
- package/dist/dto.d.ts +8 -2
- package/dist/dto.js +21 -9
- package/dist/endpoint.d.ts +15 -0
- package/dist/endpoint.js +3 -0
- package/dist/entity.d.ts +29 -0
- package/dist/entity.js +13 -0
- package/dist/exception.d.ts +20 -0
- package/dist/exception.js +33 -0
- package/dist/expr.d.ts +45 -0
- package/dist/expr.js +32 -0
- package/dist/field-rule.d.ts +20 -0
- package/dist/field-rule.js +19 -0
- package/dist/filter.d.ts +45 -0
- package/dist/filter.js +21 -0
- package/dist/flow-script.d.ts +108 -0
- package/dist/flow-script.js +505 -0
- package/dist/flow.d.ts +309 -10
- package/dist/flow.js +819 -22
- package/dist/index.d.ts +12 -1
- package/dist/index.js +14 -1
- package/dist/mermaid-driver.js +278 -9
- package/dist/method.d.ts +11 -0
- package/dist/method.js +3 -0
- package/dist/mysql-driver.js +7 -0
- package/dist/project.d.ts +5 -4
- package/dist/project.js +14 -2
- package/dist/provider.d.ts +6 -11
- package/dist/provider.js +2 -2
- package/dist/repository.d.ts +26 -0
- package/dist/repository.js +8 -0
- package/dist/service.d.ts +30 -8
- package/dist/service.js +62 -2
- package/dist/third-service.d.ts +80 -0
- package/dist/third-service.js +97 -0
- package/dist/typebox-driver.d.ts +6 -0
- package/dist/typebox-driver.js +77 -12
- package/dist/utils.d.ts +32 -10
- package/dist/utils.js +32 -11
- package/docs/aggregate.md +110 -0
- package/docs/dao-generation.md +478 -0
- package/docs/ddd-principles.md +75 -0
- package/docs/domain-event.md +137 -0
- package/docs/dto.md +73 -66
- package/docs/keyword-matcher.md +182 -0
- package/docs/third-service.md +122 -0
- package/docs/token.md +327 -0
- package/docs/trans-reentrant.md +85 -0
- package/package.json +27 -5
- package/src/action.ts +51 -10
- package/src/aggregate.ts +104 -0
- package/src/business-flow.ts +80 -0
- package/src/controller.ts +54 -0
- package/src/convert.ts +78 -15
- package/src/curd.ts +104 -93
- package/src/dao.ts +486 -13
- package/src/db.ts +199 -181
- package/src/domain-event.ts +74 -0
- package/src/dsl.ts +48 -2
- package/src/dto.ts +266 -247
- package/src/entity.ts +43 -0
- package/src/exception.ts +53 -0
- package/src/expr.ts +65 -0
- package/src/field-rule.ts +47 -0
- package/src/filter.ts +70 -0
- package/src/flow-script.ts +696 -0
- package/src/flow.ts +1226 -103
- package/src/index.ts +47 -33
- package/src/mermaid-driver.ts +339 -84
- package/src/method.ts +20 -0
- package/src/mysql-driver.ts +7 -0
- package/src/project.ts +114 -97
- package/src/repository.ts +35 -0
- package/src/service.ts +107 -20
- package/src/third-service.ts +192 -0
- package/src/typebox-driver.ts +86 -11
- package/src/utils.ts +74 -26
- package/dist/check-inheritance.d.ts +0 -9
- package/dist/check-inheritance.js +0 -58
- package/src/provider.ts +0 -73
package/src/expr.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Value expression model: the single declarative way to express computed
|
|
2
|
+
// values in dao methods — update SET expressions and criteria right sides.
|
|
3
|
+
// Structural AST (never SQL strings): column references are Field objects
|
|
4
|
+
// (definition-time ownership checks), values bind as parameters at render
|
|
5
|
+
// time. New node kinds can be added without touching existing declarations.
|
|
6
|
+
|
|
7
|
+
import type { Field } from './dsl.js';
|
|
8
|
+
|
|
9
|
+
/** Binary operator on numeric values. */
|
|
10
|
+
export type BinOp = 'add' | 'sub' | 'mul' | 'div';
|
|
11
|
+
|
|
12
|
+
/** A value expression: column reference / literal / method parameter / binary
|
|
13
|
+
* operation. Recursive — leaves are col/lit/param, bin combines them. */
|
|
14
|
+
export type ValueExpr =
|
|
15
|
+
| { kind: 'col'; field: Field }
|
|
16
|
+
| { kind: 'lit'; value: string | number }
|
|
17
|
+
| { kind: 'param'; name: string }
|
|
18
|
+
| { kind: 'bin'; op: BinOp; left: ValueExpr; right: ValueExpr };
|
|
19
|
+
|
|
20
|
+
/** An update SET assignment: `col = expr` (besides the direct-assignment
|
|
21
|
+
* columns carried by the args entity — a column must not appear in both). */
|
|
22
|
+
export interface SetExpr {
|
|
23
|
+
col: Field;
|
|
24
|
+
expr: ValueExpr;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function col(field: Field): ValueExpr {
|
|
28
|
+
return { kind: 'col', field };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function lit(value: string | number): ValueExpr {
|
|
32
|
+
return { kind: 'lit', value };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function param(name: string): ValueExpr {
|
|
36
|
+
return { kind: 'param', name };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function bin(op: BinOp, left: ValueExpr, right: ValueExpr): ValueExpr {
|
|
40
|
+
return { kind: 'bin', op, left, right };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Convenience builders for the common self-increment/decrement shapes. */
|
|
44
|
+
export const incr = (field: Field, by: ValueExpr): SetExpr => ({ col: field, expr: bin('add', col(field), by) });
|
|
45
|
+
export const decr = (field: Field, by: ValueExpr): SetExpr => ({ col: field, expr: bin('sub', col(field), by) });
|
|
46
|
+
|
|
47
|
+
/** Aggregate expression result of an aggregate query column. */
|
|
48
|
+
export interface ComputeExpr {
|
|
49
|
+
fn: 'sum' | 'avg' | 'count';
|
|
50
|
+
/** Column the function applies to; absent for count(*). */
|
|
51
|
+
field?: Field;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Aggregate expressions: Compute.sum(col) / Compute.avg(col) / Compute.count(). */
|
|
55
|
+
export const Compute = {
|
|
56
|
+
sum(field: Field): ComputeExpr {
|
|
57
|
+
return { fn: 'sum', field };
|
|
58
|
+
},
|
|
59
|
+
avg(field: Field): ComputeExpr {
|
|
60
|
+
return { fn: 'avg', field };
|
|
61
|
+
},
|
|
62
|
+
count(): ComputeExpr {
|
|
63
|
+
return { fn: 'count' };
|
|
64
|
+
},
|
|
65
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { SchemaBase } from './dsl.js';
|
|
2
|
+
|
|
3
|
+
// Field rules: the third semantic dimension of a Field. A rule is a named
|
|
4
|
+
// transformation between two ends — scale (fen↔yuan), encrypt/decrypt,
|
|
5
|
+
// mask/unmask. The rule owns both ends; a binding says which field plays
|
|
6
|
+
// which end. Rules are unique per semantic name (checked at definition).
|
|
7
|
+
|
|
8
|
+
/** One end of a field rule (e.g. 'fen' / 'yuan', 'plain' / 'cipher', 'raw' / 'masked'). */
|
|
9
|
+
export interface FieldRuleEnd {
|
|
10
|
+
/** End name — written back by defineFieldRule from the ends map key. */
|
|
11
|
+
name: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A semantic transformation rule between two field representations. */
|
|
16
|
+
export interface FieldRuleSchema extends SchemaBase {
|
|
17
|
+
type: 'fieldRule';
|
|
18
|
+
/** Rule name — the semantic uniqueness key. */
|
|
19
|
+
name: string;
|
|
20
|
+
/** The two ends of the rule, keyed by end name. */
|
|
21
|
+
ends: Record<string, FieldRuleEnd>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** One rule per semantic name. Defining the same name twice throws. */
|
|
25
|
+
const ruleRegistry = new Map<string, FieldRuleSchema>();
|
|
26
|
+
|
|
27
|
+
export function defineFieldRule(options: {
|
|
28
|
+
name: string;
|
|
29
|
+
ends: Record<string, Omit<FieldRuleEnd, 'name'>>;
|
|
30
|
+
description?: string;
|
|
31
|
+
}): FieldRuleSchema {
|
|
32
|
+
if (ruleRegistry.has(options.name)) {
|
|
33
|
+
throw new Error(`fieldRule '${options.name}' is already defined — one rule per semantic`);
|
|
34
|
+
}
|
|
35
|
+
const ends: Record<string, FieldRuleEnd> = {};
|
|
36
|
+
for (const key of Object.keys(options.ends)) {
|
|
37
|
+
ends[key] = { name: key, description: options.ends[key].description };
|
|
38
|
+
}
|
|
39
|
+
const rule: FieldRuleSchema = {
|
|
40
|
+
type: 'fieldRule',
|
|
41
|
+
name: options.name,
|
|
42
|
+
description: options.description,
|
|
43
|
+
ends,
|
|
44
|
+
};
|
|
45
|
+
ruleRegistry.set(options.name, rule);
|
|
46
|
+
return rule;
|
|
47
|
+
}
|
package/src/filter.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Field, Operator, SchemaBase } from './dsl.js';
|
|
2
|
+
import type { ValueExpr } from './expr.js';
|
|
3
|
+
import type { FrontAppSchema, ProjectApiSchema } from './project.js';
|
|
4
|
+
|
|
5
|
+
// Filter: the single declarative model for query conditions, shared by
|
|
6
|
+
// dao_schema methods and curd page lists. Conditions are AND-combined and
|
|
7
|
+
// may reference any table (cross-table filters render JOINs at the usage
|
|
8
|
+
// site, which owns the main table). Pagination is NOT part of a filter —
|
|
9
|
+
// it stays on the dao method (mode) and the curd list config.
|
|
10
|
+
|
|
11
|
+
/** One AND-combined criterion: a column plus its comparison operator. */
|
|
12
|
+
export interface FilterCondition {
|
|
13
|
+
/** Column to compare (any table — cross-table filters are allowed). */
|
|
14
|
+
field: Field;
|
|
15
|
+
/** Comparison operator; defaults to 'eq'. */
|
|
16
|
+
op?: Operator;
|
|
17
|
+
/** Right side of the comparison. Absent = the args parameter named after
|
|
18
|
+
* the column (existing semantics); present = an explicit value expression
|
|
19
|
+
* (column-vs-column, literal, computation). */
|
|
20
|
+
right?: ValueExpr;
|
|
21
|
+
/** Required (default) or optional criterion. A filter has one semantics:
|
|
22
|
+
* dao filters are required (missing criteria = error), page filters are
|
|
23
|
+
* optional (missing criteria = no WHERE). Declared by the filter author. */
|
|
24
|
+
optional?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Query filter: AND-combined conditions plus an optional keyword search. */
|
|
28
|
+
export interface FilterSchema extends SchemaBase {
|
|
29
|
+
type: 'filter';
|
|
30
|
+
/** The backend api module this filter belongs to (shared instance from
|
|
31
|
+
* project.config.ts apis). Filters are backend-side, so storage is
|
|
32
|
+
* filter_schema/{api.name}/{app.name}/filter/. */
|
|
33
|
+
api: ProjectApiSchema;
|
|
34
|
+
/** The frontend app this filter belongs to (shared instance from project.config). */
|
|
35
|
+
app: FrontAppSchema;
|
|
36
|
+
/** AND-combined conditions (may be empty when keyword is present). */
|
|
37
|
+
conditions: FilterCondition[];
|
|
38
|
+
/** Fuzzy keyword search: one input value matched against multiple columns
|
|
39
|
+
* via OR-like. Presence drives the keyword query endpoint. */
|
|
40
|
+
keyword?: { columns: Field[] };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function defineFilter(options: {
|
|
44
|
+
name: string;
|
|
45
|
+
api: ProjectApiSchema;
|
|
46
|
+
app: FrontAppSchema;
|
|
47
|
+
conditions?: FilterCondition[];
|
|
48
|
+
keyword?: { columns: Field[] };
|
|
49
|
+
description?: string;
|
|
50
|
+
}): FilterSchema {
|
|
51
|
+
if (!options.api.apps.includes(options.app)) {
|
|
52
|
+
throw new Error(`filter ${options.name}: api '${options.api.name}' does not serve app '${options.app.name}'`);
|
|
53
|
+
}
|
|
54
|
+
const conditions = options.conditions ?? [];
|
|
55
|
+
if (conditions.length === 0 && options.keyword === undefined) {
|
|
56
|
+
throw new Error(`filter ${options.name}: conditions and keyword cannot both be empty`);
|
|
57
|
+
}
|
|
58
|
+
if (options.keyword !== undefined && options.keyword.columns.length === 0) {
|
|
59
|
+
throw new Error(`filter ${options.name}: keyword columns must be non-empty`);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
type: 'filter',
|
|
63
|
+
name: options.name,
|
|
64
|
+
description: options.description,
|
|
65
|
+
api: options.api,
|
|
66
|
+
app: options.app,
|
|
67
|
+
conditions,
|
|
68
|
+
keyword: options.keyword,
|
|
69
|
+
};
|
|
70
|
+
}
|