openyida 2026.7.19 → 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 (139) hide show
  1. package/README.md +14 -0
  2. package/bin/yida.js +107 -18
  3. package/lib/app/create-app.js +12 -1
  4. package/lib/app/create-form/args.js +13 -0
  5. package/lib/app/create-form.js +154 -67
  6. package/lib/app/create-page.js +45 -9
  7. package/lib/app/get-schema.js +65 -14
  8. package/lib/app/import-app.js +92 -41
  9. package/lib/app/publish.js +289 -556
  10. package/lib/app/schema-field-resolution.js +370 -0
  11. package/lib/app/services/app-reader.js +85 -0
  12. package/lib/app/services/app-service.js +235 -0
  13. package/lib/app/services/canvas-page-compiler.js +91 -0
  14. package/lib/app/services/canvas-page-schema-builder.js +149 -0
  15. package/lib/app/services/field-bindings.js +68 -0
  16. package/lib/app/services/form-compiler.js +1922 -0
  17. package/lib/app/services/form-mode-service.js +182 -0
  18. package/lib/app/services/form-schema-patcher.js +333 -0
  19. package/lib/app/services/form-schema-reader.js +59 -0
  20. package/lib/app/services/form-service.js +379 -0
  21. package/lib/app/services/form-validation.js +562 -0
  22. package/lib/app/services/native-page-compiler.js +92 -0
  23. package/lib/app/services/native-page-schema-builder.js +428 -0
  24. package/lib/app/services/page-resource-service.js +185 -0
  25. package/lib/app/update-app.js +18 -6
  26. package/lib/auth/token-auth.js +34 -3
  27. package/lib/auth/token-store.js +22 -4
  28. package/lib/bridge/bridge.js +37 -5
  29. package/lib/core/agent-capabilities.js +5 -3
  30. package/lib/core/command-manifest.js +40 -0
  31. package/lib/core/doctor.js +15 -4
  32. package/lib/core/env-cmd.js +1 -1
  33. package/lib/core/env.js +7 -6
  34. package/lib/core/legacy-schema-guard.js +408 -0
  35. package/lib/core/locales/en.js +8 -46
  36. package/lib/core/locales/zh.js +8 -46
  37. package/lib/core/sample.js +1 -1
  38. package/lib/core/utils.js +334 -66
  39. package/lib/core/yida-client.js +104 -3
  40. package/lib/formula/evaluate.js +8 -66
  41. package/lib/formula/field-refs.js +83 -0
  42. package/lib/process/configure-process.js +44 -1992
  43. package/lib/process/create-process.js +54 -87
  44. package/lib/process/services/process-compiler.js +2056 -0
  45. package/lib/process/services/process-reader.js +232 -0
  46. package/lib/process/services/process-resource-service.js +571 -0
  47. package/lib/process/services/process-service.js +122 -0
  48. package/lib/process/services/process-stage-checkpoint.js +246 -0
  49. package/lib/report/append.js +7 -26
  50. package/lib/report/http.js +31 -5
  51. package/lib/report/index.js +10 -2
  52. package/lib/samples/yida-canvas-custom-page/business-list.canvas.jsx +63 -14
  53. package/lib/samples/yida-canvas-custom-page/dashboard-overview.canvas.jsx +176 -32
  54. package/lib/samples/yida-canvas-custom-page/data-management.canvas.jsx +228 -14
  55. package/lib/samples/yida-canvas-custom-page/split-pane-detail.canvas.jsx +204 -8
  56. package/lib/schema/adapters/app-adapter.js +210 -0
  57. package/lib/schema/adapters/form-adapter.js +1362 -0
  58. package/lib/schema/adapters/keys.js +19 -0
  59. package/lib/schema/adapters/page-adapter.js +566 -0
  60. package/lib/schema/adapters/process-adapter.js +519 -0
  61. package/lib/schema/applier.js +1878 -0
  62. package/lib/schema/apply-store.js +1083 -0
  63. package/lib/schema/command.js +645 -0
  64. package/lib/schema/dependency-graph.js +83 -0
  65. package/lib/schema/errors.js +481 -0
  66. package/lib/schema/hash.js +9 -0
  67. package/lib/schema/manifest-limits.js +177 -0
  68. package/lib/schema/manifest-loader.js +309 -0
  69. package/lib/schema/manifest-schema-v1.json +193 -0
  70. package/lib/schema/normalize-manifest.js +281 -0
  71. package/lib/schema/page-canvas-foundation.js +447 -0
  72. package/lib/schema/page-data-source-builder.js +561 -0
  73. package/lib/schema/page-foundation.js +556 -0
  74. package/lib/schema/page-source-loader.js +314 -0
  75. package/lib/schema/planner.js +691 -0
  76. package/lib/schema/remote-dispatch-boundary.js +39 -0
  77. package/lib/schema/remote-missing.js +21 -0
  78. package/lib/schema/remote-reader.js +189 -0
  79. package/lib/schema/resource-registry.js +157 -0
  80. package/lib/schema/server-revision.js +71 -0
  81. package/lib/schema/sort.js +28 -0
  82. package/lib/schema/state-store.js +589 -0
  83. package/package.json +2 -2
  84. package/scripts/postinstall.js +8 -12
  85. package/scripts/validate-package-size.js +1 -1
  86. package/yida-skills/SKILL.md +114 -29
  87. package/yida-skills/references/schema-as-code-phase1.md +99 -0
  88. package/yida-skills/references/setup-and-env.md +59 -59
  89. package/yida-skills/references/task-retrospective.md +6 -6
  90. package/yida-skills/skills/yida-app/SKILL.md +60 -14
  91. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +18 -7
  92. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +3 -3
  93. package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +7 -1
  94. package/yida-skills/skills/yida-create-app/SKILL.md +21 -3
  95. package/yida-skills/skills/yida-create-form-page/SKILL.md +19 -1
  96. package/yida-skills/skills/yida-create-page/SKILL.md +16 -3
  97. package/yida-skills/skills/yida-create-process/SKILL.md +100 -4
  98. package/yida-skills/skills/yida-custom-page/SKILL.md +19 -4
  99. package/yida-skills/skills/yida-dashboard/SKILL.md +1 -1
  100. package/yida-skills/skills/yida-dashboard/references/pitfalls.md +1 -1
  101. package/yida-skills/skills/yida-get-schema/SKILL.md +49 -5
  102. package/yida-skills/skills/yida-i18n/SKILL.md +1 -1
  103. package/yida-skills/skills/yida-integration/SKILL.md +7 -1
  104. package/yida-skills/skills/yida-login/SKILL.md +50 -99
  105. package/yida-skills/skills/yida-page-config/SKILL.md +7 -1
  106. package/yida-skills/skills/yida-page-uiux/references/app/blueprint.md +0 -1
  107. package/yida-skills/skills/yida-page-uiux/references/app/navigation-patterns.md +0 -1
  108. package/yida-skills/skills/yida-page-uiux/references/app/role-journey.md +0 -1
  109. package/yida-skills/skills/yida-page-uiux/references/dashboard/app-blueprint.md +0 -1
  110. package/yida-skills/skills/yida-page-uiux/references/dashboard/chart-contracts.md +0 -1
  111. package/yida-skills/skills/yida-page-uiux/references/dashboard/component-contracts.md +0 -1
  112. package/yida-skills/skills/yida-page-uiux/references/dashboard/layout-patterns.md +0 -1
  113. package/yida-skills/skills/yida-page-uiux/references/dashboard/theme-recipes.md +0 -1
  114. package/yida-skills/skills/yida-page-uiux/references/detail/object-narrative.md +0 -1
  115. package/yida-skills/skills/yida-page-uiux/references/detail/section-patterns.md +0 -1
  116. package/yida-skills/skills/yida-page-uiux/references/detail/timeline-and-related.md +0 -1
  117. package/yida-skills/skills/yida-page-uiux/references/landing/assets-workflow.md +0 -1
  118. package/yida-skills/skills/yida-page-uiux/references/landing/industry-playbooks.md +0 -1
  119. package/yida-skills/skills/yida-page-uiux/references/landing/research-levels.md +0 -1
  120. package/yida-skills/skills/yida-page-uiux/references/landing/section-patterns.md +0 -1
  121. package/yida-skills/skills/yida-page-uiux/references/list/drawer-detail.md +0 -1
  122. package/yida-skills/skills/yida-page-uiux/references/list/empty-loading-error.md +0 -1
  123. package/yida-skills/skills/yida-page-uiux/references/list/filter-patterns.md +0 -1
  124. package/yida-skills/skills/yida-page-uiux/references/list/table-patterns.md +0 -1
  125. package/yida-skills/skills/yida-page-uiux/references/scenes/screen.md +0 -1
  126. package/yida-skills/skills/yida-page-uiux/references/workbench/entry-patterns.md +0 -1
  127. package/yida-skills/skills/yida-page-uiux/references/workbench/portal-layouts.md +0 -1
  128. package/yida-skills/skills/yida-page-uiux/references/workbench/task-feed.md +0 -1
  129. package/yida-skills/skills/yida-page-uiux/workflow/output-decision-block.md +1 -1
  130. package/yida-skills/skills/yida-process-rule/SKILL.md +35 -1
  131. package/yida-skills/skills/yida-publish-page/SKILL.md +46 -4
  132. package/yida-skills/skills/yida-report/SKILL.md +7 -1
  133. package/yida-skills/skills-index.json +14 -46
  134. package/yida-skills/skills/large-file-write/SKILL.md +0 -93
  135. package/yida-skills/skills/large-file-write/references/write-patterns.md +0 -147
  136. package/yida-skills/skills/large-file-write/scripts/write.js +0 -157
  137. package/yida-skills/skills/sls-log-workbench/SKILL.md +0 -134
  138. package/yida-skills/skills/sls-log-workbench/references/workbench-reference.md +0 -130
  139. package/yida-skills/skills/sls-log-workbench/sls-query.js +0 -295
@@ -0,0 +1,428 @@
1
+ 'use strict';
2
+
3
+ const { stripSubtableFieldPrefix } = require('../../formula/field-refs');
4
+
5
+ function createNodeIdGenerator() {
6
+ let counter = 1;
7
+ return function nextNodeId() {
8
+ return 'node_oc' + Date.now().toString(36) + (counter++).toString(36);
9
+ };
10
+ }
11
+
12
+ function generateSuffix() {
13
+ return Date.now().toString(36) + Math.random().toString(36).substring(2, 8);
14
+ }
15
+
16
+ function getGlobalDataSourceFitConfig() {
17
+ const fitCompiled = "'use strict';\n\nvar __preParser__ = function fit(response) {\n var content = response.content !== undefined ? response.content : response;\n var error = {\n message: response.errorMsg || response.errors && response.errors[0] && response.errors[0].msg || response.content || '远程数据源请求出错,success is false'\n };\n var success = true;\n if (response.success !== undefined) {\n success = response.success;\n } else if (response.hasError !== undefined) {\n success = !response.hasError;\n }\n return {\n content: content,\n success: success,\n error: error\n };\n};";
18
+ const fitSource = "function fit(response) {\r\n const content = (response.content !== undefined) ? response.content : response;\r\n const error = {\r\n message: response.errorMsg ||\r\n (response.errors && response.errors[0] && response.errors[0].msg) ||\r\n response.content || '远程数据源请求出错,success is false',\r\n };\r\n let success = true;\r\n if (response.success !== undefined) {\r\n success = response.success;\r\n } else if (response.hasError !== undefined) {\r\n success = !response.hasError;\r\n }\r\n return {\r\n content,\r\n success,\r\n error,\r\n };\r\n}";
19
+
20
+ return {
21
+ fit: {
22
+ compiled: fitCompiled,
23
+ source: fitSource,
24
+ type: 'js',
25
+ error: {},
26
+ },
27
+ };
28
+ }
29
+
30
+ function buildDefaultPageDataSource(formUuid) {
31
+ const urlParamsDataSource = {
32
+ id: 'VCB660714833IBHEOXK376TA7XJH2AXUWR8MMW',
33
+ name: 'urlParams',
34
+ description: '当前页面地址的参数:如 aliwork.com/APP_XXX/workbench?id=1&name=宜搭,可通过 this.state.urlParams.name 获取到宜搭',
35
+ formUuid,
36
+ protocal: 'URI',
37
+ isReadonly: true,
38
+ };
39
+ const timestampDataSource = {
40
+ id: '',
41
+ name: 'timestamp',
42
+ description: '',
43
+ formUuid,
44
+ protocal: 'VALUE',
45
+ initialData: '',
46
+ };
47
+
48
+ return {
49
+ offline: [],
50
+ globalConfig: getGlobalDataSourceFitConfig(),
51
+ online: [urlParamsDataSource, timestampDataSource],
52
+ list: [urlParamsDataSource, timestampDataSource],
53
+ sync: true,
54
+ };
55
+ }
56
+
57
+ function cloneJson(value) {
58
+ if (value === undefined || value === null) {
59
+ return value;
60
+ }
61
+ return JSON.parse(JSON.stringify(value));
62
+ }
63
+
64
+ function isBuiltInPageDataSource(item) {
65
+ return !!(item && (item.name === 'urlParams' || item.name === 'timestamp'));
66
+ }
67
+
68
+ function getDataSourceIdentity(item) {
69
+ if (!item || typeof item !== 'object') {
70
+ return '';
71
+ }
72
+ if (isBuiltInPageDataSource(item)) {
73
+ return 'builtin:' + item.name;
74
+ }
75
+ if (item.id) {
76
+ return 'id:' + item.id;
77
+ }
78
+ if (item.name && item.protocal) {
79
+ return 'name:' + item.name + '|protocal:' + item.protocal;
80
+ }
81
+ if (item.name) {
82
+ return 'name:' + item.name;
83
+ }
84
+ return JSON.stringify(item);
85
+ }
86
+
87
+ function mergeDataSourceArray(existingItems, generatedItems) {
88
+ const merged = Array.isArray(existingItems) ? cloneJson(existingItems) : [];
89
+ const seen = new Set(merged.map(getDataSourceIdentity).filter(Boolean));
90
+
91
+ (Array.isArray(generatedItems) ? generatedItems : []).forEach((item) => {
92
+ const identity = getDataSourceIdentity(item);
93
+ if (!identity || !seen.has(identity)) {
94
+ merged.push(cloneJson(item));
95
+ if (identity) {
96
+ seen.add(identity);
97
+ }
98
+ }
99
+ });
100
+
101
+ return merged;
102
+ }
103
+
104
+ function mergePageDataSource(existingDataSource, generatedDataSource) {
105
+ if (!existingDataSource || typeof existingDataSource !== 'object') {
106
+ return cloneJson(generatedDataSource);
107
+ }
108
+
109
+ const existing = cloneJson(existingDataSource);
110
+ const generated = cloneJson(generatedDataSource || {});
111
+ const merged = Object.assign({}, generated, existing);
112
+
113
+ merged.offline = mergeDataSourceArray(existing.offline, generated.offline);
114
+ merged.online = mergeDataSourceArray(existing.online, generated.online);
115
+ merged.list = mergeDataSourceArray(existing.list, generated.list);
116
+ merged.globalConfig = Object.assign(
117
+ {},
118
+ generated.globalConfig || {},
119
+ existing.globalConfig || {}
120
+ );
121
+ merged.sync = existing.sync !== undefined ? existing.sync : generated.sync;
122
+
123
+ return merged;
124
+ }
125
+
126
+ function extractSchemaContent(schemaResult) {
127
+ if (!schemaResult) {
128
+ return null;
129
+ }
130
+
131
+ let content = schemaResult.content !== undefined ? schemaResult.content : schemaResult;
132
+ if (typeof content === 'string') {
133
+ try {
134
+ content = JSON.parse(content);
135
+ } catch {
136
+ return null;
137
+ }
138
+ }
139
+
140
+ if (content && typeof content === 'object' && content.pages) {
141
+ return content;
142
+ }
143
+ if (schemaResult.pages) {
144
+ return schemaResult;
145
+ }
146
+ return null;
147
+ }
148
+
149
+ function extractPageDataSource(schema) {
150
+ if (!schema || !Array.isArray(schema.pages)) {
151
+ return null;
152
+ }
153
+
154
+ function findPageDataSource(node) {
155
+ if (!node || typeof node !== 'object') {
156
+ return null;
157
+ }
158
+ if (node.componentName === 'Page' && node.dataSource) {
159
+ return node.dataSource;
160
+ }
161
+ const children = Array.isArray(node.children) ? node.children : [];
162
+ for (const child of children) {
163
+ const dataSource = findPageDataSource(child);
164
+ if (dataSource) {
165
+ return dataSource;
166
+ }
167
+ }
168
+ return null;
169
+ }
170
+
171
+ for (const page of schema.pages) {
172
+ const tree = page && Array.isArray(page.componentsTree) ? page.componentsTree : [];
173
+ for (const component of tree) {
174
+ const dataSource = findPageDataSource(component);
175
+ if (dataSource) {
176
+ return dataSource;
177
+ }
178
+ }
179
+ }
180
+ return null;
181
+ }
182
+
183
+ function countCustomPageDataSources(dataSource) {
184
+ if (!dataSource || typeof dataSource !== 'object') {
185
+ return 0;
186
+ }
187
+
188
+ const identities = new Set();
189
+ ['offline', 'online', 'list'].forEach((key) => {
190
+ (Array.isArray(dataSource[key]) ? dataSource[key] : []).forEach((item) => {
191
+ if (!isBuiltInPageDataSource(item)) {
192
+ const identity = getDataSourceIdentity(item);
193
+ if (identity) {
194
+ identities.add(identity);
195
+ }
196
+ }
197
+ });
198
+ });
199
+ return identities.size;
200
+ }
201
+
202
+ function buildNativePageSchemaContent(sourceCode, compiledCode, formUuid, options = {}) {
203
+ const onBuildingSchema = normalizeOptionalCallback(options.onBuildingSchema, 'onBuildingSchema');
204
+ const onFormulaPrefixFixed = normalizeOptionalCallback(
205
+ options.onFormulaPrefixFixed,
206
+ 'onFormulaPrefixFixed'
207
+ );
208
+ onBuildingSchema();
209
+
210
+ const sourceFix = stripSubtableFieldPrefix(sourceCode);
211
+ const compiledFix = stripSubtableFieldPrefix(compiledCode);
212
+ sourceCode = sourceFix.value;
213
+ compiledCode = compiledFix.value;
214
+ const fixedRefs = sourceFix.count + compiledFix.count;
215
+ if (fixedRefs > 0) {
216
+ onFormulaPrefixFixed(fixedRefs);
217
+ }
218
+
219
+ const nextNodeId = resolveSchemaBuilderDependency(
220
+ options.nextNodeId,
221
+ createNodeIdGenerator,
222
+ 'nextNodeId'
223
+ );
224
+ const nextSuffix = resolveSchemaBuilderDependency(
225
+ options.nextSuffix,
226
+ () => generateSuffix,
227
+ 'nextSuffix'
228
+ );
229
+ const constructorCode = "function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}";
230
+ const pageDataSource = mergePageDataSource(
231
+ options.existingDataSource,
232
+ buildDefaultPageDataSource(formUuid)
233
+ );
234
+
235
+ const schema = {
236
+ schemaType: 'superform',
237
+ schemaVersion: '5.0',
238
+ pages: [
239
+ {
240
+ utils: [
241
+ {
242
+ name: 'legaoBuiltin',
243
+ type: 'npm',
244
+ content: {
245
+ package: '@ali/vu-legao-builtin',
246
+ version: '3.0.0',
247
+ exportName: 'legaoBuiltin',
248
+ },
249
+ },
250
+ {
251
+ name: 'yidaPlugin',
252
+ type: 'npm',
253
+ content: {
254
+ package: '@ali/vu-yida-plugin',
255
+ version: '1.1.0',
256
+ exportName: 'yidaPlugin',
257
+ },
258
+ },
259
+ ],
260
+ componentsMap: [
261
+ { package: '@ali/vc-deep-yida', version: '1.5.169', componentName: 'RootHeader' },
262
+ { package: '@ali/vc-deep-yida', version: '1.5.169', componentName: 'Jsx' },
263
+ { package: '@ali/vc-deep-yida', version: '1.5.169', componentName: 'RootContent' },
264
+ { package: '@ali/vc-deep-yida', version: '1.5.169', componentName: 'RootFooter' },
265
+ { package: '@ali/vc-deep-yida', version: '1.5.169', componentName: 'Page' },
266
+ ],
267
+ componentsTree: [
268
+ {
269
+ componentName: 'Page',
270
+ id: nextNodeId(),
271
+ props: {
272
+ contentBgColor: 'white',
273
+ pageStyle: { backgroundColor: '#f2f3f5' },
274
+ contentMargin: '0',
275
+ contentPadding: '0',
276
+ showTitle: false,
277
+ contentPaddingMobile: '0',
278
+ templateVersion: '1.0.0',
279
+ contentMarginMobile: '0',
280
+ className: 'page_' + nextSuffix(),
281
+ contentBgColorMobile: 'white',
282
+ },
283
+ condition: true,
284
+ css: 'body{background-color:#f2f3f5}.vc-page-yida-page{--yida-form-content-padding:0;--yida-form-content-margin:0;--yida-layout-padding:0}.vc-deep-container-entry.vc-rootcontent{padding:0!important;margin-top:0!important;margin-right:0!important;margin-bottom:0!important;margin-left:0!important}',
285
+ methods: {
286
+ __initMethods__: {
287
+ type: 'js',
288
+ source: 'function (exports, module) { /*set actions code here*/ }',
289
+ compiled: 'function (exports, module) { /*set actions code here*/ }',
290
+ },
291
+ },
292
+ dataSource: pageDataSource,
293
+ lifeCycles: {
294
+ constructor: {
295
+ type: 'js',
296
+ compiled: constructorCode,
297
+ source: constructorCode,
298
+ },
299
+ componentWillUnmount: {
300
+ name: 'didUnmount',
301
+ id: 'didUnmount',
302
+ type: 'actionRef',
303
+ params: {},
304
+ },
305
+ componentDidMount: {
306
+ name: 'didMount',
307
+ id: 'didMount',
308
+ params: {},
309
+ type: 'actionRef',
310
+ },
311
+ },
312
+ hidden: false,
313
+ title: '',
314
+ isLocked: false,
315
+ conditionGroup: '',
316
+ children: [
317
+ {
318
+ componentName: 'RootHeader',
319
+ id: nextNodeId(),
320
+ props: {},
321
+ condition: true,
322
+ hidden: false,
323
+ title: '',
324
+ isLocked: false,
325
+ conditionGroup: '',
326
+ },
327
+ {
328
+ componentName: 'RootContent',
329
+ id: nextNodeId(),
330
+ props: {},
331
+ condition: true,
332
+ hidden: false,
333
+ title: '',
334
+ isLocked: false,
335
+ conditionGroup: '',
336
+ children: [
337
+ {
338
+ componentName: 'Jsx',
339
+ id: nextNodeId(),
340
+ props: {
341
+ render: {
342
+ type: 'js',
343
+ compiled: 'function main(){\n \n "use strict";\n\nvar __compiledFunc__ = function render() {\n return this.renderJsx();\n};\n return __compiledFunc__.apply(this, arguments);\n }',
344
+ source: 'function render() {\n return this.renderJsx();\n}',
345
+ error: {},
346
+ },
347
+ __style__: {},
348
+ fieldId: 'jsx_' + nextSuffix(),
349
+ },
350
+ condition: true,
351
+ hidden: false,
352
+ title: '',
353
+ isLocked: false,
354
+ conditionGroup: '',
355
+ },
356
+ ],
357
+ },
358
+ {
359
+ componentName: 'RootFooter',
360
+ id: nextNodeId(),
361
+ props: {},
362
+ condition: true,
363
+ hidden: false,
364
+ title: '',
365
+ isLocked: false,
366
+ conditionGroup: '',
367
+ },
368
+ ],
369
+ },
370
+ ],
371
+ id: formUuid,
372
+ connectComponent: [],
373
+ },
374
+ ],
375
+ actions: {
376
+ module: {
377
+ compiled: compiledCode,
378
+ source: sourceCode,
379
+ },
380
+ type: 'FUNCTION',
381
+ list: [
382
+ { id: 'getCustomState', title: 'getCustomState' },
383
+ { id: 'setCustomState', title: 'setCustomState' },
384
+ { id: 'forceUpdate', title: 'forceUpdate' },
385
+ { id: 'didMount', title: 'didMount' },
386
+ { id: 'didUnmount', title: 'didUnmount' },
387
+ { id: 'renderJsx', title: 'renderJsx' },
388
+ ],
389
+ },
390
+ config: {
391
+ connectComponent: [],
392
+ },
393
+ };
394
+
395
+ return JSON.stringify(schema);
396
+ }
397
+
398
+ function normalizeOptionalCallback(value, property) {
399
+ if (value === undefined) {
400
+ return () => {};
401
+ }
402
+ if (typeof value !== 'function') {
403
+ throw new TypeError(`buildNativePageSchemaContent ${property} must be a function`);
404
+ }
405
+ return value;
406
+ }
407
+
408
+ function resolveSchemaBuilderDependency(value, createDefault, property) {
409
+ if (value === undefined) {
410
+ return createDefault();
411
+ }
412
+ if (typeof value !== 'function') {
413
+ throw new TypeError(`buildSchemaContent ${property} must be a function`);
414
+ }
415
+ return value;
416
+ }
417
+
418
+ module.exports = Object.freeze({
419
+ buildDefaultPageDataSource,
420
+ buildNativePageSchemaContent,
421
+ countCustomPageDataSources,
422
+ createNodeIdGenerator,
423
+ extractPageDataSource,
424
+ extractSchemaContent,
425
+ generateSuffix,
426
+ getGlobalDataSourceFitConfig,
427
+ mergePageDataSource,
428
+ });
@@ -0,0 +1,185 @@
1
+ 'use strict';
2
+
3
+ const querystring = require('querystring');
4
+ const { schemaError } = require('../../schema/errors');
5
+ const { normalizeFormNavigationNode } = require('../form-navigation');
6
+ const { buildYidaI18n } = require('../../core/yida-i18n');
7
+ const { httpGet, httpPost } = require('../../core/utils');
8
+ const { isTokenAuthRef } = require('../../core/yida-client');
9
+ const {
10
+ createServerRevisionConflict,
11
+ isSaveFormSchemaRevisionConflict,
12
+ requireSchemaServerRevision,
13
+ } = require('../../schema/server-revision');
14
+ const { dispatchRemotePrimitive } = require('../../schema/remote-dispatch-boundary');
15
+
16
+ function assertPageWriteReady(context = {}) {
17
+ const auth = resolveAuth(context);
18
+ if (!auth || typeof auth.baseUrl !== 'string' || !auth.baseUrl) {
19
+ pageServiceError('SCHEMA_PAGE_WRITE_PRECHECK_FAILED', 'Page write authentication is not ready.');
20
+ }
21
+ if (isTokenAuthRef(auth)) {
22
+ return true;
23
+ }
24
+ if (!auth.cookies || typeof auth.csrfToken !== 'string' || !auth.csrfToken) {
25
+ pageServiceError('SCHEMA_PAGE_WRITE_PRECHECK_FAILED', 'Page write authentication is not ready.');
26
+ }
27
+ return true;
28
+ }
29
+
30
+ async function createPageShellOnce(context, input = {}) {
31
+ const auth = requireWriteAuth(context);
32
+ const request = resolveService(context, 'httpPost', httpPost);
33
+ const result = await dispatchRemotePrimitive(context, () => request(
34
+ auth.baseUrl,
35
+ `/dingtalk/web/${input.appType}/query/formdesign/saveFormSchemaInfo.json`,
36
+ querystring.stringify({
37
+ _csrf_token: auth.csrfToken,
38
+ formType: 'display',
39
+ title: JSON.stringify(buildYidaI18n(input.title, {
40
+ en_US: input.title,
41
+ ja_JP: input.title,
42
+ })),
43
+ }),
44
+ auth.cookies
45
+ ));
46
+ if (!result || result.success !== true || result.__needLogin || result.__csrfExpired) {
47
+ pageServiceError('SCHEMA_PAGE_CREATE_FAILED', 'Page create request did not return a confirmed identity.');
48
+ }
49
+ const formUuid = result.content && result.content.formUuid || result.content;
50
+ if (typeof formUuid !== 'string' || !formUuid) {
51
+ pageServiceError('SCHEMA_PAGE_CREATE_FAILED', 'Page create request did not return a confirmed identity.');
52
+ }
53
+ return { appType: input.appType, formUuid };
54
+ }
55
+
56
+ async function readPageResource(context, input = {}) {
57
+ const auth = requireReadAuth(context);
58
+ const request = resolveService(context, 'httpGet', httpGet);
59
+ const schemaResult = await dispatchRemotePrimitive(context, () => request(
60
+ auth.baseUrl,
61
+ `/alibaba/web/${input.appType}/_view/query/formdesign/getFormSchema.json`,
62
+ { formUuid: input.formUuid, schemaVersion: 'V5' },
63
+ auth.cookies
64
+ ));
65
+ if (
66
+ !schemaResult ||
67
+ schemaResult.success === false ||
68
+ schemaResult.__needLogin ||
69
+ schemaResult.__csrfExpired ||
70
+ !hasSchemaContent(schemaResult.content)
71
+ ) {
72
+ pageServiceError('SCHEMA_PAGE_READ_FAILED', 'Bound page Schema could not be read.');
73
+ }
74
+
75
+ const navigationResult = await dispatchRemotePrimitive(context, () => request(
76
+ auth.baseUrl,
77
+ `/dingtalk/web/${input.appType}/query/formnav/getFormNavigationListByOrder.json`,
78
+ { _api: 'Nav.queryList', _mock: false },
79
+ auth.cookies
80
+ ));
81
+ if (
82
+ !navigationResult ||
83
+ navigationResult.success === false ||
84
+ navigationResult.__needLogin ||
85
+ navigationResult.__csrfExpired ||
86
+ !Array.isArray(navigationResult.content)
87
+ ) {
88
+ pageServiceError('SCHEMA_PAGE_READ_FAILED', 'Bound page identity could not be read.');
89
+ }
90
+ const matches = navigationResult.content
91
+ .map(normalizeFormNavigationNode)
92
+ .filter(Boolean)
93
+ .filter(item => item.formUuid === input.formUuid);
94
+ if (matches.length !== 1) {
95
+ pageServiceError('SCHEMA_PAGE_READ_FAILED', 'Bound page identity is missing or ambiguous.');
96
+ }
97
+ return {
98
+ appType: input.appType,
99
+ formUuid: input.formUuid,
100
+ observedFormType: matches[0].formType,
101
+ observedTitle: matches[0].formName,
102
+ schema: schemaResult.content,
103
+ serverRevision: requireSchemaServerRevision(schemaResult, () => pageReadError()),
104
+ };
105
+ }
106
+
107
+ async function savePageSchemaOnce(context, input = {}) {
108
+ const auth = requireWriteAuth(context);
109
+ const request = resolveService(context, 'httpPost', httpPost);
110
+ const result = await dispatchRemotePrimitive(context, () => request(
111
+ auth.baseUrl,
112
+ `/alibaba/web/${input.appType}/_view/query/formdesign/saveFormSchema.json`,
113
+ querystring.stringify({
114
+ _csrf_token: auth.csrfToken,
115
+ appType: input.appType,
116
+ content: JSON.stringify(input.schema),
117
+ formUuid: input.formUuid,
118
+ gmtModified: requireSchemaServerRevision(
119
+ { gmtModified: input.serverRevision },
120
+ () => pageServiceError('SCHEMA_PAGE_WRITE_PRECHECK_FAILED', 'Page Schema revision is missing or invalid.')
121
+ ),
122
+ prefix: '_view',
123
+ schemaVersion: 'V5',
124
+ }),
125
+ auth.cookies
126
+ ));
127
+ if (isSaveFormSchemaRevisionConflict(result)) {
128
+ throw createServerRevisionConflict('page');
129
+ }
130
+ if (!result || result.success !== true || result.__needLogin || result.__csrfExpired) {
131
+ pageServiceError('SCHEMA_PAGE_SAVE_FAILED', 'Page Schema save did not return an explicit success response.');
132
+ }
133
+ return { success: true };
134
+ }
135
+
136
+ function pageReadError() {
137
+ return schemaError('SCHEMA_PAGE_READ_FAILED', 'Bound page Schema revision is missing or invalid.', {
138
+ details: { resourceType: 'page' },
139
+ });
140
+ }
141
+
142
+ function requireReadAuth(context) {
143
+ const auth = resolveAuth(context);
144
+ if (!auth || typeof auth.baseUrl !== 'string' || !auth.baseUrl) {
145
+ pageServiceError('SCHEMA_PAGE_READ_PRECHECK_FAILED', 'Page read authentication is not ready.');
146
+ }
147
+ if (isTokenAuthRef(auth)) {
148
+ return auth;
149
+ }
150
+ if (!auth.cookies) {
151
+ pageServiceError('SCHEMA_PAGE_READ_PRECHECK_FAILED', 'Page read authentication is not ready.');
152
+ }
153
+ return auth;
154
+ }
155
+
156
+ function requireWriteAuth(context) {
157
+ assertPageWriteReady(context);
158
+ return resolveAuth(context);
159
+ }
160
+
161
+ function resolveAuth(context) {
162
+ return context && context.authRef ? context.authRef : context;
163
+ }
164
+
165
+ function resolveService(context, name, fallback) {
166
+ return context && context.services && context.services[name] || fallback;
167
+ }
168
+
169
+ function hasSchemaContent(value) {
170
+ if (typeof value === 'string') {
171
+ return value.trim().length > 0;
172
+ }
173
+ return !!(value && typeof value === 'object' && !Array.isArray(value));
174
+ }
175
+
176
+ function pageServiceError(code, message) {
177
+ throw schemaError(code, message, { details: { resourceType: 'page' } });
178
+ }
179
+
180
+ module.exports = Object.freeze({
181
+ assertPageWriteReady,
182
+ createPageShellOnce,
183
+ readPageResource,
184
+ savePageSchemaOnce,
185
+ });
@@ -16,6 +16,10 @@ const { createAuthRef } = require('../core/yida-client');
16
16
  const { t } = require('../core/i18n');
17
17
  const { buildYidaI18n } = require('../core/yida-i18n');
18
18
  const { throwCommandError, throwUsage } = require('../core/command-errors');
19
+ const {
20
+ assertLegacyDirectWriteAllowed,
21
+ extractLegacyGuardArgs,
22
+ } = require('../core/legacy-schema-guard');
19
23
  const { assertPresetThemeKey } = require('./theme-presets');
20
24
 
21
25
  /**
@@ -218,7 +222,8 @@ async function fetchCurrentApp(appType, authRef) {
218
222
  }
219
223
 
220
224
  async function run(args) {
221
- const params = parseArgs(args);
225
+ const guardSplit = extractLegacyGuardArgs(args || []);
226
+ const params = parseArgs(guardSplit.args);
222
227
 
223
228
  // 验证必填参数
224
229
  const { c, banner, step, label, warn, success: chalkSuccess, result: chalkResult, error: chalkError } = require('../core/chalk');
@@ -235,6 +240,12 @@ async function run(args) {
235
240
  throwUsage(t('update_app.missing_update_field'), t('update_app.usage'));
236
241
  }
237
242
  assertPresetThemeKey(params.colour);
243
+ assertLegacyDirectWriteAllowed({
244
+ command: 'update-app',
245
+ resourceType: 'app',
246
+ action: 'update',
247
+ appType: params.appType,
248
+ }, { guardOptions: guardSplit.guardOptions });
238
249
 
239
250
  banner(t('update_app.title'));
240
251
  label('App', params.appType);
@@ -259,19 +270,20 @@ async function run(args) {
259
270
  }
260
271
 
261
272
  const currentApp = shellUpdate ? await fetchCurrentApp(params.appType, authRef) : null;
262
- const postDataObj = shellUpdate
263
- ? buildUpdateAppPostData(params, currentApp, authRef)
264
- : buildUpdateAppNamePostData(params, authRef);
265
- const postData = querystring.stringify(postDataObj);
266
273
  const requestPath = shellUpdate
267
274
  ? `/${params.appType}/query/app/updateApp.json?_api=Form.updateApp&_mock=false&_stamp=${Date.now()}`
268
275
  : `/query/app/updateAppName.json?_api=Form.updateAppName&_mock=false&_stamp=${Date.now()}`;
269
276
 
270
277
  const response = await requestWithAutoLogin((auth) => {
278
+ const postDataObj = shellUpdate
279
+ ? buildUpdateAppPostData(params, currentApp, auth)
280
+ : buildUpdateAppNamePostData(params, auth);
281
+ const postData = querystring.stringify(postDataObj);
271
282
  return httpPost(
272
283
  auth.baseUrl,
273
284
  requestPath,
274
- postData
285
+ postData,
286
+ auth.cookies
275
287
  );
276
288
  }, authRef);
277
289