openxiangda-cli 2.0.0-alpha.107 → 2.0.0-alpha.108
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/commands/spec.d.ts +1 -0
- package/dist/commands/spec.d.ts.map +1 -1
- package/dist/commands/spec.js +10 -0
- package/dist/commands/spec.js.map +1 -1
- package/package.json +5 -5
- package/template/AGENTS.md +3 -1
- package/template/apps/server/package.json +1 -1
- package/template/apps/web/e2e/resource-experience-fixture.tsx +42 -1
- package/template/apps/web/e2e/resources.spec.ts +30 -1
- package/template/apps/web/package.json +1 -1
- package/template/apps/web/src/main.tsx +10 -1
- package/template/apps/web/test/contracts.test.ts +2 -0
- package/template/package.json +1 -1
package/dist/commands/spec.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export default class Spec extends OpenXiangdaCommand {
|
|
|
9
9
|
title: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
risk: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
11
|
summary: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
"current-spec": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
13
|
capabilities: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
14
|
requirements: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
15
|
resources: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAkB,MAAM,YAAY,CAAC;AAWhE,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,kBAAkB;IAClD,MAAM,CAAC,OAAO,SAAiC;IAC/C,MAAM,CAAC,IAAI;;;MAMT;IACF,MAAM,CAAC,KAAK
|
|
1
|
+
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAkB,MAAM,YAAY,CAAC;AAWhE,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,kBAAkB;IAClD,MAAM,CAAC,OAAO,SAAiC;IAC/C,MAAM,CAAC,IAAI;;;MAMT;IACF,MAAM,CAAC,KAAK;;;;;;;;;;MAiCV;IAEI,GAAG;;;;;;;;;;;;;;CA4DV"}
|
package/dist/commands/spec.js
CHANGED
|
@@ -29,6 +29,11 @@ export default class Spec extends OpenXiangdaCommand {
|
|
|
29
29
|
summary: "问题摘要或关闭摘要",
|
|
30
30
|
helpValue: "<text>",
|
|
31
31
|
}),
|
|
32
|
+
"current-spec": Flags.string({
|
|
33
|
+
summary: "关闭时由用户确认当前规格已合并或不适用",
|
|
34
|
+
options: ["merged", "not-applicable"],
|
|
35
|
+
helpValue: "<merged|not-applicable>",
|
|
36
|
+
}),
|
|
32
37
|
capabilities: Flags.string({
|
|
33
38
|
summary: "逗号分隔的 CAP-* 引用",
|
|
34
39
|
helpValue: "<codes>",
|
|
@@ -85,6 +90,11 @@ export default class Spec extends OpenXiangdaCommand {
|
|
|
85
90
|
...(flags.cwd ? { root: flags.cwd } : {}),
|
|
86
91
|
id,
|
|
87
92
|
...(flags.summary ? { summary: flags.summary } : {}),
|
|
93
|
+
...(flags["current-spec"]
|
|
94
|
+
? {
|
|
95
|
+
currentSpec: flags["current-spec"],
|
|
96
|
+
}
|
|
97
|
+
: {}),
|
|
88
98
|
}));
|
|
89
99
|
}
|
|
90
100
|
throw new Error(`APPSPEC_ACTION_UNSUPPORTED: ${action}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda-cli",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.108",
|
|
4
4
|
"description": "Thin application-level CLI for OpenXiangda 2.0.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@oclif/core": "4.13.3",
|
|
24
|
-
"openxiangda-contracts": "2.0.0-alpha.
|
|
25
|
-
"openxiangda-devkit-core": "2.0.0-alpha.
|
|
26
|
-
"openxiangda-mcp": "2.0.0-alpha.
|
|
27
|
-
"openxiangda-skill-kit": "2.0.0-alpha.
|
|
24
|
+
"openxiangda-contracts": "2.0.0-alpha.50",
|
|
25
|
+
"openxiangda-devkit-core": "2.0.0-alpha.67",
|
|
26
|
+
"openxiangda-mcp": "2.0.0-alpha.67",
|
|
27
|
+
"openxiangda-skill-kit": "2.0.0-alpha.85"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"tsx": "4.23.12",
|
package/template/AGENTS.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# OpenXiangda 2.0 Application Agent Contract
|
|
2
2
|
|
|
3
3
|
- Use only the workspace-pinned CLI: `pnpm openxiangda <command>`. Never invoke a bare global `openxiangda` inside a 2.0 task.
|
|
4
|
-
- `appspec/` is the optional OpenXiangda 2.0 business-intent layer. Before changing observable behavior, read `pnpm openxiangda spec context --json
|
|
4
|
+
- `appspec/` is the optional OpenXiangda 2.0 business-intent layer. Before changing observable behavior, read the bounded index with `pnpm openxiangda spec context --json`, then select only the relevant stable ID; use no ChangeSpec for L0 work, one short ChangeSpec for L1, and add permission/rollback/concurrency detail only for L2/L3. Before close, the user—not AI—confirms `currentSpec=merged` or `not-applicable`. AppSpec is advisory and never a release gate. Never read, import or migrate 1.x `openspec/` or SDD.
|
|
5
5
|
- Use Vite, React Router, Refine Core and Ant Design. Do not add Umi, ProComponents or another admin shell.
|
|
6
|
+
- Keep generated admin routes and custom actions inside the platform Shell. Bind generated `appRoutes` to local operation pages with `defineAdminContributions`, and use only its typed `toolbar`, `row` and `detail` resource slots. Do not create another router, menu, layout, identity provider, permission store or copied CRUD page; route/action access uses capability or `allOf`/`anyOf`, while Data/App API authorization remains server-owned.
|
|
6
7
|
- Declare each resource once in `openxiangda.config.ts` with only `code`, `name`, `fields` and optional list/layout/data-policy settings. Each field owns type, label, required state, Surface flags, reference/file metadata and access. Resource codes are lower kebab-case.
|
|
7
8
|
- Never write resource-level `schemaVersion`, `appCode`, `schema`, `surface`, `capabilities`, `fieldPolicies` or `platform/data` modules. The compiler derives the strict DataResource, CRUD capabilities, Surface and AI Schema. The application manifest still starts with its one top-level `schemaVersion: 3`.
|
|
8
9
|
- Ordinary list/get/create/update/delete, filters, export and batch operations use the platform Native Data API. Do not create Function CRUD or NestJS wrappers.
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
- Fields inherit the resource read/create/update capabilities. Use field `access` only to tighten them; arrays are all-of and `false` is explicit deny. There is no `write` fallback.
|
|
14
15
|
- Field `type` is semantic, never a hand-authored database type. The supported catalog is exactly `text.short`, `text.long`, `text.rich`, `number.integer`, `number.decimal`, `boolean`, `date`, `time`, `datetime`, `date-range`, `datetime-range`, `option.single`, `option.multiple`, `cascade.single`, `cascade.multiple`, `user.single`, `user.multiple`, `department.single`, `department.multiple`, `resource-ref.single`, `resource-ref.multiple`, `file`, `image`, `signature`, `address`, `location`, `json`, `serial-number`, `uuid` and `subtable`. The compiler alone derives PostgreSQL columns, constraints and indexes.
|
|
15
16
|
- Declare every custom operation capability in `authz.capabilities` with `kind: 'backend'`, then reference that same code from the operation and its allowed roles. Generated resource CRUD capabilities do not go in this catalog.
|
|
17
|
+
- Build App Operation request/response schemas with `resourceRecordSchema`, `schemaRef`, `composeJsonSchema` and `composeAppOperationSchemas` from `openxiangda/config`. They project the same Resource declaration and canonical field value protocols; never import a physical toolchain package or repeat user, department, resource-reference or managed-file schemas by hand.
|
|
16
18
|
- Visitor duplicate protection uses `createVisitorReservation({ duplicateMatch: { fieldCode: submittedValue }, ... })`. `duplicateMatch` is a non-empty value map, never a field-name array, and no mutable pre-read is allowed.
|
|
17
19
|
- Desktop and mobile pages share values, validation and authorization, but use separate renderers. Options, members and departments store display snapshots; resource references store direct JSON display values; attachments, images and signatures use platform-managed file references.
|
|
18
20
|
- `option.*`, `user.*`, `department.*` and `resource-ref.*` values never collapse to scalar IDs. Single values store one labeled object and multiple values store object arrays. `resource-ref.*` JSON is not a foreign key, trusted target snapshot or automatically refreshed copy; current target state is read by `resourceCode` plus `value`. A resource source `labelField` must be `text.short` or `text.long`; `serial-number` is allowed in source search, description and snapshot fields, but not as the label. `location` accepts only exact WGS84 coordinates captured by DingTalk or browser geolocation; it has no manual input or `manual` source. Roles that consume directory-backed fields explicitly include `app:<app-code>:directory:read`.
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import ReactDOM from 'react-dom/client';
|
|
3
|
-
import {
|
|
3
|
+
import { Button, Typography } from 'antd';
|
|
4
|
+
import {
|
|
5
|
+
defineAdminContributions,
|
|
6
|
+
OpenXiangdaApplication,
|
|
7
|
+
} from 'openxiangda/react';
|
|
4
8
|
import type { DataFieldSurface, DataResourceSurface } from 'openxiangda/core';
|
|
5
9
|
import 'openxiangda/react/styles.css';
|
|
6
10
|
|
|
@@ -130,6 +134,42 @@ const resourceDefinitions = Object.fromEntries(
|
|
|
130
134
|
})
|
|
131
135
|
);
|
|
132
136
|
|
|
137
|
+
function ContentOperationsPage() {
|
|
138
|
+
return <Typography.Title level={2}>内容业务操作</Typography.Title>;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const adminContributions = defineAdminContributions(
|
|
142
|
+
{
|
|
143
|
+
contentOperations: {
|
|
144
|
+
code: 'content-operations',
|
|
145
|
+
path: '/admin/operations/content',
|
|
146
|
+
label: '内容业务操作',
|
|
147
|
+
surface: 'admin',
|
|
148
|
+
navigation: 'menu',
|
|
149
|
+
capability: 'app:openxiangda-application:operations:read',
|
|
150
|
+
tabPersistence: 'session',
|
|
151
|
+
keepAlive: 'none',
|
|
152
|
+
},
|
|
153
|
+
} as const,
|
|
154
|
+
{
|
|
155
|
+
pages: { contentOperations: ContentOperationsPage },
|
|
156
|
+
resources: {
|
|
157
|
+
'resource-01': {
|
|
158
|
+
toolbar: [
|
|
159
|
+
{
|
|
160
|
+
code: 'publish-selected',
|
|
161
|
+
label: '发布选中栏目',
|
|
162
|
+
capability: 'app:openxiangda-application:operations:read',
|
|
163
|
+
render: ({ selectedRecords }) => (
|
|
164
|
+
<Button>发布选中栏目({selectedRecords.length})</Button>
|
|
165
|
+
),
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
|
|
133
173
|
if (location.pathname.endsWith('/resource-experience.e2e.html')) {
|
|
134
174
|
history.replaceState({}, '', '/resource-01');
|
|
135
175
|
}
|
|
@@ -139,6 +179,7 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
|
139
179
|
<OpenXiangdaApplication
|
|
140
180
|
appCode="openxiangda-application"
|
|
141
181
|
appName="资源体验验收"
|
|
182
|
+
contributions={adminContributions}
|
|
142
183
|
resourceDefinitions={resourceDefinitions}
|
|
143
184
|
/>
|
|
144
185
|
</React.StrictMode>
|
|
@@ -341,12 +341,41 @@ test('preserves the left menu scroll position when switching resource pages', as
|
|
|
341
341
|
await expect.poll(() => scroller.evaluate(node => node.scrollTop)).toBe(240);
|
|
342
342
|
});
|
|
343
343
|
|
|
344
|
+
test('mounts generated operation routes and typed actions in the unified Shell', async ({ page }) => {
|
|
345
|
+
await mockPlatform(page, true, runtimeBase, true);
|
|
346
|
+
await page.goto('/resource-experience.e2e.html');
|
|
347
|
+
await expect(
|
|
348
|
+
page.getByRole('button', { name: '发布选中栏目(0)' })
|
|
349
|
+
).toBeVisible();
|
|
350
|
+
await page.locator('.oxa-sider').getByText('内容业务操作', { exact: true }).click();
|
|
351
|
+
await expect(page).toHaveURL('/admin/operations/content');
|
|
352
|
+
await expect(
|
|
353
|
+
page.getByRole('heading', { name: '内容业务操作' })
|
|
354
|
+
).toBeVisible();
|
|
355
|
+
await expect(page.locator('.oxa-sider')).toBeVisible();
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
test('fails closed on a direct operation route without its capability', async ({ page }) => {
|
|
359
|
+
await mockPlatform(page, false, runtimeBase, false);
|
|
360
|
+
await page.goto('/resource-experience.e2e.html');
|
|
361
|
+
await page.evaluate(() => {
|
|
362
|
+
history.pushState({}, '', '/admin/operations/content');
|
|
363
|
+
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
364
|
+
});
|
|
365
|
+
await expect(page.getByText('当前平台用户无此页面权限')).toBeVisible();
|
|
366
|
+
await expect(
|
|
367
|
+
page.locator('.oxa-sider').getByText('内容业务操作', { exact: true })
|
|
368
|
+
).toHaveCount(0);
|
|
369
|
+
});
|
|
370
|
+
|
|
344
371
|
test('keeps platform implementation guidance out of generated forms', async ({ page }) => {
|
|
345
372
|
await mockPlatform(page, true, runtimeBase, true);
|
|
346
373
|
await page.goto('/resource-experience.e2e.html');
|
|
347
374
|
await page.getByRole('button', { name: '新增内容栏目' }).click();
|
|
348
375
|
await expect(page).toHaveURL('/resource-01/new');
|
|
349
|
-
const
|
|
376
|
+
const formLabels = page.locator('.ant-form-item-label label');
|
|
377
|
+
await expect(formLabels.first()).toBeVisible();
|
|
378
|
+
const labels = await formLabels.allTextContents();
|
|
350
379
|
expect(labels.slice(0, 2)).toEqual(['栏目编码', '栏目名称']);
|
|
351
380
|
await expect(
|
|
352
381
|
page.getByText('仅显示当前角色可编辑的字段;保存时将校验数据版本与权限范围。', {
|
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import ReactDOM from 'react-dom/client';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
defineAdminContributions,
|
|
5
|
+
OpenXiangdaApplication,
|
|
6
|
+
} from 'openxiangda/react';
|
|
4
7
|
import {
|
|
5
8
|
appCode,
|
|
6
9
|
appName,
|
|
7
10
|
appPerspectives,
|
|
11
|
+
appRoutes,
|
|
8
12
|
resourceDefinitions,
|
|
9
13
|
workflowCodes,
|
|
10
14
|
} from '../../../packages/contracts/src/generated.js';
|
|
11
15
|
import 'openxiangda/react/styles.css';
|
|
12
16
|
|
|
17
|
+
const adminContributions = defineAdminContributions(appRoutes, {
|
|
18
|
+
pages: {},
|
|
19
|
+
});
|
|
20
|
+
|
|
13
21
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
14
22
|
<React.StrictMode>
|
|
15
23
|
<OpenXiangdaApplication
|
|
16
24
|
appCode={appCode}
|
|
17
25
|
appName={appName}
|
|
26
|
+
contributions={adminContributions}
|
|
18
27
|
perspectives={appPerspectives}
|
|
19
28
|
resourceDefinitions={resourceDefinitions}
|
|
20
29
|
workflows={workflowCodes}
|
|
@@ -23,6 +23,8 @@ test('clean template contains only application declarations and one React entry'
|
|
|
23
23
|
assert.deepEqual(Object.keys(resourceDefinitions).sort(), [...resourceCodes].sort());
|
|
24
24
|
assert.match(config, /data:\s*\{\s*resources:/);
|
|
25
25
|
assert.match(source, /OpenXiangdaApplication/);
|
|
26
|
+
assert.match(source, /defineAdminContributions\(appRoutes/);
|
|
27
|
+
assert.match(source, /contributions=\{adminContributions\}/);
|
|
26
28
|
assert.match(source, /from 'openxiangda\/react'/);
|
|
27
29
|
assert.match(source, /openxiangda\/react\/styles\.css/);
|
|
28
30
|
const legacyMarkers = [
|