@pylonts/dsl 1.1.6 → 1.1.12

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 (88) hide show
  1. package/README.md +4 -0
  2. package/dist/action.d.ts +32 -0
  3. package/dist/action.js +14 -0
  4. package/dist/aggregate.d.ts +38 -0
  5. package/dist/aggregate.js +46 -0
  6. package/dist/business-flow.d.ts +9 -0
  7. package/dist/business-flow.js +72 -0
  8. package/dist/controller.d.ts +17 -9
  9. package/dist/controller.js +8 -2
  10. package/dist/convert.d.ts +28 -10
  11. package/dist/convert.js +16 -5
  12. package/dist/curd.d.ts +7 -10
  13. package/dist/curd.js +3 -1
  14. package/dist/dao.d.ts +81 -53
  15. package/dist/dao.js +291 -12
  16. package/dist/db.d.ts +6 -0
  17. package/dist/db.js +10 -0
  18. package/dist/domain-event.d.ts +48 -0
  19. package/dist/domain-event.js +24 -0
  20. package/dist/dsl.d.ts +17 -2
  21. package/dist/dsl.js +7 -0
  22. package/dist/dto.d.ts +6 -4
  23. package/dist/dto.js +5 -4
  24. package/dist/entity.d.ts +29 -0
  25. package/dist/entity.js +13 -0
  26. package/dist/exception.d.ts +9 -3
  27. package/dist/exception.js +25 -1
  28. package/dist/expr.d.ts +45 -0
  29. package/dist/expr.js +32 -0
  30. package/dist/filter.d.ts +45 -0
  31. package/dist/filter.js +21 -0
  32. package/dist/flow-script.d.ts +108 -0
  33. package/dist/flow-script.js +505 -0
  34. package/dist/flow.d.ts +294 -17
  35. package/dist/flow.js +803 -18
  36. package/dist/index.d.ts +6 -2
  37. package/dist/index.js +6 -2
  38. package/dist/mermaid-driver.js +264 -24
  39. package/dist/mysql-driver.js +3 -0
  40. package/dist/project.d.ts +10 -6
  41. package/dist/project.js +35 -4
  42. package/dist/repository.d.ts +26 -0
  43. package/dist/repository.js +8 -0
  44. package/dist/service.d.ts +14 -2
  45. package/dist/service.js +49 -0
  46. package/dist/third-service.d.ts +5 -0
  47. package/dist/third-service.js +1 -0
  48. package/dist/typebox-driver.js +4 -0
  49. package/dist/utils.d.ts +9 -2
  50. package/dist/utils.js +4 -0
  51. package/docs/aggregate.md +110 -0
  52. package/docs/curd.md +146 -111
  53. package/docs/dao-generation.md +478 -0
  54. package/docs/ddd-principles.md +75 -0
  55. package/docs/domain-event.md +137 -0
  56. package/docs/keyword-matcher.md +182 -0
  57. package/docs/project.md +17 -9
  58. package/docs/token.md +327 -0
  59. package/docs/trans-reentrant.md +85 -0
  60. package/package.json +25 -6
  61. package/src/action.ts +51 -10
  62. package/src/aggregate.ts +104 -0
  63. package/src/business-flow.ts +80 -0
  64. package/src/controller.ts +25 -11
  65. package/src/convert.ts +51 -15
  66. package/src/curd.ts +12 -6
  67. package/src/dao.ts +377 -63
  68. package/src/db.ts +13 -0
  69. package/src/domain-event.ts +74 -0
  70. package/src/dsl.ts +23 -2
  71. package/src/dto.ts +9 -6
  72. package/src/entity.ts +43 -0
  73. package/src/exception.ts +30 -5
  74. package/src/expr.ts +65 -0
  75. package/src/filter.ts +70 -0
  76. package/src/flow-script.ts +696 -0
  77. package/src/flow.ts +1129 -46
  78. package/src/index.ts +6 -2
  79. package/src/mermaid-driver.ts +256 -29
  80. package/src/mysql-driver.ts +3 -0
  81. package/src/project.ts +138 -97
  82. package/src/repository.ts +35 -0
  83. package/src/service.ts +68 -3
  84. package/src/third-service.ts +6 -0
  85. package/src/typebox-driver.ts +4 -0
  86. package/src/utils.ts +13 -2
  87. package/src/endpoint.ts +0 -18
  88. package/src/provider.ts +0 -68
package/dist/expr.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ import type { Field } from './dsl.js';
2
+ /** Binary operator on numeric values. */
3
+ export type BinOp = 'add' | 'sub' | 'mul' | 'div';
4
+ /** A value expression: column reference / literal / method parameter / binary
5
+ * operation. Recursive — leaves are col/lit/param, bin combines them. */
6
+ export type ValueExpr = {
7
+ kind: 'col';
8
+ field: Field;
9
+ } | {
10
+ kind: 'lit';
11
+ value: string | number;
12
+ } | {
13
+ kind: 'param';
14
+ name: string;
15
+ } | {
16
+ kind: 'bin';
17
+ op: BinOp;
18
+ left: ValueExpr;
19
+ right: ValueExpr;
20
+ };
21
+ /** An update SET assignment: `col = expr` (besides the direct-assignment
22
+ * columns carried by the args entity — a column must not appear in both). */
23
+ export interface SetExpr {
24
+ col: Field;
25
+ expr: ValueExpr;
26
+ }
27
+ export declare function col(field: Field): ValueExpr;
28
+ export declare function lit(value: string | number): ValueExpr;
29
+ export declare function param(name: string): ValueExpr;
30
+ export declare function bin(op: BinOp, left: ValueExpr, right: ValueExpr): ValueExpr;
31
+ /** Convenience builders for the common self-increment/decrement shapes. */
32
+ export declare const incr: (field: Field, by: ValueExpr) => SetExpr;
33
+ export declare const decr: (field: Field, by: ValueExpr) => SetExpr;
34
+ /** Aggregate expression result of an aggregate query column. */
35
+ export interface ComputeExpr {
36
+ fn: 'sum' | 'avg' | 'count';
37
+ /** Column the function applies to; absent for count(*). */
38
+ field?: Field;
39
+ }
40
+ /** Aggregate expressions: Compute.sum(col) / Compute.avg(col) / Compute.count(). */
41
+ export declare const Compute: {
42
+ sum(field: Field): ComputeExpr;
43
+ avg(field: Field): ComputeExpr;
44
+ count(): ComputeExpr;
45
+ };
package/dist/expr.js ADDED
@@ -0,0 +1,32 @@
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
+ export function col(field) {
7
+ return { kind: 'col', field };
8
+ }
9
+ export function lit(value) {
10
+ return { kind: 'lit', value };
11
+ }
12
+ export function param(name) {
13
+ return { kind: 'param', name };
14
+ }
15
+ export function bin(op, left, right) {
16
+ return { kind: 'bin', op, left, right };
17
+ }
18
+ /** Convenience builders for the common self-increment/decrement shapes. */
19
+ export const incr = (field, by) => ({ col: field, expr: bin('add', col(field), by) });
20
+ export const decr = (field, by) => ({ col: field, expr: bin('sub', col(field), by) });
21
+ /** Aggregate expressions: Compute.sum(col) / Compute.avg(col) / Compute.count(). */
22
+ export const Compute = {
23
+ sum(field) {
24
+ return { fn: 'sum', field };
25
+ },
26
+ avg(field) {
27
+ return { fn: 'avg', field };
28
+ },
29
+ count() {
30
+ return { fn: 'count' };
31
+ },
32
+ };
@@ -0,0 +1,45 @@
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
+ /** One AND-combined criterion: a column plus its comparison operator. */
5
+ export interface FilterCondition {
6
+ /** Column to compare (any table — cross-table filters are allowed). */
7
+ field: Field;
8
+ /** Comparison operator; defaults to 'eq'. */
9
+ op?: Operator;
10
+ /** Right side of the comparison. Absent = the args parameter named after
11
+ * the column (existing semantics); present = an explicit value expression
12
+ * (column-vs-column, literal, computation). */
13
+ right?: ValueExpr;
14
+ /** Required (default) or optional criterion. A filter has one semantics:
15
+ * dao filters are required (missing criteria = error), page filters are
16
+ * optional (missing criteria = no WHERE). Declared by the filter author. */
17
+ optional?: boolean;
18
+ }
19
+ /** Query filter: AND-combined conditions plus an optional keyword search. */
20
+ export interface FilterSchema extends SchemaBase {
21
+ type: 'filter';
22
+ /** The backend api module this filter belongs to (shared instance from
23
+ * project.config.ts apis). Filters are backend-side, so storage is
24
+ * filter_schema/{api.name}/{app.name}/filter/. */
25
+ api: ProjectApiSchema;
26
+ /** The frontend app this filter belongs to (shared instance from project.config). */
27
+ app: FrontAppSchema;
28
+ /** AND-combined conditions (may be empty when keyword is present). */
29
+ conditions: FilterCondition[];
30
+ /** Fuzzy keyword search: one input value matched against multiple columns
31
+ * via OR-like. Presence drives the keyword query endpoint. */
32
+ keyword?: {
33
+ columns: Field[];
34
+ };
35
+ }
36
+ export declare function defineFilter(options: {
37
+ name: string;
38
+ api: ProjectApiSchema;
39
+ app: FrontAppSchema;
40
+ conditions?: FilterCondition[];
41
+ keyword?: {
42
+ columns: Field[];
43
+ };
44
+ description?: string;
45
+ }): FilterSchema;
package/dist/filter.js ADDED
@@ -0,0 +1,21 @@
1
+ export function defineFilter(options) {
2
+ if (!options.api.apps.includes(options.app)) {
3
+ throw new Error(`filter ${options.name}: api '${options.api.name}' does not serve app '${options.app.name}'`);
4
+ }
5
+ const conditions = options.conditions ?? [];
6
+ if (conditions.length === 0 && options.keyword === undefined) {
7
+ throw new Error(`filter ${options.name}: conditions and keyword cannot both be empty`);
8
+ }
9
+ if (options.keyword !== undefined && options.keyword.columns.length === 0) {
10
+ throw new Error(`filter ${options.name}: keyword columns must be non-empty`);
11
+ }
12
+ return {
13
+ type: 'filter',
14
+ name: options.name,
15
+ description: options.description,
16
+ api: options.api,
17
+ app: options.app,
18
+ conditions,
19
+ keyword: options.keyword,
20
+ };
21
+ }
@@ -0,0 +1,108 @@
1
+ import type { DtoMessage } from './dto.js';
2
+ import type { DomainEventSchema } from './domain-event.js';
3
+ import type { ExceptionSchema } from './exception.js';
4
+ import type { FlowMethodRef, FlowSchema, FlowSlot, FlowSlots, GuardCondition } from './flow.js';
5
+ /** A method call in statement position: invoke(m) mutates the input slot in
6
+ * place, invoke(m, args) passes one explicit arg slot, invoke(m, args, result)
7
+ * additionally assigns the method's results to a slot. args may be a slot
8
+ * list (multi-input methods — e.g. a predicate over two slots). In condition
9
+ * position (IF(...)), the same call is a utils predicate (result is rejected). */
10
+ export interface InvokeStep {
11
+ kind: 'invoke';
12
+ method: FlowMethodRef;
13
+ args?: FlowSlot | FlowSlot[];
14
+ result?: FlowSlot;
15
+ }
16
+ /** A construction: the slot is assigned without a method call. */
17
+ export interface WriteStep {
18
+ kind: 'write';
19
+ slot: FlowSlot;
20
+ }
21
+ /** An unconditional throw (terminal — nothing runs after it in its block). */
22
+ export interface ThrowStep {
23
+ kind: 'throw';
24
+ exception: ExceptionSchema;
25
+ message?: string;
26
+ }
27
+ /** An early return to the flow's return end (terminal in its block). */
28
+ export interface ReturnStep {
29
+ kind: 'return';
30
+ }
31
+ /** A domain event publication: writes the event to the outbox inside the
32
+ * surrounding transaction. The payload slot defaults to the flow input. */
33
+ export interface PublishStep {
34
+ kind: 'publish';
35
+ event: DomainEventSchema;
36
+ payload?: FlowSlot;
37
+ }
38
+ /** A conditional: the then-branch runs when the condition holds, the
39
+ * else-branch (or the next statement) otherwise. */
40
+ export interface IfStep {
41
+ kind: 'if';
42
+ cond: GuardCondition;
43
+ then: ScriptStep[];
44
+ else?: ScriptStep[];
45
+ }
46
+ export type CatchRoute = [exception: ExceptionSchema, steps: ScriptStep[]];
47
+ /** A protected region: body and catch handlers (and optional finally) compile
48
+ * to sub-flows; a catch's steps may be empty (swallow). */
49
+ export interface TryStep {
50
+ kind: 'try';
51
+ name?: string;
52
+ body: ScriptStep[];
53
+ catches: CatchRoute[];
54
+ finally?: ScriptStep[];
55
+ }
56
+ /** A named sub-flow region (a private method inlined as a sub-flow). */
57
+ export interface SubStep {
58
+ kind: 'sub';
59
+ name: string;
60
+ steps: ScriptStep[];
61
+ description?: string;
62
+ }
63
+ export type ScriptStep = InvokeStep | WriteStep | ThrowStep | ReturnStep | PublishStep | IfStep | TryStep | SubStep;
64
+ /** Call a method as a statement or (in IF position) as a utils predicate. */
65
+ export declare function invoke(method: FlowMethodRef, args?: FlowSlot | FlowSlot[], result?: FlowSlot): InvokeStep;
66
+ /** Assign a slot without a method call (a construction). */
67
+ export declare function write(slot: FlowSlot): WriteStep;
68
+ /** Throw an exception — inside an IF branch the condition and the exit merge
69
+ * into one guard check; bare in a block it is an unconditional exit. */
70
+ export declare function THROW(exception: ExceptionSchema, message?: string): ThrowStep;
71
+ /** Return early to the flow's return end. */
72
+ export declare function RETURN(): ReturnStep;
73
+ /** Publish a domain event — the outbox write joins the surrounding
74
+ * transaction. The payload slot must carry exactly the event's fields
75
+ * (compile-time checked against the slot's declared message). */
76
+ export declare function publish(event: DomainEventSchema, payload?: FlowSlot): PublishStep;
77
+ export interface IfBuilder {
78
+ THEN(...steps: ScriptStep[]): IfBuilt;
79
+ }
80
+ export interface IfBuilt extends IfStep {
81
+ ELSE(...steps: ScriptStep[]): IfStep;
82
+ }
83
+ /** Conditional step: IF(cond).THEN(...) with optional .ELSE(...). The
84
+ * condition is a comparison (lt/gt/eq/...) or a predicate call — an
85
+ * invoke(...) in this position is a utils predicate. */
86
+ export declare function IF(cond: GuardCondition | InvokeStep): IfBuilder;
87
+ export interface TryBuilt extends TryStep {
88
+ CATCH(...routes: CatchRoute[]): TryBuilt;
89
+ FINALLY(steps: ScriptStep[]): TryBuilt;
90
+ }
91
+ /** Protected region: TRY([...]).CATCH([Exception, [...]], ...).FINALLY([...]). */
92
+ export declare function TRY(body: ScriptStep[], name?: string): TryBuilt;
93
+ /** A named sub-flow region. */
94
+ export declare function sub(name: string, steps: ScriptStep[], description?: string): SubStep;
95
+ /** The script's slot registry: ctx.slots.args and named slots from options.slots. */
96
+ export interface FlowCtx {
97
+ /** Append statements — they run in order. */
98
+ next(...steps: ScriptStep[]): void;
99
+ slots: FlowSlots;
100
+ }
101
+ /** Compile a sequential script into a FlowSchema. options.slots declares the
102
+ * named slots (message bindings); every declared slot must be used somewhere
103
+ * in the compiled flow. */
104
+ export declare function flowScript(name: string, options: {
105
+ args: DtoMessage;
106
+ slots?: Record<string, unknown>;
107
+ description?: string;
108
+ }, build: (ctx: FlowCtx) => void): FlowSchema;