@pylonts/dsl 1.1.3 → 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/dist/bases.d.ts +1 -1
- package/dist/bases.js +2 -2
- package/dist/convert.d.ts +4 -1
- package/dist/convert.js +2 -2
- package/dist/dao.d.ts +9 -0
- package/dist/dao.js +3 -0
- package/dist/db.d.ts +2 -2
- package/dist/db.js +3 -0
- package/dist/dsl.d.ts +9 -1
- package/dist/dsl.js +10 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mysql-driver.js +4 -1
- package/dist/service.d.ts +16 -0
- package/dist/service.js +3 -0
- package/dist/typebox-driver.js +3 -2
- package/dist/utils.d.ts +9 -0
- package/dist/utils.js +3 -0
- package/docs/curd.md +110 -110
- package/docs/dto.md +66 -66
- package/docs/table.md +135 -135
- package/package.json +2 -2
- package/src/action.ts +10 -10
- package/src/asset.ts +62 -62
- package/src/bases.ts +2 -2
- package/src/component.ts +21 -21
- package/src/convert.ts +16 -13
- package/src/curd.ts +93 -93
- package/src/dao.ts +13 -0
- package/src/db.ts +181 -178
- package/src/dsl.ts +23 -0
- package/src/dto.ts +247 -247
- package/src/event.ts +12 -12
- package/src/index.ts +32 -30
- package/src/mermaid-driver.ts +84 -84
- package/src/mock.ts +12 -12
- package/src/mysql-driver.ts +4 -2
- package/src/navigation.ts +28 -28
- package/src/page-def.ts +79 -79
- package/src/page-flow.ts +153 -153
- package/src/page.ts +76 -76
- package/src/popup.ts +25 -25
- package/src/project.ts +97 -97
- package/src/provider.ts +72 -72
- package/src/ref.ts +18 -18
- package/src/route.ts +11 -11
- package/src/service.ts +21 -0
- package/src/typebox-driver.ts +193 -192
- package/src/utils.ts +16 -0
package/src/page-flow.ts
CHANGED
|
@@ -1,154 +1,154 @@
|
|
|
1
|
-
import { SchemaBase } from './dsl.js';
|
|
2
|
-
import type { ActionSchema } from './action.js';
|
|
3
|
-
import { Page, getRegisteredPages, clearRegisteredPages } from './page.js';
|
|
4
|
-
import type { PageDef } from './page-def.js';
|
|
5
|
-
import type { NavigationAction } from './navigation.js';
|
|
6
|
-
|
|
7
|
-
// Page-driven flow: every node is a page, and a page belongs to an app.
|
|
8
|
-
// Leaf nodes are pages too — a journey starts at a page and ends at a page.
|
|
9
|
-
// Page definitions (PageSchema/Page/actions) live in page.ts; this file
|
|
10
|
-
// models the flow graph between pages.
|
|
11
|
-
|
|
12
|
-
export interface PageEdge extends SchemaBase {
|
|
13
|
-
/** Trigger action; undefined = default path (success/normal). */
|
|
14
|
-
when?: ActionSchema;
|
|
15
|
-
start: Page;
|
|
16
|
-
end: Page;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface PageFlow extends SchemaBase {
|
|
20
|
-
/** Entry page. */
|
|
21
|
-
start: Page;
|
|
22
|
-
/** All pages explicitly declared by the caller. */
|
|
23
|
-
pages: Page[];
|
|
24
|
-
edges: PageEdge[];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function pageEdge(start: Page, end: Page, when?: ActionSchema, description?: string): PageEdge {
|
|
28
|
-
// Auto name for uniformity with SchemaBase; `when` stays the branch marker.
|
|
29
|
-
return { name: `${start.name}->${end.name}`, start, end, when, description };
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function definePageFlow(
|
|
33
|
-
name: string,
|
|
34
|
-
schema: {
|
|
35
|
-
start: Page;
|
|
36
|
-
pages: Page[];
|
|
37
|
-
edges: PageEdge[];
|
|
38
|
-
description?: string;
|
|
39
|
-
},
|
|
40
|
-
): PageFlow {
|
|
41
|
-
const { start, pages, edges: explicitEdges, description } = schema;
|
|
42
|
-
|
|
43
|
-
// Resolve the back action from any page's actions list (PageSchema at runtime)
|
|
44
|
-
const backAction = findBackAction(pages);
|
|
45
|
-
|
|
46
|
-
// Auto-generate back edges: for every explicit edge A→B (not itself a back),
|
|
47
|
-
// if B has no explicit back edge and no existing edge B→A, add B→A with back.
|
|
48
|
-
const hasExplicitBack = new Set<Page>();
|
|
49
|
-
for (const e of explicitEdges) {
|
|
50
|
-
if (e.when && e.when.name === 'back') hasExplicitBack.add(e.start);
|
|
51
|
-
}
|
|
52
|
-
const hasReverse = new Set<string>();
|
|
53
|
-
for (const e of explicitEdges) {
|
|
54
|
-
hasReverse.add(`${e.start.name}->${e.end.name}`);
|
|
55
|
-
}
|
|
56
|
-
const generatedBackEdges: PageEdge[] = [];
|
|
57
|
-
if (backAction) {
|
|
58
|
-
for (const e of explicitEdges) {
|
|
59
|
-
if (e.when && e.when.name === 'back') continue;
|
|
60
|
-
if (hasExplicitBack.has(e.end)) continue;
|
|
61
|
-
if (hasReverse.has(`${e.end.name}->${e.start.name}`)) continue;
|
|
62
|
-
generatedBackEdges.push({
|
|
63
|
-
name: `${e.end.name}->${e.start.name}`,
|
|
64
|
-
start: e.end,
|
|
65
|
-
end: e.start,
|
|
66
|
-
when: backAction,
|
|
67
|
-
description: 'auto-generated back edge',
|
|
68
|
-
});
|
|
69
|
-
hasExplicitBack.add(e.end);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
const edges = [...explicitEdges, ...generatedBackEdges];
|
|
73
|
-
|
|
74
|
-
// Validate: every registered page must be in the flow's pages
|
|
75
|
-
const registered = getRegisteredPages();
|
|
76
|
-
const orphaned: string[] = [];
|
|
77
|
-
for (const rp of registered) {
|
|
78
|
-
// Compare by object identity — caller passes the same reference
|
|
79
|
-
if (!pages.includes(rp as unknown as Page)) {
|
|
80
|
-
orphaned.push(rp.name);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
if (orphaned.length > 0) {
|
|
84
|
-
throw new Error(
|
|
85
|
-
`[definePageFlow "${name}"] orphaned pages (defined but not in flow): ${orphaned.join(', ')}`,
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
clearRegisteredPages();
|
|
89
|
-
|
|
90
|
-
// Validate: start must be in pages
|
|
91
|
-
if (!pages.includes(start)) {
|
|
92
|
-
throw new Error(
|
|
93
|
-
`[definePageFlow "${name}"] start page "${start.name}" not in pages`,
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Validate: every page appears in at least one edge
|
|
98
|
-
const inEdge = new Set<Page>();
|
|
99
|
-
for (const e of edges) {
|
|
100
|
-
inEdge.add(e.start);
|
|
101
|
-
inEdge.add(e.end);
|
|
102
|
-
}
|
|
103
|
-
const isolated: string[] = [];
|
|
104
|
-
for (const p of pages) {
|
|
105
|
-
if (!inEdge.has(p)) isolated.push(p.name);
|
|
106
|
-
}
|
|
107
|
-
if (isolated.length > 0) {
|
|
108
|
-
throw new Error(
|
|
109
|
-
`[definePageFlow "${name}"] isolated pages (no edges): ${isolated.join(', ')}`,
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Validate: all pages reachable from start
|
|
114
|
-
const adj = new Map<Page, Page[]>();
|
|
115
|
-
for (const p of pages) adj.set(p, []);
|
|
116
|
-
for (const e of edges) {
|
|
117
|
-
const neighbors = adj.get(e.start);
|
|
118
|
-
if (neighbors) neighbors.push(e.end);
|
|
119
|
-
}
|
|
120
|
-
const visited = new Set<Page>();
|
|
121
|
-
const stack: Page[] = [start];
|
|
122
|
-
while (stack.length > 0) {
|
|
123
|
-
const cur = stack.pop()!;
|
|
124
|
-
if (visited.has(cur)) continue;
|
|
125
|
-
visited.add(cur);
|
|
126
|
-
for (const next of adj.get(cur) ?? []) {
|
|
127
|
-
if (!visited.has(next)) stack.push(next);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
const unreachable: string[] = [];
|
|
131
|
-
for (const p of pages) {
|
|
132
|
-
if (!visited.has(p)) unreachable.push(p.name);
|
|
133
|
-
}
|
|
134
|
-
if (unreachable.length > 0) {
|
|
135
|
-
throw new Error(
|
|
136
|
-
`[definePageFlow "${name}"] unreachable pages: ${unreachable.join(', ')}`,
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return { name, description, start, pages, edges };
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/** Walk all pages' pageDef.actions (PageSchema runtime shape) to find a NavigationAction with method 'back'. */
|
|
144
|
-
function findBackAction(pages: Page[]): NavigationAction | undefined {
|
|
145
|
-
for (const p of pages) {
|
|
146
|
-
const pageDef = (p as unknown as Record<string, unknown>).pageDef as PageDef | undefined;
|
|
147
|
-
if (!pageDef?.actions) continue;
|
|
148
|
-
for (const a of pageDef.actions) {
|
|
149
|
-
const na = a as NavigationAction;
|
|
150
|
-
if (na.type === 'navigation' && na.method === 'back') return na;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return undefined;
|
|
1
|
+
import { SchemaBase } from './dsl.js';
|
|
2
|
+
import type { ActionSchema } from './action.js';
|
|
3
|
+
import { Page, getRegisteredPages, clearRegisteredPages } from './page.js';
|
|
4
|
+
import type { PageDef } from './page-def.js';
|
|
5
|
+
import type { NavigationAction } from './navigation.js';
|
|
6
|
+
|
|
7
|
+
// Page-driven flow: every node is a page, and a page belongs to an app.
|
|
8
|
+
// Leaf nodes are pages too — a journey starts at a page and ends at a page.
|
|
9
|
+
// Page definitions (PageSchema/Page/actions) live in page.ts; this file
|
|
10
|
+
// models the flow graph between pages.
|
|
11
|
+
|
|
12
|
+
export interface PageEdge extends SchemaBase {
|
|
13
|
+
/** Trigger action; undefined = default path (success/normal). */
|
|
14
|
+
when?: ActionSchema;
|
|
15
|
+
start: Page;
|
|
16
|
+
end: Page;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface PageFlow extends SchemaBase {
|
|
20
|
+
/** Entry page. */
|
|
21
|
+
start: Page;
|
|
22
|
+
/** All pages explicitly declared by the caller. */
|
|
23
|
+
pages: Page[];
|
|
24
|
+
edges: PageEdge[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function pageEdge(start: Page, end: Page, when?: ActionSchema, description?: string): PageEdge {
|
|
28
|
+
// Auto name for uniformity with SchemaBase; `when` stays the branch marker.
|
|
29
|
+
return { name: `${start.name}->${end.name}`, start, end, when, description };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function definePageFlow(
|
|
33
|
+
name: string,
|
|
34
|
+
schema: {
|
|
35
|
+
start: Page;
|
|
36
|
+
pages: Page[];
|
|
37
|
+
edges: PageEdge[];
|
|
38
|
+
description?: string;
|
|
39
|
+
},
|
|
40
|
+
): PageFlow {
|
|
41
|
+
const { start, pages, edges: explicitEdges, description } = schema;
|
|
42
|
+
|
|
43
|
+
// Resolve the back action from any page's actions list (PageSchema at runtime)
|
|
44
|
+
const backAction = findBackAction(pages);
|
|
45
|
+
|
|
46
|
+
// Auto-generate back edges: for every explicit edge A→B (not itself a back),
|
|
47
|
+
// if B has no explicit back edge and no existing edge B→A, add B→A with back.
|
|
48
|
+
const hasExplicitBack = new Set<Page>();
|
|
49
|
+
for (const e of explicitEdges) {
|
|
50
|
+
if (e.when && e.when.name === 'back') hasExplicitBack.add(e.start);
|
|
51
|
+
}
|
|
52
|
+
const hasReverse = new Set<string>();
|
|
53
|
+
for (const e of explicitEdges) {
|
|
54
|
+
hasReverse.add(`${e.start.name}->${e.end.name}`);
|
|
55
|
+
}
|
|
56
|
+
const generatedBackEdges: PageEdge[] = [];
|
|
57
|
+
if (backAction) {
|
|
58
|
+
for (const e of explicitEdges) {
|
|
59
|
+
if (e.when && e.when.name === 'back') continue;
|
|
60
|
+
if (hasExplicitBack.has(e.end)) continue;
|
|
61
|
+
if (hasReverse.has(`${e.end.name}->${e.start.name}`)) continue;
|
|
62
|
+
generatedBackEdges.push({
|
|
63
|
+
name: `${e.end.name}->${e.start.name}`,
|
|
64
|
+
start: e.end,
|
|
65
|
+
end: e.start,
|
|
66
|
+
when: backAction,
|
|
67
|
+
description: 'auto-generated back edge',
|
|
68
|
+
});
|
|
69
|
+
hasExplicitBack.add(e.end);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const edges = [...explicitEdges, ...generatedBackEdges];
|
|
73
|
+
|
|
74
|
+
// Validate: every registered page must be in the flow's pages
|
|
75
|
+
const registered = getRegisteredPages();
|
|
76
|
+
const orphaned: string[] = [];
|
|
77
|
+
for (const rp of registered) {
|
|
78
|
+
// Compare by object identity — caller passes the same reference
|
|
79
|
+
if (!pages.includes(rp as unknown as Page)) {
|
|
80
|
+
orphaned.push(rp.name);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (orphaned.length > 0) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`[definePageFlow "${name}"] orphaned pages (defined but not in flow): ${orphaned.join(', ')}`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
clearRegisteredPages();
|
|
89
|
+
|
|
90
|
+
// Validate: start must be in pages
|
|
91
|
+
if (!pages.includes(start)) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`[definePageFlow "${name}"] start page "${start.name}" not in pages`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Validate: every page appears in at least one edge
|
|
98
|
+
const inEdge = new Set<Page>();
|
|
99
|
+
for (const e of edges) {
|
|
100
|
+
inEdge.add(e.start);
|
|
101
|
+
inEdge.add(e.end);
|
|
102
|
+
}
|
|
103
|
+
const isolated: string[] = [];
|
|
104
|
+
for (const p of pages) {
|
|
105
|
+
if (!inEdge.has(p)) isolated.push(p.name);
|
|
106
|
+
}
|
|
107
|
+
if (isolated.length > 0) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`[definePageFlow "${name}"] isolated pages (no edges): ${isolated.join(', ')}`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Validate: all pages reachable from start
|
|
114
|
+
const adj = new Map<Page, Page[]>();
|
|
115
|
+
for (const p of pages) adj.set(p, []);
|
|
116
|
+
for (const e of edges) {
|
|
117
|
+
const neighbors = adj.get(e.start);
|
|
118
|
+
if (neighbors) neighbors.push(e.end);
|
|
119
|
+
}
|
|
120
|
+
const visited = new Set<Page>();
|
|
121
|
+
const stack: Page[] = [start];
|
|
122
|
+
while (stack.length > 0) {
|
|
123
|
+
const cur = stack.pop()!;
|
|
124
|
+
if (visited.has(cur)) continue;
|
|
125
|
+
visited.add(cur);
|
|
126
|
+
for (const next of adj.get(cur) ?? []) {
|
|
127
|
+
if (!visited.has(next)) stack.push(next);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const unreachable: string[] = [];
|
|
131
|
+
for (const p of pages) {
|
|
132
|
+
if (!visited.has(p)) unreachable.push(p.name);
|
|
133
|
+
}
|
|
134
|
+
if (unreachable.length > 0) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`[definePageFlow "${name}"] unreachable pages: ${unreachable.join(', ')}`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return { name, description, start, pages, edges };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Walk all pages' pageDef.actions (PageSchema runtime shape) to find a NavigationAction with method 'back'. */
|
|
144
|
+
function findBackAction(pages: Page[]): NavigationAction | undefined {
|
|
145
|
+
for (const p of pages) {
|
|
146
|
+
const pageDef = (p as unknown as Record<string, unknown>).pageDef as PageDef | undefined;
|
|
147
|
+
if (!pageDef?.actions) continue;
|
|
148
|
+
for (const a of pageDef.actions) {
|
|
149
|
+
const na = a as NavigationAction;
|
|
150
|
+
if (na.type === 'navigation' && na.method === 'back') return na;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return undefined;
|
|
154
154
|
}
|
package/src/page.ts
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
import { SchemaBase } from './dsl.js';
|
|
2
|
-
import { FrontAppSchema } from './project.js';
|
|
3
|
-
import type { PageDef } from './page-def.js';
|
|
4
|
-
import type { RouteDataSchema } from './route.js';
|
|
5
|
-
|
|
6
|
-
// Page definitions: standalone page schemas and the page node type used by
|
|
7
|
-
// page-driven flows. Kept separate from page-flow.ts (the flow graph itself).
|
|
8
|
-
|
|
9
|
-
// Module-level registry: every definePage/defineTabPage call registers its
|
|
10
|
-
// result so definePageFlow can check that no page is left out.
|
|
11
|
-
const _pageRegistry = new Set<PageSchema>();
|
|
12
|
-
|
|
13
|
-
export function getRegisteredPages(): ReadonlySet<PageSchema> {
|
|
14
|
-
return _pageRegistry;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function clearRegisteredPages(): void {
|
|
18
|
-
_pageRegistry.clear();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** Standalone page definition. A page is a shared value object: it belongs to
|
|
22
|
-
* exactly one frontend app. Actions live in the page skeleton (PageDef.actions),
|
|
23
|
-
* not on the page itself — the page only carries what the flow/topology needs. */
|
|
24
|
-
export interface PageSchema extends SchemaBase {
|
|
25
|
-
/** Short display name for topology diagrams. */
|
|
26
|
-
label: string;
|
|
27
|
-
/** The frontend app this page belongs to (shared instance from project.config). */
|
|
28
|
-
app: FrontAppSchema;
|
|
29
|
-
/** Full page skeleton definition (optional). */
|
|
30
|
-
pageDef?: PageDef;
|
|
31
|
-
/** Route params this page expects (e.g. detail page expects productId). */
|
|
32
|
-
params?: RouteDataSchema;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function definePage(schema: {
|
|
36
|
-
name: string;
|
|
37
|
-
label: string;
|
|
38
|
-
description?: string;
|
|
39
|
-
app: FrontAppSchema;
|
|
40
|
-
pageDef?: PageDef;
|
|
41
|
-
params?: RouteDataSchema;
|
|
42
|
-
}): PageSchema {
|
|
43
|
-
const p: PageSchema = { ...schema };
|
|
44
|
-
_pageRegistry.add(p);
|
|
45
|
-
return p;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** Page with bottom tab navigation. tabs collects the child pages reachable via tab switch. */
|
|
49
|
-
export interface TabPageSchema extends PageSchema {
|
|
50
|
-
tabs: PageSchema[];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function defineTabPage(schema: {
|
|
54
|
-
name: string;
|
|
55
|
-
label: string;
|
|
56
|
-
description?: string;
|
|
57
|
-
app: FrontAppSchema;
|
|
58
|
-
tabs: PageSchema[];
|
|
59
|
-
pageDef?: PageDef;
|
|
60
|
-
params?: RouteDataSchema;
|
|
61
|
-
}): TabPageSchema {
|
|
62
|
-
const p: TabPageSchema = { ...schema };
|
|
63
|
-
_pageRegistry.add(p);
|
|
64
|
-
return p;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** A page node in a page-driven flow: every node is a page, and a page belongs to an app. */
|
|
68
|
-
export interface Page extends SchemaBase {
|
|
69
|
-
/** Short display name for topology diagrams. */
|
|
70
|
-
label?: string;
|
|
71
|
-
/** The frontend app this page belongs to (shared instance from project.config). */
|
|
72
|
-
app: FrontAppSchema;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function page(app: FrontAppSchema, name: string, description?: string, label?: string): Page {
|
|
76
|
-
return { name, label, app, description };
|
|
1
|
+
import { SchemaBase } from './dsl.js';
|
|
2
|
+
import { FrontAppSchema } from './project.js';
|
|
3
|
+
import type { PageDef } from './page-def.js';
|
|
4
|
+
import type { RouteDataSchema } from './route.js';
|
|
5
|
+
|
|
6
|
+
// Page definitions: standalone page schemas and the page node type used by
|
|
7
|
+
// page-driven flows. Kept separate from page-flow.ts (the flow graph itself).
|
|
8
|
+
|
|
9
|
+
// Module-level registry: every definePage/defineTabPage call registers its
|
|
10
|
+
// result so definePageFlow can check that no page is left out.
|
|
11
|
+
const _pageRegistry = new Set<PageSchema>();
|
|
12
|
+
|
|
13
|
+
export function getRegisteredPages(): ReadonlySet<PageSchema> {
|
|
14
|
+
return _pageRegistry;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function clearRegisteredPages(): void {
|
|
18
|
+
_pageRegistry.clear();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Standalone page definition. A page is a shared value object: it belongs to
|
|
22
|
+
* exactly one frontend app. Actions live in the page skeleton (PageDef.actions),
|
|
23
|
+
* not on the page itself — the page only carries what the flow/topology needs. */
|
|
24
|
+
export interface PageSchema extends SchemaBase {
|
|
25
|
+
/** Short display name for topology diagrams. */
|
|
26
|
+
label: string;
|
|
27
|
+
/** The frontend app this page belongs to (shared instance from project.config). */
|
|
28
|
+
app: FrontAppSchema;
|
|
29
|
+
/** Full page skeleton definition (optional). */
|
|
30
|
+
pageDef?: PageDef;
|
|
31
|
+
/** Route params this page expects (e.g. detail page expects productId). */
|
|
32
|
+
params?: RouteDataSchema;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function definePage(schema: {
|
|
36
|
+
name: string;
|
|
37
|
+
label: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
app: FrontAppSchema;
|
|
40
|
+
pageDef?: PageDef;
|
|
41
|
+
params?: RouteDataSchema;
|
|
42
|
+
}): PageSchema {
|
|
43
|
+
const p: PageSchema = { ...schema };
|
|
44
|
+
_pageRegistry.add(p);
|
|
45
|
+
return p;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Page with bottom tab navigation. tabs collects the child pages reachable via tab switch. */
|
|
49
|
+
export interface TabPageSchema extends PageSchema {
|
|
50
|
+
tabs: PageSchema[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function defineTabPage(schema: {
|
|
54
|
+
name: string;
|
|
55
|
+
label: string;
|
|
56
|
+
description?: string;
|
|
57
|
+
app: FrontAppSchema;
|
|
58
|
+
tabs: PageSchema[];
|
|
59
|
+
pageDef?: PageDef;
|
|
60
|
+
params?: RouteDataSchema;
|
|
61
|
+
}): TabPageSchema {
|
|
62
|
+
const p: TabPageSchema = { ...schema };
|
|
63
|
+
_pageRegistry.add(p);
|
|
64
|
+
return p;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** A page node in a page-driven flow: every node is a page, and a page belongs to an app. */
|
|
68
|
+
export interface Page extends SchemaBase {
|
|
69
|
+
/** Short display name for topology diagrams. */
|
|
70
|
+
label?: string;
|
|
71
|
+
/** The frontend app this page belongs to (shared instance from project.config). */
|
|
72
|
+
app: FrontAppSchema;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function page(app: FrontAppSchema, name: string, description?: string, label?: string): Page {
|
|
76
|
+
return { name, label, app, description };
|
|
77
77
|
}
|
package/src/popup.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import type { ActionSchema } from './action.js';
|
|
2
|
-
import type { RefSchema } from './ref.js';
|
|
3
|
-
|
|
4
|
-
/** Display a toast notification. React: toast/message UI. Mini-program: wx.showToast. */
|
|
5
|
-
export interface ToastAction extends ActionSchema {
|
|
6
|
-
type: 'toast';
|
|
7
|
-
message: string | RefSchema;
|
|
8
|
-
icon?: 'success' | 'error' | 'loading' | 'none';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/** Display an alert dialog. React: modal. Mini-program: wx.showModal. */
|
|
12
|
-
export interface AlertAction extends ActionSchema {
|
|
13
|
-
type: 'alert';
|
|
14
|
-
title: string | RefSchema;
|
|
15
|
-
content: string | RefSchema;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const popup = {
|
|
19
|
-
toast(message: string | RefSchema, icon?: 'success' | 'error' | 'loading' | 'none'): ToastAction {
|
|
20
|
-
return { name: 'toast', type: 'toast', message, icon };
|
|
21
|
-
},
|
|
22
|
-
alert(title: string | RefSchema, content: string | RefSchema): AlertAction {
|
|
23
|
-
return { name: 'alert', type: 'alert', title, content };
|
|
24
|
-
},
|
|
25
|
-
};
|
|
1
|
+
import type { ActionSchema } from './action.js';
|
|
2
|
+
import type { RefSchema } from './ref.js';
|
|
3
|
+
|
|
4
|
+
/** Display a toast notification. React: toast/message UI. Mini-program: wx.showToast. */
|
|
5
|
+
export interface ToastAction extends ActionSchema {
|
|
6
|
+
type: 'toast';
|
|
7
|
+
message: string | RefSchema;
|
|
8
|
+
icon?: 'success' | 'error' | 'loading' | 'none';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Display an alert dialog. React: modal. Mini-program: wx.showModal. */
|
|
12
|
+
export interface AlertAction extends ActionSchema {
|
|
13
|
+
type: 'alert';
|
|
14
|
+
title: string | RefSchema;
|
|
15
|
+
content: string | RefSchema;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const popup = {
|
|
19
|
+
toast(message: string | RefSchema, icon?: 'success' | 'error' | 'loading' | 'none'): ToastAction {
|
|
20
|
+
return { name: 'toast', type: 'toast', message, icon };
|
|
21
|
+
},
|
|
22
|
+
alert(title: string | RefSchema, content: string | RefSchema): AlertAction {
|
|
23
|
+
return { name: 'alert', type: 'alert', title, content };
|
|
24
|
+
},
|
|
25
|
+
};
|