openyida 2026.7.12-1 → 2026.7.13

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/README.md CHANGED
@@ -343,8 +343,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
343
343
  | `openyida logout` | Logout / switch account |
344
344
  | `openyida auth <status\|login\|refresh\|logout>` | Login state management |
345
345
  | `openyida org <list\|switch>` | Organization management (list / switch) |
346
- | `openyida env [--json]` | Detect AI tool environment & login state |
347
- | `openyida env <setup\|list\|show\|switch\|add\|remove>` | Manage public/private Yida environment profiles |
346
+ | `openyida env [--json\|setup\|list\|show\|switch\|add\|remove] [options]` | Detect AI tool environment & login state |
348
347
 
349
348
  ### App Management
350
349
 
@@ -374,7 +373,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
374
373
  | `openyida create-form add-option <appType> <formUuid> <fieldLabel> <option1> [option2] ...` | Update a form page |
375
374
  | `openyida list-forms <appType> [--keyword <text>]` | List forms/pages in an app |
376
375
  | `openyida aggregate-table <list\|create-empty\|inspect\|preview\|save\|publish\|status> <appType> ...` | Manage aggregate tables (virtualView) |
377
- | `openyida get-schema <appType> <formUuid\|--all>` | Get one form Schema or all form Schemas |
376
+ | `openyida get-schema <appType> <formUuid\|--all> [--summary-json\|--field-map-json]` | Get one form Schema or all form Schemas |
378
377
  | `openyida er <appType> [--format mermaid\|json] [--output file] [--include-system] [--include-pages]` | Export app entity relationship diagram |
379
378
  | `openyida create-page <appType> "<name>" [--mode dashboard] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a custom display page |
380
379
  | `openyida generate-page <template>` | Generate page from curated template |
@@ -469,8 +468,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
469
468
  | `openyida update` | Check and update to latest version |
470
469
  | `openyida export-conversation [options]` | Export AI conversation records |
471
470
  | `openyida feedback <setup\|url\|dismiss\|status> [options]` | Configure experience feedback form and local reminder state |
472
- | `openyida batch <file> [--stop-on-error] [--json]` | Run OpenYida commands in batch |
473
- | `openyida batch --commands "cmd1 ; cmd2" [--stop-on-error] [--json]` | Run OpenYida commands in batch |
471
+ | `openyida batch <file>\|--commands "cmd1 ; cmd2" [--stop-on-error] [--json]` | Run OpenYida commands in batch |
474
472
  | `openyida flash-to-prd --file <path> --name "<project>"` | Convert flash notes or meeting notes to a PRD prompt |
475
473
  | `openyida ai <text\|image> [options]` | Call Yida AI text and image recognition APIs |
476
474
  | `openyida cdn-config [options]` | Configure CDN / OSS upload |
@@ -2,8 +2,8 @@
2
2
  * get-schema.js - 宜搭表单 Schema 获取命令
3
3
  *
4
4
  * 用法:
5
- * openyida get-schema <appType> <formUuid>
6
- * openyida get-schema <appType> --all [--output-dir <dir>] [--concurrency N] [--retries N]
5
+ * openyida get-schema <appType> <formUuid> [--summary-json|--field-map-json]
6
+ * openyida get-schema <appType> --all [--summary-json] [--output-dir <dir>] [--concurrency N] [--retries N]
7
7
  */
8
8
 
9
9
  'use strict';
@@ -31,7 +31,7 @@ const FIELD_TYPES_NEEDING_VALUE_SUFFIX = new Set([
31
31
  /**
32
32
  * 从 Schema 中提取字段摘要,列出每个字段的真实 fieldId、组件别名和报表用 reportFieldCode。
33
33
  * @param {object} schemaResult - getFormSchema API 返回结果
34
- * @returns {Array<{label, componentName, fieldId, alias, reportFieldCode}>}
34
+ * @returns {Array<{label, componentName, fieldId, alias, reportFieldCode, options}>}
35
35
  */
36
36
  function extractFieldSummary(schemaResult) {
37
37
  const fields = [];
@@ -62,12 +62,17 @@ function extractFieldSummary(schemaResult) {
62
62
  ? `${fieldId}_value`
63
63
  : fieldId;
64
64
  if (fieldId) {
65
+ const options = extractOptionSummary(props);
66
+ const optionSource = getOptionSource(props) || [];
65
67
  fields.push({
66
68
  label,
67
69
  componentName: node.componentName,
68
70
  fieldId,
69
71
  alias: aliasMaps.aliasByFieldId[fieldId] || '',
70
72
  reportFieldCode,
73
+ options,
74
+ optionCount: optionSource.length,
75
+ optionsTruncated: optionSource.length > options.length,
71
76
  });
72
77
  }
73
78
  }
@@ -87,6 +92,70 @@ function extractFieldSummary(schemaResult) {
87
92
  return fields;
88
93
  }
89
94
 
95
+ function normalizeOptionLabel(value) {
96
+ if (value === null || value === undefined) {
97
+ return '';
98
+ }
99
+ if (typeof value === 'object') {
100
+ return value.zh_CN || value.zh_HK || value.en_US || value.ja_JP || value.text || value.label || value.value || '';
101
+ }
102
+ return String(value);
103
+ }
104
+
105
+ function firstPresent(values) {
106
+ return values.find(value => value !== undefined && value !== null);
107
+ }
108
+
109
+ function normalizeOptionValue(value, fallback) {
110
+ if (value === null || value === undefined || value === '') {
111
+ return fallback;
112
+ }
113
+ if (typeof value === 'object') {
114
+ return value.value || value.label || value.text || fallback;
115
+ }
116
+ return String(value);
117
+ }
118
+
119
+ function optionArrayFromDataSource(dataSource) {
120
+ if (!dataSource) {
121
+ return null;
122
+ }
123
+ if (Array.isArray(dataSource)) {
124
+ return dataSource;
125
+ }
126
+ const candidates = [
127
+ dataSource.options,
128
+ dataSource.data,
129
+ dataSource.list,
130
+ dataSource.values,
131
+ ];
132
+ return candidates.find(Array.isArray) || null;
133
+ }
134
+
135
+ function getOptionSource(props = {}) {
136
+ return Array.isArray(props.options)
137
+ ? props.options
138
+ : optionArrayFromDataSource(props.dataSource);
139
+ }
140
+
141
+ function extractOptionSummary(props = {}) {
142
+ const source = getOptionSource(props);
143
+ if (!source) {
144
+ return [];
145
+ }
146
+ return source.slice(0, 50).map((item, index) => {
147
+ if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
148
+ const text = String(item);
149
+ return { label: text, value: text };
150
+ }
151
+ const label = normalizeOptionLabel(firstPresent([item.label, item.text, item.name, item.title, item.value]));
152
+ return {
153
+ label,
154
+ value: normalizeOptionValue(firstPresent([item.value, item.key, item.id]), label || String(index)),
155
+ };
156
+ });
157
+ }
158
+
90
159
  function buildComponentAliasMaps(schemaResult) {
91
160
  const aliasByFieldId = {};
92
161
  const fieldIdByAlias = {};
@@ -136,6 +205,7 @@ function parseArgs(args) {
136
205
  // 仅返回目标字段的 {componentName, fieldId, label, props}
137
206
  field: '',
138
207
  json: false,
208
+ summaryJson: false,
139
209
  };
140
210
 
141
211
  for (let index = 1; index < args.length; index++) {
@@ -159,6 +229,8 @@ function parseArgs(args) {
159
229
  index++;
160
230
  } else if (arg === '--json') {
161
231
  parsed.json = true;
232
+ } else if (arg === '--summary-json' || arg === '--field-map-json') {
233
+ parsed.summaryJson = true;
162
234
  } else if (!arg.startsWith('--') && !parsed.formUuid) {
163
235
  parsed.formUuid = arg;
164
236
  }
@@ -303,6 +375,18 @@ function printFieldSummary(result) {
303
375
  process.stderr.write(` ${c.dim}注:SelectField/EmployeeField 在报表中需加 _value 后缀${c.reset}\n\n`);
304
376
  }
305
377
 
378
+ function buildSchemaSummary(appType, formUuid, schemaResult, meta = {}) {
379
+ const fields = extractFieldSummary(schemaResult);
380
+ return {
381
+ success: true,
382
+ appType,
383
+ formUuid,
384
+ ...meta,
385
+ fieldCount: fields.length,
386
+ fields,
387
+ };
388
+ }
389
+
306
390
  function filterForms(forms, keyword) {
307
391
  if (!keyword) {
308
392
  return forms;
@@ -373,9 +457,19 @@ async function fetchSchemaRecord(appType, form, authRef, retries) {
373
457
  };
374
458
  }
375
459
 
376
- function writeBatchOutput(outputDir, records) {
460
+ function summarizeRecord(record) {
461
+ if (!record.success) {
462
+ return record;
463
+ }
464
+ const { schema, ...summary } = record;
465
+ void schema;
466
+ return summary;
467
+ }
468
+
469
+ function writeBatchOutput(outputDir, records, options = {}) {
470
+ const compact = !!options.compact;
377
471
  if (!outputDir) {
378
- return records;
472
+ return compact ? records.map(summarizeRecord) : records;
379
473
  }
380
474
 
381
475
  const resolvedDir = path.resolve(outputDir);
@@ -391,10 +485,8 @@ function writeBatchOutput(outputDir, records) {
391
485
  const filePath = path.join(resolvedDir, fileName);
392
486
  fs.writeFileSync(filePath, JSON.stringify(record.schema, null, 2), 'utf-8');
393
487
 
394
- const { schema, ...summary } = record;
395
- void schema;
396
488
  return {
397
- ...summary,
489
+ ...summarizeRecord(record),
398
490
  schemaFile: filePath,
399
491
  };
400
492
  });
@@ -452,6 +544,11 @@ async function runSingle(parsed, authRef) {
452
544
  return;
453
545
  }
454
546
 
547
+ if (parsed.summaryJson) {
548
+ console.log(JSON.stringify(buildSchemaSummary(parsed.appType, parsed.formUuid, result), null, 2));
549
+ return;
550
+ }
551
+
455
552
  chalkSuccess(t('get_schema.success'));
456
553
  printFieldSummary(result);
457
554
  console.log(JSON.stringify(result, null, 2));
@@ -494,7 +591,7 @@ async function runBatch(parsed, authRef) {
494
591
  return record;
495
592
  });
496
593
 
497
- const outputRecords = writeBatchOutput(parsed.outputDir, records);
594
+ const outputRecords = writeBatchOutput(parsed.outputDir, records, { compact: parsed.summaryJson });
498
595
  const successCount = records.filter(record => record.success).length;
499
596
  const failedCount = records.length - successCount;
500
597
 
@@ -509,6 +606,7 @@ async function runBatch(parsed, authRef) {
509
606
  total: records.length,
510
607
  successCount,
511
608
  failedCount,
609
+ summaryOnly: parsed.summaryJson || undefined,
512
610
  outputDir: parsed.outputDir ? path.resolve(parsed.outputDir) : undefined,
513
611
  forms: outputRecords,
514
612
  }, null, 2));
@@ -527,6 +625,8 @@ async function run(args) {
527
625
 
528
626
  module.exports = {
529
627
  extractFieldSummary,
628
+ extractOptionSummary,
629
+ buildSchemaSummary,
530
630
  buildComponentAliasMaps,
531
631
  parseArgs,
532
632
  filterForms,
@@ -48,8 +48,12 @@ function buildAgentCapabilities() {
48
48
  count: manifest.summary.command_count,
49
49
  group_count: manifest.summary.group_count,
50
50
  side_effect_counts: manifest.summary.side_effect_counts,
51
+ permission_mode_counts: manifest.summary.permission_mode_counts,
51
52
  read_only_command_ids: manifest.summary.read_only_command_ids,
52
53
  mutating_command_ids: manifest.summary.mutating_command_ids,
54
+ allow_command_ids: manifest.summary.allow_command_ids,
55
+ ask_command_ids: manifest.summary.ask_command_ids,
56
+ deny_command_ids: manifest.summary.deny_command_ids,
53
57
  core_workflows: manifest.summary.core_workflows,
54
58
  },
55
59
  sideEffects: {
@@ -63,11 +67,13 @@ function buildAgentCapabilities() {
63
67
  completion_contracts: {
64
68
  full_app: 'Default fast_build is complete after creating the app, core forms, primary page, publishing it, and returning an access URL.',
65
69
  },
70
+ fast_build_data_contract: 'Default fast_build page code must not call this.dataSourceMap.* unless the same run created and bound a designer data source; use this.utils.yida.* or an entry-only page by default.',
66
71
  },
67
72
  command_manifest: {
68
73
  schema_version: manifest.schema_version,
69
74
  groups: manifest.groups,
70
75
  side_effect_schema: manifest.side_effect_schema,
76
+ permission_schema: manifest.permission_schema,
71
77
  summary: manifest.summary,
72
78
  commands: manifest.commands,
73
79
  },