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
@@ -0,0 +1,182 @@
1
+ 'use strict';
2
+
3
+ const { createYidaClient } = require('../../core/yida-client');
4
+ const {
5
+ dispatchRemotePrimitive,
6
+ hasRemoteDispatchBoundary,
7
+ } = require('../../schema/remote-dispatch-boundary');
8
+
9
+ const MODE_READ_OPERATION = 'FormProcBinding.getBindingByFormUuid';
10
+ const MODE_CONVERSION_OPERATION = 'Nav.transformForm';
11
+
12
+ class FormModeServiceError extends Error {
13
+ constructor(code, message, details) {
14
+ super(message);
15
+ this.name = 'FormModeServiceError';
16
+ this.code = code;
17
+ this.details = details;
18
+ }
19
+ }
20
+
21
+ function queryFormProcessBinding(authRef, appType, formUuid, options = {}) {
22
+ const requestPath = '/' + appType + '/query/formProcBinding/getBindingByFormUuid.json';
23
+ const client = createYidaClient({ authRef });
24
+ const method = options.oneShot === true ? 'getOnce' : 'get';
25
+ return client[method](requestPath, auth => ({
26
+ _api: 'nattyFetch',
27
+ _mock: 'false',
28
+ _csrf_token: auth.csrfToken,
29
+ formUuid,
30
+ _stamp: Date.now(),
31
+ }));
32
+ }
33
+
34
+ function switchFormType(authRef, appType, formUuid, options = {}) {
35
+ const requestPath = '/' + appType + '/query/formdesign/switchFormType.json'
36
+ + '?_api=Nav.transformForm&_mock=false&_stamp=' + Date.now();
37
+ const client = createYidaClient({ authRef });
38
+ const method = options.oneShot === true ? 'postFormOnce' : 'postForm';
39
+ return client[method](requestPath, auth => ({
40
+ _csrf_token: auth.csrfToken,
41
+ _locale_time_zone_offset: '28800000',
42
+ toFormType: 'process',
43
+ formUuid,
44
+ }));
45
+ }
46
+
47
+ async function readFormMode(context, input) {
48
+ const authRef = context && context.authRef ? context.authRef : context;
49
+ const appType = input && input.appType;
50
+ const result = await dispatchRemotePrimitive(context, () => queryFormProcessBinding(
51
+ authRef,
52
+ appType,
53
+ input && input.formUuid,
54
+ { oneShot: hasRemoteDispatchBoundary(context) }
55
+ ));
56
+ const binding = normalizeFormProcessBinding(result, appType, input && input.formUuid);
57
+ if (!binding) {
58
+ throw modeError('FORM_MODE_READ_FAILED', MODE_READ_OPERATION, {
59
+ result: sanitizeModeResult(result),
60
+ });
61
+ }
62
+ if (binding.processCode) {
63
+ const observed = {
64
+ mode: 'process',
65
+ processCode: binding.processCode,
66
+ };
67
+ if (binding.processId) {
68
+ observed.processId = binding.processId;
69
+ }
70
+ return observed;
71
+ }
72
+ return { mode: 'receipt' };
73
+ }
74
+
75
+ async function convertFormToProcess(context, input) {
76
+ const authRef = context && context.authRef ? context.authRef : context;
77
+ const result = await dispatchRemotePrimitive(context, () => switchFormType(
78
+ authRef,
79
+ input && input.appType,
80
+ input && input.formUuid,
81
+ { oneShot: hasRemoteDispatchBoundary(context) }
82
+ ));
83
+ if (!result || result.success !== true) {
84
+ throw modeError('FORM_MODE_CONVERSION_FAILED', MODE_CONVERSION_OPERATION);
85
+ }
86
+ return result;
87
+ }
88
+
89
+ async function getProcessCodeFromAppParam(authRef, appType, formUuid) {
90
+ // Keep the legacy helper name for callers; the implementation now uses the exact form binding endpoint.
91
+ return getProcessCodeFromFormBinding(authRef, appType, formUuid);
92
+ }
93
+
94
+ async function getProcessCodeFromFormBinding(authRef, appType, formUuid) {
95
+ const result = await queryFormProcessBinding(authRef, appType, formUuid);
96
+ const binding = normalizeFormProcessBinding(result, appType, formUuid);
97
+ return binding && binding.processCode || null;
98
+ }
99
+
100
+ function normalizeFormProcessBinding(result, expectedAppType, expectedFormUuid) {
101
+ const content = result && result.success === true && result.content;
102
+ if (!content || typeof content !== 'object' || Array.isArray(content)) {
103
+ return null;
104
+ }
105
+ if (
106
+ isNonEmptyString(content.appType) &&
107
+ content.appType !== expectedAppType
108
+ ) {
109
+ return null;
110
+ }
111
+ if (
112
+ isNonEmptyString(content.formUuid) &&
113
+ content.formUuid !== expectedFormUuid
114
+ ) {
115
+ return null;
116
+ }
117
+ if (!Object.prototype.hasOwnProperty.call(content, 'procCode')) {
118
+ return { processCode: '' };
119
+ }
120
+ if (typeof content.procCode !== 'string') {
121
+ return null;
122
+ }
123
+ const processId = normalizeIdentifier(content.procId);
124
+ return {
125
+ processCode: content.procCode.trim(),
126
+ ...(processId ? { processId } : {}),
127
+ };
128
+ }
129
+
130
+ function normalizeIdentifier(value) {
131
+ if (typeof value === 'number' && Number.isFinite(value)) {
132
+ return String(value);
133
+ }
134
+ return isNonEmptyString(value) ? value.trim() : null;
135
+ }
136
+
137
+ function modeError(code, operation, details = {}) {
138
+ return new FormModeServiceError(code, 'Form mode operation failed.', {
139
+ operation,
140
+ ...details,
141
+ });
142
+ }
143
+
144
+ function sanitizeModeResult(result) {
145
+ if (!result || typeof result !== 'object') {
146
+ return result || null;
147
+ }
148
+ const sanitized = {};
149
+ [
150
+ 'success',
151
+ 'errorMsg',
152
+ 'errorCode',
153
+ 'code',
154
+ 'message',
155
+ '__httpStatus',
156
+ '__needLogin',
157
+ '__csrfExpired',
158
+ '__nonJsonResponse',
159
+ '__emptyBody',
160
+ ].forEach((key) => {
161
+ if (Object.prototype.hasOwnProperty.call(result, key)) {
162
+ sanitized[key] = result[key];
163
+ }
164
+ });
165
+ return sanitized;
166
+ }
167
+
168
+ function isNonEmptyString(value) {
169
+ return typeof value === 'string' && value.trim() !== '';
170
+ }
171
+
172
+ module.exports = {
173
+ FormModeServiceError,
174
+ MODE_CONVERSION_OPERATION,
175
+ MODE_READ_OPERATION,
176
+ convertFormToProcess,
177
+ getProcessCodeFromAppParam,
178
+ getProcessCodeFromFormBinding,
179
+ queryFormProcessBinding,
180
+ readFormMode,
181
+ switchFormType,
182
+ };
@@ -0,0 +1,333 @@
1
+ 'use strict';
2
+
3
+ const { createFormServiceError } = require('./form-schema-reader');
4
+
5
+ const MANAGED_PROP_KEYS = Object.freeze([
6
+ 'associationForm',
7
+ 'dataSource',
8
+ 'defaultDataSource',
9
+ 'label',
10
+ 'required',
11
+ 'validation',
12
+ ]);
13
+
14
+ function patchManagedFormSchema(currentSchemaResult, compiled, options = {}) {
15
+ const schema = clonePlain(extractSchema(currentSchemaResult));
16
+ const compiledSchema = compiled && compiled.schema || {};
17
+ const currentContainer = findFirstComponent(schema, 'FormContainer');
18
+ const compiledContainer = findFirstComponent(compiledSchema, 'FormContainer');
19
+ if (!currentContainer || !compiledContainer) {
20
+ throw createFormServiceError(
21
+ 'form Schema does not contain FormContainer',
22
+ 'FORM_SCHEMA_PATCH_INVALID'
23
+ );
24
+ }
25
+
26
+ const existingBindings = normalizeFieldBindings(options.existingBindings);
27
+ const desiredBindings = normalizeFieldBindings(compiled && compiled.fieldBindings);
28
+ const removedSemanticPath = Object.keys(existingBindings).find(semanticPath => !desiredBindings[semanticPath]);
29
+ if (removedSemanticPath) {
30
+ throw createFormServiceError(
31
+ 'managed field removal is not supported',
32
+ 'FORM_SCHEMA_DESTRUCTIVE_CHANGE_UNSUPPORTED',
33
+ { semanticPath: removedSemanticPath, operation: 'remove' }
34
+ );
35
+ }
36
+
37
+ const currentByFieldId = indexComponentsByFieldId(schema);
38
+ const compiledByFieldId = indexComponentsByFieldId(compiledSchema);
39
+ patchFormTitle(currentContainer, compiledContainer);
40
+
41
+ for (const semanticPath of Object.keys(desiredBindings).sort(compareCodePoints)) {
42
+ const fieldId = desiredBindings[semanticPath].fieldId;
43
+ const desiredComponent = compiledByFieldId.get(fieldId);
44
+ if (!desiredComponent) {
45
+ throw createFormServiceError(
46
+ 'compiled field binding was not found in generated Schema',
47
+ 'FORM_SCHEMA_PATCH_INVALID',
48
+ { semanticPath }
49
+ );
50
+ }
51
+
52
+ const currentComponent = currentByFieldId.get(fieldId);
53
+ if (currentComponent) {
54
+ if (currentComponent.componentName !== desiredComponent.componentName) {
55
+ throw createFormServiceError(
56
+ 'managed field type replacement is not supported',
57
+ 'FORM_SCHEMA_DESTRUCTIVE_CHANGE_UNSUPPORTED',
58
+ { semanticPath, operation: 'replace_type' }
59
+ );
60
+ }
61
+ assertSafeManagedPropChanges(currentComponent, desiredComponent, semanticPath);
62
+ patchManagedProps(currentComponent, desiredComponent);
63
+ continue;
64
+ }
65
+
66
+ if (existingBindings[semanticPath]) {
67
+ throw createFormServiceError(
68
+ 'managed field is missing from current Schema',
69
+ 'FORM_SCHEMA_DESTRUCTIVE_CHANGE_UNSUPPORTED',
70
+ { semanticPath, operation: 'managed_missing' }
71
+ );
72
+ }
73
+
74
+ const parentPath = parentSemanticPath(semanticPath);
75
+ const parent = parentPath
76
+ ? currentByFieldId.get(desiredBindings[parentPath] && desiredBindings[parentPath].fieldId)
77
+ : currentContainer;
78
+ if (!parent) {
79
+ throw createFormServiceError(
80
+ 'managed field parent was not found in current Schema',
81
+ 'FORM_SCHEMA_PATCH_INVALID',
82
+ { semanticPath }
83
+ );
84
+ }
85
+ if (!Array.isArray(parent.children)) {
86
+ parent.children = [];
87
+ }
88
+ const added = clonePlain(desiredComponent);
89
+ parent.children.push(added);
90
+ indexComponentTree(added, currentByFieldId);
91
+ }
92
+
93
+ mergeComponentsMap(schema, compiledSchema);
94
+ mergeComponentAliases(schema, compiledSchema, currentByFieldId);
95
+ return schema;
96
+ }
97
+
98
+ function extractSchema(schemaResult) {
99
+ let value = schemaResult && Object.prototype.hasOwnProperty.call(schemaResult, 'content')
100
+ ? schemaResult.content
101
+ : schemaResult;
102
+ if (typeof value === 'string') {
103
+ try {
104
+ value = JSON.parse(value);
105
+ } catch (error) {
106
+ throw createFormServiceError('form Schema content is not valid JSON', 'FORM_SCHEMA_PATCH_INVALID');
107
+ }
108
+ }
109
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
110
+ throw createFormServiceError('form Schema content must be an object', 'FORM_SCHEMA_PATCH_INVALID');
111
+ }
112
+ return value;
113
+ }
114
+
115
+ function patchFormTitle(currentContainer, compiledContainer) {
116
+ currentContainer.props = currentContainer.props || {};
117
+ const compiledProps = compiledContainer.props || {};
118
+ if (Object.prototype.hasOwnProperty.call(compiledProps, 'formLabel')) {
119
+ currentContainer.props.formLabel = clonePlain(compiledProps.formLabel);
120
+ }
121
+ }
122
+
123
+ function patchManagedProps(currentComponent, desiredComponent) {
124
+ currentComponent.props = currentComponent.props || {};
125
+ const desiredProps = desiredComponent.props || {};
126
+ for (const key of MANAGED_PROP_KEYS) {
127
+ if (Object.prototype.hasOwnProperty.call(desiredProps, key)) {
128
+ currentComponent.props[key] = clonePlain(desiredProps[key]);
129
+ }
130
+ }
131
+ }
132
+
133
+ function assertSafeManagedPropChanges(currentComponent, desiredComponent, semanticPath) {
134
+ const currentProps = currentComponent.props || {};
135
+ const desiredProps = desiredComponent.props || {};
136
+ const currentOptionValues = extractOptionValues(currentProps);
137
+ const desiredOptionValues = new Set(extractOptionValues(desiredProps));
138
+ if (currentOptionValues.some(value => !desiredOptionValues.has(value))) {
139
+ throw createFormServiceError(
140
+ 'managed option value deletion or rename is not supported',
141
+ 'FORM_SCHEMA_DESTRUCTIVE_CHANGE_UNSUPPORTED',
142
+ { semanticPath, operation: 'remove_option_value' }
143
+ );
144
+ }
145
+ if (
146
+ (currentProps.associationForm || desiredProps.associationForm) &&
147
+ !sameAssociationTarget(currentProps.associationForm, desiredProps.associationForm)
148
+ ) {
149
+ throw createFormServiceError(
150
+ 'managed association target replacement is not supported',
151
+ 'FORM_SCHEMA_DESTRUCTIVE_CHANGE_UNSUPPORTED',
152
+ { semanticPath, operation: 'replace_association' }
153
+ );
154
+ }
155
+ }
156
+
157
+ function extractOptionValues(props) {
158
+ const options = Array.isArray(props && props.dataSource)
159
+ ? props.dataSource
160
+ : props && props.defaultDataSource && Array.isArray(props.defaultDataSource.options)
161
+ ? props.defaultDataSource.options
162
+ : [];
163
+ return options.map((option) => {
164
+ if (option && typeof option === 'object') {
165
+ const value = option.value !== undefined
166
+ ? option.value
167
+ : option.text !== undefined
168
+ ? option.text
169
+ : option.label;
170
+ return String(value === undefined ? '' : value);
171
+ }
172
+ return String(option);
173
+ });
174
+ }
175
+
176
+ function sameAssociationTarget(left, right) {
177
+ const normalize = value => ({
178
+ appType: String(value && value.appType || ''),
179
+ formUuid: String(value && value.formUuid || ''),
180
+ });
181
+ const leftTarget = normalize(left);
182
+ const rightTarget = normalize(right);
183
+ return leftTarget.appType === rightTarget.appType &&
184
+ leftTarget.formUuid === rightTarget.formUuid;
185
+ }
186
+
187
+ function normalizeFieldBindings(bindings) {
188
+ const source = bindings && bindings.fieldBindings || bindings && bindings.fields || bindings || {};
189
+ const result = {};
190
+ const usedFieldIds = new Set();
191
+ for (const semanticPath of Object.keys(source)) {
192
+ const value = source[semanticPath];
193
+ const fieldId = typeof value === 'string'
194
+ ? value
195
+ : value && (value.fieldId || value.id || value.value);
196
+ if (fieldId) {
197
+ const normalizedFieldId = String(fieldId);
198
+ if (usedFieldIds.has(normalizedFieldId)) {
199
+ throw createFormServiceError(
200
+ 'field bindings contain a duplicate fieldId',
201
+ 'FORM_SCHEMA_PATCH_INVALID',
202
+ { semanticPath }
203
+ );
204
+ }
205
+ usedFieldIds.add(normalizedFieldId);
206
+ result[semanticPath] = { fieldId: normalizedFieldId };
207
+ }
208
+ }
209
+ return result;
210
+ }
211
+
212
+ function indexComponentsByFieldId(schema) {
213
+ const result = new Map();
214
+ visitSchemaComponents(schema, node => indexComponent(node, result));
215
+ return result;
216
+ }
217
+
218
+ function indexComponentTree(node, index) {
219
+ if (!node || typeof node !== 'object') {
220
+ return;
221
+ }
222
+ indexComponent(node, index);
223
+ if (Array.isArray(node.children)) {
224
+ node.children.forEach(child => indexComponentTree(child, index));
225
+ }
226
+ }
227
+
228
+ function indexComponent(node, index) {
229
+ const fieldId = node && node.props && node.props.fieldId;
230
+ if (!fieldId) {
231
+ return;
232
+ }
233
+ const normalizedFieldId = String(fieldId);
234
+ if (index.has(normalizedFieldId)) {
235
+ throw createFormServiceError(
236
+ 'form Schema contains a duplicate fieldId',
237
+ 'FORM_SCHEMA_PATCH_INVALID'
238
+ );
239
+ }
240
+ index.set(normalizedFieldId, node);
241
+ }
242
+
243
+ function findFirstComponent(schema, componentName) {
244
+ let found = null;
245
+ visitSchemaComponents(schema, (node) => {
246
+ if (!found && node.componentName === componentName) {
247
+ found = node;
248
+ }
249
+ });
250
+ return found;
251
+ }
252
+
253
+ function visitSchemaComponents(schema, visitor) {
254
+ const pages = schema && schema.pages;
255
+ if (!Array.isArray(pages)) {
256
+ return;
257
+ }
258
+ function visit(node) {
259
+ if (!node || typeof node !== 'object') {
260
+ return;
261
+ }
262
+ visitor(node);
263
+ if (Array.isArray(node.children)) {
264
+ node.children.forEach(visit);
265
+ }
266
+ }
267
+ pages.forEach((page) => {
268
+ const roots = page && Array.isArray(page.componentsTree) ? page.componentsTree : [];
269
+ roots.forEach(visit);
270
+ });
271
+ }
272
+
273
+ function mergeComponentsMap(schema, compiledSchema) {
274
+ const currentPage = schema && Array.isArray(schema.pages) && schema.pages[0];
275
+ const compiledPage = compiledSchema && Array.isArray(compiledSchema.pages) && compiledSchema.pages[0];
276
+ if (!currentPage || !compiledPage || !Array.isArray(compiledPage.componentsMap)) {
277
+ return;
278
+ }
279
+ const current = Array.isArray(currentPage.componentsMap) ? currentPage.componentsMap : [];
280
+ const names = new Set(current.map(item => item && item.componentName).filter(Boolean));
281
+ for (const item of compiledPage.componentsMap) {
282
+ if (item && item.componentName && !names.has(item.componentName)) {
283
+ current.push(clonePlain(item));
284
+ names.add(item.componentName);
285
+ }
286
+ }
287
+ currentPage.componentsMap = current;
288
+ }
289
+
290
+ function mergeComponentAliases(schema, compiledSchema, currentByFieldId) {
291
+ const currentPage = schema && Array.isArray(schema.pages) && schema.pages[0];
292
+ const compiledPage = compiledSchema && Array.isArray(compiledSchema.pages) && compiledSchema.pages[0];
293
+ const compiledItems = compiledPage && compiledPage.componentAlias && compiledPage.componentAlias.items;
294
+ if (!currentPage || !Array.isArray(compiledItems)) {
295
+ return;
296
+ }
297
+ const currentAlias = currentPage.componentAlias && typeof currentPage.componentAlias === 'object'
298
+ ? currentPage.componentAlias
299
+ : { items: [] };
300
+ const items = Array.isArray(currentAlias.items) ? currentAlias.items : [];
301
+ const fieldIds = new Set(items.map(item => item && item.fieldId).filter(Boolean));
302
+ for (const item of compiledItems) {
303
+ if (
304
+ item &&
305
+ item.fieldId &&
306
+ currentByFieldId.has(String(item.fieldId)) &&
307
+ !fieldIds.has(item.fieldId)
308
+ ) {
309
+ items.push(clonePlain(item));
310
+ fieldIds.add(item.fieldId);
311
+ }
312
+ }
313
+ currentAlias.items = items;
314
+ currentPage.componentAlias = currentAlias;
315
+ }
316
+
317
+ function parentSemanticPath(semanticPath) {
318
+ const separator = String(semanticPath).lastIndexOf('.');
319
+ return separator === -1 ? '' : String(semanticPath).slice(0, separator);
320
+ }
321
+
322
+ function clonePlain(value) {
323
+ return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
324
+ }
325
+
326
+ function compareCodePoints(left, right) {
327
+ return left < right ? -1 : left > right ? 1 : 0;
328
+ }
329
+
330
+ module.exports = {
331
+ MANAGED_PROP_KEYS,
332
+ patchManagedFormSchema,
333
+ };
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ const { httpGet, requestWithAutoLogin } = require('../../core/utils');
4
+ const { requireSchemaServerRevision } = require('../../schema/server-revision');
5
+ const {
6
+ dispatchRemotePrimitive,
7
+ hasRemoteDispatchBoundary,
8
+ } = require('../../schema/remote-dispatch-boundary');
9
+
10
+ function resolveAuthRef(context) {
11
+ return context && context.authRef ? context.authRef : context;
12
+ }
13
+
14
+ function createFormServiceError(message, code, details) {
15
+ const error = new Error(message);
16
+ error.code = code || 'FORM_SERVICE_FAILED';
17
+ if (details) {
18
+ error.details = details;
19
+ }
20
+ return error;
21
+ }
22
+
23
+ function assertSuccess(result, code, details) {
24
+ if (result && result.success !== false && !result.__needLogin && !result.__csrfExpired) {
25
+ return result;
26
+ }
27
+ const message = result ? result.errorMsg || 'request failed' : 'request failed';
28
+ throw createFormServiceError(message, code, Object.assign({ result }, details));
29
+ }
30
+
31
+ async function readFormSchema(context, input) {
32
+ const authRef = resolveAuthRef(context);
33
+ const services = context && context.services || {};
34
+ const requestWithAutoLoginImpl = services.requestWithAutoLogin || requestWithAutoLogin;
35
+ const httpGetImpl = services.httpGet || httpGet;
36
+ const appType = input && input.appType;
37
+ const formUuid = input && input.formUuid;
38
+ const send = auth => httpGetImpl(
39
+ auth.baseUrl,
40
+ `/alibaba/web/${appType}/_view/query/formdesign/getFormSchema.json`,
41
+ { formUuid, schemaVersion: input && input.schemaVersion || 'V5' },
42
+ auth.cookies
43
+ );
44
+ const result = hasRemoteDispatchBoundary(context)
45
+ ? await dispatchRemotePrimitive(context, () => send(authRef))
46
+ : await requestWithAutoLoginImpl(send, authRef);
47
+ const schemaResult = assertSuccess(result, 'FORM_SCHEMA_READ_FAILED', { appType, formUuid });
48
+ requireSchemaServerRevision(schemaResult, () => createFormServiceError(
49
+ 'remote Schema revision is missing or invalid',
50
+ 'FORM_SCHEMA_READ_FAILED',
51
+ { appType, formUuid }
52
+ ));
53
+ return schemaResult;
54
+ }
55
+
56
+ module.exports = {
57
+ readFormSchema,
58
+ createFormServiceError,
59
+ };