kintone-migrator 0.35.4 → 0.35.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
@@ -795,7 +795,7 @@ function compareActions$1(local, remote) {
795
795
  const diffs = [];
796
796
  if (local.index !== remote.index) diffs.push(`index: ${remote.index} -> ${local.index}`);
797
797
  if (!deepEqual(local.destApp, remote.destApp)) diffs.push(`destApp: ${formatValue(remote.destApp)} -> ${formatValue(local.destApp)}`);
798
- if (local.filterCond !== remote.filterCond) diffs.push(`filterCond: "${remote.filterCond}" -> "${local.filterCond}"`);
798
+ if (local.filterCond !== remote.filterCond) diffs.push(`filterCond: ${formatValue(remote.filterCond)} -> ${formatValue(local.filterCond)}`);
799
799
  if (!deepEqual(local.mappings, remote.mappings)) diffs.push(`mappings: ${formatValue(remote.mappings)} -> ${formatValue(local.mappings)}`);
800
800
  if (!deepEqual(local.entities, remote.entities)) diffs.push(`entities: ${formatValue(remote.entities)} -> ${formatValue(local.entities)}`);
801
801
  return diffs;
@@ -1354,6 +1354,17 @@ const SKIP_REVISION_CHECK = Symbol("skip-revision-check");
1354
1354
  /** The generation read when a caller does not specify a target. */
1355
1355
  const DEFAULT_FORM_READ_TARGET = "preview";
1356
1356
  //#endregion
1357
+ //#region src/core/domain/formSchema/services/lookupListDecoder.ts
1358
+ /**
1359
+ * Reads a lookup list (`fieldMappings`, `lookupPickerFields`) from an external
1360
+ * value. kintone represents an unset list as `""`, which reads as the empty
1361
+ * list. Returns `undefined` when the value is not a list.
1362
+ */
1363
+ function decodeLookupList(value) {
1364
+ if (value === "") return [];
1365
+ return Array.isArray(value) ? value : void 0;
1366
+ }
1367
+ //#endregion
1357
1368
  //#region src/lib/charValidation.ts
1358
1369
  /** Returns true if the string contains any control characters (0x00–0x1f or 0x7f). */
1359
1370
  function hasControlChars(s) {
@@ -1375,6 +1386,16 @@ function sanitizeForDisplay$1(s) {
1375
1386
  }
1376
1387
  //#endregion
1377
1388
  //#region src/core/domain/formSchema/valueObject.ts
1389
+ const LookupRelatedApp = {
1390
+ /**
1391
+ * kintone returns `code: ""` for a related app without an app code, while a
1392
+ * schema leaves `code` out for the same app. Both build a related app
1393
+ * without `code`, so only a non-empty `code` is kept.
1394
+ */
1395
+ create: (app, code) => code === void 0 || code === "" ? { app } : {
1396
+ app,
1397
+ code
1398
+ } };
1378
1399
  function hasInvalidFieldCodeChars(code) {
1379
1400
  if (hasControlChars(code)) return true;
1380
1401
  for (let i = 0; i < code.length; i++) {
@@ -1468,6 +1489,42 @@ function normalizeDefaultValue(type, rest) {
1468
1489
  if (rest.defaultValue !== void 0 && typeof rest.defaultValue === "string") rest.defaultValue = rest.defaultValue === "" ? [] : [rest.defaultValue];
1469
1490
  }
1470
1491
  }
1492
+ function readKintoneLookupList(value, fieldPath) {
1493
+ const list = decodeLookupList(value);
1494
+ if (list === void 0) throw new SystemError(SystemErrorCode.ExternalApiError, `Expected array at ${fieldPath}, got ${typeof value}`);
1495
+ return list;
1496
+ }
1497
+ function fromKintoneLookup(value, fieldPath) {
1498
+ assertRecord(value, fieldPath);
1499
+ assertRecord(value.relatedApp, `${fieldPath}.relatedApp`);
1500
+ const { app, code } = value.relatedApp;
1501
+ assertString(app, `${fieldPath}.relatedApp.app`);
1502
+ if (code !== void 0) assertString(code, `${fieldPath}.relatedApp.code`);
1503
+ assertString(value.relatedKeyField, `${fieldPath}.relatedKeyField`);
1504
+ const fieldMappings = readKintoneLookupList(value.fieldMappings, `${fieldPath}.fieldMappings`).map((mapping, i) => {
1505
+ const mappingPath = `${fieldPath}.fieldMappings[${i}]`;
1506
+ assertRecord(mapping, mappingPath);
1507
+ assertString(mapping.field, `${mappingPath}.field`);
1508
+ assertString(mapping.relatedField, `${mappingPath}.relatedField`);
1509
+ return {
1510
+ field: mapping.field,
1511
+ relatedField: mapping.relatedField
1512
+ };
1513
+ });
1514
+ const lookupPickerFields = readKintoneLookupList(value.lookupPickerFields, `${fieldPath}.lookupPickerFields`);
1515
+ assertStringArray(lookupPickerFields, `${fieldPath}.lookupPickerFields`);
1516
+ const { filterCond, sort } = value;
1517
+ if (filterCond !== void 0) assertString(filterCond, `${fieldPath}.filterCond`);
1518
+ if (sort !== void 0) assertString(sort, `${fieldPath}.sort`);
1519
+ return {
1520
+ relatedApp: LookupRelatedApp.create(app, code),
1521
+ relatedKeyField: value.relatedKeyField,
1522
+ fieldMappings,
1523
+ lookupPickerFields,
1524
+ ...filterCond !== void 0 ? { filterCond } : {},
1525
+ ...sort !== void 0 ? { sort } : {}
1526
+ };
1527
+ }
1471
1528
  function fromKintoneProperty(prop) {
1472
1529
  const { type, code, label, noLabel, ...rest } = prop;
1473
1530
  const base = {
@@ -1518,10 +1575,15 @@ function fromKintoneProperty(prop) {
1518
1575
  }
1519
1576
  if (!KNOWN_FIELD_TYPES.has(type)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unknown field type: ${type}`);
1520
1577
  normalizeDefaultValue(type, rest);
1578
+ const { lookup, ...others } = rest;
1579
+ const properties = lookup === void 0 ? others : {
1580
+ ...others,
1581
+ lookup: fromKintoneLookup(lookup, `${type} "${code}".lookup`)
1582
+ };
1521
1583
  return {
1522
1584
  ...base,
1523
1585
  type,
1524
- properties: rest
1586
+ properties
1525
1587
  };
1526
1588
  }
1527
1589
  function toKintoneProperty(field) {
@@ -4217,16 +4279,17 @@ async function applyAdminNotes({ container }) {
4217
4279
  //#endregion
4218
4280
  //#region src/core/domain/adminNotes/services/diffDetector.ts
4219
4281
  const CONTENT_TRUNCATE_LENGTH = 30;
4220
- function truncate(text, maxLength) {
4221
- if (text.length <= maxLength) return text;
4222
- return `${text.slice(0, maxLength)}...`;
4282
+ function formatContentPreview(text, maxLength) {
4283
+ const codePoints = Array.from(text);
4284
+ if (codePoints.length <= maxLength) return formatValue(text);
4285
+ return `${formatValue(codePoints.slice(0, maxLength).join(""))}...`;
4223
4286
  }
4224
4287
  function compareConfigs$2(local, remote) {
4225
4288
  const entries = [];
4226
4289
  if (local.content !== remote.content) entries.push({
4227
4290
  type: "modified",
4228
4291
  field: "content",
4229
- details: `"${truncate(remote.content, CONTENT_TRUNCATE_LENGTH)}" -> "${truncate(local.content, CONTENT_TRUNCATE_LENGTH)}"`
4292
+ details: `${formatContentPreview(remote.content, CONTENT_TRUNCATE_LENGTH)} -> ${formatContentPreview(local.content, CONTENT_TRUNCATE_LENGTH)}`
4230
4293
  });
4231
4294
  if (local.includeInTemplateAndDuplicates !== remote.includeInTemplateAndDuplicates) entries.push({
4232
4295
  type: "modified",
@@ -5923,6 +5986,9 @@ function validateLookupStructure(field) {
5923
5986
  const issues = [];
5924
5987
  if (lookup.relatedApp.app.trim().length === 0) issues.push(issue("error", field.code, field.type, "INVALID_LOOKUP", `Field "${field.code}" lookup must have a non-empty "relatedApp.app"`));
5925
5988
  if (lookup.relatedKeyField.trim().length === 0) issues.push(issue("error", field.code, field.type, "INVALID_LOOKUP", `Field "${field.code}" lookup must have a non-empty "relatedKeyField"`));
5989
+ lookup.fieldMappings.forEach((mapping, i) => {
5990
+ for (const key of ["field", "relatedField"]) if (mapping[key].trim().length === 0) issues.push(issue("error", field.code, field.type, "INVALID_LOOKUP", `Field "${field.code}" lookup must have a non-empty "fieldMappings[${i}].${key}"`));
5991
+ });
5926
5992
  return issues;
5927
5993
  }
5928
5994
  function validateReferenceTableRelatedApp(field) {
@@ -6205,6 +6271,42 @@ function buildFieldDefinition(base, fieldType, properties) {
6205
6271
  };
6206
6272
  }
6207
6273
  }
6274
+ function invalidLookup(code, detail) {
6275
+ return new BusinessRuleError(FormSchemaErrorCode.FsInvalidSchemaStructure, `Field "${code}" lookup ${detail}`);
6276
+ }
6277
+ function optionalString(value) {
6278
+ return value === void 0 || value === null ? void 0 : String(value);
6279
+ }
6280
+ /** Reads a lookup list; an omitted or valueless list is the empty list. */
6281
+ function optionalLookupList(code, key, value) {
6282
+ if (value === void 0 || value === null) return [];
6283
+ const list = decodeLookupList(value);
6284
+ if (list === void 0) throw invalidLookup(code, `must have a "${key}" array`);
6285
+ return list;
6286
+ }
6287
+ function parseLookup(code, raw) {
6288
+ if (!isRecord(raw)) throw invalidLookup(code, "must be an object");
6289
+ if (!isRecord(raw.relatedApp)) throw invalidLookup(code, "must have a \"relatedApp\" object");
6290
+ const rawFieldMappings = optionalLookupList(code, "fieldMappings", raw.fieldMappings);
6291
+ const lookupPickerFields = optionalLookupList(code, "lookupPickerFields", raw.lookupPickerFields).map((f) => String(f));
6292
+ const fieldMappings = rawFieldMappings.map((mapping) => {
6293
+ if (!isRecord(mapping)) throw invalidLookup(code, "must have objects in \"fieldMappings\"");
6294
+ return {
6295
+ field: String(mapping.field ?? ""),
6296
+ relatedField: String(mapping.relatedField ?? "")
6297
+ };
6298
+ });
6299
+ const filterCond = optionalString(raw.filterCond);
6300
+ const sort = optionalString(raw.sort);
6301
+ return {
6302
+ relatedApp: LookupRelatedApp.create(String(raw.relatedApp.app ?? ""), optionalString(raw.relatedApp.code)),
6303
+ relatedKeyField: String(raw.relatedKeyField ?? ""),
6304
+ fieldMappings,
6305
+ lookupPickerFields,
6306
+ ...filterCond !== void 0 ? { filterCond } : {},
6307
+ ...sort !== void 0 ? { sort } : {}
6308
+ };
6309
+ }
6208
6310
  function parseReferenceTableField(raw, code, base) {
6209
6311
  if (!isRecord(raw.referenceTable)) throw new BusinessRuleError(FormSchemaErrorCode.FsInvalidSchemaStructure, `Field "${code}" of type REFERENCE_TABLE must have a "referenceTable" property`);
6210
6312
  const refTable = raw.referenceTable;
@@ -6259,7 +6361,11 @@ function parseFieldDefinitionFromFlat(raw) {
6259
6361
  };
6260
6362
  }
6261
6363
  if (fieldType === "REFERENCE_TABLE") return parseReferenceTableField(raw, code, base);
6262
- const properties = extractProperties(raw);
6364
+ const { lookup, ...others } = extractProperties(raw);
6365
+ const properties = lookup === void 0 ? others : {
6366
+ ...others,
6367
+ lookup: parseLookup(code, lookup)
6368
+ };
6263
6369
  validateFieldProperties(code, fieldType, properties);
6264
6370
  return buildFieldDefinition(base, fieldType, properties);
6265
6371
  }
@@ -9306,7 +9412,7 @@ function compareConfigs$1(local, remote) {
9306
9412
  if (lv !== rv) entries.push({
9307
9413
  type: "modified",
9308
9414
  field,
9309
- details: suppressValues ? `${field} changed` : `"${rv}" -> "${lv}"`
9415
+ details: suppressValues ? `${field} changed` : `${formatValue(rv)} -> ${formatValue(lv)}`
9310
9416
  });
9311
9417
  }
9312
9418
  function compareBoolean(field, l, r, defaultValue) {
@@ -9487,17 +9593,17 @@ function perRecordLabel(notif) {
9487
9593
  }
9488
9594
  function describePerRecordChanges(local, remote) {
9489
9595
  const diffs = [];
9490
- if (local.title !== remote.title) diffs.push(`title: "${remote.title}" -> "${local.title}"`);
9596
+ if (local.title !== remote.title) diffs.push(`title: ${formatValue(remote.title)} -> ${formatValue(local.title)}`);
9491
9597
  if (!deepEqual(local.targets, remote.targets)) diffs.push(`targets: ${formatValue(remote.targets)} -> ${formatValue(local.targets)}`);
9492
9598
  return diffs.length > 0 ? diffs.join("\n") : "changed";
9493
9599
  }
9494
9600
  function describeReminderChanges(local, remote) {
9495
9601
  const diffs = [];
9496
- if (local.title !== remote.title) diffs.push(`title: "${remote.title}" -> "${local.title}"`);
9602
+ if (local.title !== remote.title) diffs.push(`title: ${formatValue(remote.title)} -> ${formatValue(local.title)}`);
9497
9603
  if (local.daysLater !== remote.daysLater) diffs.push(`daysLater: ${remote.daysLater} -> ${local.daysLater}`);
9498
9604
  if ((local.hoursLater ?? 0) !== (remote.hoursLater ?? 0)) diffs.push(`hoursLater: ${remote.hoursLater ?? 0} -> ${local.hoursLater ?? 0}`);
9499
- if ((local.time ?? "") !== (remote.time ?? "")) diffs.push(`time: "${remote.time ?? ""}" -> "${local.time ?? ""}"`);
9500
- if (local.filterCond !== remote.filterCond) diffs.push(`filterCond: "${remote.filterCond}" -> "${local.filterCond}"`);
9605
+ if ((local.time ?? "") !== (remote.time ?? "")) diffs.push(`time: ${formatValue(remote.time ?? "")} -> ${formatValue(local.time ?? "")}`);
9606
+ if (local.filterCond !== remote.filterCond) diffs.push(`filterCond: ${formatValue(remote.filterCond)} -> ${formatValue(local.filterCond)}`);
9501
9607
  if (!deepEqual(local.targets, remote.targets)) diffs.push(`targets: ${formatValue(remote.targets)} -> ${formatValue(local.targets)}`);
9502
9608
  return diffs.length > 0 ? diffs.join("\n") : "changed";
9503
9609
  }
@@ -9539,7 +9645,7 @@ function compareReminderSection(local, remote) {
9539
9645
  type: "added",
9540
9646
  section: "reminder",
9541
9647
  name: code,
9542
- details: `"${localNotif.title}"`
9648
+ details: formatValue(localNotif.title)
9543
9649
  });
9544
9650
  else if (!deepEqual(localNotif, remoteNotif)) entries.push({
9545
9651
  type: "modified",
@@ -9649,11 +9755,11 @@ const PluginDiffDetector = { detect: (local, remote) => {
9649
9755
  if (!remotePlugin) entries.push({
9650
9756
  type: "added",
9651
9757
  pluginId: id,
9652
- details: `"${localPlugin.name}"`
9758
+ details: formatValue(localPlugin.name)
9653
9759
  });
9654
9760
  else {
9655
9761
  const diffs = [];
9656
- if (localPlugin.name !== remotePlugin.name) diffs.push(`name: "${remotePlugin.name}" -> "${localPlugin.name}"`);
9762
+ if (localPlugin.name !== remotePlugin.name) diffs.push(`name: ${formatValue(remotePlugin.name)} -> ${formatValue(localPlugin.name)}`);
9657
9763
  if (localPlugin.enabled !== remotePlugin.enabled) diffs.push(`enabled: ${String(remotePlugin.enabled)} -> ${String(localPlugin.enabled)}`);
9658
9764
  if (diffs.length > 0) entries.push({
9659
9765
  type: "modified",
@@ -9665,7 +9771,7 @@ const PluginDiffDetector = { detect: (local, remote) => {
9665
9771
  for (const [id, remotePlugin] of remoteMap) if (!localMap.has(id)) entries.push({
9666
9772
  type: "deleted",
9667
9773
  pluginId: id,
9668
- details: `"${remotePlugin.name}"`
9774
+ details: formatValue(remotePlugin.name)
9669
9775
  });
9670
9776
  return buildDiffResult(entries);
9671
9777
  } };
@@ -9700,7 +9806,7 @@ function isExecutableUserEqual(a, b) {
9700
9806
  }
9701
9807
  function compareActions(localAction, remoteAction) {
9702
9808
  const diffs = [];
9703
- if (localAction.filterCond !== remoteAction.filterCond) diffs.push(`filterCond: "${remoteAction.filterCond}" -> "${localAction.filterCond}"`);
9809
+ if (localAction.filterCond !== remoteAction.filterCond) diffs.push(`filterCond: ${formatValue(remoteAction.filterCond)} -> ${formatValue(localAction.filterCond)}`);
9704
9810
  if (localAction.type !== remoteAction.type) diffs.push(`type: ${remoteAction.type} -> ${localAction.type}`);
9705
9811
  if (!isExecutableUserEqual(localAction.executableUser, remoteAction.executableUser)) diffs.push(`executableUser: ${formatValue(remoteAction.executableUser)} -> ${formatValue(localAction.executableUser)}`);
9706
9812
  return diffs;
@@ -9759,7 +9865,7 @@ function compareActionEntries(local, remote, entries) {
9759
9865
  type: "added",
9760
9866
  category: "action",
9761
9867
  name: actionLabel(pair.local, pair.index),
9762
- details: `filterCond: "${pair.local.filterCond}"`
9868
+ details: `filterCond: ${formatValue(pair.local.filterCond)}`
9763
9869
  });
9764
9870
  break;
9765
9871
  case "remoteOnly":
@@ -9767,7 +9873,7 @@ function compareActionEntries(local, remote, entries) {
9767
9873
  type: "deleted",
9768
9874
  category: "action",
9769
9875
  name: actionLabel(pair.remote, pair.index),
9770
- details: `filterCond: "${pair.remote.filterCond}"`
9876
+ details: `filterCond: ${formatValue(pair.remote.filterCond)}`
9771
9877
  });
9772
9878
  break;
9773
9879
  case "both": {
@@ -9884,11 +9990,11 @@ async function detectRecordPermissionDiff({ container }) {
9884
9990
  //#region src/core/domain/report/services/diffDetector.ts
9885
9991
  function compareReports(local, remote) {
9886
9992
  const diffs = [];
9887
- if (local.name !== remote.name) diffs.push(`name: "${remote.name}" -> "${local.name}"`);
9993
+ if (local.name !== remote.name) diffs.push(`name: ${formatValue(remote.name)} -> ${formatValue(local.name)}`);
9888
9994
  if (local.chartType !== remote.chartType) diffs.push(`chartType: ${remote.chartType} -> ${local.chartType}`);
9889
9995
  if ((local.chartMode ?? "") !== (remote.chartMode ?? "")) diffs.push(`chartMode: ${remote.chartMode ?? "(unset)"} -> ${local.chartMode ?? "(unset)"}`);
9890
9996
  if (local.index !== remote.index) diffs.push(`index: ${remote.index} -> ${local.index}`);
9891
- if (local.filterCond !== remote.filterCond) diffs.push(`filterCond: "${remote.filterCond}" -> "${local.filterCond}"`);
9997
+ if (local.filterCond !== remote.filterCond) diffs.push(`filterCond: ${formatValue(remote.filterCond)} -> ${formatValue(local.filterCond)}`);
9892
9998
  if (!deepEqual(local.groups, remote.groups)) diffs.push(`groups: ${formatValue(remote.groups)} -> ${formatValue(local.groups)}`);
9893
9999
  if (!deepEqual(local.aggregations, remote.aggregations)) diffs.push(`aggregations: ${formatValue(remote.aggregations)} -> ${formatValue(local.aggregations)}`);
9894
10000
  if (!deepEqual(local.sorts, remote.sorts)) diffs.push(`sorts: ${formatValue(remote.sorts)} -> ${formatValue(local.sorts)}`);
@@ -9931,7 +10037,7 @@ async function detectReportDiff({ container }) {
9931
10037
  //#endregion
9932
10038
  //#region src/core/domain/view/services/diffDetector.ts
9933
10039
  function checkOptionalStringChange(changes, field, localVal, remoteVal) {
9934
- if ((localVal ?? "") !== (remoteVal ?? "")) changes.push(`${field}: "${remoteVal ?? ""}" -> "${localVal ?? ""}"`);
10040
+ if ((localVal ?? "") !== (remoteVal ?? "")) changes.push(`${field}: ${formatValue(remoteVal ?? "")} -> ${formatValue(localVal ?? "")}`);
9935
10041
  }
9936
10042
  function describeChanges(local, remote) {
9937
10043
  const changes = [];