kintone-migrator 0.31.3 → 0.31.5

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/dist/index.mjs CHANGED
@@ -713,7 +713,7 @@ const ActionDiffDetector = { detect: (local, remote) => {
713
713
  if (diffs.length > 0) return {
714
714
  type: "modified",
715
715
  actionName: name,
716
- details: diffs.join(", ")
716
+ details: diffs.join("\n")
717
717
  };
718
718
  },
719
719
  onDeleted: (name, remoteAction) => ({
@@ -2036,8 +2036,15 @@ async function executeMultiApp(plan, executor) {
2036
2036
  continue;
2037
2037
  }
2038
2038
  try {
2039
- await executor(app);
2040
- results.push({
2039
+ const outcome = await executor(app);
2040
+ if (outcome && outcome.ok === false) {
2041
+ results.push({
2042
+ name: app.name,
2043
+ status: "failed",
2044
+ error: outcome.error
2045
+ });
2046
+ failed = true;
2047
+ } else results.push({
2041
2048
  name: app.name,
2042
2049
  status: "succeeded"
2043
2050
  });
@@ -2428,6 +2435,11 @@ function colorizeDiffEntry(type) {
2428
2435
  prefix: type === "added" ? "+" : type === "deleted" ? "-" : "~"
2429
2436
  };
2430
2437
  }
2438
+ function indentContinuationLines(text, indent = " ") {
2439
+ if (!text.includes("\n")) return text;
2440
+ const [first, ...rest] = text.split("\n");
2441
+ return [first, ...rest.map((line) => line.length > 0 ? `${indent}${line}` : line)].join("\n");
2442
+ }
2431
2443
  function printGenericDiffResult(result, title, formatEntry) {
2432
2444
  for (const w of result.warnings) p.log.warn(w);
2433
2445
  if (result.isEmpty) {
@@ -2437,7 +2449,7 @@ function printGenericDiffResult(result, title, formatEntry) {
2437
2449
  p.log.info(`Changes: ${formatDiffSummary(result.summary)}`);
2438
2450
  const lines = result.entries.map((entry) => {
2439
2451
  const { colorize, prefix } = colorizeDiffEntry(entry.type);
2440
- return formatEntry(entry, colorize, prefix);
2452
+ return indentContinuationLines(formatEntry(entry, colorize, prefix));
2441
2453
  });
2442
2454
  p.note(lines.join("\n"), title, { format: (v) => v });
2443
2455
  }
@@ -2465,7 +2477,7 @@ function printDiffResult(result) {
2465
2477
  if (result.hasLayoutChanges) p.log.info("Layout changes detected.");
2466
2478
  const lines = result.entries.map((entry) => {
2467
2479
  const { colorize, prefix } = colorizeDiffEntry(entry.type);
2468
- return `${colorize(prefix)} ${pc.dim("[")}${colorize(entry.fieldCode)}${pc.dim("]")} ${entry.fieldLabel}${pc.dim(":")} ${entry.details}`;
2480
+ return indentContinuationLines(`${colorize(prefix)} ${pc.dim("[")}${colorize(entry.fieldCode)}${pc.dim("]")} ${entry.fieldLabel}${pc.dim(":")} ${entry.details}`);
2469
2481
  });
2470
2482
  p.note(lines.join("\n"), "Diff Details", { format: (v) => v });
2471
2483
  }
@@ -2657,7 +2669,7 @@ async function routeMultiApp(values, handlers) {
2657
2669
  async function runMultiAppWithHeaders(plan, executor, successMessage) {
2658
2670
  await runMultiAppWithFailCheck(plan, async (app) => {
2659
2671
  printAppHeader(app.name, app.appId);
2660
- await executor(app);
2672
+ return executor(app);
2661
2673
  }, successMessage);
2662
2674
  }
2663
2675
  /**
@@ -3447,7 +3459,7 @@ const AppPermissionDiffDetector = { detect: (local, remote) => {
3447
3459
  if (diffs.length > 0) entries.push({
3448
3460
  type: "modified",
3449
3461
  entityKey: key,
3450
- details: diffs.join(", ")
3462
+ details: diffs.join("\n")
3451
3463
  });
3452
3464
  }
3453
3465
  }
@@ -3946,7 +3958,7 @@ function describeChanges$1(before, after) {
3946
3958
  if (before.label !== after.label) changes.push(`label: ${before.label} -> ${after.label}`);
3947
3959
  if ((before.noLabel ?? false) !== (after.noLabel ?? false)) changes.push(`noLabel: ${before.noLabel ?? false} -> ${after.noLabel ?? false}`);
3948
3960
  if (!isPropertiesEqual(before, after)) changes.push(...describePropertiesChanges(before, after));
3949
- return changes.length > 0 ? changes.join(", ") : "no visible changes";
3961
+ return changes.length > 0 ? changes.join("\n") : "no visible changes";
3950
3962
  }
3951
3963
  function isLayoutEqual(a, b) {
3952
3964
  return deepEqual(a, b);
@@ -5736,6 +5748,7 @@ function buildPhases(args) {
5736
5748
  name: "Schema",
5737
5749
  tasks: [{
5738
5750
  domain: "schema",
5751
+ storageExists: async () => (await c.schema.schemaStorage.get()).exists,
5739
5752
  run: async () => {
5740
5753
  await executeMigration({ container: c.schema });
5741
5754
  }
@@ -5745,6 +5758,7 @@ function buildPhases(args) {
5745
5758
  name: "Views & Customization",
5746
5759
  tasks: [{
5747
5760
  domain: "customize",
5761
+ storageExists: async () => (await c.customization.customizationStorage.get()).exists,
5748
5762
  run: async () => {
5749
5763
  await applyCustomization({
5750
5764
  container: c.customization,
@@ -5753,6 +5767,7 @@ function buildPhases(args) {
5753
5767
  }
5754
5768
  }, {
5755
5769
  domain: "view",
5770
+ storageExists: async () => (await c.view.viewStorage.get()).exists,
5756
5771
  run: async () => {
5757
5772
  await applyView({ container: c.view });
5758
5773
  }
@@ -5763,18 +5778,21 @@ function buildPhases(args) {
5763
5778
  tasks: [
5764
5779
  {
5765
5780
  domain: "field-acl",
5781
+ storageExists: async () => (await c.fieldPermission.fieldPermissionStorage.get()).exists,
5766
5782
  run: async () => {
5767
5783
  await applyFieldPermission({ container: c.fieldPermission });
5768
5784
  }
5769
5785
  },
5770
5786
  {
5771
5787
  domain: "app-acl",
5788
+ storageExists: async () => (await c.appPermission.appPermissionStorage.get()).exists,
5772
5789
  run: async () => {
5773
5790
  await applyAppPermission({ container: c.appPermission });
5774
5791
  }
5775
5792
  },
5776
5793
  {
5777
5794
  domain: "record-acl",
5795
+ storageExists: async () => (await c.recordPermission.recordPermissionStorage.get()).exists,
5778
5796
  run: async () => {
5779
5797
  await applyRecordPermission({ container: c.recordPermission });
5780
5798
  }
@@ -5786,42 +5804,49 @@ function buildPhases(args) {
5786
5804
  tasks: [
5787
5805
  {
5788
5806
  domain: "settings",
5807
+ storageExists: async () => (await c.settings.generalSettingsStorage.get()).exists,
5789
5808
  run: async () => {
5790
5809
  await applyGeneralSettings({ container: c.settings });
5791
5810
  }
5792
5811
  },
5793
5812
  {
5794
5813
  domain: "notification",
5814
+ storageExists: async () => (await c.notification.notificationStorage.get()).exists,
5795
5815
  run: async () => {
5796
5816
  await applyNotification({ container: c.notification });
5797
5817
  }
5798
5818
  },
5799
5819
  {
5800
5820
  domain: "report",
5821
+ storageExists: async () => (await c.report.reportStorage.get()).exists,
5801
5822
  run: async () => {
5802
5823
  await applyReport({ container: c.report });
5803
5824
  }
5804
5825
  },
5805
5826
  {
5806
5827
  domain: "action",
5828
+ storageExists: async () => (await c.action.actionStorage.get()).exists,
5807
5829
  run: async () => {
5808
5830
  await applyAction({ container: c.action });
5809
5831
  }
5810
5832
  },
5811
5833
  {
5812
5834
  domain: "process",
5835
+ storageExists: async () => (await c.process.processManagementStorage.get()).exists,
5813
5836
  run: async () => {
5814
5837
  await applyProcessManagement({ container: c.process });
5815
5838
  }
5816
5839
  },
5817
5840
  {
5818
5841
  domain: "admin-notes",
5842
+ storageExists: async () => (await c.adminNotes.adminNotesStorage.get()).exists,
5819
5843
  run: async () => {
5820
5844
  await applyAdminNotes({ container: c.adminNotes });
5821
5845
  }
5822
5846
  },
5823
5847
  {
5824
5848
  domain: "plugin",
5849
+ storageExists: async () => (await c.plugin.pluginStorage.get()).exists,
5825
5850
  run: async () => {
5826
5851
  await applyPlugin({ container: c.plugin });
5827
5852
  }
@@ -5832,6 +5857,7 @@ function buildPhases(args) {
5832
5857
  name: "Seed Data",
5833
5858
  tasks: [{
5834
5859
  domain: "seed",
5860
+ storageExists: async () => (await c.seed.seedStorage.get()).exists,
5835
5861
  run: async () => {
5836
5862
  await upsertSeed({
5837
5863
  container: c.seed,
@@ -5853,7 +5879,7 @@ function buildSkippedPhaseResult(phase, state) {
5853
5879
  domain: task.domain,
5854
5880
  success: false,
5855
5881
  error: skipError,
5856
- skipped: true
5882
+ skipped: "aborted"
5857
5883
  }))
5858
5884
  };
5859
5885
  }
@@ -5862,24 +5888,34 @@ function toError(error) {
5862
5888
  }
5863
5889
  async function executeSchemaPhase(phase, containers, state) {
5864
5890
  const results = [];
5865
- for (const task of phase.tasks) try {
5866
- await task.run();
5867
- await deployApp({ container: containers.schema });
5868
- results.push({
5869
- domain: task.domain,
5870
- success: true
5871
- });
5872
- } catch (error) {
5873
- const err = toError(error);
5874
- results.push({
5875
- domain: task.domain,
5876
- success: false,
5877
- error: err,
5878
- skipped: false
5879
- });
5880
- state.aborted = true;
5881
- state.reason = err;
5882
- state.phaseName = phase.name;
5891
+ for (const task of phase.tasks) {
5892
+ if (!await task.storageExists()) {
5893
+ results.push({
5894
+ domain: task.domain,
5895
+ success: false,
5896
+ skipped: "not-found"
5897
+ });
5898
+ continue;
5899
+ }
5900
+ try {
5901
+ await task.run();
5902
+ await deployApp({ container: containers.schema });
5903
+ results.push({
5904
+ domain: task.domain,
5905
+ success: true
5906
+ });
5907
+ } catch (error) {
5908
+ const err = toError(error);
5909
+ results.push({
5910
+ domain: task.domain,
5911
+ success: false,
5912
+ error: err,
5913
+ skipped: false
5914
+ });
5915
+ state.aborted = true;
5916
+ state.reason = err;
5917
+ state.phaseName = phase.name;
5918
+ }
5883
5919
  }
5884
5920
  return {
5885
5921
  phase: phase.name,
@@ -5894,7 +5930,15 @@ async function executeStandardPhase(phase, state) {
5894
5930
  domain: task.domain,
5895
5931
  success: false,
5896
5932
  error: createSkipError(state),
5897
- skipped: true
5933
+ skipped: "aborted"
5934
+ });
5935
+ continue;
5936
+ }
5937
+ if (!await task.storageExists()) {
5938
+ results.push({
5939
+ domain: task.domain,
5940
+ success: false,
5941
+ skipped: "not-found"
5898
5942
  });
5899
5943
  continue;
5900
5944
  }
@@ -7473,7 +7517,7 @@ function compareGeneralSection(local, remote) {
7473
7517
  type: "modified",
7474
7518
  section: "general",
7475
7519
  name: key,
7476
- details: diffs.join(", ")
7520
+ details: diffs.join("\n")
7477
7521
  });
7478
7522
  }
7479
7523
  }
@@ -7500,7 +7544,7 @@ function describePerRecordChanges(local, remote) {
7500
7544
  const diffs = [];
7501
7545
  if (local.title !== remote.title) diffs.push(`title: "${remote.title}" -> "${local.title}"`);
7502
7546
  if (!deepEqual(local.targets, remote.targets)) diffs.push(`targets: ${formatValue(remote.targets)} -> ${formatValue(local.targets)}`);
7503
- return diffs.length > 0 ? diffs.join(", ") : "changed";
7547
+ return diffs.length > 0 ? diffs.join("\n") : "changed";
7504
7548
  }
7505
7549
  function describeReminderChanges(local, remote) {
7506
7550
  const diffs = [];
@@ -7510,7 +7554,7 @@ function describeReminderChanges(local, remote) {
7510
7554
  if ((local.time ?? "") !== (remote.time ?? "")) diffs.push(`time: "${remote.time ?? ""}" -> "${local.time ?? ""}"`);
7511
7555
  if (local.filterCond !== remote.filterCond) diffs.push(`filterCond: "${remote.filterCond}" -> "${local.filterCond}"`);
7512
7556
  if (!deepEqual(local.targets, remote.targets)) diffs.push(`targets: ${formatValue(remote.targets)} -> ${formatValue(local.targets)}`);
7513
- return diffs.length > 0 ? diffs.join(", ") : "changed";
7557
+ return diffs.length > 0 ? diffs.join("\n") : "changed";
7514
7558
  }
7515
7559
  function comparePerRecordSection(local, remote) {
7516
7560
  const entries = [];
@@ -7664,7 +7708,7 @@ const PluginDiffDetector = { detect: (local, remote) => {
7664
7708
  if (diffs.length > 0) entries.push({
7665
7709
  type: "modified",
7666
7710
  pluginId: id,
7667
- details: diffs.join(", ")
7711
+ details: diffs.join("\n")
7668
7712
  });
7669
7713
  }
7670
7714
  }
@@ -7733,7 +7777,7 @@ function compareStates(local, remote, entries) {
7733
7777
  type: "modified",
7734
7778
  category: "state",
7735
7779
  name,
7736
- details: stateDiffs.join(", ")
7780
+ details: stateDiffs.join("\n")
7737
7781
  });
7738
7782
  }
7739
7783
  for (const name of remoteStateNames) if (!localStateNames.has(name)) entries.push({
@@ -7760,7 +7804,7 @@ function compareActionEntries(local, remote, entries) {
7760
7804
  type: "modified",
7761
7805
  category: "action",
7762
7806
  name,
7763
- details: actionDiffs.join(", ")
7807
+ details: actionDiffs.join("\n")
7764
7808
  });
7765
7809
  }
7766
7810
  }
@@ -7904,7 +7948,7 @@ const ReportDiffDetector = { detect: (local, remote) => {
7904
7948
  if (diffs.length > 0) return {
7905
7949
  type: "modified",
7906
7950
  reportName: name,
7907
- details: diffs.join(", ")
7951
+ details: diffs.join("\n")
7908
7952
  };
7909
7953
  },
7910
7954
  onDeleted: (name, remoteReport) => ({
@@ -7957,7 +8001,7 @@ const ViewDiffDetector = { detect: (localViews, remoteViews) => {
7957
8001
  if (changes.length > 0) return {
7958
8002
  type: "modified",
7959
8003
  viewName: name,
7960
- details: changes.join(", ")
8004
+ details: changes.join("\n")
7961
8005
  };
7962
8006
  },
7963
8007
  onDeleted: (name, remoteView) => ({
@@ -8154,7 +8198,8 @@ const domainDisplayName$1 = {
8154
8198
  function formatTaskResult(result) {
8155
8199
  const name = domainDisplayName$1[result.domain];
8156
8200
  if (result.success) return ` ${pc.green("✓")} ${name}`;
8157
- if (result.skipped) return ` ${pc.yellow("⊘")} ${name} ${pc.dim("—")} ${pc.yellow("skipped")}`;
8201
+ if (result.skipped === "not-found") return ` ${pc.yellow("⊘")} ${name} ${pc.dim("—")} ${pc.yellow("skipped (file not found)")}`;
8202
+ if (result.skipped === "aborted") return ` ${pc.yellow("⊘")} ${name} ${pc.dim("—")} ${pc.yellow("skipped")}`;
8158
8203
  return ` ${pc.red("✗")} ${name} ${pc.dim("—")} ${pc.red(`failed (${formatErrorForDisplay(result.error)})`)}`;
8159
8204
  }
8160
8205
  function printPhaseResult(phaseResult) {
@@ -8175,6 +8220,7 @@ function printApplyAllResults(output) {
8175
8220
  const skipped = allResults.filter((r) => !r.success && r.skipped).length;
8176
8221
  if (output.deployed) p.log.success("Deployed to production.");
8177
8222
  else if (output.deployError) p.log.warn(`Deployment failed: ${formatErrorForDisplay(output.deployError)}`);
8223
+ else if (succeeded === 0 && failed === 0 && skipped > 0) p.log.info("No config files found. Nothing to apply.");
8178
8224
  else if (succeeded === 0) p.log.warn("Not deployed due to errors.");
8179
8225
  else if (failed > 0 || skipped > 0) p.log.info("Deployment skipped (no Phase 2-4 changes applied successfully).");
8180
8226
  const parts = [];
@@ -8314,19 +8360,20 @@ async function runApplyAll(cliConfig, appName, options) {
8314
8360
  const diffFailCount = diffResults.filter((r) => !r.success).length;
8315
8361
  ds.stop(`Comparison complete.${diffFailCount > 0 ? ` (${diffFailCount} failed)` : ""}`);
8316
8362
  printDiffAllResults(diffResults);
8317
- p.log.info("Note: Seed data will be upserted (no diff preview available).");
8363
+ const seedExists = (await containers.seed.seedStorage.get()).exists;
8364
+ if (seedExists) p.log.info("Note: Seed data will be upserted (no diff preview available).");
8318
8365
  const hasChanges = diffResults.some((r) => r.success && !r.result.isEmpty);
8319
- if (!hasChanges) p.log.success("No changes detected. Seed data will still be upserted.");
8366
+ if (!hasChanges) p.log.success(seedExists ? "No changes detected. Seed data will still be upserted." : "No changes detected.");
8320
8367
  if (options.dryRun) {
8321
8368
  p.log.info("Dry run complete. No changes will be applied.");
8322
- if (!hasChanges) p.log.info("Note: Seed data would still be upserted when running without --dry-run.");
8323
- return;
8369
+ if (!hasChanges && seedExists) p.log.info("Note: Seed data would still be upserted when running without --dry-run.");
8370
+ return { ok: true };
8324
8371
  }
8325
8372
  if (!options.skipConfirm) {
8326
8373
  const shouldContinue = await p.confirm({ message: "Apply these changes?" });
8327
8374
  if (p.isCancel(shouldContinue) || !shouldContinue) {
8328
8375
  p.cancel("Apply cancelled.");
8329
- return;
8376
+ return { ok: true };
8330
8377
  }
8331
8378
  }
8332
8379
  const as = p.spinner();
@@ -8335,10 +8382,14 @@ async function runApplyAll(cliConfig, appName, options) {
8335
8382
  containers,
8336
8383
  customizeBasePath
8337
8384
  });
8338
- const applyFailCount = output.phases.flatMap((pr) => pr.results).filter((r) => !r.success).length;
8385
+ const applyFailCount = output.phases.flatMap((pr) => pr.results).filter((r) => !r.success && r.skipped !== "not-found").length;
8339
8386
  as.stop(`Apply complete.${applyFailCount > 0 ? ` (${applyFailCount} failed)` : ""}`);
8340
8387
  printApplyAllResults(output);
8341
- if (output.phases.flatMap((pr) => pr.results).some((r) => !r.success) || !output.deployed) process.exitCode = 1;
8388
+ if (output.phases.flatMap((pr) => pr.results).some((r) => !r.success && r.skipped !== "not-found") || output.deployError) return {
8389
+ ok: false,
8390
+ error: output.deployError ?? new SystemError(SystemErrorCode.ExecutionError, `Apply failed for ${appName}.`)
8391
+ };
8392
+ return { ok: true };
8342
8393
  }
8343
8394
  var apply_default$10 = define({
8344
8395
  name: "apply",
@@ -8355,16 +8406,16 @@ var apply_default$10 = define({
8355
8406
  process.exitCode = 1;
8356
8407
  },
8357
8408
  singleApp: async (app, projectConfig) => {
8358
- await runApplyAll(resolveAppCliConfig(app, projectConfig, values), app.name, {
8409
+ if (!(await runApplyAll(resolveAppCliConfig(app, projectConfig, values), app.name, {
8359
8410
  skipConfirm,
8360
8411
  dryRun
8361
- });
8412
+ })).ok) process.exitCode = 1;
8362
8413
  },
8363
8414
  multiApp: async (plan, projectConfig) => {
8364
8415
  await runMultiAppWithFailCheck(plan, async (app) => {
8365
8416
  const cliConfig = resolveAppCliConfig(app, projectConfig, values);
8366
8417
  printAppHeader(app.name, app.appId);
8367
- await runApplyAll(cliConfig, app.name, {
8418
+ return runApplyAll(cliConfig, app.name, {
8368
8419
  skipConfirm,
8369
8420
  dryRun
8370
8421
  });