openyida 2026.7.21 → 2026.7.23-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/yida.js +29 -2
- package/lib/app/canvas-compile.js +44 -12
- package/lib/app/create-form/definition-reader.js +22 -2
- package/lib/app/create-form.js +378 -43
- package/lib/app/generate-page.js +42 -1
- package/lib/app/publish.js +27 -0
- package/lib/app/services/form-compiler.js +66 -4
- package/lib/core/agent-capabilities.js +258 -0
- package/lib/core/command-manifest.js +236 -0
- package/lib/core/locales/en.js +11 -0
- package/lib/core/locales/zh.js +11 -0
- package/package.json +1 -1
- package/scripts/postinstall.js +4 -0
- package/scripts/validate-command-manifest.js +72 -0
- package/yida-skills/SKILL.md +12 -5
- package/yida-skills/references/setup-and-env.md +12 -10
- package/yida-skills/skills/yida-app/SKILL.md +24 -3
- package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +9 -3
- package/yida-skills/skills/yida-canvas-custom-page/references/dependencies-and-cdn.md +5 -1
- package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +2 -0
- package/yida-skills/skills/yida-canvas-data-binding/SKILL.md +1 -0
- package/yida-skills/skills/yida-create-form-page/SKILL.md +10 -0
- package/yida-skills/skills/yida-custom-page/SKILL.md +3 -0
- package/yida-skills/skills/yida-get-schema/SKILL.md +8 -2
- package/yida-skills/skills/yida-login/SKILL.md +9 -7
- package/yida-skills/skills/yida-publish-page/SKILL.md +3 -1
- package/yida-skills/skills-index.json +1 -1
package/bin/yida.js
CHANGED
|
@@ -14,7 +14,7 @@ const { version: currentVersion } = require('../package.json');
|
|
|
14
14
|
const { t } = require('../lib/core/i18n');
|
|
15
15
|
const { warn } = require('../lib/core/chalk');
|
|
16
16
|
const { CliError, isCliError, toErrorPayload } = require('../lib/core/cli-error');
|
|
17
|
-
const { COMMAND_GROUPS, buildCommandManifest } = require('../lib/core/command-manifest');
|
|
17
|
+
const { COMMAND_GROUPS, buildCommandManifest, findCommandSuggestion } = require('../lib/core/command-manifest');
|
|
18
18
|
|
|
19
19
|
const command = process.argv[2];
|
|
20
20
|
const args = process.argv.slice(3);
|
|
@@ -477,6 +477,33 @@ function throwCliUsage(...lines) {
|
|
|
477
477
|
});
|
|
478
478
|
}
|
|
479
479
|
|
|
480
|
+
function formatSuggestionMessage(suggestion) {
|
|
481
|
+
if (!suggestion) {
|
|
482
|
+
return '';
|
|
483
|
+
}
|
|
484
|
+
if (suggestion.message_key) {
|
|
485
|
+
return t(suggestion.message_key, ...(suggestion.message_args || []));
|
|
486
|
+
}
|
|
487
|
+
return '';
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function throwUnknownCommand(commandName, commandArgs = []) {
|
|
491
|
+
const suggestion = findCommandSuggestion([commandName, ...commandArgs]);
|
|
492
|
+
const lines = [t('cli.unknown_command', commandName)];
|
|
493
|
+
if (suggestion) {
|
|
494
|
+
lines.push(t('cli.command_suggestion', suggestion.suggested_usage));
|
|
495
|
+
const suggestionMessage = formatSuggestionMessage(suggestion);
|
|
496
|
+
if (suggestionMessage) {
|
|
497
|
+
lines.push(suggestionMessage);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
lines.push(t('cli.run_help'));
|
|
501
|
+
throw new CliError(lines.filter(Boolean).join('\n'), {
|
|
502
|
+
code: 'INVALID_ARGUMENTS',
|
|
503
|
+
details: suggestion ? { suggestion } : undefined,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
|
|
480
507
|
function hasHelpFlag(cliArgs = []) {
|
|
481
508
|
return cliArgs.includes('--help') || cliArgs.includes('-h');
|
|
482
509
|
}
|
|
@@ -1147,7 +1174,7 @@ async function main() {
|
|
|
1147
1174
|
}
|
|
1148
1175
|
|
|
1149
1176
|
default: {
|
|
1150
|
-
|
|
1177
|
+
throwUnknownCommand(command, args);
|
|
1151
1178
|
}
|
|
1152
1179
|
}
|
|
1153
1180
|
}
|
|
@@ -35,8 +35,9 @@ const Babel = require('@babel/standalone');
|
|
|
35
35
|
* 逐条镜像自 @ali/vc-deep-yida 的
|
|
36
36
|
* src/components/yida-code-canvas/dependencies.ts → getModuleAliasMap()
|
|
37
37
|
* 只保留运行时真正用到的 windowAlias(资源 URL 由画布运行时按别名注入,
|
|
38
|
-
* 本地编译不关心 CDN
|
|
39
|
-
*
|
|
38
|
+
* 本地编译不关心 CDN 地址)。默认拒绝未收录依赖;如果宜搭物料依赖表已经
|
|
39
|
+
* 先于 CLI 升级,可临时设置 OPENYIDA_CANVAS_ALLOW_UNSUPPORTED_IMPORTS=1
|
|
40
|
+
* 退回旧的 window["pkg"] 映射,避免白名单漂移阻断发布。
|
|
40
41
|
* @type {Record<string, string>}
|
|
41
42
|
*/
|
|
42
43
|
const MODULE_ALIAS_MAP = {
|
|
@@ -59,6 +60,19 @@ const IMPORT_SIDE_EFFECT_PATTERN = /import\s+['"]([^'"]+)['"]/g;
|
|
|
59
60
|
const REQUIRE_PATTERN = /require\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
60
61
|
const DYNAMIC_IMPORT_PATTERN = /import\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
61
62
|
|
|
63
|
+
function isTruthy(value) {
|
|
64
|
+
return ['1', 'true', 'yes', 'on'].includes(String(value || '').trim().toLowerCase());
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function shouldAllowUnsupportedBareImports(options = {}, env = process.env) {
|
|
68
|
+
return options.allowUnsupportedBareImports === true ||
|
|
69
|
+
isTruthy(env.OPENYIDA_CANVAS_ALLOW_UNSUPPORTED_IMPORTS);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function packageTempName(pkg) {
|
|
73
|
+
return String(pkg || 'module').replace(/[^A-Za-z0-9_$]+/g, '_') || 'module';
|
|
74
|
+
}
|
|
75
|
+
|
|
62
76
|
function stripJsComments(code) {
|
|
63
77
|
return String(code || '')
|
|
64
78
|
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
@@ -113,16 +127,27 @@ function resolveWindowAlias(pkg) {
|
|
|
113
127
|
* export const x = ... → const x = ...(去掉 export 关键字)
|
|
114
128
|
* @param {{ types: import('@babel/types') }} babel
|
|
115
129
|
*/
|
|
116
|
-
function esmToWindowPlugin({ types: t }) {
|
|
117
|
-
|
|
118
|
-
|
|
130
|
+
function esmToWindowPlugin({ types: t }, options = {}) {
|
|
131
|
+
const allowUnsupportedBareImports = options.allowUnsupportedBareImports === true;
|
|
132
|
+
|
|
133
|
+
function moduleExpr(pkg, alias) {
|
|
119
134
|
if (alias) {
|
|
120
135
|
return t.memberExpression(t.identifier('window'), t.identifier(alias));
|
|
121
136
|
}
|
|
122
|
-
// 未收录包:退化为 window["pkg"],运行时若未注入会自然报错(与线上一致)。
|
|
123
137
|
return t.memberExpression(t.identifier('window'), t.stringLiteral(pkg), true);
|
|
124
138
|
}
|
|
125
139
|
|
|
140
|
+
function buildUnsupportedBareImportError(path, pkg) {
|
|
141
|
+
return path.buildCodeFrameError(
|
|
142
|
+
`Code Canvas 不支持从裸包 "${pkg}" 导入绑定。`
|
|
143
|
+
+ '只允许 MODULE_ALIAS_MAP 白名单依赖;'
|
|
144
|
+
+ '宜搭平台运行态全局对象请显式使用 window.* 访问'
|
|
145
|
+
+ '(例如 window.Deep、window.DeepYida、window.YidaNativeComponents),不要从包中 import。'
|
|
146
|
+
+ '若已确认宜搭物料运行态已注入该包且 CLI 白名单滞后,可临时设置 '
|
|
147
|
+
+ 'OPENYIDA_CANVAS_ALLOW_UNSUPPORTED_IMPORTS=1 退回 legacy window["pkg"] 映射。'
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
126
151
|
return {
|
|
127
152
|
name: 'yida-esm-to-window',
|
|
128
153
|
visitor: {
|
|
@@ -140,10 +165,14 @@ function esmToWindowPlugin({ types: t }) {
|
|
|
140
165
|
path.remove();
|
|
141
166
|
return;
|
|
142
167
|
}
|
|
168
|
+
const alias = resolveWindowAlias(pkg);
|
|
169
|
+
if (!alias && !allowUnsupportedBareImports) {
|
|
170
|
+
throw buildUnsupportedBareImportError(path, pkg);
|
|
171
|
+
}
|
|
143
172
|
|
|
144
173
|
const decls = [];
|
|
145
|
-
const tmp = path.scope.generateUidIdentifier(
|
|
146
|
-
decls.push(t.variableDeclarator(t.cloneNode(tmp), moduleExpr(pkg)));
|
|
174
|
+
const tmp = path.scope.generateUidIdentifier(alias || packageTempName(pkg));
|
|
175
|
+
decls.push(t.variableDeclarator(t.cloneNode(tmp), moduleExpr(pkg, alias)));
|
|
147
176
|
|
|
148
177
|
const namedProps = [];
|
|
149
178
|
for (const spec of specifiers) {
|
|
@@ -230,7 +259,7 @@ function esmToWindowPlugin({ types: t }) {
|
|
|
230
259
|
* @param {string} source 原始 React/JSX/TSX 源码
|
|
231
260
|
* @returns {{ runtimeCode: string, importedModules: string }}
|
|
232
261
|
*/
|
|
233
|
-
function compileCanvasLocal(source) {
|
|
262
|
+
function compileCanvasLocal(source, options = {}) {
|
|
234
263
|
const importedModules = extractImportedModules(source);
|
|
235
264
|
|
|
236
265
|
// 第一步:剥类型 + 转 JSX(classic runtime,产出 React.createElement,
|
|
@@ -265,7 +294,9 @@ function compileCanvasLocal(source) {
|
|
|
265
294
|
// 第二步:把 import/export 改写成 window 别名 + YidaComp。
|
|
266
295
|
const stage2 = Babel.transform(intermediate, {
|
|
267
296
|
filename: 'canvas.js',
|
|
268
|
-
plugins: [esmToWindowPlugin
|
|
297
|
+
plugins: [[esmToWindowPlugin, {
|
|
298
|
+
allowUnsupportedBareImports: shouldAllowUnsupportedBareImports(options),
|
|
299
|
+
}]],
|
|
269
300
|
sourceType: 'module',
|
|
270
301
|
compact: false,
|
|
271
302
|
babelrc: false,
|
|
@@ -286,14 +317,14 @@ function compileCanvasLocal(source) {
|
|
|
286
317
|
* @param {object} [options] 兼容占位,未使用
|
|
287
318
|
* @returns {Promise<{ runtimeCode: string, importedModules: string }>}
|
|
288
319
|
*/
|
|
289
|
-
function compileCanvas(source, options = {}) {
|
|
320
|
+
function compileCanvas(source, options = {}) {
|
|
290
321
|
return new Promise((resolve, reject) => {
|
|
291
322
|
if (typeof source !== 'string' || source.trim() === '') {
|
|
292
323
|
reject(new Error('canvas 编译源码为空'));
|
|
293
324
|
return;
|
|
294
325
|
}
|
|
295
326
|
try {
|
|
296
|
-
resolve(compileCanvasLocal(source));
|
|
327
|
+
resolve(compileCanvasLocal(source, options));
|
|
297
328
|
} catch (compileError) {
|
|
298
329
|
const detail = compileError && compileError.message ? compileError.message : String(compileError);
|
|
299
330
|
reject(new Error(`Code Canvas 本地编译失败: ${detail}`));
|
|
@@ -306,5 +337,6 @@ module.exports = {
|
|
|
306
337
|
compileCanvasLocal,
|
|
307
338
|
extractImportedModules,
|
|
308
339
|
resolveWindowAlias,
|
|
340
|
+
shouldAllowUnsupportedBareImports,
|
|
309
341
|
MODULE_ALIAS_MAP,
|
|
310
342
|
};
|
|
@@ -17,6 +17,26 @@ function readJsonInput(value, options) {
|
|
|
17
17
|
return fs.readFileSync(resolvedPath, 'utf-8');
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
function normalizeCreateFields(fields) {
|
|
21
|
+
if (
|
|
22
|
+
!Array.isArray(fields)
|
|
23
|
+
|| fields.length === 0
|
|
24
|
+
|| !fields.every((item) => (
|
|
25
|
+
item
|
|
26
|
+
&& typeof item === 'object'
|
|
27
|
+
&& !Array.isArray(item)
|
|
28
|
+
&& String(item.action || '').toLowerCase() === 'add'
|
|
29
|
+
&& item.field
|
|
30
|
+
&& typeof item.field === 'object'
|
|
31
|
+
&& !Array.isArray(item.field)
|
|
32
|
+
))
|
|
33
|
+
) {
|
|
34
|
+
return fields;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return fields.map((item) => item.field);
|
|
38
|
+
}
|
|
39
|
+
|
|
20
40
|
function createDefinitionReaders(dependencies) {
|
|
21
41
|
const {
|
|
22
42
|
fs,
|
|
@@ -43,9 +63,9 @@ function createDefinitionReaders(dependencies) {
|
|
|
43
63
|
let columns = 1;
|
|
44
64
|
|
|
45
65
|
if (Array.isArray(parsed)) {
|
|
46
|
-
fields = parsed;
|
|
66
|
+
fields = normalizeCreateFields(parsed);
|
|
47
67
|
} else if (typeof parsed === 'object' && parsed !== null) {
|
|
48
|
-
fields = parsed.fields || [];
|
|
68
|
+
fields = normalizeCreateFields(parsed.fields || []);
|
|
49
69
|
columns = parsed.columns !== undefined ? parsed.columns : 1;
|
|
50
70
|
if (Array.isArray(parsed.validations)) {
|
|
51
71
|
validations = parsed.validations;
|