openxiangda 1.0.229 → 1.0.230

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 (2) hide show
  1. package/lib/cli.js +176 -8
  2. package/package.json +1 -1
package/lib/cli.js CHANGED
@@ -14212,18 +14212,36 @@ async function resource(args) {
14212
14212
  .map(item => item.formCode || item.form)
14213
14213
  .filter(Boolean)
14214
14214
  );
14215
+ const scopeGrantSourceNeedsInitialSync = (
14216
+ manifest.scopeGrantSources || []
14217
+ ).some(item => item.sync === true);
14215
14218
  const stagedChangeId =
14216
14219
  readStringFlag(flags, 'change') ||
14217
14220
  getStoredChangeBaseline(target, { access: 'reconciliation-read' })
14218
14221
  ?.changeId ||
14219
14222
  '';
14220
- if (workflowFormCodes.length > 0 && stagedChangeId) {
14223
+ const scopeGrantSourceFormCodes =
14224
+ scopeGrantSourceNeedsInitialSync && stagedChangeId
14225
+ ? await resolveScopeGrantSourceFormCodes(
14226
+ config,
14227
+ target,
14228
+ manifest.scopeGrantSources || []
14229
+ )
14230
+ : [];
14231
+ const stagedContractFormCodes = unique([
14232
+ ...workflowFormCodes,
14233
+ ...scopeGrantSourceFormCodes,
14234
+ ]).sort();
14235
+ if (
14236
+ stagedContractFormCodes.length > 0 &&
14237
+ stagedChangeId
14238
+ ) {
14221
14239
  stagedFormBindingOverlays =
14222
14240
  await resolveReusableStagedFormReleaseOverlays(
14223
14241
  config,
14224
14242
  target,
14225
14243
  stagedChangeId,
14226
- { formCodes: workflowFormCodes }
14244
+ { formCodes: stagedContractFormCodes }
14227
14245
  );
14228
14246
  }
14229
14247
  validateWorkspaceResourceBindings(
@@ -14381,6 +14399,7 @@ async function resource(args) {
14381
14399
  replaceManifest: Boolean(flags['replace-manifest']),
14382
14400
  changeId:
14383
14401
  flags.change || getStoredChangeBaseline(target)?.changeId || null,
14402
+ stagedFormBindingOverlays,
14384
14403
  activateFormBundles: Boolean(flags.activate),
14385
14404
  stageBackendReleaseOnly:
14386
14405
  Boolean(flags['stage-only']) &&
@@ -23293,7 +23312,84 @@ async function publishScopeDimensionResources(config, target, dimensions, result
23293
23312
  }
23294
23313
  }
23295
23314
 
23315
+ async function resolveScopeGrantSourceFormCodes(
23316
+ config,
23317
+ target,
23318
+ sources = []
23319
+ ) {
23320
+ const formCodes = [];
23321
+ const appendFormCode = value => {
23322
+ const candidate = String(value || '').trim();
23323
+ if (!candidate) return;
23324
+ if (target.bound.resources?.forms?.[candidate]?.formUuid) {
23325
+ formCodes.push(candidate);
23326
+ return;
23327
+ }
23328
+ for (const [code, entry] of Object.entries(
23329
+ target.bound.resources?.forms || {}
23330
+ )) {
23331
+ if (String(entry?.formUuid || '').trim() === candidate) {
23332
+ formCodes.push(code);
23333
+ return;
23334
+ }
23335
+ }
23336
+ };
23337
+ const dimensionCodes = new Set();
23338
+ for (const source of sources || []) {
23339
+ appendFormCode(
23340
+ source.sourceFormCode ||
23341
+ source.formCode ||
23342
+ source.sourceFormUuid ||
23343
+ source.formUuid
23344
+ );
23345
+ for (const mapping of source.dimensionMappings || source.dimensions || []) {
23346
+ const code = String(
23347
+ mapping?.dimensionCode || mapping?.dimension || ''
23348
+ ).trim();
23349
+ if (code) dimensionCodes.add(code);
23350
+ }
23351
+ }
23352
+ if (dimensionCodes.size > 0) {
23353
+ const dimensions = await requestWithAuth(
23354
+ config,
23355
+ target.profileName,
23356
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/scope/dimensions`
23357
+ );
23358
+ for (const dimension of normalizeItems(dimensions)) {
23359
+ const code = String(
23360
+ dimension?.code || dimension?.resourceCode || ''
23361
+ ).trim();
23362
+ if (!dimensionCodes.has(code)) continue;
23363
+ appendFormCode(dimension.sourceFormUuid || dimension.formUuid);
23364
+ }
23365
+ }
23366
+ return unique(formCodes).sort();
23367
+ }
23368
+
23296
23369
  async function publishScopeGrantSourceResources(config, target, sources, result, options = {}) {
23370
+ const stagedFormBindingOverlays =
23371
+ options.stagedFormBindingOverlays instanceof Map
23372
+ ? options.stagedFormBindingOverlays
23373
+ : new Map();
23374
+ let dimensionMap = new Map();
23375
+ if (
23376
+ stagedFormBindingOverlays.size > 0 &&
23377
+ (sources || []).some(item => item.sync === true)
23378
+ ) {
23379
+ const dimensions = await requestWithAuth(
23380
+ config,
23381
+ target.profileName,
23382
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/scope/dimensions`
23383
+ );
23384
+ dimensionMap = new Map(
23385
+ normalizeItems(dimensions)
23386
+ .map(item => [
23387
+ String(item.code || item.resourceCode || '').trim(),
23388
+ item,
23389
+ ])
23390
+ .filter(([code]) => Boolean(code))
23391
+ );
23392
+ }
23297
23393
  for (const item of sources) {
23298
23394
  const code = item.code || item.resourceCode;
23299
23395
  if (shouldSkipNoopResource(options, 'scopeGrantSource', code)) {
@@ -23316,17 +23412,88 @@ async function publishScopeGrantSourceResources(config, target, sources, result,
23316
23412
  id: data?.id,
23317
23413
  };
23318
23414
  if (item.sync === true) {
23319
- published.sync = await requestWithAuth(
23320
- config,
23321
- target.profileName,
23322
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/scope/grant-sources/${encodeURIComponent(code)}/sync`,
23323
- { method: 'POST', body: { dryRun: false } }
23324
- );
23415
+ const syncDecision = buildScopeGrantSourceSyncDecision({
23416
+ source: body,
23417
+ dimensionMap,
23418
+ stagedFormBindingOverlays,
23419
+ });
23420
+ if (syncDecision.defer) {
23421
+ published.sync = {
23422
+ status: 'deferred-until-form-activation',
23423
+ reason: syncDecision.reason,
23424
+ formUuids: syncDecision.formUuids,
23425
+ formCodes: syncDecision.formCodes,
23426
+ resumeTrigger: 'on_write_after_app_finalize',
23427
+ };
23428
+ result.warnings.push(
23429
+ `scopeGrantSource:${code}: 初始同步依赖同一 deployment 的新 staged FormRelease,当前尚无 active 数据表;已保存 on_write 配置,App finalize 后首次表单写入会自动物化`
23430
+ );
23431
+ } else {
23432
+ published.sync = await requestWithAuth(
23433
+ config,
23434
+ target.profileName,
23435
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/scope/grant-sources/${encodeURIComponent(code)}/sync`,
23436
+ { method: 'POST', body: { dryRun: false } }
23437
+ );
23438
+ }
23325
23439
  }
23326
23440
  result.published.push(published);
23327
23441
  }
23328
23442
  }
23329
23443
 
23444
+ function buildScopeGrantSourceSyncDecision({
23445
+ source,
23446
+ dimensionMap = new Map(),
23447
+ stagedFormBindingOverlays = new Map(),
23448
+ } = {}) {
23449
+ const stagedNewForms = new Map(
23450
+ Array.from(stagedFormBindingOverlays.values())
23451
+ .filter(item => item?.parentReleaseId === null && item?.formUuid)
23452
+ .map(item => [
23453
+ String(item.formUuid).trim(),
23454
+ String(item.formCode || '').trim(),
23455
+ ])
23456
+ );
23457
+ if (stagedNewForms.size === 0) {
23458
+ return {
23459
+ defer: false,
23460
+ reason: null,
23461
+ formUuids: [],
23462
+ formCodes: [],
23463
+ };
23464
+ }
23465
+ const referencedFormUuids = [
23466
+ source?.sourceFormUuid,
23467
+ ...(source?.dimensionMappings || []).map(mapping => {
23468
+ const code = String(
23469
+ mapping?.dimensionCode || mapping?.dimension || ''
23470
+ ).trim();
23471
+ const dimension = dimensionMap.get(code);
23472
+ return dimension?.sourceFormUuid || dimension?.formUuid;
23473
+ }),
23474
+ ]
23475
+ .map(value => String(value || '').trim())
23476
+ .filter(Boolean);
23477
+ const formUuids = unique(
23478
+ referencedFormUuids.filter(formUuid =>
23479
+ stagedNewForms.has(formUuid)
23480
+ )
23481
+ ).sort();
23482
+ return {
23483
+ defer: formUuids.length > 0,
23484
+ reason:
23485
+ formUuids.length > 0
23486
+ ? 'staged_new_form_has_no_active_data_table'
23487
+ : null,
23488
+ formUuids,
23489
+ formCodes: unique(
23490
+ formUuids
23491
+ .map(formUuid => stagedNewForms.get(formUuid))
23492
+ .filter(Boolean)
23493
+ ).sort(),
23494
+ };
23495
+ }
23496
+
23330
23497
  async function publishDataScopePolicyResources(config, target, policies, result, options = {}) {
23331
23498
  for (const item of policies) {
23332
23499
  const code = item.code || item.resourceCode;
@@ -29263,6 +29430,7 @@ function buildWorkspacePublishEnv(
29263
29430
 
29264
29431
  module.exports = {
29265
29432
  buildResourceManifestSddTargets,
29433
+ buildScopeGrantSourceSyncDecision,
29266
29434
  main,
29267
29435
  satisfiedFormCodesFromContext,
29268
29436
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.229",
3
+ "version": "1.0.230",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {