openxiangda 1.0.134 → 1.0.135

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/README.md +6 -0
  2. package/lib/cli.js +947 -16
  3. package/lib/sdd.js +777 -0
  4. package/lib/workspace-init.js +3 -0
  5. package/openxiangda-skills/SKILL.md +4 -0
  6. package/openxiangda-skills/references/pages/page-sdk.md +3 -0
  7. package/openxiangda-skills/references/pages/publish-flow.md +16 -0
  8. package/openxiangda-skills/references/platform-data-model.md +19 -4
  9. package/openxiangda-skills/skills/openxiangda-core/SKILL.md +2 -0
  10. package/package.json +2 -1
  11. package/packages/sdk/dist/{ProcessPreview-Dfc4-wIq.d.mts → ProcessPreview-Ci8_UsbN.d.mts} +4 -0
  12. package/packages/sdk/dist/{ProcessPreview-Dfc4-wIq.d.ts → ProcessPreview-Ci8_UsbN.d.ts} +4 -0
  13. package/packages/sdk/dist/build/index.cjs.map +1 -1
  14. package/packages/sdk/dist/build/index.d.mts +7 -0
  15. package/packages/sdk/dist/build/index.d.ts +7 -0
  16. package/packages/sdk/dist/build/index.mjs.map +1 -1
  17. package/packages/sdk/dist/components/index.cjs +32 -4
  18. package/packages/sdk/dist/components/index.cjs.map +1 -1
  19. package/packages/sdk/dist/components/index.d.mts +8 -2
  20. package/packages/sdk/dist/components/index.d.ts +8 -2
  21. package/packages/sdk/dist/components/index.mjs +32 -4
  22. package/packages/sdk/dist/components/index.mjs.map +1 -1
  23. package/packages/sdk/dist/runtime/index.cjs +181 -28
  24. package/packages/sdk/dist/runtime/index.cjs.map +1 -1
  25. package/packages/sdk/dist/runtime/index.d.mts +2 -2
  26. package/packages/sdk/dist/runtime/index.d.ts +2 -2
  27. package/packages/sdk/dist/runtime/index.mjs +181 -28
  28. package/packages/sdk/dist/runtime/index.mjs.map +1 -1
  29. package/packages/sdk/dist/runtime/react.cjs +152 -25
  30. package/packages/sdk/dist/runtime/react.cjs.map +1 -1
  31. package/packages/sdk/dist/runtime/react.d.mts +57 -4
  32. package/packages/sdk/dist/runtime/react.d.ts +57 -4
  33. package/packages/sdk/dist/runtime/react.mjs +152 -25
  34. package/packages/sdk/dist/runtime/react.mjs.map +1 -1
  35. package/templates/openxiangda-react-spa/.cursor/rules/openxiangda.mdc +1 -0
  36. package/templates/openxiangda-react-spa/.qoder/rules/openxiangda.md +1 -0
  37. package/templates/openxiangda-react-spa/AGENTS.md +3 -0
  38. package/templates/openxiangda-react-spa/app-workspace.config.ts +14 -0
  39. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda.mdc +1 -0
  40. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda.md +1 -0
  41. package/templates/sy-lowcode-app-workspace/AGENTS.md +4 -0
  42. package/templates/sy-lowcode-app-workspace/app-workspace.config.ts +14 -0
  43. package/templates/sy-lowcode-app-workspace/src/types/app-workspace.types.ts +12 -0
@@ -2,6 +2,7 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const { spawnSync } = require('child_process');
4
4
  const { getProfile, loadConfig, saveProjectState } = require('./config');
5
+ const { initSddWorkspace } = require('./sdd');
5
6
 
6
7
  const ROOT_DIR = path.join(__dirname, '..');
7
8
  const LEGACY_TEMPLATE_DIR = path.join(ROOT_DIR, 'templates', 'sy-lowcode-app-workspace');
@@ -37,6 +38,7 @@ function initWorkspace(options = {}) {
37
38
  copyTemplate(templateDir, targetDir, {
38
39
  __WORKSPACE_PACKAGE_NAME__: packageName,
39
40
  });
41
+ const sdd = initSddWorkspace({ cwd: targetDir });
40
42
 
41
43
  let bound = null;
42
44
  if (profileName && appType) {
@@ -88,6 +90,7 @@ function initWorkspace(options = {}) {
88
90
  templateDir,
89
91
  installedDependencies: install,
90
92
  bound,
93
+ sdd,
91
94
  nextSteps: buildNextSteps(targetDir, install, bound),
92
95
  };
93
96
  }
@@ -40,6 +40,9 @@ OpenXiangda supports two workspace modes. Classic `sy-lowcode-app-workspace` pub
40
40
  ### Hard rules — always
41
41
 
42
42
  - ✅ Publish classic workspaces through `openxiangda workspace publish --profile <name>`; publish React SPA forms first with `openxiangda workspace publish --form <formCode>`, then resources/runtime through `openxiangda resource validate` → `openxiangda resource publish --dry-run` → `openxiangda resource publish` → `openxiangda runtime deploy`.
43
+ - ✅ High-risk changes must be attached to SDD records before implementation/publish. Run `openxiangda sdd context --json`; for forms/pages/resources/functions/automations/workflows/JS_CODE/runtime/config changes create or continue `openxiangda sdd propose <change>`, wait for user confirmation, run `openxiangda sdd approve <change>`, then verify with `openxiangda sdd verify <change> --changed`.
44
+ - ✅ Before publishing AI-authored changes, run `openxiangda workspace plan --changed --json` and `openxiangda workspace check --changed`. Fix reported fake IDs, fallback data, direct `/openxiangda-api` page calls, missing schema, or resource/runtime omissions before publish.
45
+ - ✅ When unsure about runtime response shape, run `openxiangda contract explain <contract-name> --json`. `sdk.form.create` returns identifiers and generated serial number values only; fetch detail explicitly for full row data, formula results, or other server-generated fields.
43
46
  - ✅ Architecture-class requests are plan-gated by default. For 新应用、复杂页面、登录注册、公开访问、权限数据范围、流程自动化、连接器/通知、外部集成, first run `openxiangda doctor --json` when a workspace exists and `openxiangda design gates --topic <code> --json`; then ask the user to confirm the design. Before confirmation, only read files, inspect/snapshot, dry-run, ask questions, and write/output design docs. Do not edit source files, write platform resources, send notifications, publish, or deploy.
44
47
  - ✅ `runtime deploy` defaults to staged multipart `dist/` uploads plus a final manifest. Use `--upload-mode legacy-json` only for old platform servers.
45
48
  - ✅ User token lives in `~/.openxiangda/profiles.json`; project state in `.openxiangda/state.json` (IDs only).
@@ -65,6 +68,7 @@ OpenXiangda supports two workspace modes. Classic `sy-lowcode-app-workspace` pub
65
68
  - ❌ Using `openxiangda form create` / `form publish` / `page publish` as the normal page generation path. They are low-level repair commands.
66
69
  - ❌ Implementing an architecture-class request before the user confirms the design. This includes creating files, mutating platform resources, publishing runtime, sending notifications, or calling live write/delete endpoints.
67
70
  - ❌ Running a full publish after editing one file. Default to `--changed --dry-run` → `--changed`, or targeted `--page` / `--form`.
71
+ - ❌ Generating fake form instance IDs, mock rows, fallback schemas, or fallback display data to make a broken API path look successful.
68
72
  - ❌ Storing tokens, AK, SK, or third-party API secrets in project files. Shared env (`APP_OSS_*`, feedback robot) goes to `~/.openxiangda/.env`.
69
73
  - ❌ Raw native HTML form controls in AI-authored workspace code (`<input>`, `<select>`, `<textarea>`, file inputs, hand-written pickers, hand-written upload controls). They are allowed only inside OpenXiangda SDK/platform component internals.
70
74
  - ❌ Using `?publicAccess=guest` or form `publicAccess` settings for new React SPA apps. Those are legacy `sy-lowcode-view` compatibility only.
@@ -18,6 +18,9 @@ Guidelines:
18
18
  - Use `sdk.notification.sendByType` and `batchSendByType` for reusable business messages. Custom notification types must be declared in `src/resources/notifications/` and published with `openxiangda resource publish`.
19
19
  - Use `sdk.organization.departments.*` and `sdk.organization.accounts.*` only for admin-style app pages that intentionally manage platform departments/accounts. The current user needs `app:organization:manage` on the app. Do not call legacy `/user` or `/department` write endpoints from pages.
20
20
  - Use `sdk.workCenter.listItems({ boxType })` and `sdk.workCenter.getStats()` for current-user work center lists and counts. `boxType` is one of `todo`, `done`, `cc`, or `initiated`. This is the end-user task/handled/cc/initiated surface; do not build todo pages by reading workflow operation logs, automation logs, or raw process-task tables.
21
+ - `sdk.form.create` returns identifiers and generated serial number values only. Treat `formInstId` / `formInstanceId` as the required success contract; `serialNumber` / `serialNumbers` are present only when the form has `SerialNumberField`. Do not expect the save response to contain the full row, formula results, or other server-generated field values. Call `sdk.form.getDetail` explicitly after create when those values are needed.
22
+ - Missing `formInstId` / `formInstanceId` is a real error in strict mode. Do not create fake IDs, mock rows, or fallback display data to hide it.
23
+ - `lookupAfterCreate` is legacy compatibility only. New pages should save, read the returned instance ID, then explicitly query detail if needed.
21
24
  - Use `createAuthClient` from `openxiangda/runtime` or `LoginPage` / `useAuth` from `openxiangda/runtime/react` for application login pages. Auth provider App Functions return identity assertions only; platform auth owns create/bind/reject/token decisions.
22
25
  - Use `PublicAccessGate` from `openxiangda/runtime/react` or `createPublicAccessClient` from `openxiangda/runtime` for React SPA public pages under `/view/:appType/public/*`. Do not append old `?publicAccess=guest` links in new apps.
23
26
  - In React SPA apps, wrap route children with `OpenXiangdaPageProvider` inside `OpenXiangdaProvider` before using `usePageSdk()`, `usePageContext()`, `useDataSource()`, or `useFormViewPermissions()`. `OpenXiangdaProvider` alone is not enough and missing the page provider causes `usePageSdkStore 必须在 PageProvider 内使用`.
@@ -16,6 +16,10 @@ activate. Use `openxiangda workspace publish ...` as the external entry.
16
16
  For day-to-day AI edits, prefer a targeted publish:
17
17
 
18
18
  ```bash
19
+ # First ask OpenXiangda for the release plan and reliability checks.
20
+ openxiangda workspace plan --changed --json
21
+ openxiangda workspace check --changed
22
+
19
23
  # Preview what git-touched forms/pages would publish.
20
24
  openxiangda workspace publish --profile <name> --changed --dry-run
21
25
 
@@ -39,6 +43,18 @@ Targeted publish skips `src/resources` by default. Add `--resources` if resource
39
43
  manifests changed too, or run `openxiangda resource plan|publish` separately.
40
44
  Use `--skip-resources` when you explicitly want forms/pages only.
41
45
 
46
+ React SPA workspaces use a fixed release order:
47
+
48
+ ```bash
49
+ openxiangda workspace plan --changed --json
50
+ openxiangda workspace publish --profile <name> --form <formCode>
51
+ openxiangda resource publish --profile <name>
52
+ openxiangda runtime deploy --profile <name>
53
+ ```
54
+
55
+ If `workspace check --changed` reports risky AI fallback code, missing schema,
56
+ or direct platform API calls, fix those issues before publishing.
57
+
42
58
  The CLI injects:
43
59
 
44
60
  - `OPENXIANGDA_PROFILE`
@@ -19,9 +19,16 @@
19
19
  - **写入端**:前端/Agent 提交什么格式,数据库就存什么格式。
20
20
  - **读取端**:API 查询返回的就是原始 JSON 结构,**不会**额外执行字典翻译、用户名补全或部门名拼接。
21
21
  - **展示端**:选择类字段的中文名(label)已经随数据写入,前端直接取 `item.label` 即可,**禁止**再次基于 `value` 去查字典。
22
- - **操作端**:业务逻辑、过滤、查询条件统一以 `item.value` 为准(稳定、不随显示文案变化)。
23
-
24
- > 这意味着:label 是"快照",value 是"语义键"。一旦字段值落库,label 与 value 一起被冻结,后续即便选项字典改名也不会影响历史数据展示。
22
+ - **操作端**:业务逻辑、过滤、查询条件统一以 `item.value` 为准(稳定、不随显示文案变化)。
23
+
24
+ > 这意味着:label 是"快照",value 是"语义键"。一旦字段值落库,label 与 value 一起被冻结,后续即便选项字典改名也不会影响历史数据展示。
25
+
26
+ ### 1.3 保存接口响应契约
27
+
28
+ - `sdk.form.create` / `saveFormData` / `submitFormData` 只承诺返回实例标识和保存时已生成的流水号字段,例如 `formInstId`、`formInstanceId`、`processInstanceId`、`serialNumber`、`serialNumbers`。
29
+ - 保存接口**不返回完整业务数据**,也不承诺返回公式回填或其他服务端格式化后的字段值。
30
+ - 需要读取完整行数据、公式回填或非流水号服务端字段时,必须在拿到 `formInstId` 后显式调用 `sdk.form.getDetail({ formUuid, formInstId })`。
31
+ - 禁止生成假 ID(例如 `inst_${Date.now()}`),禁止在业务代码中手写 `response.data || response.result` 猜返回结构。
25
32
 
26
33
  ---
27
34
 
@@ -64,7 +71,15 @@ type MultiSelectValue = Option[];
64
71
  ```
65
72
 
66
73
  - **单选/多选的判定**取决于字段配置 `multiple: boolean`,而非字段类型本身。
67
- - **多选字段始终为数组**,即使用户只勾选了一项,也是 `[{label, value}]`,**不要降级为对象**。
74
+ - **多选字段始终为数组**,即使用户只勾选了一项,也是 `[{label, value}]`,**不要降级为对象**。
75
+
76
+ ### 2.2 字段类型变更
77
+
78
+ - 字段创建后对应数据库列类型已经固定。`TextField` 是 `TEXT`,`SelectField` / `RadioField` / 附件 / 子表等复杂字段是 `JSONB`。
79
+ - 把 `TextField` 改成 `SelectField` 不是纯 UI 改动,而是 `TEXT -> JSONB` 的破坏性存储类型变更。
80
+ - 平台会阻断已有列的破坏性类型变更。需要迁移时采用显式 shadow migration:旧列重命名为 `fieldId__legacy_yyyymmdd`,再创建原 `fieldId` 的新类型列。
81
+ - 回填必须提供明确转换规则,例如文本 `"待处理"` 转 `{ "label": "待处理", "value": "pending" }`;平台和 AI 都不能自动猜。
82
+ - 发布前可用 `openxiangda form schema-plan <formCode> --schema-json <file> --json` 检查 `safeAdd`、`compatibleNoop`、`breakingTypeChanges`。
68
83
 
69
84
  ---
70
85
 
@@ -19,8 +19,10 @@ description: Core OpenXiangda CLI workflow — normal-user token login, platform
19
19
  openxiangda env --profile <name>
20
20
  openxiangda auth status --profile <name>
21
21
  openxiangda update check --json # if updateAvailable: openxiangda update install
22
+ openxiangda sdd context --json # high-risk changes need an approved SDD change
22
23
 
23
24
  # 2. preview the change set (NEVER skip --dry-run on routine edits)
25
+ openxiangda sdd verify <change> --changed
24
26
  openxiangda workspace publish --profile <name> --changed --dry-run
25
27
 
26
28
  # 3. publish only what changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.134",
3
+ "version": "1.0.135",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {
@@ -73,6 +73,7 @@
73
73
  "test:help-no-side-effects": "node scripts/help-no-side-effects-smoke.mjs",
74
74
  "test:app-function-fallback": "node scripts/app-function-source-fallback-smoke.mjs",
75
75
  "test:runtime-deploy": "node scripts/runtime-deploy-smoke.mjs",
76
+ "test:sdd": "node scripts/sdd-smoke.mjs",
76
77
  "test:skill-install": "bash scripts/skill-install-smoke.sh",
77
78
  "test:workspace-init": "bash scripts/workspace-init-smoke.sh"
78
79
  },
@@ -316,6 +316,10 @@ interface FormEngineConfig {
316
316
  navigation?: {
317
317
  basePath?: string;
318
318
  };
319
+ compatibility?: {
320
+ apiContracts?: 'strict' | 'legacy';
321
+ legacyFallbacks?: boolean;
322
+ };
319
323
  effects?: FormEffect[];
320
324
  }
321
325
  type FormEffectConditionOperator = 'eq' | 'ne' | 'in' | 'notIn' | 'contains' | 'empty' | 'notEmpty' | 'between' | 'changed';
@@ -316,6 +316,10 @@ interface FormEngineConfig {
316
316
  navigation?: {
317
317
  basePath?: string;
318
318
  };
319
+ compatibility?: {
320
+ apiContracts?: 'strict' | 'legacy';
321
+ legacyFallbacks?: boolean;
322
+ };
319
323
  effects?: FormEffect[];
320
324
  }
321
325
  type FormEffectConditionOperator = 'eq' | 'ne' | 'in' | 'notIn' | 'contains' | 'empty' | 'notEmpty' | 'between' | 'changed';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/build/index.ts"],"sourcesContent":["export type CssIsolation = 'namespace' | 'shadow' | 'none';\nexport type WorkspaceRuntimeMode = 'legacy' | 'react-spa';\n\nexport interface AppWorkspaceConfig {\n appType?: string;\n appName?: string;\n runtimeMode?: WorkspaceRuntimeMode;\n platformUrl?: string;\n servicePrefix?: string;\n appKey?: string;\n appSecret?: string;\n userId?: string;\n version?: string;\n buildId?: string;\n oss?: {\n region?: string;\n bucket?: string;\n accessKeyId?: string;\n accessKeySecret?: string;\n pathPrefix?: string;\n corsOrigins?: string[];\n skipCors?: boolean;\n };\n defaults?: {\n protocolVersion?: string;\n frameworkVersion?: string;\n cssIsolation?: CssIsolation;\n formMenuParentId?: string;\n formMenuIcon?: string;\n pageMenuParentId?: string;\n pageMenuIcon?: string;\n formBuilderVersion?: string;\n };\n forms?: { dir?: string; publishLegacyBundle?: boolean };\n pages?: { dir?: string };\n}\n\nexport function defineAppWorkspaceConfig<T extends AppWorkspaceConfig>(config: T): T {\n return config;\n}\n\nconst DEFAULT_NAMESPACE_PREFIX = '.sy-app-workspace';\n\nfunction splitCssSelectors(selector: string) {\n const selectors: string[] = [];\n let depth = 0;\n let quote = '';\n let current = '';\n for (const char of selector) {\n if (quote) {\n current += char;\n if (char === quote) quote = '';\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n current += char;\n continue;\n }\n if (char === '(' || char === '[') depth += 1;\n if (char === ')' || char === ']') depth -= 1;\n if (char === ',' && depth === 0) {\n selectors.push(current.trim());\n current = '';\n continue;\n }\n current += char;\n }\n if (current.trim()) selectors.push(current.trim());\n return selectors;\n}\n\nfunction shouldSkipNamespace(selector: string, prefix: string) {\n if (!selector || selector.includes(prefix)) return true;\n if (/^(html|body|:root)(\\b|:|\\[|$)/.test(selector)) return true;\n if (/^(@|from\\b|to\\b|\\d+%)/.test(selector)) return true;\n if (/^\\.(ant|sy-ant|anticon|adm)-/.test(selector)) return true;\n return false;\n}\n\nfunction createAntdSelectorAlias(selector: string) {\n const aliased = selector\n .replace(/(^|[^A-Za-z0-9_-])\\.ant-/g, '$1.sy-ant-')\n .replace(/(^|[^A-Za-z0-9_-])\\.anticon-/g, '$1.sy-anticon-')\n .replace(/(^|[^A-Za-z0-9_-])\\.anticon(?=$|[^A-Za-z0-9_-])/g, '$1.sy-anticon');\n return aliased === selector ? null : aliased;\n}\n\nexport function createOpenXiangdaNamespaceCssPlugin(\n prefix = DEFAULT_NAMESPACE_PREFIX,\n) {\n return {\n postcssPlugin: 'openxiangda-namespace-css',\n Rule(rule: { selector?: string; parent?: any }) {\n if (!rule.selector) return;\n let parent = rule.parent;\n while (parent) {\n if (parent.type === 'atrule' && /keyframes$/i.test(parent.name)) {\n return;\n }\n parent = parent.parent;\n }\n rule.selector = Array.from(\n new Set(\n splitCssSelectors(rule.selector).flatMap((selector) => {\n const scopedSelector = shouldSkipNamespace(selector, prefix)\n ? selector\n : `${prefix} ${selector}`;\n const antdAlias = createAntdSelectorAlias(scopedSelector);\n return antdAlias ? [scopedSelector, antdAlias] : [scopedSelector];\n }),\n ),\n ).join(', ');\n },\n };\n}\n\n(createOpenXiangdaNamespaceCssPlugin as any).postcss = true;\n\nexport const createNamespaceCssPlugin = createOpenXiangdaNamespaceCssPlugin;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqCO,SAAS,yBAAuD,QAAc;AACnF,SAAO;AACT;AAEA,IAAM,2BAA2B;AAEjC,SAAS,kBAAkB,UAAkB;AAC3C,QAAM,YAAsB,CAAC;AAC7B,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,MAAI,UAAU;AACd,aAAW,QAAQ,UAAU;AAC3B,QAAI,OAAO;AACT,iBAAW;AACX,UAAI,SAAS,MAAO,SAAQ;AAC5B;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,KAAK;AAChC,cAAQ;AACR,iBAAW;AACX;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,IAAK,UAAS;AAC3C,QAAI,SAAS,OAAO,SAAS,IAAK,UAAS;AAC3C,QAAI,SAAS,OAAO,UAAU,GAAG;AAC/B,gBAAU,KAAK,QAAQ,KAAK,CAAC;AAC7B,gBAAU;AACV;AAAA,IACF;AACA,eAAW;AAAA,EACb;AACA,MAAI,QAAQ,KAAK,EAAG,WAAU,KAAK,QAAQ,KAAK,CAAC;AACjD,SAAO;AACT;AAEA,SAAS,oBAAoB,UAAkB,QAAgB;AAC7D,MAAI,CAAC,YAAY,SAAS,SAAS,MAAM,EAAG,QAAO;AACnD,MAAI,gCAAgC,KAAK,QAAQ,EAAG,QAAO;AAC3D,MAAI,wBAAwB,KAAK,QAAQ,EAAG,QAAO;AACnD,MAAI,+BAA+B,KAAK,QAAQ,EAAG,QAAO;AAC1D,SAAO;AACT;AAEA,SAAS,wBAAwB,UAAkB;AACjD,QAAM,UAAU,SACb,QAAQ,6BAA6B,YAAY,EACjD,QAAQ,iCAAiC,gBAAgB,EACzD,QAAQ,oDAAoD,eAAe;AAC9E,SAAO,YAAY,WAAW,OAAO;AACvC;AAEO,SAAS,oCACd,SAAS,0BACT;AACA,SAAO;AAAA,IACL,eAAe;AAAA,IACf,KAAK,MAA2C;AAC9C,UAAI,CAAC,KAAK,SAAU;AACpB,UAAI,SAAS,KAAK;AAClB,aAAO,QAAQ;AACb,YAAI,OAAO,SAAS,YAAY,cAAc,KAAK,OAAO,IAAI,GAAG;AAC/D;AAAA,QACF;AACA,iBAAS,OAAO;AAAA,MAClB;AACA,WAAK,WAAW,MAAM;AAAA,QACpB,IAAI;AAAA,UACF,kBAAkB,KAAK,QAAQ,EAAE,QAAQ,CAAC,aAAa;AACrD,kBAAM,iBAAiB,oBAAoB,UAAU,MAAM,IACvD,WACA,GAAG,MAAM,IAAI,QAAQ;AACzB,kBAAM,YAAY,wBAAwB,cAAc;AACxD,mBAAO,YAAY,CAAC,gBAAgB,SAAS,IAAI,CAAC,cAAc;AAAA,UAClE,CAAC;AAAA,QACH;AAAA,MACF,EAAE,KAAK,IAAI;AAAA,IACb;AAAA,EACF;AACF;AAEC,oCAA4C,UAAU;AAEhD,IAAM,2BAA2B;","names":[]}
1
+ {"version":3,"sources":["../../src/build/index.ts"],"sourcesContent":["export type CssIsolation = 'namespace' | 'shadow' | 'none';\nexport type WorkspaceRuntimeMode = 'legacy' | 'react-spa';\n\nexport interface AppWorkspaceConfig {\n appType?: string;\n appName?: string;\n runtimeMode?: WorkspaceRuntimeMode;\n platformUrl?: string;\n servicePrefix?: string;\n appKey?: string;\n appSecret?: string;\n userId?: string;\n version?: string;\n buildId?: string;\n oss?: {\n region?: string;\n bucket?: string;\n accessKeyId?: string;\n accessKeySecret?: string;\n pathPrefix?: string;\n corsOrigins?: string[];\n skipCors?: boolean;\n };\n defaults?: {\n protocolVersion?: string;\n frameworkVersion?: string;\n cssIsolation?: CssIsolation;\n formMenuParentId?: string;\n formMenuIcon?: string;\n pageMenuParentId?: string;\n pageMenuIcon?: string;\n formBuilderVersion?: string;\n };\n forms?: { dir?: string; publishLegacyBundle?: boolean };\n pages?: { dir?: string };\n governance?: {\n sdd?: {\n enabled?: boolean;\n strictHighRisk?: boolean;\n path?: string;\n };\n };\n}\n\nexport function defineAppWorkspaceConfig<T extends AppWorkspaceConfig>(config: T): T {\n return config;\n}\n\nconst DEFAULT_NAMESPACE_PREFIX = '.sy-app-workspace';\n\nfunction splitCssSelectors(selector: string) {\n const selectors: string[] = [];\n let depth = 0;\n let quote = '';\n let current = '';\n for (const char of selector) {\n if (quote) {\n current += char;\n if (char === quote) quote = '';\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n current += char;\n continue;\n }\n if (char === '(' || char === '[') depth += 1;\n if (char === ')' || char === ']') depth -= 1;\n if (char === ',' && depth === 0) {\n selectors.push(current.trim());\n current = '';\n continue;\n }\n current += char;\n }\n if (current.trim()) selectors.push(current.trim());\n return selectors;\n}\n\nfunction shouldSkipNamespace(selector: string, prefix: string) {\n if (!selector || selector.includes(prefix)) return true;\n if (/^(html|body|:root)(\\b|:|\\[|$)/.test(selector)) return true;\n if (/^(@|from\\b|to\\b|\\d+%)/.test(selector)) return true;\n if (/^\\.(ant|sy-ant|anticon|adm)-/.test(selector)) return true;\n return false;\n}\n\nfunction createAntdSelectorAlias(selector: string) {\n const aliased = selector\n .replace(/(^|[^A-Za-z0-9_-])\\.ant-/g, '$1.sy-ant-')\n .replace(/(^|[^A-Za-z0-9_-])\\.anticon-/g, '$1.sy-anticon-')\n .replace(/(^|[^A-Za-z0-9_-])\\.anticon(?=$|[^A-Za-z0-9_-])/g, '$1.sy-anticon');\n return aliased === selector ? null : aliased;\n}\n\nexport function createOpenXiangdaNamespaceCssPlugin(\n prefix = DEFAULT_NAMESPACE_PREFIX,\n) {\n return {\n postcssPlugin: 'openxiangda-namespace-css',\n Rule(rule: { selector?: string; parent?: any }) {\n if (!rule.selector) return;\n let parent = rule.parent;\n while (parent) {\n if (parent.type === 'atrule' && /keyframes$/i.test(parent.name)) {\n return;\n }\n parent = parent.parent;\n }\n rule.selector = Array.from(\n new Set(\n splitCssSelectors(rule.selector).flatMap((selector) => {\n const scopedSelector = shouldSkipNamespace(selector, prefix)\n ? selector\n : `${prefix} ${selector}`;\n const antdAlias = createAntdSelectorAlias(scopedSelector);\n return antdAlias ? [scopedSelector, antdAlias] : [scopedSelector];\n }),\n ),\n ).join(', ');\n },\n };\n}\n\n(createOpenXiangdaNamespaceCssPlugin as any).postcss = true;\n\nexport const createNamespaceCssPlugin = createOpenXiangdaNamespaceCssPlugin;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4CO,SAAS,yBAAuD,QAAc;AACnF,SAAO;AACT;AAEA,IAAM,2BAA2B;AAEjC,SAAS,kBAAkB,UAAkB;AAC3C,QAAM,YAAsB,CAAC;AAC7B,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,MAAI,UAAU;AACd,aAAW,QAAQ,UAAU;AAC3B,QAAI,OAAO;AACT,iBAAW;AACX,UAAI,SAAS,MAAO,SAAQ;AAC5B;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,KAAK;AAChC,cAAQ;AACR,iBAAW;AACX;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,IAAK,UAAS;AAC3C,QAAI,SAAS,OAAO,SAAS,IAAK,UAAS;AAC3C,QAAI,SAAS,OAAO,UAAU,GAAG;AAC/B,gBAAU,KAAK,QAAQ,KAAK,CAAC;AAC7B,gBAAU;AACV;AAAA,IACF;AACA,eAAW;AAAA,EACb;AACA,MAAI,QAAQ,KAAK,EAAG,WAAU,KAAK,QAAQ,KAAK,CAAC;AACjD,SAAO;AACT;AAEA,SAAS,oBAAoB,UAAkB,QAAgB;AAC7D,MAAI,CAAC,YAAY,SAAS,SAAS,MAAM,EAAG,QAAO;AACnD,MAAI,gCAAgC,KAAK,QAAQ,EAAG,QAAO;AAC3D,MAAI,wBAAwB,KAAK,QAAQ,EAAG,QAAO;AACnD,MAAI,+BAA+B,KAAK,QAAQ,EAAG,QAAO;AAC1D,SAAO;AACT;AAEA,SAAS,wBAAwB,UAAkB;AACjD,QAAM,UAAU,SACb,QAAQ,6BAA6B,YAAY,EACjD,QAAQ,iCAAiC,gBAAgB,EACzD,QAAQ,oDAAoD,eAAe;AAC9E,SAAO,YAAY,WAAW,OAAO;AACvC;AAEO,SAAS,oCACd,SAAS,0BACT;AACA,SAAO;AAAA,IACL,eAAe;AAAA,IACf,KAAK,MAA2C;AAC9C,UAAI,CAAC,KAAK,SAAU;AACpB,UAAI,SAAS,KAAK;AAClB,aAAO,QAAQ;AACb,YAAI,OAAO,SAAS,YAAY,cAAc,KAAK,OAAO,IAAI,GAAG;AAC/D;AAAA,QACF;AACA,iBAAS,OAAO;AAAA,MAClB;AACA,WAAK,WAAW,MAAM;AAAA,QACpB,IAAI;AAAA,UACF,kBAAkB,KAAK,QAAQ,EAAE,QAAQ,CAAC,aAAa;AACrD,kBAAM,iBAAiB,oBAAoB,UAAU,MAAM,IACvD,WACA,GAAG,MAAM,IAAI,QAAQ;AACzB,kBAAM,YAAY,wBAAwB,cAAc;AACxD,mBAAO,YAAY,CAAC,gBAAgB,SAAS,IAAI,CAAC,cAAc;AAAA,UAClE,CAAC;AAAA,QACH;AAAA,MACF,EAAE,KAAK,IAAI;AAAA,IACb;AAAA,EACF;AACF;AAEC,oCAA4C,UAAU;AAEhD,IAAM,2BAA2B;","names":[]}
@@ -37,6 +37,13 @@ interface AppWorkspaceConfig {
37
37
  pages?: {
38
38
  dir?: string;
39
39
  };
40
+ governance?: {
41
+ sdd?: {
42
+ enabled?: boolean;
43
+ strictHighRisk?: boolean;
44
+ path?: string;
45
+ };
46
+ };
40
47
  }
41
48
  declare function defineAppWorkspaceConfig<T extends AppWorkspaceConfig>(config: T): T;
42
49
  declare function createOpenXiangdaNamespaceCssPlugin(prefix?: string): {
@@ -37,6 +37,13 @@ interface AppWorkspaceConfig {
37
37
  pages?: {
38
38
  dir?: string;
39
39
  };
40
+ governance?: {
41
+ sdd?: {
42
+ enabled?: boolean;
43
+ strictHighRisk?: boolean;
44
+ path?: string;
45
+ };
46
+ };
40
47
  }
41
48
  declare function defineAppWorkspaceConfig<T extends AppWorkspaceConfig>(config: T): T;
42
49
  declare function createOpenXiangdaNamespaceCssPlugin(prefix?: string): {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/build/index.ts"],"sourcesContent":["export type CssIsolation = 'namespace' | 'shadow' | 'none';\nexport type WorkspaceRuntimeMode = 'legacy' | 'react-spa';\n\nexport interface AppWorkspaceConfig {\n appType?: string;\n appName?: string;\n runtimeMode?: WorkspaceRuntimeMode;\n platformUrl?: string;\n servicePrefix?: string;\n appKey?: string;\n appSecret?: string;\n userId?: string;\n version?: string;\n buildId?: string;\n oss?: {\n region?: string;\n bucket?: string;\n accessKeyId?: string;\n accessKeySecret?: string;\n pathPrefix?: string;\n corsOrigins?: string[];\n skipCors?: boolean;\n };\n defaults?: {\n protocolVersion?: string;\n frameworkVersion?: string;\n cssIsolation?: CssIsolation;\n formMenuParentId?: string;\n formMenuIcon?: string;\n pageMenuParentId?: string;\n pageMenuIcon?: string;\n formBuilderVersion?: string;\n };\n forms?: { dir?: string; publishLegacyBundle?: boolean };\n pages?: { dir?: string };\n}\n\nexport function defineAppWorkspaceConfig<T extends AppWorkspaceConfig>(config: T): T {\n return config;\n}\n\nconst DEFAULT_NAMESPACE_PREFIX = '.sy-app-workspace';\n\nfunction splitCssSelectors(selector: string) {\n const selectors: string[] = [];\n let depth = 0;\n let quote = '';\n let current = '';\n for (const char of selector) {\n if (quote) {\n current += char;\n if (char === quote) quote = '';\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n current += char;\n continue;\n }\n if (char === '(' || char === '[') depth += 1;\n if (char === ')' || char === ']') depth -= 1;\n if (char === ',' && depth === 0) {\n selectors.push(current.trim());\n current = '';\n continue;\n }\n current += char;\n }\n if (current.trim()) selectors.push(current.trim());\n return selectors;\n}\n\nfunction shouldSkipNamespace(selector: string, prefix: string) {\n if (!selector || selector.includes(prefix)) return true;\n if (/^(html|body|:root)(\\b|:|\\[|$)/.test(selector)) return true;\n if (/^(@|from\\b|to\\b|\\d+%)/.test(selector)) return true;\n if (/^\\.(ant|sy-ant|anticon|adm)-/.test(selector)) return true;\n return false;\n}\n\nfunction createAntdSelectorAlias(selector: string) {\n const aliased = selector\n .replace(/(^|[^A-Za-z0-9_-])\\.ant-/g, '$1.sy-ant-')\n .replace(/(^|[^A-Za-z0-9_-])\\.anticon-/g, '$1.sy-anticon-')\n .replace(/(^|[^A-Za-z0-9_-])\\.anticon(?=$|[^A-Za-z0-9_-])/g, '$1.sy-anticon');\n return aliased === selector ? null : aliased;\n}\n\nexport function createOpenXiangdaNamespaceCssPlugin(\n prefix = DEFAULT_NAMESPACE_PREFIX,\n) {\n return {\n postcssPlugin: 'openxiangda-namespace-css',\n Rule(rule: { selector?: string; parent?: any }) {\n if (!rule.selector) return;\n let parent = rule.parent;\n while (parent) {\n if (parent.type === 'atrule' && /keyframes$/i.test(parent.name)) {\n return;\n }\n parent = parent.parent;\n }\n rule.selector = Array.from(\n new Set(\n splitCssSelectors(rule.selector).flatMap((selector) => {\n const scopedSelector = shouldSkipNamespace(selector, prefix)\n ? selector\n : `${prefix} ${selector}`;\n const antdAlias = createAntdSelectorAlias(scopedSelector);\n return antdAlias ? [scopedSelector, antdAlias] : [scopedSelector];\n }),\n ),\n ).join(', ');\n },\n };\n}\n\n(createOpenXiangdaNamespaceCssPlugin as any).postcss = true;\n\nexport const createNamespaceCssPlugin = createOpenXiangdaNamespaceCssPlugin;\n"],"mappings":";AAqCO,SAAS,yBAAuD,QAAc;AACnF,SAAO;AACT;AAEA,IAAM,2BAA2B;AAEjC,SAAS,kBAAkB,UAAkB;AAC3C,QAAM,YAAsB,CAAC;AAC7B,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,MAAI,UAAU;AACd,aAAW,QAAQ,UAAU;AAC3B,QAAI,OAAO;AACT,iBAAW;AACX,UAAI,SAAS,MAAO,SAAQ;AAC5B;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,KAAK;AAChC,cAAQ;AACR,iBAAW;AACX;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,IAAK,UAAS;AAC3C,QAAI,SAAS,OAAO,SAAS,IAAK,UAAS;AAC3C,QAAI,SAAS,OAAO,UAAU,GAAG;AAC/B,gBAAU,KAAK,QAAQ,KAAK,CAAC;AAC7B,gBAAU;AACV;AAAA,IACF;AACA,eAAW;AAAA,EACb;AACA,MAAI,QAAQ,KAAK,EAAG,WAAU,KAAK,QAAQ,KAAK,CAAC;AACjD,SAAO;AACT;AAEA,SAAS,oBAAoB,UAAkB,QAAgB;AAC7D,MAAI,CAAC,YAAY,SAAS,SAAS,MAAM,EAAG,QAAO;AACnD,MAAI,gCAAgC,KAAK,QAAQ,EAAG,QAAO;AAC3D,MAAI,wBAAwB,KAAK,QAAQ,EAAG,QAAO;AACnD,MAAI,+BAA+B,KAAK,QAAQ,EAAG,QAAO;AAC1D,SAAO;AACT;AAEA,SAAS,wBAAwB,UAAkB;AACjD,QAAM,UAAU,SACb,QAAQ,6BAA6B,YAAY,EACjD,QAAQ,iCAAiC,gBAAgB,EACzD,QAAQ,oDAAoD,eAAe;AAC9E,SAAO,YAAY,WAAW,OAAO;AACvC;AAEO,SAAS,oCACd,SAAS,0BACT;AACA,SAAO;AAAA,IACL,eAAe;AAAA,IACf,KAAK,MAA2C;AAC9C,UAAI,CAAC,KAAK,SAAU;AACpB,UAAI,SAAS,KAAK;AAClB,aAAO,QAAQ;AACb,YAAI,OAAO,SAAS,YAAY,cAAc,KAAK,OAAO,IAAI,GAAG;AAC/D;AAAA,QACF;AACA,iBAAS,OAAO;AAAA,MAClB;AACA,WAAK,WAAW,MAAM;AAAA,QACpB,IAAI;AAAA,UACF,kBAAkB,KAAK,QAAQ,EAAE,QAAQ,CAAC,aAAa;AACrD,kBAAM,iBAAiB,oBAAoB,UAAU,MAAM,IACvD,WACA,GAAG,MAAM,IAAI,QAAQ;AACzB,kBAAM,YAAY,wBAAwB,cAAc;AACxD,mBAAO,YAAY,CAAC,gBAAgB,SAAS,IAAI,CAAC,cAAc;AAAA,UAClE,CAAC;AAAA,QACH;AAAA,MACF,EAAE,KAAK,IAAI;AAAA,IACb;AAAA,EACF;AACF;AAEC,oCAA4C,UAAU;AAEhD,IAAM,2BAA2B;","names":[]}
1
+ {"version":3,"sources":["../../src/build/index.ts"],"sourcesContent":["export type CssIsolation = 'namespace' | 'shadow' | 'none';\nexport type WorkspaceRuntimeMode = 'legacy' | 'react-spa';\n\nexport interface AppWorkspaceConfig {\n appType?: string;\n appName?: string;\n runtimeMode?: WorkspaceRuntimeMode;\n platformUrl?: string;\n servicePrefix?: string;\n appKey?: string;\n appSecret?: string;\n userId?: string;\n version?: string;\n buildId?: string;\n oss?: {\n region?: string;\n bucket?: string;\n accessKeyId?: string;\n accessKeySecret?: string;\n pathPrefix?: string;\n corsOrigins?: string[];\n skipCors?: boolean;\n };\n defaults?: {\n protocolVersion?: string;\n frameworkVersion?: string;\n cssIsolation?: CssIsolation;\n formMenuParentId?: string;\n formMenuIcon?: string;\n pageMenuParentId?: string;\n pageMenuIcon?: string;\n formBuilderVersion?: string;\n };\n forms?: { dir?: string; publishLegacyBundle?: boolean };\n pages?: { dir?: string };\n governance?: {\n sdd?: {\n enabled?: boolean;\n strictHighRisk?: boolean;\n path?: string;\n };\n };\n}\n\nexport function defineAppWorkspaceConfig<T extends AppWorkspaceConfig>(config: T): T {\n return config;\n}\n\nconst DEFAULT_NAMESPACE_PREFIX = '.sy-app-workspace';\n\nfunction splitCssSelectors(selector: string) {\n const selectors: string[] = [];\n let depth = 0;\n let quote = '';\n let current = '';\n for (const char of selector) {\n if (quote) {\n current += char;\n if (char === quote) quote = '';\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n current += char;\n continue;\n }\n if (char === '(' || char === '[') depth += 1;\n if (char === ')' || char === ']') depth -= 1;\n if (char === ',' && depth === 0) {\n selectors.push(current.trim());\n current = '';\n continue;\n }\n current += char;\n }\n if (current.trim()) selectors.push(current.trim());\n return selectors;\n}\n\nfunction shouldSkipNamespace(selector: string, prefix: string) {\n if (!selector || selector.includes(prefix)) return true;\n if (/^(html|body|:root)(\\b|:|\\[|$)/.test(selector)) return true;\n if (/^(@|from\\b|to\\b|\\d+%)/.test(selector)) return true;\n if (/^\\.(ant|sy-ant|anticon|adm)-/.test(selector)) return true;\n return false;\n}\n\nfunction createAntdSelectorAlias(selector: string) {\n const aliased = selector\n .replace(/(^|[^A-Za-z0-9_-])\\.ant-/g, '$1.sy-ant-')\n .replace(/(^|[^A-Za-z0-9_-])\\.anticon-/g, '$1.sy-anticon-')\n .replace(/(^|[^A-Za-z0-9_-])\\.anticon(?=$|[^A-Za-z0-9_-])/g, '$1.sy-anticon');\n return aliased === selector ? null : aliased;\n}\n\nexport function createOpenXiangdaNamespaceCssPlugin(\n prefix = DEFAULT_NAMESPACE_PREFIX,\n) {\n return {\n postcssPlugin: 'openxiangda-namespace-css',\n Rule(rule: { selector?: string; parent?: any }) {\n if (!rule.selector) return;\n let parent = rule.parent;\n while (parent) {\n if (parent.type === 'atrule' && /keyframes$/i.test(parent.name)) {\n return;\n }\n parent = parent.parent;\n }\n rule.selector = Array.from(\n new Set(\n splitCssSelectors(rule.selector).flatMap((selector) => {\n const scopedSelector = shouldSkipNamespace(selector, prefix)\n ? selector\n : `${prefix} ${selector}`;\n const antdAlias = createAntdSelectorAlias(scopedSelector);\n return antdAlias ? [scopedSelector, antdAlias] : [scopedSelector];\n }),\n ),\n ).join(', ');\n },\n };\n}\n\n(createOpenXiangdaNamespaceCssPlugin as any).postcss = true;\n\nexport const createNamespaceCssPlugin = createOpenXiangdaNamespaceCssPlugin;\n"],"mappings":";AA4CO,SAAS,yBAAuD,QAAc;AACnF,SAAO;AACT;AAEA,IAAM,2BAA2B;AAEjC,SAAS,kBAAkB,UAAkB;AAC3C,QAAM,YAAsB,CAAC;AAC7B,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,MAAI,UAAU;AACd,aAAW,QAAQ,UAAU;AAC3B,QAAI,OAAO;AACT,iBAAW;AACX,UAAI,SAAS,MAAO,SAAQ;AAC5B;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,KAAK;AAChC,cAAQ;AACR,iBAAW;AACX;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,IAAK,UAAS;AAC3C,QAAI,SAAS,OAAO,SAAS,IAAK,UAAS;AAC3C,QAAI,SAAS,OAAO,UAAU,GAAG;AAC/B,gBAAU,KAAK,QAAQ,KAAK,CAAC;AAC7B,gBAAU;AACV;AAAA,IACF;AACA,eAAW;AAAA,EACb;AACA,MAAI,QAAQ,KAAK,EAAG,WAAU,KAAK,QAAQ,KAAK,CAAC;AACjD,SAAO;AACT;AAEA,SAAS,oBAAoB,UAAkB,QAAgB;AAC7D,MAAI,CAAC,YAAY,SAAS,SAAS,MAAM,EAAG,QAAO;AACnD,MAAI,gCAAgC,KAAK,QAAQ,EAAG,QAAO;AAC3D,MAAI,wBAAwB,KAAK,QAAQ,EAAG,QAAO;AACnD,MAAI,+BAA+B,KAAK,QAAQ,EAAG,QAAO;AAC1D,SAAO;AACT;AAEA,SAAS,wBAAwB,UAAkB;AACjD,QAAM,UAAU,SACb,QAAQ,6BAA6B,YAAY,EACjD,QAAQ,iCAAiC,gBAAgB,EACzD,QAAQ,oDAAoD,eAAe;AAC9E,SAAO,YAAY,WAAW,OAAO;AACvC;AAEO,SAAS,oCACd,SAAS,0BACT;AACA,SAAO;AAAA,IACL,eAAe;AAAA,IACf,KAAK,MAA2C;AAC9C,UAAI,CAAC,KAAK,SAAU;AACpB,UAAI,SAAS,KAAK;AAClB,aAAO,QAAQ;AACb,YAAI,OAAO,SAAS,YAAY,cAAc,KAAK,OAAO,IAAI,GAAG;AAC/D;AAAA,QACF;AACA,iBAAS,OAAO;AAAA,MAClB;AACA,WAAK,WAAW,MAAM;AAAA,QACpB,IAAI;AAAA,UACF,kBAAkB,KAAK,QAAQ,EAAE,QAAQ,CAAC,aAAa;AACrD,kBAAM,iBAAiB,oBAAoB,UAAU,MAAM,IACvD,WACA,GAAG,MAAM,IAAI,QAAQ;AACzB,kBAAM,YAAY,wBAAwB,cAAc;AACxD,mBAAO,YAAY,CAAC,gBAAgB,SAAS,IAAI,CAAC,cAAc;AAAA,UAClE,CAAC;AAAA,QACH;AAAA,MACF,EAAE,KAAK,IAAI;AAAA,IACb;AAAA,EACF;AACF;AAEC,oCAA4C,UAAU;AAEhD,IAAM,2BAA2B;","names":[]}
@@ -16183,7 +16183,23 @@ var pickFormInstanceId = (value) => {
16183
16183
  if (!value) return void 0;
16184
16184
  if (typeof value === "string") return value;
16185
16185
  if (typeof value !== "object") return void 0;
16186
- return value.formInstanceId || value.formInstId || value.instanceId || value.id || pickFormInstanceId(value.result) || pickFormInstanceId(value.data);
16186
+ const direct = value.formInstanceId || value.formInstId || value.instanceId || value.id;
16187
+ if (direct) return pickFormInstanceId(direct);
16188
+ for (const candidate of [value.result, value.data, value.raw]) {
16189
+ const picked = pickFormInstanceId(candidate);
16190
+ if (picked) return picked;
16191
+ }
16192
+ return void 0;
16193
+ };
16194
+ var getSubmitResultFormInstanceId = (submitResponse, config, submitBehavior) => {
16195
+ const responseId = pickFormInstanceId(submitResponse);
16196
+ if (responseId) return responseId;
16197
+ if (submitBehavior !== "create" && config.formInstanceId) {
16198
+ return config.formInstanceId;
16199
+ }
16200
+ throw new Error(
16201
+ "\u63D0\u4EA4\u63A5\u53E3\u672A\u8FD4\u56DE formInstId/formInstanceId\u3002\u4FDD\u5B58\u63A5\u53E3\u53EA\u8FD4\u56DE\u5B9E\u4F8B\u6807\u8BC6\u548C\u5DF2\u751F\u6210\u7684\u6D41\u6C34\u53F7\uFF1B\u5982\u9700\u5B8C\u6574\u6570\u636E\u3001\u516C\u5F0F\u56DE\u586B\u6216\u5176\u4ED6\u670D\u52A1\u7AEF\u5B57\u6BB5\uFF0C\u8BF7\u4FDD\u5B58\u6210\u529F\u540E\u518D\u67E5\u8BE2\u8BE6\u60C5\u3002"
16202
+ );
16187
16203
  };
16188
16204
  var normalizeFormDataForSubmit = (schema, formData) => {
16189
16205
  const next = { ...formData };
@@ -16382,7 +16398,7 @@ var InnerFormContent = ({
16382
16398
  selectedApprovers: initiatorSelectedApprovers,
16383
16399
  initiatorSelectedApprovers
16384
16400
  });
16385
- const formInstId = pickFormInstanceId(submitResponse) || config.formInstanceId || `inst_${Date.now()}`;
16401
+ const formInstId = getSubmitResultFormInstanceId(submitResponse, config, submitBehavior);
16386
16402
  if (config.submit?.afterSubmit) {
16387
16403
  await config.submit.afterSubmit({
16388
16404
  formInstanceId: formInstId,
@@ -16406,6 +16422,7 @@ var InnerFormContent = ({
16406
16422
  }
16407
16423
  } catch (error) {
16408
16424
  console.error("[FormSubmitTemplate] Submit failed:", error);
16425
+ import_antd37.message.error(error instanceof Error ? error.message : "\u63D0\u4EA4\u5931\u8D25");
16409
16426
  } finally {
16410
16427
  setSubmitting(false);
16411
16428
  }
@@ -17433,6 +17450,7 @@ var StandardFormPage = ({
17433
17450
  formInstanceId,
17434
17451
  defaultUploadProvider,
17435
17452
  submitBehavior,
17453
+ compatibility,
17436
17454
  onSubmit,
17437
17455
  onSubmitSuccess,
17438
17456
  inDrawer
@@ -17506,6 +17524,7 @@ var StandardFormPage = ({
17506
17524
  defaultUploadProvider,
17507
17525
  submitBehavior,
17508
17526
  permissions,
17527
+ compatibility,
17509
17528
  api
17510
17529
  },
17511
17530
  formType,
@@ -18466,6 +18485,7 @@ var DataManagementList = ({
18466
18485
  detailPageUrlBuilder,
18467
18486
  submitRenderer,
18468
18487
  requestOverride,
18488
+ allowSchemaFallback = false,
18469
18489
  rowActions = [],
18470
18490
  maxVisibleRowActions
18471
18491
  }) => {
@@ -18633,6 +18653,11 @@ var DataManagementList = ({
18633
18653
  const nextSearchKeyWord = saved?.filter?.searchKeyWord || "";
18634
18654
  const nextFilterGroup = hydrateFilterGroup(saved?.filter?.group);
18635
18655
  const nextFormType = propFormType || schemaResult.formType || "form";
18656
+ if (!schemaResult.schema && !allowSchemaFallback) {
18657
+ throw new Error(
18658
+ `\u8868\u5355 schema \u4E0D\u5B58\u5728\u6216\u672A\u53D1\u5E03: ${formUuid}\u3002\u8BF7\u5148\u53D1\u5E03\u8868\u5355 schema\uFF1B\u4E25\u683C\u6A21\u5F0F\u4E0D\u4F1A\u751F\u6210\u515C\u5E95\u8868\u5355\u3002`
18659
+ );
18660
+ }
18636
18661
  setFields(allFields);
18637
18662
  setRuntimeFormSchema(
18638
18663
  schemaResult.schema || buildFallbackFormSchema({
@@ -18663,7 +18688,7 @@ var DataManagementList = ({
18663
18688
  });
18664
18689
  } catch (error) {
18665
18690
  console.error("[DataManagementList] load schema failed:", error);
18666
- import_antd39.message.error("\u52A0\u8F7D\u8868\u5355\u914D\u7F6E\u5931\u8D25");
18691
+ import_antd39.message.error(error instanceof Error ? error.message : "\u52A0\u8F7D\u8868\u5355\u914D\u7F6E\u5931\u8D25");
18667
18692
  } finally {
18668
18693
  if (mounted) setSchemaLoading(false);
18669
18694
  }
@@ -18674,6 +18699,7 @@ var DataManagementList = ({
18674
18699
  };
18675
18700
  }, [
18676
18701
  appType,
18702
+ allowSchemaFallback,
18677
18703
  forcedConfig,
18678
18704
  formTitle,
18679
18705
  formUuid,
@@ -19682,7 +19708,8 @@ function LowcodePageRenderer({ schema, context }) {
19682
19708
  forcedConfig: props.forcedConfig,
19683
19709
  showForcedConfig: props.showForcedConfig,
19684
19710
  maxVisibleRowActions: props.maxVisibleRowActions,
19685
- requestOverride
19711
+ requestOverride,
19712
+ allowSchemaFallback: props.allowSchemaFallback ?? context?.compatibility?.legacyFallbacks ?? false
19686
19713
  },
19687
19714
  node.id
19688
19715
  );
@@ -19695,6 +19722,7 @@ function LowcodePageRenderer({ schema, context }) {
19695
19722
  mode: props.mode || context?.mode || "submit",
19696
19723
  appType: props.appType || appType,
19697
19724
  formUuid: props.formUuid || props.schema?.formMeta?.formUuid,
19725
+ compatibility: props.compatibility || context?.compatibility,
19698
19726
  inDrawer: props.inDrawer ?? true
19699
19727
  },
19700
19728
  node.id