openxiangda-cli 2.0.0-alpha.183 → 2.0.0-alpha.186

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 (43) hide show
  1. package/dist/commands/admin.d.ts.map +1 -1
  2. package/dist/commands/admin.js +5 -3
  3. package/dist/commands/admin.js.map +1 -1
  4. package/dist/commands/auth.d.ts +30 -0
  5. package/dist/commands/auth.d.ts.map +1 -0
  6. package/dist/commands/auth.js +13 -0
  7. package/dist/commands/auth.js.map +1 -0
  8. package/dist/commands/spec.js +1 -1
  9. package/dist/commands/spec.js.map +1 -1
  10. package/package.json +5 -5
  11. package/template/AGENTS.md +2 -2
  12. package/template/apps/web/e2e/README.md +7 -0
  13. package/template/apps/web/package.json +2 -2
  14. package/template/apps/web/playwright.config.ts +3 -5
  15. package/template/apps/web/vite.config.ts +1 -9
  16. package/template/appspec/app.md +5 -1
  17. package/template/package.json +1 -1
  18. package/template/apps/web/data-api-live.e2e.html +0 -15
  19. package/template/apps/web/e2e/client-fixture.ts +0 -5
  20. package/template/apps/web/e2e/component-defaults-fixture.css +0 -15
  21. package/template/apps/web/e2e/data-api-live-fixture.tsx +0 -162
  22. package/template/apps/web/e2e/data-api-live.spec.ts +0 -144
  23. package/template/apps/web/e2e/field-protocol-fixture.tsx +0 -387
  24. package/template/apps/web/e2e/field-protocol.spec.ts +0 -285
  25. package/template/apps/web/e2e/mobile-files.spec.ts +0 -96
  26. package/template/apps/web/e2e/mobile-reference-fixture.tsx +0 -314
  27. package/template/apps/web/e2e/mobile-reference.spec.ts +0 -360
  28. package/template/apps/web/e2e/mobile-selection.spec.ts +0 -199
  29. package/template/apps/web/e2e/resource-experience-fixture.tsx +0 -491
  30. package/template/apps/web/e2e/resource-platform-mock.ts +0 -202
  31. package/template/apps/web/e2e/resources.spec.ts +0 -488
  32. package/template/apps/web/e2e/standard-admin.spec.ts +0 -511
  33. package/template/apps/web/e2e/workflow-entry-fixture.tsx +0 -107
  34. package/template/apps/web/e2e/workflow-entry.spec.ts +0 -556
  35. package/template/apps/web/e2e/workflow-experience-fixture.tsx +0 -338
  36. package/template/apps/web/e2e/workflow.spec.ts +0 -1265
  37. package/template/apps/web/field-protocol.e2e.html +0 -22
  38. package/template/apps/web/mobile-reference.e2e.html +0 -27
  39. package/template/apps/web/resource-experience.e2e.html +0 -16
  40. package/template/apps/web/scripts/check.mjs +0 -43
  41. package/template/apps/web/test/contracts.test.ts +0 -163
  42. package/template/apps/web/workflow-entry.e2e.html +0 -15
  43. package/template/apps/web/workflow-experience.e2e.html +0 -15
@@ -1,338 +0,0 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom/client';
3
- import {
4
- defineApplicationContributions,
5
- OpenXiangdaApplication,
6
- type AdminNavigationInput,
7
- type AdminPagesInput,
8
- type StandardApplicationTodoCenterProps,
9
- type StandardUserPageFrameProps,
10
- type StandardUserSurfaceContributions,
11
- } from 'openxiangda/react';
12
- import { useParams, useSearchParams } from 'react-router-dom';
13
- import { appCode } from '../../../packages/contracts/src/generated.js';
14
- import 'openxiangda/react/styles.css';
15
-
16
- const fixtureParams = new URLSearchParams(window.location.search);
17
- const standardSurfaceMode = fixtureParams.get('surfaces');
18
-
19
- const workflowDefinitions = [
20
- {
21
- code: 'purchase-approval',
22
- title: '采购审批',
23
- launch: { mode: 'standalone' },
24
- subject: {
25
- resourceCode: 'purchase-orders',
26
- factProjection: { amount: 'amount' },
27
- summaryFields: ['amount'],
28
- },
29
- processOperationCode: 'openxiangda.workflow.purchase-approval.submit',
30
- },
31
- ] as const;
32
-
33
- const resourceDefinitions = {
34
- 'purchase-orders': {
35
- code: 'purchase-orders',
36
- name: '采购申请',
37
- capabilities: {
38
- read: `app:${appCode}:data:purchase-orders:read`,
39
- create: `app:${appCode}:data:purchase-orders:create`,
40
- update: `app:${appCode}:data:purchase-orders:update`,
41
- delete: `app:${appCode}:data:purchase-orders:delete`,
42
- },
43
- surface: {
44
- mutationOwner: 'native',
45
- generated: { list: true, detail: true, create: true, update: true, delete: true },
46
- fields: {
47
- amount: {
48
- label: '申请金额',
49
- type: 'number.decimal',
50
- widget: 'money',
51
- requiredHint: true,
52
- readCapabilities: [`app:${appCode}:data:purchase-orders:read`],
53
- createCapabilities: [`app:${appCode}:data:purchase-orders:create`],
54
- updateCapabilities: [`app:${appCode}:data:purchase-orders:update`],
55
- },
56
- },
57
- form: { layout: 'flat', fieldOrder: ['amount'] },
58
- mobile: { enabled: true },
59
- },
60
- },
61
- } as const;
62
-
63
- const detailRoutes = {
64
- desktop: {
65
- code: 'purchase-detail',
66
- path: '/admin/operations/purchases/:instanceId',
67
- label: '采购审批详情',
68
- surface: 'admin',
69
- tabPersistence: 'none',
70
- keepAlive: 'none',
71
- },
72
- mobile: {
73
- code: 'purchase-detail-mobile',
74
- path: '/m/purchases/:instanceId',
75
- label: '移动采购审批详情',
76
- surface: 'user',
77
- tabPersistence: 'none',
78
- keepAlive: 'none',
79
- },
80
- } as const;
81
-
82
- function CustomWorkflowDetail() {
83
- const { instanceId } = useParams();
84
- const [search] = useSearchParams();
85
- return (
86
- <div data-testid="custom-workflow-detail">
87
- 自定义流程详情 {instanceId} / {search.get('taskId') || 'instance'}
88
- </div>
89
- );
90
- }
91
-
92
- function StandardFrame({
93
- back,
94
- canGoBack,
95
- children,
96
- device,
97
- pageKind,
98
- route,
99
- }: StandardUserPageFrameProps) {
100
- return (
101
- <section
102
- data-can-go-back={String(canGoBack)}
103
- data-page-kind={pageKind}
104
- data-route-code={route.routeCode}
105
- data-route-params={JSON.stringify(route.params)}
106
- data-testid={`standard-frame-${device}`}
107
- >
108
- <button onClick={back} type="button">返回</button>
109
- {children}
110
- </section>
111
- );
112
- }
113
-
114
- function CustomTodo({
115
- device,
116
- error,
117
- hasMore,
118
- items,
119
- loadMore,
120
- loading,
121
- loadingMore,
122
- openItem,
123
- query,
124
- refresh,
125
- setQuery,
126
- }: StandardApplicationTodoCenterProps) {
127
- return (
128
- <main data-testid={`custom-todo-${device}`}>
129
- <h1>{device === 'mobile' ? '移动应用待办' : '桌面应用待办'}</h1>
130
- <output data-testid="custom-todo-query">
131
- {query.view}/{String(query.unread)}/{query.keyword || 'all'}
132
- </output>
133
- {error ? <div role="alert">{error}</div> : null}
134
- <button onClick={() => void refresh()} type="button">刷新待办</button>
135
- <button
136
- onClick={() => setQuery({ unread: !query.unread })}
137
- type="button"
138
- >
139
- 切换未读
140
- </button>
141
- <ul aria-busy={loading || loadingMore}>
142
- {items.map(item => (
143
- <li key={item.messageId}>
144
- <button onClick={() => void openItem(item)} type="button">
145
- {item.title}
146
- </button>
147
- </li>
148
- ))}
149
- </ul>
150
- <button
151
- disabled={!hasMore || loadingMore}
152
- onClick={() => void loadMore()}
153
- type="button"
154
- >
155
- 加载更多
156
- </button>
157
- </main>
158
- );
159
- }
160
-
161
- function BrokenTodo(_props: StandardApplicationTodoCenterProps) {
162
- throw new Error('fixture standard user renderer failure');
163
- }
164
-
165
- const standardUserSurfaces: StandardUserSurfaceContributions | undefined =
166
- standardSurfaceMode
167
- ? {
168
- frame: { desktop: StandardFrame, mobile: StandardFrame },
169
- applicationTodoCenter: {
170
- desktop:
171
- standardSurfaceMode === 'error' ? BrokenTodo : CustomTodo,
172
- mobile: standardSurfaceMode === 'error' ? BrokenTodo : CustomTodo,
173
- },
174
- }
175
- : undefined;
176
-
177
- const applicationContributions = defineApplicationContributions(detailRoutes, {
178
- pages: {
179
- desktop: CustomWorkflowDetail,
180
- mobile: CustomWorkflowDetail,
181
- },
182
- ...(standardUserSurfaces ? { standardUserSurfaces } : {}),
183
- });
184
-
185
- const adminPages = [] as const satisfies AdminPagesInput;
186
-
187
- const routeManifest = {
188
- schemaVersion: 'openxiangda.application-route-manifest/v3',
189
- appCode,
190
- devicePolicy: {
191
- kind: 'viewport-family',
192
- mobileMaxWidthPx: 900,
193
- desktopMinWidthPx: 901,
194
- },
195
- rootEntry: { code: 'application-root', desktop: '/', mobile: '/m/' },
196
- authentication: {
197
- desktop: { routeCode: 'application-login', path: '/login' },
198
- mobile: { routeCode: 'application-login-mobile', path: '/m/login' },
199
- },
200
- routes: [
201
- {
202
- code: 'application:todo-center',
203
- kind: 'application-todo-center',
204
- desktop: {
205
- routeCode: 'application.todo-center.desktop',
206
- path: '/todos',
207
- surface: 'user',
208
- pathParams: [],
209
- requiresAuthentication: true,
210
- },
211
- mobile: {
212
- routeCode: 'application.todo-center.mobile',
213
- path: '/m/todos',
214
- surface: 'user',
215
- pathParams: [],
216
- requiresAuthentication: true,
217
- },
218
- },
219
- {
220
- code: 'workflow:work-center',
221
- kind: 'workflow-work-center',
222
- desktop: {
223
- routeCode: 'workflow.work.center.desktop',
224
- path: '/work-center',
225
- surface: 'user',
226
- pathParams: [],
227
- requiresAuthentication: true,
228
- },
229
- mobile: {
230
- routeCode: 'workflow.work.center.mobile',
231
- path: '/m/work-center',
232
- surface: 'user',
233
- pathParams: [],
234
- requiresAuthentication: true,
235
- },
236
- },
237
- {
238
- code: 'workflow:task',
239
- kind: 'workflow-task',
240
- desktop: {
241
- routeCode: 'workflow.task.desktop',
242
- path: '/tasks/:taskId',
243
- surface: 'user',
244
- pathParams: ['taskId'],
245
- requiresAuthentication: true,
246
- },
247
- mobile: {
248
- routeCode: 'workflow.task.mobile',
249
- path: '/m/tasks/:taskId',
250
- surface: 'user',
251
- pathParams: ['taskId'],
252
- requiresAuthentication: true,
253
- },
254
- },
255
- {
256
- code: 'workflow:instance',
257
- kind: 'workflow-instance',
258
- desktop: {
259
- routeCode: 'workflow.instance.desktop',
260
- path: '/workflows/:instanceId',
261
- surface: 'user',
262
- pathParams: ['instanceId'],
263
- requiresAuthentication: true,
264
- },
265
- mobile: {
266
- routeCode: 'workflow.instance.mobile',
267
- path: '/m/workflows/:instanceId',
268
- surface: 'user',
269
- pathParams: ['instanceId'],
270
- requiresAuthentication: true,
271
- },
272
- },
273
- {
274
- code: 'workflow:purchase-approval:launch',
275
- kind: 'workflow-launch',
276
- workflowCode: 'purchase-approval',
277
- desktop: {
278
- routeCode: 'workflow.purchase-approval.launch.desktop',
279
- path: '/workflows/:workflowCode/start',
280
- surface: 'user',
281
- pathParams: ['workflowCode'],
282
- requiresAuthentication: true,
283
- },
284
- mobile: {
285
- routeCode: 'workflow.purchase-approval.launch.mobile',
286
- path: '/m/workflows/:workflowCode/start',
287
- surface: 'user',
288
- pathParams: ['workflowCode'],
289
- requiresAuthentication: true,
290
- },
291
- },
292
- ],
293
- digest: '34cc08a02cd187a07d9e2d2f99c1080b5b86f3a4512f9e0f43ff4cb05b7195fa',
294
- } as const;
295
-
296
- const adminNavigation = [] as const satisfies AdminNavigationInput;
297
-
298
- const initialPath = fixtureParams.get('initial') || '/work-center';
299
- const runtimeBase = fixtureParams.get('base')?.trim();
300
- if (runtimeBase) {
301
- for (const [name, content] of [
302
- ['openxiangda-runtime-base', runtimeBase],
303
- ['openxiangda-app-code', appCode],
304
- ['openxiangda-environment', 'preproduction'],
305
- ] as const) {
306
- const meta =
307
- document.querySelector<HTMLMetaElement>(`meta[name="${name}"]`) ||
308
- document.createElement('meta');
309
- meta.name = name;
310
- meta.content = content;
311
- if (!meta.parentElement) document.head.appendChild(meta);
312
- }
313
- }
314
- if (location.pathname.endsWith('/workflow-experience.e2e.html')) {
315
- const stateToken = fixtureParams.get('state');
316
- history.replaceState(
317
- stateToken
318
- ? { usr: { routeNegotiationState: stateToken }, key: 'fixture-state' }
319
- : {},
320
- '',
321
- initialPath,
322
- );
323
- }
324
-
325
- ReactDOM.createRoot(document.getElementById('root')!).render(
326
- <React.StrictMode>
327
- <OpenXiangdaApplication
328
- appCode={appCode}
329
- appName="流程体验验收"
330
- adminNavigation={adminNavigation}
331
- adminPages={adminPages}
332
- routeManifest={routeManifest}
333
- contributions={applicationContributions}
334
- resourceDefinitions={resourceDefinitions}
335
- workflows={workflowDefinitions}
336
- />
337
- </React.StrictMode>
338
- );