openxiangda-cli 2.0.0-alpha.182 → 2.0.0-alpha.185

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 (50) hide show
  1. package/dist/base.js +2 -2
  2. package/dist/base.js.map +1 -1
  3. package/dist/commands/admin.d.ts.map +1 -1
  4. package/dist/commands/admin.js +5 -3
  5. package/dist/commands/admin.js.map +1 -1
  6. package/dist/commands/create.d.ts +1 -0
  7. package/dist/commands/create.d.ts.map +1 -1
  8. package/dist/commands/create.js +34 -16
  9. package/dist/commands/create.js.map +1 -1
  10. package/dist/commands/dev.d.ts.map +1 -1
  11. package/dist/commands/dev.js +1 -1
  12. package/dist/commands/dev.js.map +1 -1
  13. package/dist/commands/login.js +1 -1
  14. package/dist/commands/login.js.map +1 -1
  15. package/dist/commands/spec.js +1 -1
  16. package/dist/commands/spec.js.map +1 -1
  17. package/package.json +5 -5
  18. package/template/AGENTS.md +2 -2
  19. package/template/apps/web/e2e/README.md +7 -0
  20. package/template/apps/web/package.json +2 -2
  21. package/template/apps/web/playwright.config.ts +3 -5
  22. package/template/apps/web/vite.config.ts +1 -9
  23. package/template/appspec/app.md +5 -1
  24. package/template/package.json +1 -1
  25. package/template/apps/web/data-api-live.e2e.html +0 -15
  26. package/template/apps/web/e2e/client-fixture.ts +0 -5
  27. package/template/apps/web/e2e/component-defaults-fixture.css +0 -15
  28. package/template/apps/web/e2e/data-api-live-fixture.tsx +0 -162
  29. package/template/apps/web/e2e/data-api-live.spec.ts +0 -144
  30. package/template/apps/web/e2e/field-protocol-fixture.tsx +0 -387
  31. package/template/apps/web/e2e/field-protocol.spec.ts +0 -285
  32. package/template/apps/web/e2e/mobile-files.spec.ts +0 -96
  33. package/template/apps/web/e2e/mobile-reference-fixture.tsx +0 -314
  34. package/template/apps/web/e2e/mobile-reference.spec.ts +0 -360
  35. package/template/apps/web/e2e/mobile-selection.spec.ts +0 -199
  36. package/template/apps/web/e2e/resource-experience-fixture.tsx +0 -491
  37. package/template/apps/web/e2e/resource-platform-mock.ts +0 -202
  38. package/template/apps/web/e2e/resources.spec.ts +0 -488
  39. package/template/apps/web/e2e/standard-admin.spec.ts +0 -511
  40. package/template/apps/web/e2e/workflow-entry-fixture.tsx +0 -107
  41. package/template/apps/web/e2e/workflow-entry.spec.ts +0 -556
  42. package/template/apps/web/e2e/workflow-experience-fixture.tsx +0 -338
  43. package/template/apps/web/e2e/workflow.spec.ts +0 -1265
  44. package/template/apps/web/field-protocol.e2e.html +0 -22
  45. package/template/apps/web/mobile-reference.e2e.html +0 -27
  46. package/template/apps/web/resource-experience.e2e.html +0 -16
  47. package/template/apps/web/scripts/check.mjs +0 -43
  48. package/template/apps/web/test/contracts.test.ts +0 -163
  49. package/template/apps/web/workflow-entry.e2e.html +0 -15
  50. package/template/apps/web/workflow-experience.e2e.html +0 -15
@@ -1,22 +0,0 @@
1
- <!doctype html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <meta name="openxiangda-runtime-base" content="/" />
7
- <meta name="openxiangda-app-code" content="field-protocol-fixture" />
8
- <meta name="openxiangda-environment" content="preproduction" />
9
- <title>Field protocol acceptance</title>
10
- <style>
11
- html { background-color: rgb(248, 249, 250); }
12
- body { color: rgb(31, 32, 33); font-size: 17px; font-family: monospace; }
13
- a { color: rgb(101, 42, 140); }
14
- output[data-saved-values] { display: block; overflow-wrap: anywhere; }
15
- </style>
16
- </head>
17
- <body>
18
- <a id="outside-mobile" href="#root">页面外部链接</a>
19
- <div id="root"></div>
20
- <script type="module" src="/e2e/field-protocol-fixture.tsx"></script>
21
- </body>
22
- </html>
@@ -1,27 +0,0 @@
1
- <!doctype html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <meta name="openxiangda-runtime-base" content="/" />
7
- <meta name="openxiangda-app-code" content="field-protocol-fixture" />
8
- <meta name="openxiangda-environment" content="preproduction" />
9
- <title>移动表单组件</title>
10
- <style>
11
- body { margin: 0; }
12
- .reference-form { min-height: 100dvh; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
13
- .reference-form .oxa-mobile-header { position: sticky; top: 0; z-index: 5; }
14
- .reference-form .reference-group { margin: 0 12px 16px; padding: 0 16px; background: white; border-radius: 10px; }
15
- .reference-form .reference-group > div:last-child .oxa-mobile-field { border-bottom: 0; }
16
- .reference-form .reference-group-title { font-size: 14px; font-weight: 400; color: #888; padding: 0 24px; margin: 20px 0 10px; }
17
- .reference-form .reference-content { padding-bottom: 86px; }
18
- .reference-form [data-field-code] { scroll-margin-top: 82px; }
19
- .reference-form output { display: none; }
20
- .reference-form .reference-notice { padding: 8px 24px; color: #1677ff; }
21
- </style>
22
- </head>
23
- <body>
24
- <div id="root"></div>
25
- <script type="module" src="/e2e/mobile-reference-fixture.tsx"></script>
26
- </body>
27
- </html>
@@ -1,16 +0,0 @@
1
- <!doctype html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <meta name="openxiangda-runtime-base" content="/" />
7
- <meta name="openxiangda-app-code" content="openxiangda-application" />
8
- <meta name="openxiangda-environment" content="preproduction" />
9
- <title>Resource experience acceptance</title>
10
- </head>
11
- <body>
12
- <div id="outside-ui" style="height:0;overflow:hidden;font-family:monospace;color:rgb(31,32,33);background:rgb(248,249,250)">宿主页面</div>
13
- <div id="root"></div>
14
- <script type="module" src="/e2e/resource-experience-fixture.tsx"></script>
15
- </body>
16
- </html>
@@ -1,43 +0,0 @@
1
- import { readFileSync, readdirSync } from 'node:fs';
2
- import { join, resolve } from 'node:path';
3
-
4
- const root = resolve(import.meta.dirname, '..');
5
- const files = [];
6
- function visit(directory) {
7
- for (const entry of readdirSync(directory, { withFileTypes: true })) {
8
- const path = join(directory, entry.name);
9
- if (entry.isDirectory() && !['.umi', '.umi-production', '.turbopack'].includes(entry.name)) visit(path);
10
- else if (/\.(?:ts|tsx)$/.test(entry.name)) files.push(path);
11
- }
12
- }
13
- visit(join(root, 'src'));
14
- const lines = files.reduce((total, file) => total + readFileSync(file, 'utf8').split(/\r?\n/).length, 0);
15
- // The shared Surface renderer is deliberately counted as application source;
16
- // keep its small budget explicit instead of hiding it in generated output.
17
- // Field Kit families are separate modules so a semantic field does not add a
18
- // branch to one universal renderer. Keep explicit ceilings while allowing the
19
- // complete 30-field standard kit to remain decomposed.
20
- if (files.length > 36) throw new Error(`WEB_SOURCE_FILE_BUDGET_EXCEEDED:${files.length}>36`);
21
- if (lines > 10_000) throw new Error(`WEB_BUSINESS_LOC_BUDGET_EXCEEDED:${lines}>10000`);
22
- const source = files.map((file) => readFileSync(file, 'utf8')).join('\n');
23
- for (const marker of [
24
- '@umijs/',
25
- 'openxiangda-' + 'admin',
26
- 'openxiangda-' + 'user',
27
- 'instrument_query',
28
- 'instrument_save',
29
- 'function.invoke',
30
- 'authorization' + '-mode',
31
- 'focused' + '_role',
32
- '/native/current' + '-user',
33
- 'college-' + 'am',
34
- 'user-' + 'wang',
35
- 'dept-' + 'am-test',
36
- ]) {
37
- if (source.includes(marker)) throw new Error(`WEB_FORBIDDEN_MARKER:${marker}`);
38
- }
39
- const playwright = readFileSync(join(root, 'playwright.config.ts'), 'utf8');
40
- if (!playwright.includes('reuseExistingServer: false')) {
41
- throw new Error('WEB_E2E_MUST_NOT_REUSE_UNKNOWN_SERVER');
42
- }
43
- process.stdout.write(`Verified Vite/Refine web source: ${files.length} files, ${lines} LOC.\n`);
@@ -1,163 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import { existsSync, readFileSync, readdirSync } from 'node:fs';
3
- import test from 'node:test';
4
- import { readRuntimeMount, resolveApplicationBasename } from 'openxiangda/core';
5
- import {
6
- notificationTemplateCodes,
7
- platformAuthManifest,
8
- resourceCodes,
9
- resourceDefinitions,
10
- } from '../../../packages/contracts/src/generated.js';
11
-
12
- test('clean template contains application declarations, document reset and one React entry', () => {
13
- const config = readFileSync(
14
- new URL('../../../openxiangda.config.ts', import.meta.url),
15
- 'utf8'
16
- );
17
- const source = readFileSync(new URL('../src/main.tsx', import.meta.url), 'utf8');
18
- const productionSources = readdirSync(new URL('../src', import.meta.url), {
19
- withFileTypes: true,
20
- })
21
- .filter(entry => entry.isFile())
22
- .map(entry => entry.name)
23
- .sort();
24
- assert.deepEqual(productionSources, ['document.css', 'main.tsx']);
25
- assert.deepEqual(Object.keys(resourceDefinitions).sort(), [...resourceCodes].sort());
26
- assert.equal(
27
- notificationTemplateCodes.applicationInformational,
28
- 'application.informational.standard'
29
- );
30
- assert.equal(platformAuthManifest?.protectedUserRouteCount, 2);
31
- assert.equal(platformAuthManifest?.surfaces.length, 2);
32
- assert.match(config, /defineOpenXiangdaApp/);
33
- assert.match(source, /OpenXiangdaApplication/);
34
- assert.match(source, /routes: appRoutes, authenticationSurfaces/);
35
- assert.match(source, /DefaultDesktopApplicationLoginSurface/);
36
- assert.match(source, /DefaultMobileApplicationLoginSurface/);
37
- assert.match(source, /contributions=\{applicationContributions\}/);
38
- assert.match(source, /publicAccess=\{anonymousPublicAccess\}/);
39
- assert.match(source, /from 'openxiangda\/react'/);
40
- assert.match(source, /openxiangda\/react\/styles\.css/);
41
- const legacyMarkers = [
42
- 'instruments',
43
- 'colleges',
44
- '仪器' + '资源管理',
45
- '学院' + '字典',
46
- 'HGY',
47
- 'Instrument',
48
- ];
49
- assert.doesNotMatch(`${config}\n${source}`, new RegExp(legacyMarkers.join('|')));
50
- });
51
-
52
- test('application manifests expose one direct OpenXiangda dependency', () => {
53
- for (const relative of [
54
- '../../../package.json',
55
- '../package.json',
56
- ...(existsSync(new URL('../../server/package.json', import.meta.url)) ? ['../../server/package.json'] : []),
57
- ]) {
58
- const manifest = JSON.parse(
59
- readFileSync(new URL(relative, import.meta.url), 'utf8')
60
- ) as Record<string, Record<string, string>>;
61
- const dependencies = Object.entries({
62
- ...(manifest.dependencies || {}),
63
- ...(manifest.devDependencies || {}),
64
- ...(manifest.peerDependencies || {}),
65
- }).filter(([name]) =>
66
- name === 'openxiangda' || name.startsWith('openxiangda-')
67
- );
68
- assert.deepEqual(
69
- dependencies.map(([name]) => name),
70
- dependencies.length ? ['openxiangda'] : []
71
- );
72
- }
73
- });
74
-
75
- test('runtime metadata stays mount-scoped', () => {
76
- const mount = readRuntimeMount(
77
- name =>
78
- ({
79
- 'openxiangda-runtime-base': '/view/example-app/',
80
- 'openxiangda-app-code': 'example-app',
81
- 'openxiangda-environment': 'preproduction',
82
- })[name]
83
- );
84
- assert.equal(resolveApplicationBasename(mount), '/view/example-app');
85
- });
86
-
87
- test('resource E2E harness owns the standard export download response', () => {
88
- const source = readFileSync(
89
- new URL('../e2e/resource-platform-mock.ts', import.meta.url),
90
- 'utf8'
91
- );
92
- assert.match(source, /\/native\\\/data\\\/\(\[\^\/\]\+\)\\\/export\$/);
93
- assert.match(source, /content-disposition/);
94
- assert.match(source, /text\/csv/);
95
- });
96
-
97
- test('published E2E harnesses do not write evidence into the platform source repository', () => {
98
- const workflowSource = readFileSync(
99
- new URL('../e2e/workflow.spec.ts', import.meta.url),
100
- 'utf8'
101
- );
102
- assert.doesNotMatch(workflowSource, /docs\/architecture|evidenceDirectory/);
103
- });
104
-
105
- test('E2E experience fixtures explicitly own every tested route', () => {
106
- const resourceFixture = readFileSync(
107
- new URL('../e2e/resource-experience-fixture.tsx', import.meta.url),
108
- 'utf8'
109
- );
110
- for (let index = 1; index <= 12; index += 1) {
111
- const code = `resource-${String(index).padStart(2, '0')}`;
112
- const pageCode = `resource:${code}:list`;
113
- assert.match(resourceFixture, new RegExp(`pageCode: '${pageCode}'`));
114
- assert.match(resourceFixture, new RegExp(`code: '${pageCode}'`));
115
- }
116
-
117
- const workflowFixture = readFileSync(
118
- new URL('../e2e/workflow-experience-fixture.tsx', import.meta.url),
119
- 'utf8'
120
- );
121
- assert.match(workflowFixture, /code: 'workflow:work-center'/);
122
- assert.match(workflowFixture, /code: 'workflow:task'/);
123
- assert.match(workflowFixture, /code: 'workflow:instance'/);
124
- assert.match(workflowFixture, /path: '\/work-center'/);
125
- assert.match(workflowFixture, /path: '\/tasks\/:taskId'/);
126
- assert.match(workflowFixture, /path: '\/workflows\/:instanceId'/);
127
- assert.doesNotMatch(
128
- workflowFixture,
129
- /path: '\/(?:m\/)?admin\/(?:todos|work-center|tasks|workflows)/
130
- );
131
- });
132
-
133
- test('browser acceptance serializes the prewarmed Vite HTML entrypoints', () => {
134
- const viteConfig = readFileSync(new URL('../vite.config.ts', import.meta.url), 'utf8');
135
- const playwrightConfig = readFileSync(
136
- new URL('../playwright.config.ts', import.meta.url),
137
- 'utf8'
138
- );
139
- const htmlEntries = readdirSync(new URL('..', import.meta.url))
140
- .filter(name => name.endsWith('.e2e.html'))
141
- .sort();
142
- assert.deepEqual(htmlEntries, [
143
- 'data-api-live.e2e.html',
144
- 'field-protocol.e2e.html',
145
- 'mobile-reference.e2e.html',
146
- 'resource-experience.e2e.html',
147
- 'workflow-entry.e2e.html',
148
- 'workflow-experience.e2e.html',
149
- ]);
150
- for (const entry of htmlEntries) {
151
- assert.ok(viteConfig.includes(`'${entry}'`), `missing optimizeDeps entry ${entry}`);
152
- }
153
- assert.match(playwrightConfig, /workers:\s*1/);
154
- });
155
-
156
- test('the platform package owns Web build verification policy', () => {
157
- const verifier = readFileSync(
158
- new URL('../scripts/verify-build.mjs', import.meta.url),
159
- 'utf8'
160
- );
161
- assert.match(verifier, /verifyOpenXiangdaWebBuild/);
162
- assert.doesNotMatch(verifier, /2_650_000|800_000|600_000/);
163
- });
@@ -1,15 +0,0 @@
1
- <!doctype html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <meta name="openxiangda-runtime-base" content="/" />
7
- <meta name="openxiangda-app-code" content="openxiangda-application" />
8
- <meta name="openxiangda-environment" content="preproduction" />
9
- <title>Workflow entry acceptance</title>
10
- </head>
11
- <body>
12
- <div id="root"></div>
13
- <script type="module" src="/e2e/workflow-entry-fixture.tsx"></script>
14
- </body>
15
- </html>
@@ -1,15 +0,0 @@
1
- <!doctype html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <meta name="openxiangda-runtime-base" content="/" />
7
- <meta name="openxiangda-app-code" content="openxiangda-application" />
8
- <meta name="openxiangda-environment" content="preproduction" />
9
- <title>Workflow experience acceptance</title>
10
- </head>
11
- <body>
12
- <div id="root"></div>
13
- <script type="module" src="/e2e/workflow-experience-fixture.tsx"></script>
14
- </body>
15
- </html>