openyida 2026.7.18 → 2026.7.21

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 (200) hide show
  1. package/README.md +37 -2
  2. package/bin/yida.js +113 -18
  3. package/docs/capabilities.md +202 -0
  4. package/lib/agent-center/agent-center.js +2 -3
  5. package/lib/app/app-list.js +3 -4
  6. package/lib/app/build-page.js +13 -6
  7. package/lib/app/check-page.js +16 -6
  8. package/lib/app/compile.js +17 -7
  9. package/lib/app/create-app.js +14 -2
  10. package/lib/app/create-form/api-path.js +25 -0
  11. package/lib/app/create-form/args.js +13 -0
  12. package/lib/app/create-form/commands.js +4 -0
  13. package/lib/app/create-form/definition-reader.js +23 -23
  14. package/lib/app/create-form/field-normalizers.js +26 -7
  15. package/lib/app/create-form/schema-patch.js +4 -1
  16. package/lib/app/create-form.js +155 -68
  17. package/lib/app/create-page.js +47 -10
  18. package/lib/app/generate-page.js +20 -1
  19. package/lib/app/get-form-config.js +2 -1
  20. package/lib/app/get-schema.js +67 -15
  21. package/lib/app/import-app.js +94 -42
  22. package/lib/app/list-forms.js +4 -8
  23. package/lib/app/page-ir.js +140 -0
  24. package/lib/app/publish.js +289 -556
  25. package/lib/app/schema-field-resolution.js +370 -0
  26. package/lib/app/services/app-reader.js +85 -0
  27. package/lib/app/services/app-service.js +235 -0
  28. package/lib/app/services/canvas-page-compiler.js +91 -0
  29. package/lib/app/services/canvas-page-schema-builder.js +149 -0
  30. package/lib/app/services/field-bindings.js +68 -0
  31. package/lib/app/services/form-compiler.js +1922 -0
  32. package/lib/app/services/form-mode-service.js +182 -0
  33. package/lib/app/services/form-schema-patcher.js +333 -0
  34. package/lib/app/services/form-schema-reader.js +59 -0
  35. package/lib/app/services/form-service.js +379 -0
  36. package/lib/app/services/form-validation.js +562 -0
  37. package/lib/app/services/native-page-compiler.js +92 -0
  38. package/lib/app/services/native-page-schema-builder.js +428 -0
  39. package/lib/app/services/page-resource-service.js +185 -0
  40. package/lib/app/update-app.js +22 -9
  41. package/lib/app/update-form-config.js +4 -2
  42. package/lib/asset/asset-cmd.js +19 -6
  43. package/lib/auth/oauth-loopback.js +376 -15
  44. package/lib/auth/token-auth.js +34 -3
  45. package/lib/auth/token-store.js +22 -4
  46. package/lib/basic-info/basic-info.js +2 -1
  47. package/lib/bridge/bridge.js +43 -18
  48. package/lib/core/agent-capabilities.js +5 -3
  49. package/lib/core/command-errors.js +38 -0
  50. package/lib/core/command-manifest.js +59 -1
  51. package/lib/core/copy.js +12 -0
  52. package/lib/core/doctor.js +15 -4
  53. package/lib/core/env-cmd.js +1 -1
  54. package/lib/core/env.js +7 -6
  55. package/lib/core/i18n.js +66 -8
  56. package/lib/core/legacy-schema-guard.js +408 -0
  57. package/lib/core/locales/en.js +38 -46
  58. package/lib/core/locales/zh.js +30 -46
  59. package/lib/core/sample.js +12 -2
  60. package/lib/core/utils.js +334 -66
  61. package/lib/core/yida-client.js +108 -5
  62. package/lib/corp-efficiency/corp-efficiency.js +2 -2
  63. package/lib/corp-manager/corp-manager.js +3 -3
  64. package/lib/formula/evaluate.js +11 -68
  65. package/lib/formula/field-refs.js +83 -0
  66. package/lib/i18n-management/i18n-management.js +2 -3
  67. package/lib/process/configure-process.js +44 -1992
  68. package/lib/process/create-process.js +54 -87
  69. package/lib/process/preview-process.js +20 -8
  70. package/lib/process/services/process-compiler.js +2056 -0
  71. package/lib/process/services/process-reader.js +232 -0
  72. package/lib/process/services/process-resource-service.js +571 -0
  73. package/lib/process/services/process-service.js +122 -0
  74. package/lib/process/services/process-stage-checkpoint.js +246 -0
  75. package/lib/report/append.js +7 -26
  76. package/lib/report/http.js +31 -5
  77. package/lib/report/index.js +10 -2
  78. package/lib/samples/yida-canvas-custom-page/business-list.canvas.jsx +63 -14
  79. package/lib/samples/yida-canvas-custom-page/dashboard-overview.canvas.jsx +176 -32
  80. package/lib/samples/yida-canvas-custom-page/dashboard-starter.canvas.jsx +5 -2
  81. package/lib/samples/yida-canvas-custom-page/data-management.canvas.jsx +228 -14
  82. package/lib/samples/yida-canvas-custom-page/portal-shell-home.canvas.jsx +2 -2
  83. package/lib/samples/yida-canvas-custom-page/split-pane-detail.canvas.jsx +206 -10
  84. package/lib/samples/yida-custom-page/data-management.oyd.jsx +14 -3
  85. package/lib/samples/yida-custom-page/design-tokens.js +2 -2
  86. package/lib/samples/yida-custom-page/detail-profile.oyd.jsx +1 -1
  87. package/lib/samples/yida-custom-page/portal-shell-home.oyd.jsx +7 -2
  88. package/lib/samples/yida-custom-page/split-pane-detail.oyd.jsx +2 -1
  89. package/lib/schema/adapters/app-adapter.js +210 -0
  90. package/lib/schema/adapters/form-adapter.js +1362 -0
  91. package/lib/schema/adapters/keys.js +19 -0
  92. package/lib/schema/adapters/page-adapter.js +566 -0
  93. package/lib/schema/adapters/process-adapter.js +519 -0
  94. package/lib/schema/applier.js +1878 -0
  95. package/lib/schema/apply-store.js +1083 -0
  96. package/lib/schema/command.js +645 -0
  97. package/lib/schema/dependency-graph.js +83 -0
  98. package/lib/schema/errors.js +481 -0
  99. package/lib/schema/hash.js +9 -0
  100. package/lib/schema/manifest-limits.js +177 -0
  101. package/lib/schema/manifest-loader.js +309 -0
  102. package/lib/schema/manifest-schema-v1.json +193 -0
  103. package/lib/schema/normalize-manifest.js +281 -0
  104. package/lib/schema/page-canvas-foundation.js +447 -0
  105. package/lib/schema/page-data-source-builder.js +561 -0
  106. package/lib/schema/page-foundation.js +556 -0
  107. package/lib/schema/page-source-loader.js +314 -0
  108. package/lib/schema/planner.js +691 -0
  109. package/lib/schema/remote-dispatch-boundary.js +39 -0
  110. package/lib/schema/remote-missing.js +21 -0
  111. package/lib/schema/remote-reader.js +189 -0
  112. package/lib/schema/resource-registry.js +157 -0
  113. package/lib/schema/server-revision.js +71 -0
  114. package/lib/schema/sort.js +28 -0
  115. package/lib/schema/state-store.js +589 -0
  116. package/package.json +10 -8
  117. package/scripts/check-release-risks.js +254 -0
  118. package/scripts/generate-command-docs.js +6 -1
  119. package/scripts/i18n-baseline.json +11 -11
  120. package/scripts/postinstall.js +8 -12
  121. package/scripts/validate-ci.sh +15 -11
  122. package/scripts/validate-i18n.js +30 -9
  123. package/scripts/validate-package-size.js +5 -2
  124. package/scripts/validate-skills.js +4 -0
  125. package/scripts/validate-structure.js +15 -0
  126. package/yida-skills/SKILL.md +117 -30
  127. package/yida-skills/references/schema-as-code-phase1.md +99 -0
  128. package/yida-skills/references/setup-and-env.md +59 -59
  129. package/yida-skills/references/task-retrospective.md +6 -6
  130. package/yida-skills/skills/yida-app/SKILL.md +78 -17
  131. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +18 -7
  132. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +3 -3
  133. package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +15 -0
  134. package/yida-skills/skills/yida-create-app/SKILL.md +21 -3
  135. package/yida-skills/skills/yida-create-form-page/SKILL.md +19 -1
  136. package/yida-skills/skills/yida-create-page/SKILL.md +16 -3
  137. package/yida-skills/skills/yida-create-process/SKILL.md +100 -4
  138. package/yida-skills/skills/yida-custom-page/SKILL.md +19 -4
  139. package/yida-skills/skills/yida-dashboard/SKILL.md +1 -1
  140. package/yida-skills/skills/yida-dashboard/references/pitfalls.md +1 -1
  141. package/yida-skills/skills/yida-get-schema/SKILL.md +49 -5
  142. package/yida-skills/skills/yida-i18n/SKILL.md +1 -1
  143. package/yida-skills/skills/yida-integration/SKILL.md +7 -1
  144. package/yida-skills/skills/yida-login/SKILL.md +50 -99
  145. package/yida-skills/skills/yida-page-config/SKILL.md +7 -1
  146. package/yida-skills/skills/yida-page-uiux/references/app/blueprint.md +0 -1
  147. package/yida-skills/skills/yida-page-uiux/references/app/navigation-patterns.md +0 -1
  148. package/yida-skills/skills/yida-page-uiux/references/app/role-journey.md +0 -1
  149. package/yida-skills/skills/yida-page-uiux/references/dashboard/app-blueprint.md +0 -1
  150. package/yida-skills/skills/yida-page-uiux/references/dashboard/chart-contracts.md +0 -1
  151. package/yida-skills/skills/yida-page-uiux/references/dashboard/component-contracts.md +0 -1
  152. package/yida-skills/skills/yida-page-uiux/references/dashboard/layout-patterns.md +0 -1
  153. package/yida-skills/skills/yida-page-uiux/references/dashboard/theme-recipes.md +0 -1
  154. package/yida-skills/skills/yida-page-uiux/references/detail/object-narrative.md +0 -1
  155. package/yida-skills/skills/yida-page-uiux/references/detail/section-patterns.md +0 -1
  156. package/yida-skills/skills/yida-page-uiux/references/detail/timeline-and-related.md +0 -1
  157. package/yida-skills/skills/yida-page-uiux/references/landing/assets-workflow.md +0 -1
  158. package/yida-skills/skills/yida-page-uiux/references/landing/industry-playbooks.md +0 -1
  159. package/yida-skills/skills/yida-page-uiux/references/landing/research-levels.md +0 -1
  160. package/yida-skills/skills/yida-page-uiux/references/landing/section-patterns.md +0 -1
  161. package/yida-skills/skills/yida-page-uiux/references/list/drawer-detail.md +0 -1
  162. package/yida-skills/skills/yida-page-uiux/references/list/empty-loading-error.md +0 -1
  163. package/yida-skills/skills/yida-page-uiux/references/list/filter-patterns.md +0 -1
  164. package/yida-skills/skills/yida-page-uiux/references/list/table-patterns.md +0 -1
  165. package/yida-skills/skills/yida-page-uiux/references/scenes/screen.md +0 -1
  166. package/yida-skills/skills/yida-page-uiux/references/workbench/entry-patterns.md +0 -1
  167. package/yida-skills/skills/yida-page-uiux/references/workbench/portal-layouts.md +0 -1
  168. package/yida-skills/skills/yida-page-uiux/references/workbench/task-feed.md +0 -1
  169. package/yida-skills/skills/yida-page-uiux/workflow/output-decision-block.md +1 -1
  170. package/yida-skills/skills/yida-process-rule/SKILL.md +35 -1
  171. package/yida-skills/skills/yida-publish-page/SKILL.md +46 -4
  172. package/yida-skills/skills/yida-report/SKILL.md +9 -235
  173. package/yida-skills/skills/yida-report/references/schema-builder-details.md +239 -0
  174. package/yida-skills/skills/yida-skill-evaluator/SKILL.md +170 -0
  175. package/yida-skills/skills-index.json +238 -54
  176. package/lib/core/locales/ar.js +0 -834
  177. package/lib/core/locales/de.js +0 -834
  178. package/lib/core/locales/es.js +0 -834
  179. package/lib/core/locales/fr.js +0 -834
  180. package/lib/core/locales/hi.js +0 -834
  181. package/lib/core/locales/ja.js +0 -1227
  182. package/lib/core/locales/ko.js +0 -836
  183. package/lib/core/locales/pt.js +0 -834
  184. package/lib/core/locales/vi.js +0 -834
  185. package/lib/core/locales/zh-HK.js +0 -1263
  186. package/project/pages/src/demo-birthday-game.oyd.jsx +0 -832
  187. package/project/pages/src/demo-chip-insight.oyd.jsx +0 -983
  188. package/project/pages/src/demo-compat-smoke.oyd.jsx +0 -58
  189. package/project/pages/src/demo-crm-batch-entry.oyd.jsx +0 -805
  190. package/project/pages/src/demo-crm-dashboard.oyd.jsx +0 -677
  191. package/project/pages/src/demo-future-vision-2026.oyd.jsx +0 -1102
  192. package/project/pages/src/demo-ppt.oyd.jsx +0 -1192
  193. package/project/pages/src/demo-salary-calculator.oyd.jsx +0 -904
  194. package/project/pages/src/openyida-knowledge-doc.oyd.jsx +0 -1714
  195. package/yida-skills/skills/large-file-write/SKILL.md +0 -93
  196. package/yida-skills/skills/large-file-write/references/write-patterns.md +0 -147
  197. package/yida-skills/skills/large-file-write/scripts/write.js +0 -157
  198. package/yida-skills/skills/sls-log-workbench/SKILL.md +0 -134
  199. package/yida-skills/skills/sls-log-workbench/references/workbench-reference.md +0 -130
  200. package/yida-skills/skills/sls-log-workbench/sls-query.js +0 -295
@@ -59,24 +59,38 @@
59
59
  const fs = require('fs');
60
60
  const path = require('path');
61
61
  const querystring = require('querystring');
62
- const { loadAuthData, triggerLogin, resolveBaseUrl, httpPost, httpGet, requestWithAutoLogin } = require('../core/utils');
62
+ const { httpPost, httpGet, requestWithAutoLogin } = require('../core/utils');
63
+ const { createAuthRef } = require('../core/yida-client');
63
64
  const { CliError } = require('../core/cli-error');
64
65
  const { t } = require('../core/i18n');
65
66
  const { safeParseJson } = require('../core/safe-json');
66
67
  const { buildYidaI18n, normalizeYidaLocale, resolveContentLocale } = require('../core/yida-i18n');
67
68
  const { banner, step, label, success, fail, warn, info, error, result, usage, hint, listItem } = require('../core/chalk');
68
- const { parseOpenOption, withBrowserHandoff } = require('../core/browser-handoff');
69
+ const { parseOpenOption: parseBrowserOpenOption, withBrowserHandoff } = require('../core/browser-handoff');
70
+ const {
71
+ assertLegacyDirectWriteAllowed,
72
+ extractLegacyGuardArgs,
73
+ } = require('../core/legacy-schema-guard');
69
74
  const { default: babelTransform } = require('../core/babel-transform');
70
75
  const { normalizeFormulaFieldRefs } = require('../formula/evaluate');
71
76
  const { createParseArgs } = require('./create-form/args');
72
77
  const { createDefinitionReaders } = require('./create-form/definition-reader');
73
78
  const { dispatchCreateFormCommand } = require('./create-form/commands');
74
- const { buildApiPath } = require('./create-form/schema-builder');
79
+ const { buildApiPath } = require('./create-form/api-path');
75
80
  const { deepMerge, splitJsonPointer } = require('./create-form/schema-patch');
76
81
  const { FORM_RULES_BLOCK_END, FORM_RULES_BLOCK_START } = require('./create-form/rule-builder');
77
82
  const { SMART_VALIDATION_BLOCK_END, SMART_VALIDATION_BLOCK_START } = require('./create-form/validation-builder');
78
83
  const { createFieldNormalizers } = require('./create-form/field-normalizers');
79
84
 
85
+ function parseOpenOption(inputArgs) {
86
+ const openOption = parseBrowserOpenOption(inputArgs);
87
+ const guardSplit = extractLegacyGuardArgs(openOption.args);
88
+ return Object.assign({}, openOption, {
89
+ args: guardSplit.args,
90
+ legacyGuardOptions: guardSplit.guardOptions,
91
+ });
92
+ }
93
+
80
94
  // ── 选项类字段类型 ───────────────────────────────────
81
95
  const OPTION_FIELD_TYPES = ['RadioField', 'SelectField', 'CheckboxField', 'MultiSelectField'];
82
96
 
@@ -3982,27 +3996,30 @@ function applyChangesToSchema(schema, changes) {
3982
3996
 
3983
3997
  // ── 发送 POST 请求(支持 302 自动重登录) ────────────
3984
3998
 
3985
- function sendPostRequest(baseUrl, requestPath, extraParams, formUuid) {
3986
- const postData = querystring.stringify(extraParams);
3999
+ function sendPostRequest(baseUrl, requestPath, extraParams, formUuid, authRef) {
4000
+ const authParams = authRef && authRef.csrfToken ? { _csrf_token: authRef.csrfToken } : {};
4001
+ const postData = querystring.stringify(Object.assign(authParams, extraParams));
3987
4002
  const referer = formUuid
3988
4003
  ? `${baseUrl}/alibaba/web/${extraParams.appType || ''}/design/pageDesigner?formUuid=${formUuid}`
3989
4004
  : baseUrl + '/';
3990
- return httpPost(baseUrl, requestPath, postData, { referer });
4005
+ return httpPost(baseUrl, requestPath, postData, authRef && authRef.cookies, { referer });
3991
4006
  }
3992
4007
 
3993
4008
  // ── 发送 updateFormConfig 请求 ───────────────────────
3994
4009
 
3995
- function sendUpdateConfigRequest(baseUrl, appType, formUuid, version, value) {
3996
- const postData = querystring.stringify({
4010
+ function sendUpdateConfigRequest(baseUrl, appType, formUuid, version, value, authRef) {
4011
+ const authParams = authRef && authRef.csrfToken ? { _csrf_token: authRef.csrfToken } : {};
4012
+ const postData = querystring.stringify(Object.assign(authParams, {
3997
4013
  formUuid: formUuid,
3998
4014
  version: version,
3999
4015
  configType: 'MINI_RESOURCE',
4000
4016
  value: value,
4001
- });
4017
+ }));
4002
4018
  return httpPost(
4003
4019
  baseUrl,
4004
4020
  `/dingtalk/web/${appType}/query/formdesign/updateFormConfig.json`,
4005
- postData
4021
+ postData,
4022
+ authRef && authRef.cookies
4006
4023
  );
4007
4024
  }
4008
4025
 
@@ -4013,6 +4030,33 @@ function resolveCorpId(authData) {
4013
4030
  return '';
4014
4031
  }
4015
4032
 
4033
+ function extractSchemaServerRevision(schemaResult) {
4034
+ const content = schemaResult && schemaResult.content && typeof schemaResult.content === 'object'
4035
+ ? schemaResult.content
4036
+ : null;
4037
+ const candidates = [
4038
+ schemaResult && schemaResult.gmtModified,
4039
+ schemaResult && schemaResult.serverRevision,
4040
+ content && content.gmtModified,
4041
+ content && content.serverRevision,
4042
+ content && content.version,
4043
+ schemaResult && schemaResult.version,
4044
+ ];
4045
+ for (const candidate of candidates) {
4046
+ if (candidate !== undefined && candidate !== null && String(candidate).trim() !== '') {
4047
+ return candidate;
4048
+ }
4049
+ }
4050
+ return undefined;
4051
+ }
4052
+
4053
+ function requireSchemaServerRevision(serverRevision, details) {
4054
+ if (serverRevision === undefined || serverRevision === null || String(serverRevision).trim() === '') {
4055
+ throwCreateFormError('Missing form schema server revision from exact readback.', 'CREATE_FORM_SCHEMA_REVISION_INVALID', details);
4056
+ }
4057
+ return serverRevision;
4058
+ }
4059
+
4016
4060
  // ── 保存 Schema 并更新表单配置(create/update 共用)──
4017
4061
  //
4018
4062
  // 封装了 saveFormSchema + updateFormConfig 两步,以及各自的 302 自动重登录重试。
@@ -4027,6 +4071,7 @@ async function saveSchemaAndUpdateConfig(authRef, appType, formUuid, schema, ver
4027
4071
  info(t('create_form.formula_prefix_fixed', fixedRefs));
4028
4072
  }
4029
4073
  ensureDividerThemeAction(schema);
4074
+ const serverRevision = requireSchemaServerRevision(version, { appType, formUuid });
4030
4075
 
4031
4076
  step(saveStep, t('create_form.step_save_schema', saveStep));
4032
4077
  info(t('create_form.sending_save'));
@@ -4035,8 +4080,9 @@ async function saveSchemaAndUpdateConfig(authRef, appType, formUuid, schema, ver
4035
4080
  return sendPostRequest(
4036
4081
  auth.baseUrl,
4037
4082
  buildApiPath(appType, 'saveFormSchema', { prefix: '_view' }),
4038
- { appType: appType, formUuid: formUuid, content: JSON.stringify(schema), schemaVersion: 'V5', prefix: '_view' },
4039
- formUuid
4083
+ { appType: appType, formUuid: formUuid, content: JSON.stringify(schema), schemaVersion: 'V5', prefix: '_view', gmtModified: serverRevision },
4084
+ formUuid,
4085
+ auth
4040
4086
  );
4041
4087
  }, authRef);
4042
4088
 
@@ -4063,7 +4109,7 @@ async function saveSchemaAndUpdateConfig(authRef, appType, formUuid, schema, ver
4063
4109
  info(t('create_form.sending_config'));
4064
4110
 
4065
4111
  const configResult = await requestWithAutoLogin(function (auth) {
4066
- return sendUpdateConfigRequest(auth.baseUrl, appType, formUuid, version || 1, 0);
4112
+ return sendUpdateConfigRequest(auth.baseUrl, appType, formUuid, version || 1, 0, auth);
4067
4113
  }, authRef);
4068
4114
 
4069
4115
  return { saveResult: saveResult, configResult: configResult };
@@ -4094,7 +4140,9 @@ async function mainCreate(parsedArgs, authRef) {
4094
4140
  return sendPostRequest(
4095
4141
  auth.baseUrl,
4096
4142
  buildApiPath(appType, 'saveFormSchemaInfo'),
4097
- { formType: 'receipt', title: JSON.stringify(i18n(formTitle)) }
4143
+ { formType: 'receipt', title: JSON.stringify(i18n(formTitle)) },
4144
+ undefined,
4145
+ auth
4098
4146
  );
4099
4147
  }, authRef);
4100
4148
 
@@ -4110,6 +4158,14 @@ async function mainCreate(parsedArgs, authRef) {
4110
4158
 
4111
4159
  const formUuid = createResult.content.formUuid || createResult.content;
4112
4160
  success(t('create_form.blank_created', formUuid));
4161
+ const shellSchemaResult = await requestWithAutoLogin(function (auth) {
4162
+ return sendGetRequest(
4163
+ auth.baseUrl,
4164
+ buildApiPath(appType, 'getFormSchema', { prefix: '_view', namespace: 'alibaba' }),
4165
+ { formUuid: formUuid, schemaVersion: 'V5' }
4166
+ );
4167
+ }, authRef);
4168
+ const serverRevision = extractSchemaServerRevision(shellSchemaResult);
4113
4169
 
4114
4170
  // Step 4 & 5: 生成 Schema 并保存,然后更新表单配置
4115
4171
  const corpId = resolveCorpId(authRef.authData);
@@ -4125,7 +4181,7 @@ async function mainCreate(parsedArgs, authRef) {
4125
4181
  const appliedValidations = applySmartValidations(schema, createValidationRules);
4126
4182
  info('已为创建表单写入 ' + appliedValidations.appliedRules.length + ' 条字段校验');
4127
4183
  }
4128
- const { configResult } = await saveSchemaAndUpdateConfig(authRef, appType, formUuid, schema, 1, 4);
4184
+ const { configResult } = await saveSchemaAndUpdateConfig(authRef, appType, formUuid, schema, serverRevision, 4);
4129
4185
 
4130
4186
  // 输出结果
4131
4187
  const formUrl = authRef.baseUrl + '/' + appType + '/workbench/' + formUuid;
@@ -4156,6 +4212,70 @@ async function mainCreate(parsedArgs, authRef) {
4156
4212
  }
4157
4213
  }
4158
4214
 
4215
+ async function createFormForLegacyProcess(context, input) {
4216
+ const authRef = context && context.authRef ? context.authRef : context;
4217
+ const parsedArgs = {
4218
+ mode: 'create',
4219
+ appType: input.appType,
4220
+ formTitle: input.formTitle,
4221
+ fieldsJsonOrFile: input.fieldsJsonFile,
4222
+ layout: input.layout || 'single',
4223
+ theme: input.theme || 'default',
4224
+ labelAlign: input.labelAlign || 'top',
4225
+ contentLocale: input.contentLocale || null,
4226
+ browserOpenMode: 'off',
4227
+ };
4228
+
4229
+ const { appType, formTitle, fieldsJsonOrFile, layout, theme, labelAlign } = parsedArgs;
4230
+ const { fields, validations } = readFieldsDefinition(fieldsJsonOrFile);
4231
+ const fieldCount = countDataFieldDefinitions(fields);
4232
+ const createResult = await requestWithAutoLogin(function (auth) {
4233
+ return sendPostRequest(
4234
+ auth.baseUrl,
4235
+ buildApiPath(appType, 'saveFormSchemaInfo'),
4236
+ { formType: 'receipt', title: JSON.stringify(i18n(formTitle)) },
4237
+ undefined,
4238
+ auth
4239
+ );
4240
+ }, authRef);
4241
+
4242
+ if (!createResult || !createResult.success || !createResult.content) {
4243
+ const errorMsg = createResult ? createResult.errorMsg || t('common.unknown_error') : t('common.request_failed');
4244
+ throwCreateFormError(errorMsg, 'CREATE_FORM_CREATE_BLANK_FAILED', {
4245
+ appType,
4246
+ result: createResult,
4247
+ });
4248
+ }
4249
+
4250
+ const formUuid = createResult.content.formUuid || createResult.content;
4251
+ const shellSchemaResult = await requestWithAutoLogin(function (auth) {
4252
+ return sendGetRequest(
4253
+ auth.baseUrl,
4254
+ buildApiPath(appType, 'getFormSchema', { prefix: '_view', namespace: 'alibaba' }),
4255
+ { formUuid: formUuid, schemaVersion: 'V5' }
4256
+ );
4257
+ }, authRef);
4258
+ const serverRevision = extractSchemaServerRevision(shellSchemaResult);
4259
+ const corpId = resolveCorpId(authRef.authData || authRef.cookieData || authRef);
4260
+ const schema = buildFormSchema(formTitle, fields, formUuid, corpId, appType, layout, theme, labelAlign);
4261
+ const createValidationRules = collectSmartValidationRulesFromFields(fields).concat(validations || []);
4262
+ if (createValidationRules.length > 0) {
4263
+ applySmartValidations(schema, createValidationRules);
4264
+ }
4265
+ const { saveResult, configResult } = await saveSchemaAndUpdateConfig(authRef, appType, formUuid, schema, serverRevision, 4);
4266
+ return {
4267
+ success: true,
4268
+ appType,
4269
+ formUuid,
4270
+ formTitle,
4271
+ fieldCount,
4272
+ createResult,
4273
+ saveResult,
4274
+ configResult,
4275
+ url: authRef.baseUrl + '/' + appType + '/workbench/' + formUuid,
4276
+ };
4277
+ }
4278
+
4159
4279
  // ── 为 SerialNumberField 补全 formula(递归处理子表)──
4160
4280
  //
4161
4281
  // 遍历字段列表,对每个 SerialNumberField:
@@ -4232,12 +4352,7 @@ async function mainAddOption(parsedArgs, authRef) {
4232
4352
  }
4233
4353
 
4234
4354
  let schema;
4235
- let version = 1;
4236
- if (schemaResult.content && typeof schemaResult.content === 'object' && schemaResult.content.version !== undefined) {
4237
- version = schemaResult.content.version;
4238
- } else if (schemaResult.version !== undefined) {
4239
- version = schemaResult.version;
4240
- }
4355
+ const version = extractSchemaServerRevision(schemaResult);
4241
4356
  if (schemaResult.content) {
4242
4357
  schema = typeof schemaResult.content === 'string' ? JSON.parse(schemaResult.content) : schemaResult.content;
4243
4358
  } else if (schemaResult.pages) {
@@ -4399,12 +4514,7 @@ async function mainBindDataSource(parsedArgs, authRef) {
4399
4514
  }
4400
4515
 
4401
4516
  let schema;
4402
- let version = 1;
4403
- if (schemaResult.content && typeof schemaResult.content === 'object' && schemaResult.content.version !== undefined) {
4404
- version = schemaResult.content.version;
4405
- } else if (schemaResult.version !== undefined) {
4406
- version = schemaResult.version;
4407
- }
4517
+ const version = extractSchemaServerRevision(schemaResult);
4408
4518
  if (schemaResult.content) {
4409
4519
  schema = typeof schemaResult.content === 'string' ? JSON.parse(schemaResult.content) : schemaResult.content;
4410
4520
  } else if (schemaResult.pages) {
@@ -4545,12 +4655,7 @@ async function mainRule(parsedArgs, authRef) {
4545
4655
  }
4546
4656
 
4547
4657
  let schema;
4548
- let version = 1;
4549
- if (schemaResult.content && typeof schemaResult.content === 'object' && schemaResult.content.version !== undefined) {
4550
- version = schemaResult.content.version;
4551
- } else if (schemaResult.version !== undefined) {
4552
- version = schemaResult.version;
4553
- }
4658
+ const version = extractSchemaServerRevision(schemaResult);
4554
4659
 
4555
4660
  if (schemaResult.content) {
4556
4661
  schema = typeof schemaResult.content === 'string' ? JSON.parse(schemaResult.content) : schemaResult.content;
@@ -4672,12 +4777,7 @@ async function mainPatch(parsedArgs, authRef) {
4672
4777
  }
4673
4778
 
4674
4779
  let schema;
4675
- let version = 1;
4676
- if (schemaResult.content && typeof schemaResult.content === 'object' && schemaResult.content.version !== undefined) {
4677
- version = schemaResult.content.version;
4678
- } else if (schemaResult.version !== undefined) {
4679
- version = schemaResult.version;
4680
- }
4780
+ const version = extractSchemaServerRevision(schemaResult);
4681
4781
 
4682
4782
  if (schemaResult.content) {
4683
4783
  schema = typeof schemaResult.content === 'string' ? JSON.parse(schemaResult.content) : schemaResult.content;
@@ -4784,12 +4884,7 @@ async function mainValidation(parsedArgs, authRef) {
4784
4884
  }
4785
4885
 
4786
4886
  let schema;
4787
- let version = 1;
4788
- if (schemaResult.content && typeof schemaResult.content === 'object' && schemaResult.content.version !== undefined) {
4789
- version = schemaResult.content.version;
4790
- } else if (schemaResult.version !== undefined) {
4791
- version = schemaResult.version;
4792
- }
4887
+ const version = extractSchemaServerRevision(schemaResult);
4793
4888
 
4794
4889
  if (schemaResult.content) {
4795
4890
  schema = typeof schemaResult.content === 'string' ? JSON.parse(schemaResult.content) : schemaResult.content;
@@ -4913,13 +5008,7 @@ async function mainUpdate(parsedArgs, authRef) {
4913
5008
 
4914
5009
  // 从返回结果中提取 schema 内容和版本号
4915
5010
  let schema;
4916
- let version = 1;
4917
-
4918
- if (schemaResult.content && typeof schemaResult.content === 'object' && schemaResult.content.version !== undefined) {
4919
- version = schemaResult.content.version;
4920
- } else if (schemaResult.version !== undefined) {
4921
- version = schemaResult.version;
4922
- }
5011
+ const version = extractSchemaServerRevision(schemaResult);
4923
5012
 
4924
5013
  if (schemaResult.content) {
4925
5014
  schema = typeof schemaResult.content === 'string' ? JSON.parse(schemaResult.content) : schemaResult.content;
@@ -5057,24 +5146,21 @@ async function mainUpdate(parsedArgs, authRef) {
5057
5146
 
5058
5147
  async function run(args) {
5059
5148
  const parsedArgs = parseArgs(args);
5149
+ if (parsedArgs.help) {
5150
+ return parsedArgs;
5151
+ }
5152
+ assertLegacyDirectWriteAllowed({
5153
+ command: `create-form ${parsedArgs.mode}`,
5154
+ resourceType: 'form',
5155
+ action: parsedArgs.mode === 'create' ? 'create' : 'update',
5156
+ appType: parsedArgs.appType,
5157
+ formUuid: parsedArgs.formUuid,
5158
+ }, { guardOptions: parsedArgs.legacyGuardOptions });
5060
5159
 
5061
5160
  step(1, t('common.step_login', 1));
5062
- let authData = loadAuthData();
5063
- if (!authData) {
5064
- warn(t('common.login_no_cache'));
5065
- authData = triggerLogin();
5066
- }
5067
- const baseUrl = resolveBaseUrl(authData);
5068
- const authRef = {
5069
- baseUrl,
5070
- authData,
5071
- authMode: authData.auth_mode || '',
5072
- authSource: authData.auth_source || '',
5073
- corpId: authData.corp_id || '',
5074
- userId: authData.user_id || '',
5075
- };
5076
- success(t('common.login_ready', baseUrl));
5077
- label('Locale:', resolveContentLocale({ locale: parsedArgs.contentLocale, baseUrl: baseUrl }));
5161
+ const authRef = createAuthRef();
5162
+ success(t('common.login_ready', authRef.baseUrl));
5163
+ label('Locale:', resolveContentLocale({ locale: parsedArgs.contentLocale, baseUrl: authRef.baseUrl }));
5078
5164
 
5079
5165
  return dispatchCreateFormCommand(
5080
5166
  parsedArgs,
@@ -5099,6 +5185,7 @@ if (require.main === module) {
5099
5185
  }
5100
5186
 
5101
5187
  module.exports = {
5188
+ createFormForLegacyProcess,
5102
5189
  run,
5103
5190
  parseArgs,
5104
5191
  _private: {
@@ -15,21 +15,40 @@ const { createAuthRef } = require('../core/yida-client');
15
15
  const { t } = require('../core/i18n');
16
16
  const { buildYidaI18n, buildYidaTitleI18n, normalizeYidaLocale, resolveContentLocale } = require('../core/yida-i18n');
17
17
  const { parseOpenOption, withBrowserHandoff } = require('../core/browser-handoff');
18
+ const { throwCommandError } = require('../core/command-errors');
19
+ const {
20
+ assertLegacyDirectWriteAllowed,
21
+ extractLegacyGuardArgs,
22
+ } = require('../core/legacy-schema-guard');
18
23
 
19
24
  function parseArgs(args) {
20
25
  const openOption = parseOpenOption(args);
26
+ const guardSplit = extractLegacyGuardArgs(openOption.args);
21
27
  const filteredArgs = [];
22
28
  let mode = 'default';
23
29
  let locale = null;
24
30
 
25
- for (let i = 0; i < openOption.args.length; i++) {
26
- const arg = openOption.args[i];
27
- if (arg === '--mode' && openOption.args[i + 1]) {
28
- mode = openOption.args[++i];
31
+ if (guardSplit.args.includes('--help') || guardSplit.args.includes('-h')) {
32
+ return {
33
+ args: [],
34
+ appType: null,
35
+ pageName: null,
36
+ mode,
37
+ locale,
38
+ help: true,
39
+ openMode: openOption.mode,
40
+ legacyGuardOptions: guardSplit.guardOptions,
41
+ };
42
+ }
43
+
44
+ for (let i = 0; i < guardSplit.args.length; i++) {
45
+ const arg = guardSplit.args[i];
46
+ if (arg === '--mode' && guardSplit.args[i + 1]) {
47
+ mode = guardSplit.args[++i];
29
48
  continue;
30
49
  }
31
- if ((arg === '--locale' || arg === '--content-locale' || arg === '--lang') && openOption.args[i + 1]) {
32
- locale = openOption.args[++i];
50
+ if ((arg === '--locale' || arg === '--content-locale' || arg === '--lang') && guardSplit.args[i + 1]) {
51
+ locale = guardSplit.args[++i];
33
52
  if (!normalizeYidaLocale(locale)) {
34
53
  throw new Error(`Unsupported locale: ${locale}`);
35
54
  }
@@ -45,10 +64,11 @@ function parseArgs(args) {
45
64
  mode,
46
65
  locale,
47
66
  openMode: openOption.mode,
67
+ legacyGuardOptions: guardSplit.guardOptions,
48
68
  };
49
69
  }
50
70
 
51
- function buildPageInfoPostData(formUuid, pageName, isRenderNav) {
71
+ function buildPageInfoPostData(formUuid, pageName, isRenderNav, csrfToken) {
52
72
  const titleJson = JSON.stringify(buildYidaTitleI18n(pageName, {
53
73
  en_US: pageName,
54
74
  ja_JP: pageName,
@@ -56,6 +76,7 @@ function buildPageInfoPostData(formUuid, pageName, isRenderNav) {
56
76
 
57
77
  return querystring.stringify({
58
78
  _api: 'Form.updateFormSchemaInfo',
79
+ _csrf_token: csrfToken,
59
80
  _locale_time_zone_offset: '28800000',
60
81
  formUuid,
61
82
  serialSwitch: 'n',
@@ -89,7 +110,8 @@ async function configureDashboardMode(authRef, appType, pageId, pageName) {
89
110
  return httpPost(
90
111
  auth.baseUrl,
91
112
  `/dingtalk/web/${appType}/query/formdesign/updateFormSchemaInfo.json`,
92
- buildPageInfoPostData(pageId, pageName, false)
113
+ buildPageInfoPostData(pageId, pageName, false, auth.csrfToken),
114
+ auth.cookies
93
115
  );
94
116
  }, authRef);
95
117
  }
@@ -103,6 +125,13 @@ async function run(args) {
103
125
  chalkError(err.message, { hint: t('create_page.usage') });
104
126
  }
105
127
 
128
+ if (options.help) {
129
+ const { usage, hint } = require('../core/chalk');
130
+ usage(t('create_page.usage'), t('create_page.example'));
131
+ hint(t('create_page.mode_hint'));
132
+ return options;
133
+ }
134
+
106
135
  if (options.args.length < 2) {
107
136
  const { error: chalkError } = require('../core/chalk');
108
137
  chalkError(t('create_page.usage'), { hint: t('create_page.example') });
@@ -111,6 +140,12 @@ async function run(args) {
111
140
  const appType = options.appType;
112
141
  const pageName = options.pageName;
113
142
  const mode = options.mode;
143
+ assertLegacyDirectWriteAllowed({
144
+ command: 'create-page',
145
+ resourceType: 'page',
146
+ action: 'create',
147
+ appType,
148
+ }, { guardOptions: options.legacyGuardOptions });
114
149
  if (mode !== 'default' && mode !== 'dashboard') {
115
150
  const { error: chalkError } = require('../core/chalk');
116
151
  chalkError(t('create_page.err_mode_invalid', mode), { hint: t('create_page.mode_hint') });
@@ -137,13 +172,15 @@ async function run(args) {
137
172
 
138
173
  const response = await requestWithAutoLogin((auth) => {
139
174
  const postData = querystring.stringify({
175
+ _csrf_token: auth.csrfToken,
140
176
  formType: 'display',
141
177
  title: JSON.stringify(buildYidaI18n(pageName, { en_US: pageName, ja_JP: pageName })),
142
178
  });
143
179
  return httpPost(
144
180
  auth.baseUrl,
145
181
  `/dingtalk/web/${appType}/query/formdesign/saveFormSchemaInfo.json`,
146
- postData
182
+ postData,
183
+ auth.cookies
147
184
  );
148
185
  }, authRef);
149
186
 
@@ -181,7 +218,7 @@ async function run(args) {
181
218
  const errorMsg = response ? response.errorMsg || response.error || t('common.unknown_error') : t('common.request_failed');
182
219
  chalkResult(false, t('create_page.failed', errorMsg));
183
220
  console.log(JSON.stringify({ success: false, error: errorMsg }));
184
- process.exit(1);
221
+ throwCommandError(errorMsg);
185
222
  }
186
223
  }
187
224
 
@@ -10,6 +10,7 @@ const { runLintCheck } = require('./page-linter');
10
10
  const { compileSource } = require('./page-compiler');
11
11
  const { compileCanvasLocal } = require('./canvas-compile');
12
12
  const { buildPageFile, isAuthoringPath } = require('./page-compat');
13
+ const { throwCommandError } = require('../core/command-errors');
13
14
  const {
14
15
  buildTemplateVariablesFromIr,
15
16
  escapeJsStringValue,
@@ -459,6 +460,21 @@ function reportMaterialStatus(precheck) {
459
460
  (precheck.materialGaps || []).forEach((g) => hint(' · ' + g));
460
461
  }
461
462
 
463
+ function reportDomainFidelity(ir) {
464
+ const fidelity = ir && ir.domainFidelity;
465
+ if (!fidelity || fidelity.status === 'domain-ready') {
466
+ return;
467
+ }
468
+ warn(`业务定制度:${fidelity.status}(score ${fidelity.score})——当前页面仍带有 sample fallback,只能作为草稿或参考骨架。`);
469
+ if (fidelity.sampleFallbacks && fidelity.sampleFallbacks.length) {
470
+ hint(' · 仍使用 sample 默认内容:' + fidelity.sampleFallbacks.join(', '));
471
+ }
472
+ (fidelity.missing || []).forEach((item) => hint(' · 缺少:' + item));
473
+ if (fidelity.guidance) {
474
+ hint(' · ' + fidelity.guidance);
475
+ }
476
+ }
477
+
462
478
  function reportNavigationConfig(ir) {
463
479
  const blueprint = ir && ir.appBlueprint;
464
480
  if (!blueprint || blueprint.renderNav !== false) {
@@ -548,6 +564,7 @@ async function run(args) {
548
564
  success(t('generate_page.done', outputPath));
549
565
  hint(t('generate_page.hint'));
550
566
  reportMaterialStatus(materialPrecheck);
567
+ reportDomainFidelity(ir);
551
568
  reportNavigationConfig(ir);
552
569
 
553
570
  if (mode === 'canvas') {
@@ -563,6 +580,7 @@ async function run(args) {
563
580
  ['Mode', 'canvas'],
564
581
  ['Scene', ir.scene],
565
582
  ['Material status', ir.assets && ir.assets.materialStatus],
583
+ ['Domain fidelity', ir.domainFidelity ? ir.domainFidelity.status : 'n/a'],
566
584
  ['Research level', ir.researchLevel],
567
585
  ['Archetype', ir.archetype],
568
586
  ['Visual profile', ir.visualProfile && ir.visualProfile.name],
@@ -591,7 +609,7 @@ async function run(args) {
591
609
 
592
610
  const lintPassed = runLintCheck(checkSource, checkPath);
593
611
  if (!lintPassed) {
594
- process.exit(1);
612
+ throwCommandError(t('check_page.failed'));
595
613
  }
596
614
 
597
615
  if (options.compile || spec.compile === true) {
@@ -602,6 +620,7 @@ async function run(args) {
602
620
  ['Mode', 'native'],
603
621
  ['Scene', ir.scene],
604
622
  ['Material status', ir.assets && ir.assets.materialStatus],
623
+ ['Domain fidelity', ir.domainFidelity ? ir.domainFidelity.status : 'n/a'],
605
624
  ['Research level', ir.researchLevel],
606
625
  ['Archetype', ir.archetype],
607
626
  ['Visual profile', ir.visualProfile && ir.visualProfile.name],
@@ -20,6 +20,7 @@ const {
20
20
  } = require('../core/utils');
21
21
  const { t } = require('../core/i18n');
22
22
  const { banner, step, label, info, success, error, result } = require('../core/chalk');
23
+ const { throwCommandError } = require('../core/command-errors');
23
24
 
24
25
  // 常用配置字段白名单(人读摘要),--json 会输出完整对象
25
26
  const SUMMARY_FIELDS = [
@@ -115,7 +116,7 @@ async function run(args) {
115
116
  message: (resp && resp.errorMsg) || t('get_form_config.read_failed_msg'),
116
117
  errorCode: resp && resp.errorCode,
117
118
  }, null, 2));
118
- process.exit(1);
119
+ throwCommandError(errorMsg);
119
120
  }
120
121
 
121
122
  const cfg = resp.content || resp.result || resp.data || {};