openxiangda-cli 2.0.0-alpha.12 → 2.0.0-alpha.120
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 +13 -14
- package/bin/run.js +79 -1
- package/dist/base.d.ts +40 -5
- package/dist/base.d.ts.map +1 -1
- package/dist/base.js +123 -10
- package/dist/base.js.map +1 -1
- package/dist/commands/accept.d.ts +25 -0
- package/dist/commands/accept.d.ts.map +1 -0
- package/dist/commands/accept.js +21 -0
- package/dist/commands/accept.js.map +1 -0
- package/dist/commands/cancel.d.ts +16 -1
- package/dist/commands/cancel.d.ts.map +1 -1
- package/dist/commands/cancel.js +1 -1
- package/dist/commands/cancel.js.map +1 -1
- package/dist/commands/check.d.ts +17 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +15 -3
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/create.d.ts +25 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +101 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/deploy.d.ts +21 -8
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +29 -16
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts +18 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +24 -3
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/login.d.ts +26 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +73 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logs.d.ts +17 -2
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +2 -2
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/retry.d.ts +16 -1
- package/dist/commands/retry.d.ts.map +1 -1
- package/dist/commands/retry.js +5 -2
- package/dist/commands/retry.js.map +1 -1
- package/dist/commands/rollback.d.ts +17 -4
- package/dist/commands/rollback.d.ts.map +1 -1
- package/dist/commands/rollback.js +11 -4
- package/dist/commands/rollback.js.map +1 -1
- package/dist/commands/skill.d.ts +28 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +43 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/spec.d.ts +36 -0
- package/dist/commands/spec.d.ts.map +1 -0
- package/dist/commands/spec.js +117 -0
- package/dist/commands/spec.js.map +1 -0
- package/dist/commands/start.d.ts +25 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +18 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +16 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/stop.d.ts +25 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +18 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/create-workspace.d.ts +31 -0
- package/dist/create-workspace.d.ts.map +1 -0
- package/dist/create-workspace.js +273 -0
- package/dist/create-workspace.js.map +1 -0
- package/dist/toolchain-capsule.d.ts +4 -0
- package/dist/toolchain-capsule.d.ts.map +1 -0
- package/dist/toolchain-capsule.js +116 -0
- package/dist/toolchain-capsule.js.map +1 -0
- package/package.json +16 -9
- package/template/.dockerignore +23 -0
- package/template/.env.example +3 -0
- package/template/AGENTS.md +25 -0
- package/template/README.md +43 -0
- package/template/_gitignore +14 -0
- package/template/apps/server/Dockerfile +20 -0
- package/template/apps/server/package.json +27 -0
- package/template/apps/server/src/app.module.ts +43 -0
- package/template/apps/server/src/main.ts +5 -0
- package/template/apps/server/test/smoke.test.ts +16 -0
- package/template/apps/server/tsconfig.json +9 -0
- package/template/apps/web/data-api-live.e2e.html +15 -0
- package/template/apps/web/e2e/client-fixture.ts +5 -0
- package/template/apps/web/e2e/data-api-live-fixture.tsx +162 -0
- package/template/apps/web/e2e/data-api-live.spec.ts +144 -0
- package/template/apps/web/e2e/field-protocol-fixture.tsx +347 -0
- package/template/apps/web/e2e/field-protocol.spec.ts +195 -0
- package/template/apps/web/e2e/resource-experience-fixture.tsx +380 -0
- package/template/apps/web/e2e/resources.spec.ts +478 -0
- package/template/apps/web/e2e/workflow-experience-fixture.tsx +144 -0
- package/template/apps/web/e2e/workflow.spec.ts +576 -0
- package/template/apps/web/field-protocol.e2e.html +15 -0
- package/template/apps/web/index.html +12 -0
- package/template/apps/web/package.json +32 -0
- package/template/apps/web/playwright.config.ts +47 -0
- package/template/apps/web/resource-experience.e2e.html +15 -0
- package/template/apps/web/scripts/check.mjs +43 -0
- package/template/apps/web/scripts/verify-build.mjs +6 -0
- package/template/apps/web/src/main.tsx +41 -0
- package/template/apps/web/test/contracts.test.ts +149 -0
- package/template/apps/web/test/loopback.test.ts +62 -0
- package/template/apps/web/tsconfig.json +12 -0
- package/template/apps/web/vite.config.ts +40 -0
- package/template/apps/web/workflow-experience.e2e.html +15 -0
- package/template/appspec/app.md +36 -0
- package/template/openxiangda.config.ts +34 -0
- package/template/package.json +28 -0
- package/template/packages/contracts/package.json +23 -0
- package/template/packages/contracts/src/generated.ts +135 -0
- package/template/packages/contracts/src/index.ts +1 -0
- package/template/packages/contracts/tsconfig.json +9 -0
- package/template/pnpm-workspace.yaml +7 -0
- package/template/scripts/verify-template-budget.mjs +49 -0
- package/template/tsconfig.base.json +13 -0
- package/dist/commands/app/create.d.ts +0 -15
- package/dist/commands/app/create.d.ts.map +0 -1
- package/dist/commands/app/create.js +0 -42
- package/dist/commands/app/create.js.map +0 -1
- package/dist/commands/app/info.d.ts +0 -9
- package/dist/commands/app/info.d.ts.map +0 -1
- package/dist/commands/app/info.js +0 -10
- package/dist/commands/app/info.js.map +0 -1
- package/dist/commands/app/link.d.ts +0 -10
- package/dist/commands/app/link.d.ts.map +0 -1
- package/dist/commands/app/link.js +0 -16
- package/dist/commands/app/link.js.map +0 -1
- package/dist/commands/app/provision.d.ts +0 -9
- package/dist/commands/app/provision.d.ts.map +0 -1
- package/dist/commands/app/provision.js +0 -10
- package/dist/commands/app/provision.js.map +0 -1
- package/dist/commands/auth/login.d.ts +0 -10
- package/dist/commands/auth/login.d.ts.map +0 -1
- package/dist/commands/auth/login.js +0 -34
- package/dist/commands/auth/login.js.map +0 -1
- package/dist/commands/auth/logout.d.ts +0 -6
- package/dist/commands/auth/logout.d.ts.map +0 -1
- package/dist/commands/auth/logout.js +0 -10
- package/dist/commands/auth/logout.js.map +0 -1
- package/dist/commands/auth/status.d.ts +0 -6
- package/dist/commands/auth/status.d.ts.map +0 -1
- package/dist/commands/auth/status.js +0 -19
- package/dist/commands/auth/status.js.map +0 -1
- package/dist/commands/build.d.ts +0 -11
- package/dist/commands/build.d.ts.map +0 -1
- package/dist/commands/build.js +0 -23
- package/dist/commands/build.js.map +0 -1
- package/dist/commands/doctor.d.ts +0 -9
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js +0 -7
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/event/delivery/list.d.ts +0 -10
- package/dist/commands/event/delivery/list.d.ts.map +0 -1
- package/dist/commands/event/delivery/list.js +0 -14
- package/dist/commands/event/delivery/list.js.map +0 -1
- package/dist/commands/event/delivery/replay.d.ts +0 -13
- package/dist/commands/event/delivery/replay.d.ts.map +0 -1
- package/dist/commands/event/delivery/replay.js +0 -16
- package/dist/commands/event/delivery/replay.js.map +0 -1
- package/dist/commands/event/subscription/list.d.ts +0 -9
- package/dist/commands/event/subscription/list.d.ts.map +0 -1
- package/dist/commands/event/subscription/list.js +0 -10
- package/dist/commands/event/subscription/list.js.map +0 -1
- package/dist/commands/event/subscription/rotate-secret.d.ts +0 -15
- package/dist/commands/event/subscription/rotate-secret.d.ts.map +0 -1
- package/dist/commands/event/subscription/rotate-secret.js +0 -33
- package/dist/commands/event/subscription/rotate-secret.js.map +0 -1
- package/dist/commands/event/subscription/status.d.ts +0 -14
- package/dist/commands/event/subscription/status.d.ts.map +0 -1
- package/dist/commands/event/subscription/status.js +0 -19
- package/dist/commands/event/subscription/status.js.map +0 -1
- package/dist/commands/event/timer/list.d.ts +0 -9
- package/dist/commands/event/timer/list.d.ts.map +0 -1
- package/dist/commands/event/timer/list.js +0 -10
- package/dist/commands/event/timer/list.js.map +0 -1
- package/dist/commands/event/timer/status.d.ts +0 -14
- package/dist/commands/event/timer/status.d.ts.map +0 -1
- package/dist/commands/event/timer/status.js +0 -19
- package/dist/commands/event/timer/status.js.map +0 -1
- package/dist/commands/generate.d.ts +0 -10
- package/dist/commands/generate.d.ts.map +0 -1
- package/dist/commands/generate.js +0 -8
- package/dist/commands/generate.js.map +0 -1
- package/dist/commands/oauth/audit/list.d.ts +0 -12
- package/dist/commands/oauth/audit/list.d.ts.map +0 -1
- package/dist/commands/oauth/audit/list.js +0 -20
- package/dist/commands/oauth/audit/list.js.map +0 -1
- package/dist/commands/oauth/client/create.d.ts +0 -13
- package/dist/commands/oauth/client/create.d.ts.map +0 -1
- package/dist/commands/oauth/client/create.js +0 -34
- package/dist/commands/oauth/client/create.js.map +0 -1
- package/dist/commands/oauth/client/list.d.ts +0 -9
- package/dist/commands/oauth/client/list.d.ts.map +0 -1
- package/dist/commands/oauth/client/list.js +0 -10
- package/dist/commands/oauth/client/list.js.map +0 -1
- package/dist/commands/oauth/client/revoke.d.ts +0 -12
- package/dist/commands/oauth/client/revoke.d.ts.map +0 -1
- package/dist/commands/oauth/client/revoke.js +0 -12
- package/dist/commands/oauth/client/revoke.js.map +0 -1
- package/dist/commands/oauth/client/rotate.d.ts +0 -13
- package/dist/commands/oauth/client/rotate.d.ts.map +0 -1
- package/dist/commands/oauth/client/rotate.js +0 -20
- package/dist/commands/oauth/client/rotate.js.map +0 -1
- package/dist/commands/oauth/client/update.d.ts +0 -15
- package/dist/commands/oauth/client/update.d.ts.map +0 -1
- package/dist/commands/oauth/client/update.js +0 -23
- package/dist/commands/oauth/client/update.js.map +0 -1
- package/dist/commands/oauth/runtime/rotate.d.ts +0 -12
- package/dist/commands/oauth/runtime/rotate.d.ts.map +0 -1
- package/dist/commands/oauth/runtime/rotate.js +0 -31
- package/dist/commands/oauth/runtime/rotate.js.map +0 -1
- package/dist/commands/oauth/runtime/status.d.ts +0 -10
- package/dist/commands/oauth/runtime/status.d.ts.map +0 -1
- package/dist/commands/oauth/runtime/status.js +0 -17
- package/dist/commands/oauth/runtime/status.js.map +0 -1
- package/dist/commands/promote.d.ts +0 -13
- package/dist/commands/promote.d.ts.map +0 -1
- package/dist/commands/promote.js +0 -9
- package/dist/commands/promote.js.map +0 -1
- package/dist/commands/secret/audit/list.d.ts +0 -14
- package/dist/commands/secret/audit/list.d.ts.map +0 -1
- package/dist/commands/secret/audit/list.js +0 -16
- package/dist/commands/secret/audit/list.js.map +0 -1
- package/dist/commands/secret/create.d.ts +0 -18
- package/dist/commands/secret/create.d.ts.map +0 -1
- package/dist/commands/secret/create.js +0 -33
- package/dist/commands/secret/create.js.map +0 -1
- package/dist/commands/secret/delete.d.ts +0 -15
- package/dist/commands/secret/delete.d.ts.map +0 -1
- package/dist/commands/secret/delete.js +0 -20
- package/dist/commands/secret/delete.js.map +0 -1
- package/dist/commands/secret/list.d.ts +0 -10
- package/dist/commands/secret/list.d.ts.map +0 -1
- package/dist/commands/secret/list.js +0 -14
- package/dist/commands/secret/list.js.map +0 -1
- package/dist/commands/secret/rotate.d.ts +0 -18
- package/dist/commands/secret/rotate.d.ts.map +0 -1
- package/dist/commands/secret/rotate.js +0 -30
- package/dist/commands/secret/rotate.js.map +0 -1
- package/dist/commands/secret/update.d.ts +0 -17
- package/dist/commands/secret/update.d.ts.map +0 -1
- package/dist/commands/secret/update.js +0 -37
- package/dist/commands/secret/update.js.map +0 -1
- package/dist/commands/skill/install.d.ts +0 -11
- package/dist/commands/skill/install.d.ts.map +0 -1
- package/dist/commands/skill/install.js +0 -52
- package/dist/commands/skill/install.js.map +0 -1
- package/dist/commands/skill/validate.d.ts +0 -9
- package/dist/commands/skill/validate.d.ts.map +0 -1
- package/dist/commands/skill/validate.js +0 -32
- package/dist/commands/skill/validate.js.map +0 -1
- package/dist/commands/test.d.ts +0 -9
- package/dist/commands/test.d.ts.map +0 -1
- package/dist/commands/test.js +0 -7
- package/dist/commands/test.js.map +0 -1
- package/dist/commands/workflow/provider/list.d.ts +0 -10
- package/dist/commands/workflow/provider/list.d.ts.map +0 -1
- package/dist/commands/workflow/provider/list.js +0 -14
- package/dist/commands/workflow/provider/list.js.map +0 -1
- package/dist/commands/workflow/provider/rotate.d.ts +0 -15
- package/dist/commands/workflow/provider/rotate.d.ts.map +0 -1
- package/dist/commands/workflow/provider/rotate.js +0 -24
- package/dist/commands/workflow/provider/rotate.js.map +0 -1
- package/dist/secret-value.d.ts +0 -5
- package/dist/secret-value.d.ts.map +0 -1
- package/dist/secret-value.js +0 -15
- package/dist/secret-value.js.map +0 -1
|
@@ -0,0 +1,15 @@
|
|
|
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="root"></div>
|
|
13
|
+
<script type="module" src="/e2e/resource-experience-fixture.tsx"></script>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
|
@@ -0,0 +1,43 @@
|
|
|
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`);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { verifyOpenXiangdaWebBuild } from 'openxiangda/testing';
|
|
2
|
+
|
|
3
|
+
const result = verifyOpenXiangdaWebBuild(new URL('../dist', import.meta.url));
|
|
4
|
+
process.stdout.write(
|
|
5
|
+
`Verified Vite build: ${result.totalBytes} bytes, ${result.totalJavaScriptGzipBytes} total gzip bytes, ${result.initialJavaScriptGzipBytes} initial gzip bytes.\n`
|
|
6
|
+
);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom/client';
|
|
3
|
+
import {
|
|
4
|
+
defineApplicationContributions,
|
|
5
|
+
defineWorkflowLaunchContributions,
|
|
6
|
+
OpenXiangdaApplication,
|
|
7
|
+
} from 'openxiangda/react';
|
|
8
|
+
import {
|
|
9
|
+
appCode,
|
|
10
|
+
appName,
|
|
11
|
+
appPerspectives,
|
|
12
|
+
appRoutes,
|
|
13
|
+
adminNavigation,
|
|
14
|
+
adminPages,
|
|
15
|
+
resourceDefinitions,
|
|
16
|
+
workflowDefinitions,
|
|
17
|
+
} from '../../../packages/contracts/src/generated.js';
|
|
18
|
+
import 'openxiangda/react/styles.css';
|
|
19
|
+
|
|
20
|
+
const applicationContributions = defineApplicationContributions(appRoutes, {
|
|
21
|
+
pages: {},
|
|
22
|
+
});
|
|
23
|
+
const workflowContributions = defineWorkflowLaunchContributions(
|
|
24
|
+
workflowDefinitions,
|
|
25
|
+
{},
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
29
|
+
<React.StrictMode>
|
|
30
|
+
<OpenXiangdaApplication
|
|
31
|
+
appCode={appCode}
|
|
32
|
+
appName={appName}
|
|
33
|
+
adminNavigation={adminNavigation}
|
|
34
|
+
adminPages={adminPages}
|
|
35
|
+
contributions={applicationContributions}
|
|
36
|
+
perspectives={appPerspectives}
|
|
37
|
+
resourceDefinitions={resourceDefinitions}
|
|
38
|
+
workflows={workflowContributions}
|
|
39
|
+
/>
|
|
40
|
+
</React.StrictMode>,
|
|
41
|
+
);
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
3
|
+
import test from 'node:test';
|
|
4
|
+
import { readRuntimeMount, resolveApplicationBasename } from 'openxiangda/core';
|
|
5
|
+
import {
|
|
6
|
+
notificationTemplateCodes,
|
|
7
|
+
resourceCodes,
|
|
8
|
+
resourceDefinitions,
|
|
9
|
+
} from '../../../packages/contracts/src/generated.js';
|
|
10
|
+
|
|
11
|
+
test('clean template contains only application declarations and one React entry', () => {
|
|
12
|
+
const config = readFileSync(
|
|
13
|
+
new URL('../../../openxiangda.config.ts', import.meta.url),
|
|
14
|
+
'utf8'
|
|
15
|
+
);
|
|
16
|
+
const source = readFileSync(new URL('../src/main.tsx', import.meta.url), 'utf8');
|
|
17
|
+
const productionSources = readdirSync(new URL('../src', import.meta.url), {
|
|
18
|
+
withFileTypes: true,
|
|
19
|
+
})
|
|
20
|
+
.filter(entry => entry.isFile())
|
|
21
|
+
.map(entry => entry.name)
|
|
22
|
+
.sort();
|
|
23
|
+
assert.deepEqual(productionSources, ['main.tsx']);
|
|
24
|
+
assert.deepEqual(Object.keys(resourceDefinitions).sort(), [...resourceCodes].sort());
|
|
25
|
+
assert.equal(
|
|
26
|
+
notificationTemplateCodes.applicationInformational,
|
|
27
|
+
'application.informational.standard'
|
|
28
|
+
);
|
|
29
|
+
assert.match(config, /data:\s*\{\s*resources:/);
|
|
30
|
+
assert.match(source, /OpenXiangdaApplication/);
|
|
31
|
+
assert.match(source, /defineApplicationContributions\(appRoutes/);
|
|
32
|
+
assert.match(source, /contributions=\{applicationContributions\}/);
|
|
33
|
+
assert.match(source, /from 'openxiangda\/react'/);
|
|
34
|
+
assert.match(source, /openxiangda\/react\/styles\.css/);
|
|
35
|
+
const legacyMarkers = [
|
|
36
|
+
'instruments',
|
|
37
|
+
'colleges',
|
|
38
|
+
'仪器' + '资源管理',
|
|
39
|
+
'学院' + '字典',
|
|
40
|
+
'HGY',
|
|
41
|
+
'Instrument',
|
|
42
|
+
];
|
|
43
|
+
assert.doesNotMatch(`${config}\n${source}`, new RegExp(legacyMarkers.join('|')));
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('application manifests expose one direct OpenXiangda dependency', () => {
|
|
47
|
+
for (const relative of [
|
|
48
|
+
'../../../package.json',
|
|
49
|
+
'../package.json',
|
|
50
|
+
'../../server/package.json',
|
|
51
|
+
]) {
|
|
52
|
+
const manifest = JSON.parse(
|
|
53
|
+
readFileSync(new URL(relative, import.meta.url), 'utf8')
|
|
54
|
+
) as Record<string, Record<string, string>>;
|
|
55
|
+
const dependencies = Object.entries({
|
|
56
|
+
...(manifest.dependencies || {}),
|
|
57
|
+
...(manifest.devDependencies || {}),
|
|
58
|
+
...(manifest.peerDependencies || {}),
|
|
59
|
+
}).filter(([name]) =>
|
|
60
|
+
name === 'openxiangda' || name.startsWith('openxiangda-')
|
|
61
|
+
);
|
|
62
|
+
assert.deepEqual(
|
|
63
|
+
dependencies.map(([name]) => name),
|
|
64
|
+
dependencies.length ? ['openxiangda'] : []
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('runtime metadata stays mount-scoped', () => {
|
|
70
|
+
const mount = readRuntimeMount(
|
|
71
|
+
name =>
|
|
72
|
+
({
|
|
73
|
+
'openxiangda-runtime-base': '/view/example-app/',
|
|
74
|
+
'openxiangda-app-code': 'example-app',
|
|
75
|
+
'openxiangda-environment': 'preproduction',
|
|
76
|
+
})[name]
|
|
77
|
+
);
|
|
78
|
+
assert.equal(resolveApplicationBasename(mount), '/view/example-app');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('resource E2E harness owns the standard export download response', () => {
|
|
82
|
+
const source = readFileSync(
|
|
83
|
+
new URL('../e2e/resources.spec.ts', import.meta.url),
|
|
84
|
+
'utf8'
|
|
85
|
+
);
|
|
86
|
+
assert.match(source, /\/native\\\/data\\\/\(\[\^\/\]\+\)\\\/export\$/);
|
|
87
|
+
assert.match(source, /content-disposition/);
|
|
88
|
+
assert.match(source, /text\/csv/);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('published E2E harnesses do not write evidence into the platform source repository', () => {
|
|
92
|
+
const workflowSource = readFileSync(
|
|
93
|
+
new URL('../e2e/workflow.spec.ts', import.meta.url),
|
|
94
|
+
'utf8'
|
|
95
|
+
);
|
|
96
|
+
assert.doesNotMatch(workflowSource, /docs\/architecture|evidenceDirectory/);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('E2E experience fixtures explicitly own every tested admin route', () => {
|
|
100
|
+
const resourceFixture = readFileSync(
|
|
101
|
+
new URL('../e2e/resource-experience-fixture.tsx', import.meta.url),
|
|
102
|
+
'utf8'
|
|
103
|
+
);
|
|
104
|
+
for (let index = 1; index <= 12; index += 1) {
|
|
105
|
+
const code = `resource-${String(index).padStart(2, '0')}`;
|
|
106
|
+
const pageCode = `resource:${code}:list`;
|
|
107
|
+
assert.match(resourceFixture, new RegExp(`pageCode: '${pageCode}'`));
|
|
108
|
+
assert.match(resourceFixture, new RegExp(`code: '${pageCode}'`));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const workflowFixture = readFileSync(
|
|
112
|
+
new URL('../e2e/workflow-experience-fixture.tsx', import.meta.url),
|
|
113
|
+
'utf8'
|
|
114
|
+
);
|
|
115
|
+
assert.match(workflowFixture, /code: 'workflow:work-center'/);
|
|
116
|
+
assert.match(workflowFixture, /code: 'workflow:task'/);
|
|
117
|
+
assert.match(workflowFixture, /code: 'workflow:instance'/);
|
|
118
|
+
assert.match(workflowFixture, /pageCode: 'workflow:work-center'/);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('browser acceptance serializes the prewarmed Vite HTML entrypoints', () => {
|
|
122
|
+
const viteConfig = readFileSync(new URL('../vite.config.ts', import.meta.url), 'utf8');
|
|
123
|
+
const playwrightConfig = readFileSync(
|
|
124
|
+
new URL('../playwright.config.ts', import.meta.url),
|
|
125
|
+
'utf8'
|
|
126
|
+
);
|
|
127
|
+
const htmlEntries = readdirSync(new URL('..', import.meta.url))
|
|
128
|
+
.filter(name => name.endsWith('.e2e.html'))
|
|
129
|
+
.sort();
|
|
130
|
+
assert.deepEqual(htmlEntries, [
|
|
131
|
+
'data-api-live.e2e.html',
|
|
132
|
+
'field-protocol.e2e.html',
|
|
133
|
+
'resource-experience.e2e.html',
|
|
134
|
+
'workflow-experience.e2e.html',
|
|
135
|
+
]);
|
|
136
|
+
for (const entry of htmlEntries) {
|
|
137
|
+
assert.ok(viteConfig.includes(`'${entry}'`), `missing optimizeDeps entry ${entry}`);
|
|
138
|
+
}
|
|
139
|
+
assert.match(playwrightConfig, /workers:\s*1/);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test('the platform package owns Web build verification policy', () => {
|
|
143
|
+
const verifier = readFileSync(
|
|
144
|
+
new URL('../scripts/verify-build.mjs', import.meta.url),
|
|
145
|
+
'utf8'
|
|
146
|
+
);
|
|
147
|
+
assert.match(verifier, /verifyOpenXiangdaWebBuild/);
|
|
148
|
+
assert.doesNotMatch(verifier, /2_650_000|800_000|600_000/);
|
|
149
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { createServer } from 'node:net';
|
|
4
|
+
import { networkInterfaces } from 'node:os';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
import test from 'node:test';
|
|
7
|
+
|
|
8
|
+
test('Vite is reachable on loopback and not on a LAN interface', async t => {
|
|
9
|
+
const port = await freePort();
|
|
10
|
+
const root = resolve(import.meta.dirname, '..');
|
|
11
|
+
const child = spawn('pnpm', ['exec', 'vite', '--port', String(port), '--strictPort'], {
|
|
12
|
+
cwd: root,
|
|
13
|
+
stdio: 'ignore',
|
|
14
|
+
env: {
|
|
15
|
+
...process.env,
|
|
16
|
+
OPENXIANGDA_WEB_PORT: String(port),
|
|
17
|
+
OPENXIANGDA_DEV_PROXY: 'http://127.0.0.1:7001',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
try {
|
|
21
|
+
await waitFor(`http://127.0.0.1:${port}`);
|
|
22
|
+
const lan = Object.values(networkInterfaces())
|
|
23
|
+
.flat()
|
|
24
|
+
.find(address => address?.family === 'IPv4' && !address.internal)?.address;
|
|
25
|
+
if (!lan) {
|
|
26
|
+
t.diagnostic('No non-loopback IPv4 interface; loopback reachability verified.');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
await assert.rejects(
|
|
30
|
+
fetch(`http://${lan}:${port}`, {
|
|
31
|
+
signal: AbortSignal.timeout(500),
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
} finally {
|
|
35
|
+
child.kill('SIGTERM');
|
|
36
|
+
await new Promise(resolve => child.once('exit', resolve));
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
async function freePort() {
|
|
41
|
+
return await new Promise<number>((resolve, reject) => {
|
|
42
|
+
const server = createServer();
|
|
43
|
+
server.once('error', reject);
|
|
44
|
+
server.listen({ host: '127.0.0.1', port: 0 }, () => {
|
|
45
|
+
const address = server.address();
|
|
46
|
+
const port = typeof address === 'object' && address ? address.port : 0;
|
|
47
|
+
server.close(error => (error ? reject(error) : resolve(port)));
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function waitFor(url: string) {
|
|
53
|
+
const deadline = Date.now() + 10_000;
|
|
54
|
+
while (Date.now() < deadline) {
|
|
55
|
+
try {
|
|
56
|
+
const response = await fetch(url);
|
|
57
|
+
if (response.ok) return;
|
|
58
|
+
} catch {}
|
|
59
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
60
|
+
}
|
|
61
|
+
throw new Error(`VITE_READINESS_TIMEOUT:${url}`);
|
|
62
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"jsx": "react-jsx",
|
|
7
|
+
"noEmit": true,
|
|
8
|
+
"exactOptionalPropertyTypes": false,
|
|
9
|
+
"types": ["vite/client", "node"]
|
|
10
|
+
},
|
|
11
|
+
"include": ["src", "test", "vite.config.ts", "playwright.config.ts"]
|
|
12
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import react from '@vitejs/plugin-react';
|
|
2
|
+
import { defineConfig } from 'vite';
|
|
3
|
+
|
|
4
|
+
const connectedProxy =
|
|
5
|
+
process.env.OPENXIANGDA_DEV_PROXY?.trim() || 'http://127.0.0.1:7001';
|
|
6
|
+
const port = Number(process.env.OPENXIANGDA_WEB_PORT || 5173);
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
plugins: [react()],
|
|
10
|
+
base: './',
|
|
11
|
+
optimizeDeps: {
|
|
12
|
+
entries: [
|
|
13
|
+
'index.html',
|
|
14
|
+
'data-api-live.e2e.html',
|
|
15
|
+
'field-protocol.e2e.html',
|
|
16
|
+
'resource-experience.e2e.html',
|
|
17
|
+
'workflow-experience.e2e.html',
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
server: {
|
|
21
|
+
host: '127.0.0.1',
|
|
22
|
+
port,
|
|
23
|
+
strictPort: true,
|
|
24
|
+
proxy: {
|
|
25
|
+
'/service': { target: connectedProxy, changeOrigin: false },
|
|
26
|
+
'/api': { target: connectedProxy, changeOrigin: false },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
build: {
|
|
30
|
+
sourcemap: false,
|
|
31
|
+
rollupOptions: {
|
|
32
|
+
output: {
|
|
33
|
+
manualChunks: {
|
|
34
|
+
react: ['react', 'react-dom', 'react-router-dom'],
|
|
35
|
+
refine: ['@refinedev/core'],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
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>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
schema: openxiangda.appspec/app/v1
|
|
3
|
+
app: "openxiangda-application"
|
|
4
|
+
title: "OpenXiangda 应用"
|
|
5
|
+
status: active
|
|
6
|
+
---
|
|
7
|
+
# OpenXiangda 应用
|
|
8
|
+
|
|
9
|
+
AppSpec 是可选的业务意图辅助层,不是发布门禁。资源、字段、权限和动作仍以
|
|
10
|
+
`openxiangda.config.ts` 与实时编译合同为准。
|
|
11
|
+
|
|
12
|
+
## 业务目标
|
|
13
|
+
|
|
14
|
+
<!-- 用业务语言说明应用解决的问题和可观察结果。 -->
|
|
15
|
+
|
|
16
|
+
## 角色
|
|
17
|
+
|
|
18
|
+
<!-- 只记录业务角色及其目标;稳定 role code 在能力规格中引用。 -->
|
|
19
|
+
|
|
20
|
+
## 范围
|
|
21
|
+
|
|
22
|
+
### 包含
|
|
23
|
+
|
|
24
|
+
### 不包含
|
|
25
|
+
|
|
26
|
+
## 能力目录
|
|
27
|
+
|
|
28
|
+
<!-- 复杂业务再在 capabilities/ 下增加 CAP-*;小应用可以只维护本文件。 -->
|
|
29
|
+
|
|
30
|
+
## 术语
|
|
31
|
+
|
|
32
|
+
## 跨能力约束
|
|
33
|
+
|
|
34
|
+
## 未确认问题
|
|
35
|
+
|
|
36
|
+
- 无。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defineAdminNavigation, defineOpenXiangdaApp } from 'openxiangda/config';
|
|
2
|
+
|
|
3
|
+
/** Clean application scaffold: declare resources and fields, then generate CRUD. */
|
|
4
|
+
export default defineOpenXiangdaApp({
|
|
5
|
+
schemaVersion: 3,
|
|
6
|
+
app: { code: 'openxiangda-application', name: 'OpenXiangda 应用' },
|
|
7
|
+
frontend: {
|
|
8
|
+
root: 'apps/web',
|
|
9
|
+
routes: [],
|
|
10
|
+
admin: { navigation: defineAdminNavigation([]) },
|
|
11
|
+
},
|
|
12
|
+
backend: {
|
|
13
|
+
root: 'apps/server',
|
|
14
|
+
runtime: 'node',
|
|
15
|
+
framework: 'nestjs',
|
|
16
|
+
enabled: false,
|
|
17
|
+
isolation: 'shared',
|
|
18
|
+
resourceProfile: 'light',
|
|
19
|
+
secrets: [],
|
|
20
|
+
operations: [],
|
|
21
|
+
},
|
|
22
|
+
platform: { root: 'platform' },
|
|
23
|
+
authz: {
|
|
24
|
+
capabilities: [],
|
|
25
|
+
roles: [],
|
|
26
|
+
scopeDimensions: [],
|
|
27
|
+
scopeSources: [],
|
|
28
|
+
dataPolicies: [],
|
|
29
|
+
authorizationTransitions: [],
|
|
30
|
+
},
|
|
31
|
+
data: { resources: [] },
|
|
32
|
+
events: { schemas: [], subscriptions: [], timers: [], dateTriggers: [] },
|
|
33
|
+
workflows: { definitions: [], bindings: [], activations: [], providers: [], editableParameters: [] },
|
|
34
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "openxiangda-application",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"packageManager": "pnpm@10.15.1",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=22.12"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"openxiangda": "openxiangda",
|
|
11
|
+
"prepare": "pnpm workspace:build",
|
|
12
|
+
"workspace:build": "pnpm --filter @app/contracts build",
|
|
13
|
+
"predev": "pnpm workspace:build",
|
|
14
|
+
"dev": "pnpm --parallel --filter './apps/*' dev",
|
|
15
|
+
"dev:web": "pnpm --filter @app/web dev",
|
|
16
|
+
"dev:server": "pnpm --filter @app/server dev",
|
|
17
|
+
"precheck": "pnpm workspace:build",
|
|
18
|
+
"check": "pnpm --recursive check && node scripts/verify-template-budget.mjs",
|
|
19
|
+
"pretest": "pnpm workspace:build",
|
|
20
|
+
"test": "pnpm --recursive test",
|
|
21
|
+
"test:e2e": "pnpm --filter @app/web test:e2e",
|
|
22
|
+
"build": "pnpm --recursive build"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"openxiangda": "2.0.0-alpha.34",
|
|
26
|
+
"typescript": "5.9.3"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@app/contracts",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"openxiangda-source": "./src/index.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
17
|
+
"test": "node -e \"process.stdout.write('generated contracts checked by TypeScript\\n')\"",
|
|
18
|
+
"build": "tsc -p tsconfig.json"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"typescript": "5.9.3"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// Generated by OpenXiangda 2.0 Native compiler. Do not edit by hand.
|
|
2
|
+
export const compilerContractVersion = "native-2" as const;
|
|
3
|
+
export const appCode = "openxiangda-application" as const;
|
|
4
|
+
export const appName = "OpenXiangda 应用" as const;
|
|
5
|
+
export const appPerspectives = [] as const;
|
|
6
|
+
export const resourceCodes = [] as const;
|
|
7
|
+
export const resourceSurfaces = {} as const;
|
|
8
|
+
export const resourceDefinitions = {} as const;
|
|
9
|
+
export const capabilities = [
|
|
10
|
+
"app:openxiangda-application:directory:read",
|
|
11
|
+
"app:role:assign",
|
|
12
|
+
"app:role:define",
|
|
13
|
+
"app:role:grant-capability",
|
|
14
|
+
"app:role:read",
|
|
15
|
+
"app:scope-grant:manage",
|
|
16
|
+
"app:super-admin:manage"
|
|
17
|
+
] as const;
|
|
18
|
+
export const appOperations = {} as const;
|
|
19
|
+
export const appRoutes = {} as const;
|
|
20
|
+
export const adminPages = [] as const;
|
|
21
|
+
export const adminNavigation = [] as const;
|
|
22
|
+
export const eventTypes = [] as const;
|
|
23
|
+
export const eventSubscriptionCodes = [] as const;
|
|
24
|
+
export const eventHandlerManifest = {
|
|
25
|
+
"schemaVersion": "openxiangda.event-handler-manifest/v2",
|
|
26
|
+
"appCode": "openxiangda-application",
|
|
27
|
+
"handlers": []
|
|
28
|
+
} as const;
|
|
29
|
+
export const eventHandlers = {} as const;
|
|
30
|
+
export const eventSchemas = [] as const;
|
|
31
|
+
export const workflowCodes = [] as const;
|
|
32
|
+
export const workflowDefinitions = [] as const;
|
|
33
|
+
export const notificationTemplateCodes = {
|
|
34
|
+
applicationInformational: "application.informational.standard",
|
|
35
|
+
} as const;
|
|
36
|
+
|
|
37
|
+
export type ResourceCode = (typeof resourceCodes)[number];
|
|
38
|
+
export type Capability = (typeof capabilities)[number];
|
|
39
|
+
export type AppOperation = (typeof appOperations)[keyof typeof appOperations];
|
|
40
|
+
export type AppRoute = (typeof appRoutes)[keyof typeof appRoutes];
|
|
41
|
+
export type AdminPage = (typeof adminPages)[number];
|
|
42
|
+
export type AdminNavigationGroup = (typeof adminNavigation)[number];
|
|
43
|
+
export type AppPerspective = (typeof appPerspectives)[number];
|
|
44
|
+
export type EventType = (typeof eventTypes)[number];
|
|
45
|
+
export type EventSubscriptionCode = (typeof eventSubscriptionCodes)[number];
|
|
46
|
+
export type EventTypesForSubscription<TCode extends EventSubscriptionCode> = never;
|
|
47
|
+
export type WorkflowCode = (typeof workflowCodes)[number];
|
|
48
|
+
export type NotificationTemplateCode = (typeof notificationTemplateCodes)[keyof typeof notificationTemplateCodes];
|
|
49
|
+
|
|
50
|
+
export interface OpenXiangdaCloudEvent<TType extends EventType = EventType, TData extends Record<string, unknown> = Record<string, unknown>> {
|
|
51
|
+
specversion: "1.0";
|
|
52
|
+
id: string;
|
|
53
|
+
source: string;
|
|
54
|
+
type: TType;
|
|
55
|
+
subject?: string;
|
|
56
|
+
time: string;
|
|
57
|
+
datacontenttype: "application/json";
|
|
58
|
+
dataschema?: string;
|
|
59
|
+
data: TData;
|
|
60
|
+
tenantid: string;
|
|
61
|
+
appcode: typeof appCode;
|
|
62
|
+
environment: string;
|
|
63
|
+
traceid?: string;
|
|
64
|
+
schemaversion: string;
|
|
65
|
+
}
|
|
66
|
+
export type EventHandlerInput<TCode extends EventSubscriptionCode> = OpenXiangdaCloudEvent<EventTypesForSubscription<TCode>>;
|
|
67
|
+
|
|
68
|
+
export interface LabeledValue {
|
|
69
|
+
label: string;
|
|
70
|
+
value: string;
|
|
71
|
+
description?: string;
|
|
72
|
+
color?: string;
|
|
73
|
+
}
|
|
74
|
+
export interface ResourceReferenceValue extends LabeledValue {
|
|
75
|
+
resourceCode: string;
|
|
76
|
+
snapshot?: Record<string, unknown>;
|
|
77
|
+
}
|
|
78
|
+
export interface DepartmentReferenceValue extends LabeledValue {
|
|
79
|
+
fullPath?: string;
|
|
80
|
+
path?: LabeledValue[];
|
|
81
|
+
parent?: LabeledValue;
|
|
82
|
+
}
|
|
83
|
+
export interface UserReferenceValue extends LabeledValue {
|
|
84
|
+
avatarUrl?: string;
|
|
85
|
+
employeeNo?: string;
|
|
86
|
+
title?: string;
|
|
87
|
+
mobile?: string;
|
|
88
|
+
email?: string;
|
|
89
|
+
departments?: DepartmentReferenceValue[];
|
|
90
|
+
}
|
|
91
|
+
export interface DateRangeValue { start: string; end: string; }
|
|
92
|
+
export type CascadePathValue = LabeledValue[];
|
|
93
|
+
export interface DataFileRef {
|
|
94
|
+
schemaVersion: 'openxiangda.data-file-ref/v2';
|
|
95
|
+
id: string;
|
|
96
|
+
name: string;
|
|
97
|
+
size: number;
|
|
98
|
+
contentType: string;
|
|
99
|
+
}
|
|
100
|
+
export interface DataImageRef extends DataFileRef {
|
|
101
|
+
width: number;
|
|
102
|
+
height: number;
|
|
103
|
+
thumbnailUrl: string;
|
|
104
|
+
previewUrl: string;
|
|
105
|
+
}
|
|
106
|
+
export interface StableSignatureValue {
|
|
107
|
+
file: Omit<DataFileRef, 'schemaVersion'>;
|
|
108
|
+
signer?: UserReferenceValue;
|
|
109
|
+
signedAt: string;
|
|
110
|
+
points?: Array<{ x: number; y: number; t: number }>;
|
|
111
|
+
hash: string;
|
|
112
|
+
}
|
|
113
|
+
export interface StableAddressValue {
|
|
114
|
+
country?: LabeledValue;
|
|
115
|
+
province?: LabeledValue;
|
|
116
|
+
city?: LabeledValue;
|
|
117
|
+
district?: LabeledValue;
|
|
118
|
+
street?: LabeledValue;
|
|
119
|
+
detail?: string;
|
|
120
|
+
fullAddress?: string;
|
|
121
|
+
}
|
|
122
|
+
export interface StableLocationSnapshot {
|
|
123
|
+
address?: string;
|
|
124
|
+
name?: string;
|
|
125
|
+
province?: string;
|
|
126
|
+
city?: string;
|
|
127
|
+
district?: string;
|
|
128
|
+
accuracy?: number;
|
|
129
|
+
capturedAt?: string;
|
|
130
|
+
}
|
|
131
|
+
export type StableLocationValue = StableLocationSnapshot & {
|
|
132
|
+
source: 'browser' | 'dingTalk';
|
|
133
|
+
longitude: number;
|
|
134
|
+
latitude: number;
|
|
135
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './generated.js';
|