@pylonts/dsl 1.0.6 → 1.1.2
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/action.d.ts +7 -0
- package/dist/action.js +3 -0
- 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/component.d.ts +20 -0
- package/dist/component.js +1 -0
- package/dist/convert.d.ts +9 -0
- package/dist/convert.js +3 -0
- package/dist/curd.d.ts +62 -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 +56 -0
- package/dist/db.js +100 -0
- package/dist/dictionary.d.ts +26 -5
- package/dist/dictionary.js +21 -8
- package/dist/dsl.d.ts +10 -49
- package/dist/dsl.js +12 -103
- package/dist/dto.d.ts +12 -9
- package/dist/dto.js +25 -34
- package/dist/enum-driver.d.ts +1 -1
- package/dist/enum-driver.js +1 -4
- package/dist/event.d.ts +8 -0
- package/dist/event.js +3 -0
- 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 +31 -17
- package/dist/index.js +31 -33
- package/dist/mermaid-driver.d.ts +2 -2
- package/dist/mermaid-driver.js +4 -7
- package/dist/mock.d.ts +12 -0
- package/dist/mock.js +1 -0
- package/dist/mysql-driver.d.ts +5 -1
- package/dist/mysql-driver.js +25 -10
- package/dist/navigation.d.ts +22 -0
- package/dist/navigation.js +15 -0
- package/dist/page-def.d.ts +40 -0
- package/dist/page-def.js +38 -0
- package/dist/page-flow.d.ts +5 -3
- package/dist/page-flow.js +109 -18
- package/dist/page.d.ts +37 -15
- package/dist/page.js +23 -13
- package/dist/pattern.js +2 -6
- package/dist/patterns/retry.d.ts +1 -1
- package/dist/patterns/retry.js +2 -6
- package/dist/popup.d.ts +18 -0
- package/dist/popup.js +8 -0
- package/dist/project.d.ts +25 -13
- package/dist/project.js +41 -6
- package/dist/prototype.d.ts +1 -1
- package/dist/prototype.js +1 -4
- package/dist/provider.d.ts +54 -0
- package/dist/provider.js +18 -0
- package/dist/ref.d.ts +14 -0
- package/dist/ref.js +6 -0
- package/dist/route.d.ts +8 -0
- package/dist/route.js +3 -0
- 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 +6 -6
- package/docs/enum.md +24 -24
- package/docs/project.md +2 -2
- package/docs/table.md +53 -16
- package/package.json +5 -3
- package/src/action.ts +11 -0
- package/src/asset.ts +63 -0
- package/src/bases.ts +30 -20
- package/src/component.ts +22 -0
- package/src/convert.ts +13 -0
- package/src/curd.ts +94 -0
- package/src/db-config.ts +8 -0
- package/src/db.ts +153 -0
- package/src/dictionary.ts +45 -19
- package/src/dsl.ts +13 -106
- package/src/dto.ts +25 -12
- package/src/enum-driver.ts +42 -42
- package/src/event.ts +12 -0
- package/src/flow.ts +103 -103
- package/src/import-base.ts +15 -0
- package/src/index.ts +31 -17
- package/src/mermaid-driver.ts +5 -4
- package/src/mock.ts +12 -0
- package/src/mysql-driver.ts +25 -6
- package/src/navigation.ts +29 -0
- package/src/page-def.ts +80 -0
- package/src/page-flow.ts +117 -15
- package/src/page.ts +57 -20
- package/src/patterns/retry.ts +54 -54
- package/src/popup.ts +25 -0
- package/src/project.ts +57 -14
- package/src/prototype.ts +29 -29
- package/src/provider.ts +73 -0
- package/src/ref.ts +19 -0
- package/src/route.ts +12 -0
- package/src/typebox-driver.ts +192 -187
- package/src/utils.ts +11 -6
- package/src/check-inheritance.ts +0 -86
package/src/project.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { SchemaBase } from './dsl';
|
|
1
|
+
import { SchemaBase } from './dsl.js';
|
|
2
|
+
import type { TableSchema } from './db.js';
|
|
2
3
|
|
|
3
4
|
// Project topology definitions: describe the applications (frontends) and
|
|
4
5
|
// backend APIs of a repository, and which frontends each API serves.
|
|
@@ -7,49 +8,91 @@ import { SchemaBase } from './dsl';
|
|
|
7
8
|
export type FrontType = 'admin' | 'wxmini';
|
|
8
9
|
|
|
9
10
|
/** A frontend application (e.g. admin console, wechat mini program). */
|
|
10
|
-
export interface
|
|
11
|
+
export interface FrontAppSchema extends SchemaBase {
|
|
11
12
|
type: FrontType;
|
|
12
13
|
/** Source directory relative to project root, e.g. 'web-admin/'. */
|
|
13
14
|
dir: string;
|
|
15
|
+
/**
|
|
16
|
+
* Tenant table for this app. When set, all tables with a foreign key
|
|
17
|
+
* pointing to this table get automatic tenant scoping: the tenant PK
|
|
18
|
+
* value is injected from `user.id` into all curd operations.
|
|
19
|
+
*/
|
|
20
|
+
tenant?: TableSchema;
|
|
14
21
|
}
|
|
15
22
|
|
|
16
|
-
/** A backend API service. apps references shared
|
|
17
|
-
export interface
|
|
23
|
+
/** A backend API service. apps references shared FrontAppSchema instances. */
|
|
24
|
+
export interface ProjectApiSchema extends SchemaBase {
|
|
18
25
|
/** Source directory relative to project root, e.g. 'api/'. */
|
|
19
26
|
dir: string;
|
|
20
27
|
/** Frontends this API serves. Direct instance references (see defineProject). */
|
|
21
|
-
apps:
|
|
28
|
+
apps: FrontAppSchema[];
|
|
22
29
|
/** API base URL prefix shared by all apps it serves, e.g. '/mall'. '' = no prefix. */
|
|
23
30
|
contextPath?: string;
|
|
31
|
+
/** API service base URL for node clients, e.g. 'http://127.0.0.1:3000'. */
|
|
32
|
+
baseUrl?: string;
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
/** A third-party system (e.g. wechat pay, unionpay). Owns its own
|
|
27
36
|
* implementation dir and contract (controller_types), just like an API,
|
|
28
37
|
* but is not part of this repo's served surface. */
|
|
29
|
-
export interface
|
|
38
|
+
export interface ThirdApiSchema extends SchemaBase {
|
|
30
39
|
/** Source directory relative to project root, e.g. 'wechat/'. */
|
|
31
40
|
dir: string;
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
export interface ProjectSchema extends SchemaBase {
|
|
35
|
-
apps:
|
|
36
|
-
apis:
|
|
37
|
-
thirdApis:
|
|
44
|
+
apps: FrontAppSchema[];
|
|
45
|
+
apis: ProjectApiSchema[];
|
|
46
|
+
thirdApis: ThirdApiSchema[];
|
|
38
47
|
}
|
|
39
48
|
|
|
40
49
|
/**
|
|
41
|
-
* Defines the project topology.
|
|
50
|
+
* Defines the project topology. FrontAppSchema instances are shared value objects:
|
|
42
51
|
* api.apps references the same instances from project.apps, so an app served
|
|
43
52
|
* by multiple APIs is defined once and referenced many times.
|
|
53
|
+
*
|
|
54
|
+
* Runtime-validates app type whitelist, unique names and api.apps reference
|
|
55
|
+
* integrity (same style as defineTable/defineCurd).
|
|
44
56
|
*/
|
|
45
57
|
export function defineProject(
|
|
46
58
|
name: string,
|
|
47
59
|
schema: {
|
|
48
60
|
description?: string;
|
|
49
|
-
apps:
|
|
50
|
-
apis:
|
|
51
|
-
thirdApis?:
|
|
61
|
+
apps: FrontAppSchema[];
|
|
62
|
+
apis: ProjectApiSchema[];
|
|
63
|
+
thirdApis?: ThirdApiSchema[];
|
|
52
64
|
},
|
|
53
65
|
): ProjectSchema {
|
|
54
|
-
|
|
66
|
+
const project: ProjectSchema = { name, ...schema, thirdApis: schema.thirdApis ?? [] };
|
|
67
|
+
|
|
68
|
+
const appNames = new Set<string>();
|
|
69
|
+
for (const app of project.apps) {
|
|
70
|
+
if (!app.name) throw new Error(`project ${name}: app name is required`);
|
|
71
|
+
if (appNames.has(app.name)) throw new Error(`project ${name}: duplicate app name '${app.name}'`);
|
|
72
|
+
appNames.add(app.name);
|
|
73
|
+
if (app.type !== 'admin' && app.type !== 'wxmini') {
|
|
74
|
+
throw new Error(`project ${name}: app '${app.name}' must be type 'admin' or 'wxmini' (got '${app.type}')`);
|
|
75
|
+
}
|
|
76
|
+
if (!app.dir) throw new Error(`project ${name}: app '${app.name}' dir is required`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const apiNames = new Set<string>();
|
|
80
|
+
for (const api of project.apis) {
|
|
81
|
+
if (!api.name) throw new Error(`project ${name}: api name is required`);
|
|
82
|
+
if (apiNames.has(api.name)) throw new Error(`project ${name}: duplicate api name '${api.name}'`);
|
|
83
|
+
apiNames.add(api.name);
|
|
84
|
+
if (!api.dir) throw new Error(`project ${name}: api '${api.name}' dir is required`);
|
|
85
|
+
for (const ref of api.apps) {
|
|
86
|
+
if (!project.apps.includes(ref)) {
|
|
87
|
+
throw new Error(`project ${name}: api '${api.name}' references app '${ref.name}' that is not a shared instance in project.apps (define once and reference it)`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (const third of project.thirdApis) {
|
|
93
|
+
if (!third.name) throw new Error(`project ${name}: thirdApi name is required`);
|
|
94
|
+
if (!third.dir) throw new Error(`project ${name}: thirdApi '${third.name}' dir is required`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return project;
|
|
55
98
|
}
|
package/src/prototype.ts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import { SchemaBase } from './dsl';
|
|
2
|
-
|
|
3
|
-
// Prototype definitions: high-level design of a page. A prototype lists only
|
|
4
|
-
// the fields a page needs — no types, no bindings to apps/APIs/tables. Field
|
|
5
|
-
// details (DTO/table definitions) are written separately and connected later.
|
|
6
|
-
|
|
7
|
-
/** Display metadata for a prototype field. */
|
|
8
|
-
export interface PrototypeFieldMeta {
|
|
9
|
-
label: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface PrototypeSchema extends SchemaBase {
|
|
14
|
-
/** Field requirements: key is the field name, value is display metadata. */
|
|
15
|
-
fields: Record<string, PrototypeFieldMeta>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Defines a page prototype. The field keys become the names referenced by
|
|
20
|
-
* later DTO/table definitions; here they only carry label/description.
|
|
21
|
-
*/
|
|
22
|
-
export function definePrototype(
|
|
23
|
-
name: string,
|
|
24
|
-
schema: {
|
|
25
|
-
description?: string;
|
|
26
|
-
fields: Record<string, PrototypeFieldMeta>;
|
|
27
|
-
},
|
|
28
|
-
): PrototypeSchema {
|
|
29
|
-
return { name, ...schema };
|
|
1
|
+
import { SchemaBase } from './dsl.js';
|
|
2
|
+
|
|
3
|
+
// Prototype definitions: high-level design of a page. A prototype lists only
|
|
4
|
+
// the fields a page needs — no types, no bindings to apps/APIs/tables. Field
|
|
5
|
+
// details (DTO/table definitions) are written separately and connected later.
|
|
6
|
+
|
|
7
|
+
/** Display metadata for a prototype field. */
|
|
8
|
+
export interface PrototypeFieldMeta {
|
|
9
|
+
label: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface PrototypeSchema extends SchemaBase {
|
|
14
|
+
/** Field requirements: key is the field name, value is display metadata. */
|
|
15
|
+
fields: Record<string, PrototypeFieldMeta>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Defines a page prototype. The field keys become the names referenced by
|
|
20
|
+
* later DTO/table definitions; here they only carry label/description.
|
|
21
|
+
*/
|
|
22
|
+
export function definePrototype(
|
|
23
|
+
name: string,
|
|
24
|
+
schema: {
|
|
25
|
+
description?: string;
|
|
26
|
+
fields: Record<string, PrototypeFieldMeta>;
|
|
27
|
+
},
|
|
28
|
+
): PrototypeSchema {
|
|
29
|
+
return { name, ...schema };
|
|
30
30
|
}
|
package/src/provider.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { ImportBase } from './import-base.js';
|
|
2
|
+
import type { ImportableSchemaBase } from './dsl.js';
|
|
3
|
+
import type { DtoField, DtoMessage, DtoArrayField, DtoObjectField } from './dto.js';
|
|
4
|
+
import type { ActionSchema } from './action.js';
|
|
5
|
+
import type { RefSchema } from './ref.js';
|
|
6
|
+
import type { ConvertSchema } from './convert.js';
|
|
7
|
+
|
|
8
|
+
// ProviderSchema: an API function signature (args DTO + results DTO).
|
|
9
|
+
|
|
10
|
+
/** Parameter data source for a call argument. */
|
|
11
|
+
export type DataRef =
|
|
12
|
+
| { type: 'route'; key: string }
|
|
13
|
+
| { type: 'data'; key: string }
|
|
14
|
+
| { type: 'value'; value: unknown };
|
|
15
|
+
|
|
16
|
+
/** Create a route-parameter reference. */
|
|
17
|
+
export function route(key: string): DataRef {
|
|
18
|
+
return { type: 'route', key };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Create a page-data reference. */
|
|
22
|
+
export function data(key: string): DataRef {
|
|
23
|
+
return { type: 'data', key };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface CallAction extends ActionSchema {
|
|
27
|
+
type: 'call';
|
|
28
|
+
func: ProviderSchema;
|
|
29
|
+
args?: Record<string, DtoField | DtoMessage | DtoArrayField | DtoObjectField | RefSchema | string>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
export function call(func: ProviderSchema, args?: Record<string, DtoField | DtoMessage | DtoArrayField | DtoObjectField | RefSchema | string>): CallAction {
|
|
34
|
+
return { name: func.name, type: 'call', func, args };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Provider function signature. The generated API client exposes one function
|
|
38
|
+
* per endpoint; ProviderSchema gives that function a name and types. */
|
|
39
|
+
export interface ProviderSchema extends ImportableSchemaBase {
|
|
40
|
+
isAsync: boolean;
|
|
41
|
+
/** Input DTO (buildInput / buildQuery / buildPk result). */
|
|
42
|
+
args: DtoMessage;
|
|
43
|
+
/** Output DTO (buildOutput result) or primitive. */
|
|
44
|
+
results: DtoMessage | number | boolean | string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Define a provider function. */
|
|
48
|
+
export function defineProvider(
|
|
49
|
+
name: string,
|
|
50
|
+
schema: {
|
|
51
|
+
isAsync: boolean;
|
|
52
|
+
args: DtoMessage;
|
|
53
|
+
results: DtoMessage | number | boolean | string;
|
|
54
|
+
description?: string;
|
|
55
|
+
importRef?: ImportBase;
|
|
56
|
+
},
|
|
57
|
+
): ProviderSchema {
|
|
58
|
+
return { name, ...schema };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Assign a call's result to a page data field.
|
|
62
|
+
* React: setState({ [field]: await ... }). Mini-program: this.setData({ [field]: ... }). */
|
|
63
|
+
export interface SetDataAction extends ActionSchema {
|
|
64
|
+
type: 'setData';
|
|
65
|
+
call: CallAction;
|
|
66
|
+
field: DtoField;
|
|
67
|
+
/** Optional field-level transform before assignment. */
|
|
68
|
+
convert?: ConvertSchema;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function setData(call: CallAction, field: DtoField, convert?: ConvertSchema): SetDataAction {
|
|
72
|
+
return { name: 'setData', type: 'setData', call, field, convert };
|
|
73
|
+
}
|
package/src/ref.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CollectionSchemaBase } from './dsl.js';
|
|
2
|
+
import type { DtoField } from './dto.js';
|
|
3
|
+
|
|
4
|
+
/** A reference to a field within another schema. Carries a .schema back-reference
|
|
5
|
+
* so the driver knows where the data comes from (route params, page data, etc.). */
|
|
6
|
+
export interface RefSchema {
|
|
7
|
+
name: string;
|
|
8
|
+
/** Schema back-reference — tells driver the data source. */
|
|
9
|
+
schema: CollectionSchemaBase;
|
|
10
|
+
/** The referenced field instance. */
|
|
11
|
+
field: DtoField;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Create a reference to a field in a source schema.
|
|
15
|
+
* Writes back field.schema to the source so the driver can trace origin. */
|
|
16
|
+
export function defineRef(source: CollectionSchemaBase, field: DtoField): RefSchema {
|
|
17
|
+
field.schema = source;
|
|
18
|
+
return { name: field.name, schema: source, field };
|
|
19
|
+
}
|
package/src/route.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CollectionSchemaBase } from './dsl.js';
|
|
2
|
+
import type { DtoField } from './dto.js';
|
|
3
|
+
|
|
4
|
+
/** Route params: data that arrives from the navigation URL / route. */
|
|
5
|
+
export interface RouteDataSchema extends CollectionSchemaBase {
|
|
6
|
+
type: 'route';
|
|
7
|
+
fields: Record<string, DtoField>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function defineRouteData(name: string, fields: RouteDataSchema['fields']): RouteDataSchema {
|
|
11
|
+
return { name, type: 'route', fields };
|
|
12
|
+
}
|