openxiangda 1.0.237 → 1.0.239

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.
@@ -2,6 +2,8 @@ const crypto = require('crypto');
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
4
  const {
5
+ collectConfigurationManifestCodes,
6
+ collectManifestCodes,
5
7
  compileAppPackage,
6
8
  sha256,
7
9
  sha256Canonical,
@@ -220,17 +222,25 @@ function createDeliveryV2Executor(dependencies) {
220
222
  const originalCwd = process.cwd();
221
223
  const executionTarget = {
222
224
  ...input.target,
223
- deploymentId: input.target.deploymentId || null,
225
+ deploymentId:
226
+ input.run?.deploymentId ||
227
+ input.run?.control?.deploymentId ||
228
+ input.target.deploymentId ||
229
+ null,
224
230
  };
225
231
  let activeRun = input.run;
226
232
  let currentStep = 'preparing';
227
233
  let currentComponent = 'delivery-v2';
228
234
  try {
229
235
  process.chdir(input.executionRoot);
236
+ const executionTargets = normalizeLegacyPackageTargetsForExecution(
237
+ input.targets,
238
+ input.executionRoot
239
+ );
230
240
  deps.installDeliveryContext(
231
241
  executionTarget,
232
242
  activeRun,
233
- input.targets
243
+ executionTargets
234
244
  );
235
245
  restoreDeliveryCheckpointFiles(
236
246
  input.executionRoot,
@@ -252,7 +262,7 @@ function createDeliveryV2Executor(dependencies) {
252
262
  );
253
263
  const steps = decorateSteps(
254
264
  buildWorkspaceReleaseSteps(
255
- input.targets,
265
+ executionTargets,
256
266
  input.packageManifest.runtimeMode,
257
267
  executionTarget.profileName,
258
268
  activeRun.control?.changeId
@@ -285,6 +295,14 @@ function createDeliveryV2Executor(dependencies) {
285
295
  activeRun.result?.[doneStage] || { resumed: true };
286
296
  continue;
287
297
  }
298
+ if (step.id === 'app-finalize') {
299
+ prepareAppFinalizeStep(step, {
300
+ executionRoot: input.executionRoot,
301
+ run: activeRun,
302
+ target: executionTarget,
303
+ steps,
304
+ });
305
+ }
288
306
  currentStep = step.id;
289
307
  currentComponent = step.stagedKind || step.id;
290
308
  const result = await deps.runOpenXiangdaInProcess(step.args, {
@@ -785,6 +803,22 @@ function decorateSteps(
785
803
  step.args.push('--environment-id', target.environmentId);
786
804
  }
787
805
  step.args.push('--delivery-run-id', run.id);
806
+ const stagedIndex = step.args.indexOf('--staged-resources-json');
807
+ if (stagedIndex >= 0 && target.deploymentId) {
808
+ step.args[stagedIndex + 1] = path
809
+ .relative(
810
+ executionRoot,
811
+ path.join(
812
+ deliveryReleaseDirectory(
813
+ executionRoot,
814
+ run.control?.changeId,
815
+ target.deploymentId
816
+ ),
817
+ 'staged-resources.json'
818
+ )
819
+ )
820
+ .replace(/\\/g, '/');
821
+ }
788
822
  }
789
823
  step.command = commandFromArgs(step.args);
790
824
  result.push(step);
@@ -852,6 +886,70 @@ function compactStepResult(stepId, result, context = {}) {
852
886
  return compact;
853
887
  }
854
888
 
889
+ function prepareAppFinalizeStep(step, context = {}) {
890
+ const stagedIndex = step.args.indexOf('--staged-resources-json');
891
+ if (stagedIndex < 0) {
892
+ return {
893
+ mode: 'frozen-capture',
894
+ stagedResourceCount: 0,
895
+ };
896
+ }
897
+
898
+ const stagedStepIds = (context.steps || [])
899
+ .filter(candidate => Boolean(candidate.stagedKind))
900
+ .map(candidate => candidate.id);
901
+ const incompleteStagedCheckpoints = stagedStepIds.filter(stepId => {
902
+ const checkpointResult =
903
+ context.run?.result?.[checkpointName('done', stepId)];
904
+ if (!checkpointResult?.id) return false;
905
+ return (
906
+ normalizeCheckpointStagedResources(
907
+ checkpointResult.stagedResources || []
908
+ ).length === 0
909
+ );
910
+ });
911
+ if (incompleteStagedCheckpoints.length > 0) {
912
+ throw deliveryError(
913
+ 'DELIVERY_CHECKPOINT_STAGED_RESOURCES_MISSING',
914
+ `服务端检查点 ${incompleteStagedCheckpoints.join(
915
+ ', '
916
+ )} 已记录子 Release,但缺少可恢复 stagedResources`,
917
+ false
918
+ );
919
+ }
920
+
921
+ const restored = restoreDeliveryCheckpointFiles(
922
+ context.executionRoot,
923
+ context.run,
924
+ context.target
925
+ );
926
+ if (restored.stagedResourceCount === 0) {
927
+ step.args.splice(stagedIndex, 2);
928
+ step.command = commandFromArgs(step.args);
929
+ return {
930
+ mode: 'frozen-capture',
931
+ stagedResourceCount: 0,
932
+ };
933
+ }
934
+
935
+ const stagedResourcesPath = path.resolve(
936
+ context.executionRoot,
937
+ step.args[stagedIndex + 1]
938
+ );
939
+ if (!fs.existsSync(stagedResourcesPath)) {
940
+ throw deliveryError(
941
+ 'DELIVERY_CHECKPOINT_FILE_MISSING',
942
+ '服务端 stagedResources 检查点已恢复,但 app-finalize 暂存资源文件缺失',
943
+ false
944
+ );
945
+ }
946
+ step.command = commandFromArgs(step.args);
947
+ return {
948
+ mode: 'staged-children',
949
+ stagedResourceCount: restored.stagedResourceCount,
950
+ };
951
+ }
952
+
855
953
  function restoreDeliveryCheckpointFiles(executionRoot, run, target) {
856
954
  const changeId = String(run?.control?.changeId || '').trim();
857
955
  if (!changeId) return { stagedResourceCount: 0, restored: false };
@@ -1090,6 +1188,66 @@ function defaultIdempotencyKey(kind, target, digest) {
1090
1188
  ].join(':');
1091
1189
  }
1092
1190
 
1191
+ function normalizeLegacyPackageTargetsForExecution(targets, executionRoot) {
1192
+ const selectors = targets?.resourceSelectors?.dataViews;
1193
+ if (!Array.isArray(selectors) || selectors.length === 0) return targets;
1194
+ const dataViewDir = path.join(
1195
+ path.resolve(executionRoot),
1196
+ 'src',
1197
+ 'resources',
1198
+ 'data-views'
1199
+ );
1200
+ if (!fs.existsSync(dataViewDir)) return targets;
1201
+
1202
+ const actualCodes = new Set();
1203
+ const legacyNestedCodes = new Set();
1204
+ const visit = directory => {
1205
+ for (const entry of fs
1206
+ .readdirSync(directory, { withFileTypes: true })
1207
+ .sort((left, right) => left.name.localeCompare(right.name))) {
1208
+ const absolute = path.join(directory, entry.name);
1209
+ if (entry.isDirectory()) {
1210
+ visit(absolute);
1211
+ continue;
1212
+ }
1213
+ if (!entry.isFile() || !entry.name.endsWith('.json')) continue;
1214
+ let value;
1215
+ try {
1216
+ value = JSON.parse(fs.readFileSync(absolute, 'utf8'));
1217
+ } catch {
1218
+ // The resource command remains responsible for reporting malformed
1219
+ // manifests. This compatibility normalization only narrows selectors.
1220
+ continue;
1221
+ }
1222
+ const topLevelCodes = collectConfigurationManifestCodes(
1223
+ 'data-view',
1224
+ value
1225
+ );
1226
+ for (const code of topLevelCodes) {
1227
+ actualCodes.add(code);
1228
+ }
1229
+ const topLevelSet = new Set(topLevelCodes);
1230
+ for (const code of collectManifestCodes(value)) {
1231
+ if (!topLevelSet.has(code)) legacyNestedCodes.add(code);
1232
+ }
1233
+ }
1234
+ };
1235
+ visit(dataViewDir);
1236
+ if (actualCodes.size === 0 || legacyNestedCodes.size === 0) return targets;
1237
+
1238
+ const filtered = selectors.filter(
1239
+ code => !legacyNestedCodes.has(String(code)) || actualCodes.has(String(code))
1240
+ );
1241
+ if (filtered.length === selectors.length) return targets;
1242
+ return {
1243
+ ...targets,
1244
+ resourceSelectors: {
1245
+ ...(targets.resourceSelectors || {}),
1246
+ dataViews: filtered,
1247
+ },
1248
+ };
1249
+ }
1250
+
1093
1251
  function normalizeDigest(value) {
1094
1252
  const digest = String(value || '')
1095
1253
  .trim()
@@ -1162,6 +1320,9 @@ module.exports = {
1162
1320
  CONFIG_TARGET_BY_RESOURCE_TYPE,
1163
1321
  compactStepResult,
1164
1322
  createDeliveryV2Executor,
1323
+ decorateSteps,
1324
+ normalizeLegacyPackageTargetsForExecution,
1325
+ prepareAppFinalizeStep,
1165
1326
  releaseTargets,
1166
1327
  restoreDeliveryCheckpointFiles,
1167
1328
  structuredFailure,
@@ -285,7 +285,9 @@ function discoverResourceInventory(workspaceRoot, files) {
285
285
  relative.startsWith(prefix)
286
286
  );
287
287
  if (matched) {
288
- for (const code of codes) addConfiguration(matched[1], code);
288
+ for (const code of collectConfigurationManifestCodes(matched[1], value)) {
289
+ addConfiguration(matched[1], code);
290
+ }
289
291
  }
290
292
  }
291
293
  return {
@@ -301,6 +303,33 @@ function discoverResourceInventory(workspaceRoot, files) {
301
303
  };
302
304
  }
303
305
 
306
+ function collectConfigurationManifestCodes(type, value) {
307
+ if (type !== 'data-view') return collectManifestCodes(value);
308
+
309
+ const result = new Set();
310
+ const addItem = item => {
311
+ if (!item || typeof item !== 'object' || Array.isArray(item)) return;
312
+ const code = String(item.code || item.resourceCode || '').trim();
313
+ if (code) result.add(code);
314
+ };
315
+ if (Array.isArray(value)) {
316
+ value.forEach(addItem);
317
+ return [...result];
318
+ }
319
+ if (!value || typeof value !== 'object') return [];
320
+ const rootCode = String(value.code || value.resourceCode || '').trim();
321
+ if (rootCode) {
322
+ result.add(rootCode);
323
+ return [...result];
324
+ }
325
+ for (const key of ['dataViews', 'data-views']) {
326
+ const items = value[key];
327
+ if (Array.isArray(items)) items.forEach(addItem);
328
+ else addItem(items);
329
+ }
330
+ return [...result];
331
+ }
332
+
304
333
  function collectManifestCodes(value, result = new Set()) {
305
334
  if (Array.isArray(value)) {
306
335
  for (const item of value) collectManifestCodes(item, result);
@@ -686,6 +715,8 @@ module.exports = {
686
715
  COMPILER_VERSION,
687
716
  PACKAGE_SCHEMA_VERSION,
688
717
  canonicalJson,
718
+ collectConfigurationManifestCodes,
719
+ collectManifestCodes,
689
720
  compileAppPackage,
690
721
  discoverResourceInventory,
691
722
  layerForSourceFile,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.237",
3
+ "version": "1.0.239",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {