openxiangda 1.0.93 → 1.0.95
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/lib/cli.js +105 -1
- package/lib/design-gates.js +65 -3
- package/package.json +2 -1
package/lib/cli.js
CHANGED
|
@@ -237,6 +237,10 @@ async function update(args) {
|
|
|
237
237
|
const requestedSubcommand = args[0] && !args[0].startsWith('--') ? args[0] : 'check';
|
|
238
238
|
const parsedArgs = requestedSubcommand === args[0] ? args.slice(1) : args;
|
|
239
239
|
const { flags } = parseArgs(parsedArgs);
|
|
240
|
+
if (wantsSubcommandHelp(requestedSubcommand, flags)) {
|
|
241
|
+
print('用法: openxiangda update check|install [--json] [--registry https://registry.npmjs.org] [--no-skills]');
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
240
244
|
const registry = normalizeNpmRegistry(flags.registry || OFFICIAL_NPM_REGISTRY);
|
|
241
245
|
|
|
242
246
|
if (requestedSubcommand === 'check') {
|
|
@@ -457,8 +461,12 @@ async function design(args) {
|
|
|
457
461
|
|
|
458
462
|
async function doctor(args) {
|
|
459
463
|
const { flags } = parseArgs(args);
|
|
464
|
+
if (flags.help || flags.h) {
|
|
465
|
+
print('用法: openxiangda doctor [--profile name] [--app-type APP_XXX] [--agent codex] [--json]');
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
460
468
|
const config = loadConfig();
|
|
461
|
-
const profileName = flags
|
|
469
|
+
const profileName = resolveDoctorProfileName(config, flags);
|
|
462
470
|
const result = {
|
|
463
471
|
cli: {
|
|
464
472
|
version: CURRENT_VERSION,
|
|
@@ -553,6 +561,24 @@ async function doctor(args) {
|
|
|
553
561
|
printDoctorReport(result);
|
|
554
562
|
}
|
|
555
563
|
|
|
564
|
+
function resolveDoctorProfileName(config, flags) {
|
|
565
|
+
if (flags.profile) return flags.profile;
|
|
566
|
+
const state = loadProjectState();
|
|
567
|
+
const boundEntries = Object.entries(state.profiles || {}).filter(([, bound]) => bound?.appType);
|
|
568
|
+
const requestedAppType = flags['app-type'];
|
|
569
|
+
if (requestedAppType) {
|
|
570
|
+
const matched = boundEntries.find(([, bound]) => bound.appType === requestedAppType);
|
|
571
|
+
if (matched) return matched[0];
|
|
572
|
+
}
|
|
573
|
+
if (config.currentProfile && state.profiles?.[config.currentProfile]?.appType) {
|
|
574
|
+
return config.currentProfile;
|
|
575
|
+
}
|
|
576
|
+
if (boundEntries.length === 1) {
|
|
577
|
+
return boundEntries[0][0];
|
|
578
|
+
}
|
|
579
|
+
return config.currentProfile;
|
|
580
|
+
}
|
|
581
|
+
|
|
556
582
|
function printDoctorReport(result) {
|
|
557
583
|
const lines = [
|
|
558
584
|
`OpenXiangda doctor v${result.cli.version}`,
|
|
@@ -577,6 +603,10 @@ function printDoctorReport(result) {
|
|
|
577
603
|
async function platform(args) {
|
|
578
604
|
const [subcommand, ...rest] = args;
|
|
579
605
|
const { flags, positional } = parseArgs(rest);
|
|
606
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
607
|
+
print('用法: openxiangda platform add|list|use|remove');
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
580
610
|
const config = loadConfig();
|
|
581
611
|
|
|
582
612
|
if (subcommand === 'add') {
|
|
@@ -652,6 +682,16 @@ async function platform(args) {
|
|
|
652
682
|
|
|
653
683
|
async function login(args) {
|
|
654
684
|
const { flags, positional } = parseArgs(args);
|
|
685
|
+
if (
|
|
686
|
+
flags.help ||
|
|
687
|
+
flags.h ||
|
|
688
|
+
positional[0] === 'help' ||
|
|
689
|
+
positional[0] === '--help' ||
|
|
690
|
+
positional[0] === '-h'
|
|
691
|
+
) {
|
|
692
|
+
print('用法: openxiangda login <platform-url> [--profile name] [--no-open] [--json]');
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
655
695
|
const config = loadConfig();
|
|
656
696
|
const rawUrl = positional[0];
|
|
657
697
|
const profileName = flags.profile || config.currentProfile || 'default';
|
|
@@ -765,6 +805,10 @@ function normalizePlatformSessionUrl(value, baseUrl) {
|
|
|
765
805
|
async function auth(args) {
|
|
766
806
|
const [subcommand, ...rest] = args;
|
|
767
807
|
const { flags } = parseArgs(rest);
|
|
808
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
809
|
+
print('用法: openxiangda auth status|refresh|logout [--profile name] [--json]');
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
768
812
|
|
|
769
813
|
if (subcommand === 'status') {
|
|
770
814
|
const config = loadConfig();
|
|
@@ -819,6 +863,10 @@ async function auth(args) {
|
|
|
819
863
|
|
|
820
864
|
async function env(args) {
|
|
821
865
|
const { flags } = parseArgs(args);
|
|
866
|
+
if (flags.help || flags.h) {
|
|
867
|
+
print('用法: openxiangda env [--profile name] [--json]');
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
822
870
|
const config = loadConfig();
|
|
823
871
|
const globalEnv = loadGlobalEnv();
|
|
824
872
|
const profileName = flags.profile || config.currentProfile;
|
|
@@ -856,6 +904,12 @@ async function env(args) {
|
|
|
856
904
|
async function feedback(args) {
|
|
857
905
|
const [subcommand, ...rest] = args;
|
|
858
906
|
const { flags, positional } = parseArgs(rest);
|
|
907
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
908
|
+
print(
|
|
909
|
+
'用法: openxiangda feedback preview|submit --summary <text> [--type bug] [--severity medium] [--profile name] [--yes] [--json]'
|
|
910
|
+
);
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
859
913
|
|
|
860
914
|
if (subcommand !== 'preview' && subcommand !== 'submit') {
|
|
861
915
|
fail(
|
|
@@ -1279,6 +1333,10 @@ function summarizeOssEnv(globalEnv) {
|
|
|
1279
1333
|
async function workspace(args) {
|
|
1280
1334
|
const [subcommand, ...rest] = args;
|
|
1281
1335
|
const { flags, positional } = parseArgs(rest);
|
|
1336
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
1337
|
+
print('用法: openxiangda workspace init|bind|publish [--changed [--since ref]|--form code|--page code|--only list] [--dry-run] [--force] [--resources|--skip-resources]');
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1282
1340
|
const config = loadConfig();
|
|
1283
1341
|
|
|
1284
1342
|
if (subcommand === 'init') {
|
|
@@ -1411,6 +1469,10 @@ async function workspace(args) {
|
|
|
1411
1469
|
async function app(args) {
|
|
1412
1470
|
const [subcommand, ...rest] = args;
|
|
1413
1471
|
const { flags, positional } = parseArgs(rest);
|
|
1472
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
1473
|
+
print('用法: openxiangda app list|create|snapshot [--profile name] [--json]');
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1414
1476
|
const config = loadConfig();
|
|
1415
1477
|
const profileName = flags.profile || config.currentProfile;
|
|
1416
1478
|
|
|
@@ -1481,6 +1543,10 @@ function extractCreatedAppType(data) {
|
|
|
1481
1543
|
async function form(args) {
|
|
1482
1544
|
const [subcommand, ...rest] = args;
|
|
1483
1545
|
const { flags, positional } = parseArgs(rest);
|
|
1546
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
1547
|
+
print('用法: openxiangda form list|create|bind|pull|publish [--profile name] [--json]');
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1484
1550
|
const config = loadConfig();
|
|
1485
1551
|
const profileName = flags.profile || config.currentProfile;
|
|
1486
1552
|
|
|
@@ -1589,6 +1655,10 @@ async function form(args) {
|
|
|
1589
1655
|
async function page(args) {
|
|
1590
1656
|
const [subcommand, ...rest] = args;
|
|
1591
1657
|
const { flags, positional } = parseArgs(rest);
|
|
1658
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
1659
|
+
print('用法: openxiangda page list|publish|bind|releases|activate [--profile name] [--json]');
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1592
1662
|
const config = loadConfig();
|
|
1593
1663
|
const profileName = flags.profile || config.currentProfile;
|
|
1594
1664
|
|
|
@@ -1709,6 +1779,10 @@ async function page(args) {
|
|
|
1709
1779
|
async function menu(args) {
|
|
1710
1780
|
const [subcommand, ...rest] = args;
|
|
1711
1781
|
const { flags, positional } = parseArgs(rest);
|
|
1782
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
1783
|
+
print('用法: openxiangda menu list|create|update|sort|bind|delete [--profile name] [--json]');
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1712
1786
|
const config = loadConfig();
|
|
1713
1787
|
const profileName = flags.profile || config.currentProfile;
|
|
1714
1788
|
|
|
@@ -2794,6 +2868,12 @@ async function notification(args) {
|
|
|
2794
2868
|
async function permission(args) {
|
|
2795
2869
|
const [subcommand, ...rest] = args;
|
|
2796
2870
|
const { flags, positional } = parseArgs(rest);
|
|
2871
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
2872
|
+
print(
|
|
2873
|
+
'用法: openxiangda permission role-list|role-create|role-update|role-delete|role-bind|role-users|role-add-users|page-group-list|page-group-create|page-group-update|page-group-delete|page-group-bind|form-group-list|form-group-create|form-group-update|form-group-delete|form-group-bind|form-summary|menu-permissions|audit'
|
|
2874
|
+
);
|
|
2875
|
+
return;
|
|
2876
|
+
}
|
|
2797
2877
|
const config = loadConfig();
|
|
2798
2878
|
const profileName = flags.profile || config.currentProfile;
|
|
2799
2879
|
|
|
@@ -3246,6 +3326,12 @@ async function permission(args) {
|
|
|
3246
3326
|
async function settings(args) {
|
|
3247
3327
|
const [subcommand, ...rest] = args;
|
|
3248
3328
|
const { flags, positional } = parseArgs(rest);
|
|
3329
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
3330
|
+
print(
|
|
3331
|
+
'用法: openxiangda settings get|save|indexes|indexes-save|data-management|data-management-save|public-access|public-access-save|public-access-delete'
|
|
3332
|
+
);
|
|
3333
|
+
return;
|
|
3334
|
+
}
|
|
3249
3335
|
const config = loadConfig();
|
|
3250
3336
|
const profileName = flags.profile || config.currentProfile;
|
|
3251
3337
|
|
|
@@ -3841,6 +3927,16 @@ function formatBytes(value) {
|
|
|
3841
3927
|
async function inspect(args) {
|
|
3842
3928
|
const [subcommand, ...rest] = args;
|
|
3843
3929
|
const { flags, positional } = parseArgs(rest);
|
|
3930
|
+
if (
|
|
3931
|
+
subcommand === 'help' ||
|
|
3932
|
+
subcommand === '--help' ||
|
|
3933
|
+
subcommand === '-h' ||
|
|
3934
|
+
flags.help ||
|
|
3935
|
+
flags.h
|
|
3936
|
+
) {
|
|
3937
|
+
print('用法: openxiangda inspect app|form|workflow|automation|permissions [--profile name] [--json]');
|
|
3938
|
+
return;
|
|
3939
|
+
}
|
|
3844
3940
|
const config = loadConfig();
|
|
3845
3941
|
const profileName = flags.profile || config.currentProfile;
|
|
3846
3942
|
|
|
@@ -3947,6 +4043,7 @@ async function commands(args) {
|
|
|
3947
4043
|
'permission form-group-list|form-group-create|form-group-update|form-group-delete|form-group-bind|form-summary|menu-permissions',
|
|
3948
4044
|
'settings get|save|indexes|indexes-save|data-management|data-management-save|public-access|public-access-save|public-access-delete',
|
|
3949
4045
|
'resource validate|plan|publish|pull|typegen|explain',
|
|
4046
|
+
'runtime deploy|releases|activate',
|
|
3950
4047
|
'inspect app|form|workflow|automation|permissions',
|
|
3951
4048
|
'feedback preview|submit',
|
|
3952
4049
|
'skill install|status|bootstrap',
|
|
@@ -3980,6 +4077,10 @@ function printWorkspaceInitReport(result) {
|
|
|
3980
4077
|
async function skill(args) {
|
|
3981
4078
|
const [subcommand, ...rest] = args;
|
|
3982
4079
|
const { flags, positional } = parseArgs(rest);
|
|
4080
|
+
if (wantsSubcommandHelp(subcommand, flags)) {
|
|
4081
|
+
print('用法: openxiangda skill install|status [--agent codex|claude|qoder|dual] [--dest <skills-dir>] [--force] [--dry-run] [--json]\n openxiangda skill bootstrap [<dir>] [--force] [--dry-run] [--json]');
|
|
4082
|
+
return;
|
|
4083
|
+
}
|
|
3983
4084
|
const options = {
|
|
3984
4085
|
agent: flags.agent || 'codex',
|
|
3985
4086
|
dest: flags.dest,
|
|
@@ -4965,6 +5066,9 @@ function validateWorkspaceResources(manifest) {
|
|
|
4965
5066
|
const errors = [];
|
|
4966
5067
|
const warnings = [];
|
|
4967
5068
|
const counts = {};
|
|
5069
|
+
if (!fs.existsSync(manifest.baseDir)) {
|
|
5070
|
+
warnings.push('未发现 src/resources;多资源正式开发请在该目录声明资源,或使用一等 CLI 子命令进行只读诊断/小步维护');
|
|
5071
|
+
}
|
|
4968
5072
|
for (const spec of RESOURCE_SPECS) {
|
|
4969
5073
|
const items = manifest[spec.key] || [];
|
|
4970
5074
|
counts[spec.key] = items.length;
|
package/lib/design-gates.js
CHANGED
|
@@ -219,15 +219,77 @@ const DESIGN_GATE_TOPICS = [
|
|
|
219
219
|
},
|
|
220
220
|
];
|
|
221
221
|
|
|
222
|
+
const DESIGN_GATE_TOPIC_ALIASES = {
|
|
223
|
+
app: 'new-app',
|
|
224
|
+
application: 'new-app',
|
|
225
|
+
dashboard: 'complex-page',
|
|
226
|
+
page: 'complex-page',
|
|
227
|
+
pages: 'complex-page',
|
|
228
|
+
login: 'auth',
|
|
229
|
+
register: 'auth',
|
|
230
|
+
registration: 'auth',
|
|
231
|
+
sso: 'auth',
|
|
232
|
+
public: 'public-access',
|
|
233
|
+
guest: 'public-access',
|
|
234
|
+
visitor: 'public-access',
|
|
235
|
+
visitors: 'public-access',
|
|
236
|
+
permission: 'permissions',
|
|
237
|
+
role: 'permissions',
|
|
238
|
+
roles: 'permissions',
|
|
239
|
+
workflow: 'workflow-automation',
|
|
240
|
+
automation: 'workflow-automation',
|
|
241
|
+
function: 'workflow-automation',
|
|
242
|
+
functions: 'workflow-automation',
|
|
243
|
+
'app-function': 'workflow-automation',
|
|
244
|
+
js_code: 'workflow-automation',
|
|
245
|
+
jscode: 'workflow-automation',
|
|
246
|
+
connector: 'connector-notification',
|
|
247
|
+
connectors: 'connector-notification',
|
|
248
|
+
notification: 'connector-notification',
|
|
249
|
+
notifications: 'connector-notification',
|
|
250
|
+
integration: 'connector-notification',
|
|
251
|
+
integrations: 'connector-notification',
|
|
252
|
+
webhook: 'connector-notification',
|
|
253
|
+
resource: 'resource-maintenance',
|
|
254
|
+
resources: 'resource-maintenance',
|
|
255
|
+
maintenance: 'resource-maintenance',
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
function resolveTopicSelection(topicCode) {
|
|
259
|
+
if (!topicCode || topicCode === 'all') {
|
|
260
|
+
return { requested: ['all'], wanted: null, unknown: [] };
|
|
261
|
+
}
|
|
262
|
+
const knownCodes = new Set(DESIGN_GATE_TOPICS.map(topic => topic.code));
|
|
263
|
+
const requested = String(topicCode)
|
|
264
|
+
.split(/[,/|+\s]+/)
|
|
265
|
+
.map(item => item.trim())
|
|
266
|
+
.filter(Boolean);
|
|
267
|
+
const wanted = new Set();
|
|
268
|
+
const unknown = [];
|
|
269
|
+
for (const item of requested) {
|
|
270
|
+
const normalized = item.toLowerCase();
|
|
271
|
+
const code = DESIGN_GATE_TOPIC_ALIASES[normalized] || normalized;
|
|
272
|
+
if (knownCodes.has(code)) {
|
|
273
|
+
wanted.add(code);
|
|
274
|
+
} else {
|
|
275
|
+
unknown.push(item);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return { requested, wanted, unknown };
|
|
279
|
+
}
|
|
280
|
+
|
|
222
281
|
function selectTopics(topicCode) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
return DESIGN_GATE_TOPICS.filter(topic => wanted.has(topic.code));
|
|
282
|
+
const selection = resolveTopicSelection(topicCode);
|
|
283
|
+
if (!selection.wanted) return DESIGN_GATE_TOPICS;
|
|
284
|
+
return DESIGN_GATE_TOPICS.filter(topic => selection.wanted.has(topic.code));
|
|
226
285
|
}
|
|
227
286
|
|
|
228
287
|
function getDesignGates(topicCode) {
|
|
288
|
+
const selection = resolveTopicSelection(topicCode);
|
|
229
289
|
return {
|
|
230
290
|
hardRule: DESIGN_GATE_HARD_RULE,
|
|
291
|
+
requestedTopics: selection.requested,
|
|
292
|
+
unknownTopics: selection.unknown,
|
|
231
293
|
topics: selectTopics(topicCode),
|
|
232
294
|
};
|
|
233
295
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.95",
|
|
4
4
|
"description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"bin": {
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"test:resource-plan": "node scripts/resource-plan-smoke.mjs",
|
|
68
68
|
"test:design-gates": "node scripts/design-gates-smoke.mjs",
|
|
69
69
|
"test:resource-cli": "node scripts/resource-cli-smoke.mjs",
|
|
70
|
+
"test:help-no-side-effects": "node scripts/help-no-side-effects-smoke.mjs",
|
|
70
71
|
"test:app-function-fallback": "node scripts/app-function-source-fallback-smoke.mjs",
|
|
71
72
|
"test:runtime-deploy": "node scripts/runtime-deploy-smoke.mjs",
|
|
72
73
|
"test:skill-install": "bash scripts/skill-install-smoke.sh",
|