@pylonts/dsl 1.1.4 → 1.1.5

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/src/project.ts CHANGED
@@ -1,98 +1,98 @@
1
- import { SchemaBase } from './dsl.js';
2
- import type { TableSchema } from './db.js';
3
-
4
- // Project topology definitions: describe the applications (frontends) and
5
- // backend APIs of a repository, and which frontends each API serves.
6
-
7
- /** Frontend form factor. Closed enum, extend when new form factors appear. */
8
- export type FrontType = 'admin' | 'wxmini';
9
-
10
- /** A frontend application (e.g. admin console, wechat mini program). */
11
- export interface FrontAppSchema extends SchemaBase {
12
- type: FrontType;
13
- /** Source directory relative to project root, e.g. 'web-admin/'. */
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;
21
- }
22
-
23
- /** A backend API service. apps references shared FrontAppSchema instances. */
24
- export interface ProjectApiSchema extends SchemaBase {
25
- /** Source directory relative to project root, e.g. 'api/'. */
26
- dir: string;
27
- /** Frontends this API serves. Direct instance references (see defineProject). */
28
- apps: FrontAppSchema[];
29
- /** API base URL prefix shared by all apps it serves, e.g. '/mall'. '' = no prefix. */
30
- contextPath?: string;
31
- /** API service base URL for node clients, e.g. 'http://127.0.0.1:3000'. */
32
- baseUrl?: string;
33
- }
34
-
35
- /** A third-party system (e.g. wechat pay, unionpay). Owns its own
36
- * implementation dir and contract (controller_types), just like an API,
37
- * but is not part of this repo's served surface. */
38
- export interface ThirdApiSchema extends SchemaBase {
39
- /** Source directory relative to project root, e.g. 'wechat/'. */
40
- dir: string;
41
- }
42
-
43
- export interface ProjectSchema extends SchemaBase {
44
- apps: FrontAppSchema[];
45
- apis: ProjectApiSchema[];
46
- thirdApis: ThirdApiSchema[];
47
- }
48
-
49
- /**
50
- * Defines the project topology. FrontAppSchema instances are shared value objects:
51
- * api.apps references the same instances from project.apps, so an app served
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).
56
- */
57
- export function defineProject(
58
- name: string,
59
- schema: {
60
- description?: string;
61
- apps: FrontAppSchema[];
62
- apis: ProjectApiSchema[];
63
- thirdApis?: ThirdApiSchema[];
64
- },
65
- ): ProjectSchema {
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;
1
+ import { SchemaBase } from './dsl.js';
2
+ import type { TableSchema } from './db.js';
3
+
4
+ // Project topology definitions: describe the applications (frontends) and
5
+ // backend APIs of a repository, and which frontends each API serves.
6
+
7
+ /** Frontend form factor. Closed enum, extend when new form factors appear. */
8
+ export type FrontType = 'admin' | 'wxmini';
9
+
10
+ /** A frontend application (e.g. admin console, wechat mini program). */
11
+ export interface FrontAppSchema extends SchemaBase {
12
+ type: FrontType;
13
+ /** Source directory relative to project root, e.g. 'web-admin/'. */
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;
21
+ }
22
+
23
+ /** A backend API service. apps references shared FrontAppSchema instances. */
24
+ export interface ProjectApiSchema extends SchemaBase {
25
+ /** Source directory relative to project root, e.g. 'api/'. */
26
+ dir: string;
27
+ /** Frontends this API serves. Direct instance references (see defineProject). */
28
+ apps: FrontAppSchema[];
29
+ /** API base URL prefix shared by all apps it serves, e.g. '/mall'. '' = no prefix. */
30
+ contextPath?: string;
31
+ /** API service base URL for node clients, e.g. 'http://127.0.0.1:3000'. */
32
+ baseUrl?: string;
33
+ }
34
+
35
+ /** A third-party system (e.g. wechat pay, unionpay). Owns its own
36
+ * implementation dir and contract (controller_types), just like an API,
37
+ * but is not part of this repo's served surface. */
38
+ export interface ThirdApiSchema extends SchemaBase {
39
+ /** Source directory relative to project root, e.g. 'wechat/'. */
40
+ dir: string;
41
+ }
42
+
43
+ export interface ProjectSchema extends SchemaBase {
44
+ apps: FrontAppSchema[];
45
+ apis: ProjectApiSchema[];
46
+ thirdApis: ThirdApiSchema[];
47
+ }
48
+
49
+ /**
50
+ * Defines the project topology. FrontAppSchema instances are shared value objects:
51
+ * api.apps references the same instances from project.apps, so an app served
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).
56
+ */
57
+ export function defineProject(
58
+ name: string,
59
+ schema: {
60
+ description?: string;
61
+ apps: FrontAppSchema[];
62
+ apis: ProjectApiSchema[];
63
+ thirdApis?: ThirdApiSchema[];
64
+ },
65
+ ): ProjectSchema {
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;
98
98
  }
package/src/provider.ts CHANGED
@@ -1,73 +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 };
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
73
  }
package/src/ref.ts CHANGED
@@ -1,19 +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 };
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
19
  }
package/src/route.ts CHANGED
@@ -1,12 +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 };
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
12
  }
package/src/service.ts CHANGED
@@ -1,21 +1,21 @@
1
- import { SchemaBase } from './dsl.js';
2
- import { FrontAppSchema } from './project.js';
3
- import type { DtoArrayField, DtoField, DtoMessage, DtoObjectField } from './dto.js';
4
-
5
- /** A frontend service bound to exactly one frontend app. */
6
- export interface ServiceSchema extends SchemaBase {
7
- type: 'service';
8
- /** The frontend app this service belongs to (shared instance from project.config). */
9
- app: FrontAppSchema;
10
- }
11
-
12
- export function defineService(name: string, app: FrontAppSchema, description?: string): ServiceSchema {
13
- return { name, type: 'service', app, description };
14
- }
15
-
16
- /** A method exposed by a service. */
17
- export interface ServiceMethodSchema extends SchemaBase {
18
- type: 'method';
19
- name: string;
20
- fields: Record<string, DtoField | DtoMessage | DtoArrayField | DtoObjectField>;
1
+ import { SchemaBase } from './dsl.js';
2
+ import { FrontAppSchema } from './project.js';
3
+ import type { DtoArrayField, DtoField, DtoMessage, DtoObjectField } from './dto.js';
4
+
5
+ /** A frontend service bound to exactly one frontend app. */
6
+ export interface ServiceSchema extends SchemaBase {
7
+ type: 'service';
8
+ /** The frontend app this service belongs to (shared instance from project.config). */
9
+ app: FrontAppSchema;
10
+ }
11
+
12
+ export function defineService(name: string, app: FrontAppSchema, description?: string): ServiceSchema {
13
+ return { name, type: 'service', app, description };
14
+ }
15
+
16
+ /** A method exposed by a service. */
17
+ export interface ServiceMethodSchema extends SchemaBase {
18
+ type: 'method';
19
+ name: string;
20
+ fields: Record<string, DtoField | DtoMessage | DtoArrayField | DtoObjectField>;
21
21
  }