kintone-migrator 0.23.0 → 0.24.0
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 +1254 -279
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -321,6 +321,18 @@ function isSystemError(error) {
|
|
|
321
321
|
return error instanceof SystemError;
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region src/lib/typeGuards.ts
|
|
326
|
+
/**
|
|
327
|
+
* Narrows `unknown` to a plain `Record<string, unknown>`.
|
|
328
|
+
* Returns true when the value is a non-null, non-array plain object.
|
|
329
|
+
* Excludes built-in types (Date, RegExp, Map, Set) that are technically
|
|
330
|
+
* objects but should not be treated as string-keyed records.
|
|
331
|
+
*/
|
|
332
|
+
function isRecord$1(value) {
|
|
333
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof Map) && !(value instanceof Set);
|
|
334
|
+
}
|
|
335
|
+
|
|
324
336
|
//#endregion
|
|
325
337
|
//#region src/core/domain/typeGuards.ts
|
|
326
338
|
/**
|
|
@@ -328,13 +340,6 @@ function isSystemError(error) {
|
|
|
328
340
|
* Use these functions instead of `as` casts when working with `unknown` values.
|
|
329
341
|
*/
|
|
330
342
|
/**
|
|
331
|
-
* Narrows `unknown` to `Record<string, unknown>`.
|
|
332
|
-
* Returns true when the value is a non-null object (and not an array).
|
|
333
|
-
*/
|
|
334
|
-
function isRecord$1(value) {
|
|
335
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
343
|
* Narrows `unknown` to `{ code: string }`.
|
|
339
344
|
*/
|
|
340
345
|
function hasCode(value) {
|
|
@@ -1964,42 +1969,73 @@ function colorizeDiffEntry(type) {
|
|
|
1964
1969
|
prefix: type === "added" ? "+" : type === "deleted" ? "-" : "~"
|
|
1965
1970
|
};
|
|
1966
1971
|
}
|
|
1967
|
-
function
|
|
1972
|
+
function printGenericDiffResult(result, title, formatEntry) {
|
|
1973
|
+
for (const w of result.warnings) p.log.warn(w);
|
|
1968
1974
|
if (result.isEmpty) {
|
|
1969
1975
|
p.log.info("No changes detected.");
|
|
1970
1976
|
return;
|
|
1971
1977
|
}
|
|
1972
1978
|
p.log.info(`Changes: ${formatDiffSummary(result.summary)}`);
|
|
1973
|
-
if (result.hasLayoutChanges) p.log.info("Layout changes detected.");
|
|
1974
1979
|
const lines = result.entries.map((entry) => {
|
|
1975
1980
|
const { colorize, prefix } = colorizeDiffEntry(entry.type);
|
|
1976
|
-
return
|
|
1981
|
+
return formatEntry(entry, colorize, prefix);
|
|
1977
1982
|
});
|
|
1978
|
-
p.note(lines.join("\n"),
|
|
1983
|
+
p.note(lines.join("\n"), title, { format: (v) => v });
|
|
1979
1984
|
}
|
|
1980
|
-
function
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1985
|
+
function printActionDiffResult(result) {
|
|
1986
|
+
printGenericDiffResult(result, "Action Diff Details", (entry, colorize, prefix) => `${colorize(prefix)} ${colorize(entry.actionName)}${pc.dim(":")} ${entry.details}`);
|
|
1987
|
+
}
|
|
1988
|
+
function printAdminNotesDiffResult(result) {
|
|
1989
|
+
printFieldDiffResult(result, "Admin Notes Diff Details");
|
|
1990
|
+
}
|
|
1991
|
+
function printAppPermissionDiffResult(result) {
|
|
1992
|
+
printGenericDiffResult(result, "App Permission Diff Details", (entry, colorize, prefix) => `${colorize(prefix)} ${colorize(entry.entityKey)}${pc.dim(":")} ${entry.details}`);
|
|
1993
|
+
}
|
|
1994
|
+
function printCustomizationDiffResult(result) {
|
|
1995
|
+
printGenericDiffResult(result, "Customization Diff Details", (entry, colorize, prefix) => {
|
|
1996
|
+
const location = entry.platform === "config" ? entry.category : `${entry.platform}.${entry.category}`;
|
|
1997
|
+
return `${colorize(prefix)} ${pc.dim("[")}${colorize(location)}${pc.dim("]")} ${entry.name}${pc.dim(":")} ${entry.details}`;
|
|
1989
1998
|
});
|
|
1990
|
-
p.note(lines.join("\n"), "View Diff Details", { format: (v) => v });
|
|
1991
1999
|
}
|
|
1992
|
-
function
|
|
2000
|
+
function printDiffResult(result) {
|
|
1993
2001
|
if (result.isEmpty) {
|
|
1994
2002
|
p.log.info("No changes detected.");
|
|
1995
2003
|
return;
|
|
1996
2004
|
}
|
|
1997
2005
|
p.log.info(`Changes: ${formatDiffSummary(result.summary)}`);
|
|
2006
|
+
if (result.hasLayoutChanges) p.log.info("Layout changes detected.");
|
|
1998
2007
|
const lines = result.entries.map((entry) => {
|
|
1999
2008
|
const { colorize, prefix } = colorizeDiffEntry(entry.type);
|
|
2000
|
-
return `${colorize(prefix)} ${pc.dim("[")}${colorize(entry.
|
|
2009
|
+
return `${colorize(prefix)} ${pc.dim("[")}${colorize(entry.fieldCode)}${pc.dim("]")} ${entry.fieldLabel}${pc.dim(":")} ${entry.details}`;
|
|
2001
2010
|
});
|
|
2002
|
-
p.note(lines.join("\n"), "
|
|
2011
|
+
p.note(lines.join("\n"), "Diff Details", { format: (v) => v });
|
|
2012
|
+
}
|
|
2013
|
+
function printFieldPermissionDiffResult(result) {
|
|
2014
|
+
printGenericDiffResult(result, "Field Permission Diff Details", (entry, colorize, prefix) => `${colorize(prefix)} ${pc.dim("[")}${colorize(entry.fieldCode)}${pc.dim("]:")} ${entry.details}`);
|
|
2015
|
+
}
|
|
2016
|
+
function printGeneralSettingsDiffResult(result) {
|
|
2017
|
+
printFieldDiffResult(result, "General Settings Diff Details");
|
|
2018
|
+
}
|
|
2019
|
+
function printNotificationDiffResult(result) {
|
|
2020
|
+
printGenericDiffResult(result, "Notification Diff Details", (entry, colorize, prefix) => `${colorize(prefix)} ${pc.dim("[")}${colorize(entry.section)}${pc.dim("]")} ${entry.name}${pc.dim(":")} ${entry.details}`);
|
|
2021
|
+
}
|
|
2022
|
+
function printPluginDiffResult(result) {
|
|
2023
|
+
printGenericDiffResult(result, "Plugin Diff Details", (entry, colorize, prefix) => `${colorize(prefix)} ${colorize(entry.pluginId)}${pc.dim(":")} ${entry.details}`);
|
|
2024
|
+
}
|
|
2025
|
+
function printProcessDiffResult(result) {
|
|
2026
|
+
printGenericDiffResult(result, "Process Management Diff Details", (entry, colorize, prefix) => `${colorize(prefix)} ${pc.dim("[")}${colorize(entry.category)}${pc.dim("]")} ${entry.name}${pc.dim(":")} ${entry.details}`);
|
|
2027
|
+
}
|
|
2028
|
+
function printRecordPermissionDiffResult(result) {
|
|
2029
|
+
printGenericDiffResult(result, "Record Permission Diff Details", (entry, colorize, prefix) => `${colorize(prefix)} ${pc.dim("[")}${colorize(entry.filterCond === "" ? "(all records)" : entry.filterCond)}${pc.dim("]:")} ${entry.details}`);
|
|
2030
|
+
}
|
|
2031
|
+
function printReportDiffResult(result) {
|
|
2032
|
+
printGenericDiffResult(result, "Report Diff Details", (entry, colorize, prefix) => `${colorize(prefix)} ${colorize(entry.reportName)}${pc.dim(":")} ${entry.details}`);
|
|
2033
|
+
}
|
|
2034
|
+
function printViewDiffResult(result) {
|
|
2035
|
+
printGenericDiffResult(result, "View Diff Details", (entry, colorize, prefix) => `${colorize(prefix)} ${colorize(entry.viewName)}${pc.dim(":")} ${entry.details}`);
|
|
2036
|
+
}
|
|
2037
|
+
function printFieldDiffResult(result, title) {
|
|
2038
|
+
printGenericDiffResult(result, title, (entry, colorize, prefix) => `${colorize(prefix)} ${colorize(entry.field)}${pc.dim(":")} ${entry.details}`);
|
|
2003
2039
|
}
|
|
2004
2040
|
function printAppHeader(appName, appId) {
|
|
2005
2041
|
p.log.step(`\n=== [${pc.bold(appName)}] (app: ${appId}) ===`);
|
|
@@ -2051,8 +2087,13 @@ async function promptDeploy(container, skipConfirm) {
|
|
|
2051
2087
|
}
|
|
2052
2088
|
const ds = p.spinner();
|
|
2053
2089
|
ds.start("Deploying to production...");
|
|
2054
|
-
|
|
2055
|
-
|
|
2090
|
+
try {
|
|
2091
|
+
await deployApp({ container });
|
|
2092
|
+
ds.stop("Deployment complete.");
|
|
2093
|
+
} catch (error) {
|
|
2094
|
+
ds.stop("Deployment failed.");
|
|
2095
|
+
throw error;
|
|
2096
|
+
}
|
|
2056
2097
|
p.log.success("Deployed to production.");
|
|
2057
2098
|
}
|
|
2058
2099
|
|
|
@@ -2321,7 +2362,7 @@ function serializeMapping(mapping) {
|
|
|
2321
2362
|
if (mapping.srcField !== void 0) result.srcField = mapping.srcField;
|
|
2322
2363
|
return result;
|
|
2323
2364
|
}
|
|
2324
|
-
function serializeEntity$
|
|
2365
|
+
function serializeEntity$2(entity) {
|
|
2325
2366
|
return {
|
|
2326
2367
|
type: entity.type,
|
|
2327
2368
|
code: entity.code
|
|
@@ -2332,7 +2373,7 @@ function serializeActionConfig(config) {
|
|
|
2332
2373
|
index: config.index,
|
|
2333
2374
|
destApp: serializeDestApp(config.destApp),
|
|
2334
2375
|
mappings: config.mappings.map(serializeMapping),
|
|
2335
|
-
entities: config.entities.map(serializeEntity$
|
|
2376
|
+
entities: config.entities.map(serializeEntity$2),
|
|
2336
2377
|
filterCond: config.filterCond
|
|
2337
2378
|
};
|
|
2338
2379
|
}
|
|
@@ -2407,6 +2448,238 @@ var capture_default$13 = define({
|
|
|
2407
2448
|
}
|
|
2408
2449
|
});
|
|
2409
2450
|
|
|
2451
|
+
//#endregion
|
|
2452
|
+
//#region src/lib/deepEqual.ts
|
|
2453
|
+
function isArrayEqual(a, b, seen) {
|
|
2454
|
+
if (!Array.isArray(b)) return false;
|
|
2455
|
+
if (a.length !== b.length) return false;
|
|
2456
|
+
for (let i = 0; i < a.length; i++) if (!deepEqualInner(a[i], b[i], seen)) return false;
|
|
2457
|
+
return true;
|
|
2458
|
+
}
|
|
2459
|
+
function isRecordEqual(a, b, seen) {
|
|
2460
|
+
const keysA = Object.keys(a);
|
|
2461
|
+
const keysB = Object.keys(b);
|
|
2462
|
+
if (keysA.length !== keysB.length) return false;
|
|
2463
|
+
for (const key of keysA) {
|
|
2464
|
+
if (!Object.hasOwn(b, key)) return false;
|
|
2465
|
+
if (!deepEqualInner(a[key], b[key], seen)) return false;
|
|
2466
|
+
}
|
|
2467
|
+
return true;
|
|
2468
|
+
}
|
|
2469
|
+
function isMapEqual$1(a, b, seen) {
|
|
2470
|
+
if (!(b instanceof Map)) return false;
|
|
2471
|
+
if (a.size !== b.size) return false;
|
|
2472
|
+
for (const [key, valA] of a) {
|
|
2473
|
+
if (!b.has(key)) return false;
|
|
2474
|
+
if (!deepEqualInner(valA, b.get(key), seen)) return false;
|
|
2475
|
+
}
|
|
2476
|
+
return true;
|
|
2477
|
+
}
|
|
2478
|
+
function isSetEqual(a, b, _seen) {
|
|
2479
|
+
if (!(b instanceof Set)) return false;
|
|
2480
|
+
if (a.size !== b.size) return false;
|
|
2481
|
+
const remaining = [...b];
|
|
2482
|
+
for (const valA of a) {
|
|
2483
|
+
const idx = remaining.findIndex((valB) => deepEqualInner(valA, valB, /* @__PURE__ */ new WeakSet()));
|
|
2484
|
+
if (idx === -1) return false;
|
|
2485
|
+
remaining.splice(idx, 1);
|
|
2486
|
+
}
|
|
2487
|
+
return true;
|
|
2488
|
+
}
|
|
2489
|
+
function deepEqualInner(a, b, seen) {
|
|
2490
|
+
if (a === b) return true;
|
|
2491
|
+
if (a === null || b === null) return a === b;
|
|
2492
|
+
if (typeof a !== typeof b) return false;
|
|
2493
|
+
if (typeof a !== "object") return false;
|
|
2494
|
+
const objA = a;
|
|
2495
|
+
const objB = b;
|
|
2496
|
+
if (seen.has(objA) || seen.has(objB)) return false;
|
|
2497
|
+
seen.add(objA);
|
|
2498
|
+
seen.add(objB);
|
|
2499
|
+
if (Array.isArray(objA)) return isArrayEqual(objA, objB, seen);
|
|
2500
|
+
if (objA instanceof Date && objB instanceof Date) return objA.getTime() === objB.getTime();
|
|
2501
|
+
if (objA instanceof Date || objB instanceof Date) return false;
|
|
2502
|
+
if (objA instanceof RegExp && objB instanceof RegExp) return String(objA) === String(objB);
|
|
2503
|
+
if (objA instanceof RegExp || objB instanceof RegExp) return false;
|
|
2504
|
+
if (objA instanceof Map) return isMapEqual$1(objA, objB, seen);
|
|
2505
|
+
if (objB instanceof Map) return false;
|
|
2506
|
+
if (objA instanceof Set) return isSetEqual(objA, objB, seen);
|
|
2507
|
+
if (objB instanceof Set) return false;
|
|
2508
|
+
if (isRecord$1(objA) && isRecord$1(objB)) return isRecordEqual(objA, objB, seen);
|
|
2509
|
+
return false;
|
|
2510
|
+
}
|
|
2511
|
+
/**
|
|
2512
|
+
* Deep equality comparison for structured data.
|
|
2513
|
+
* Supports primitives, plain objects, arrays, Date, RegExp, Map, and Set.
|
|
2514
|
+
* Has circular reference protection via a WeakSet-based seen check (tracks both sides).
|
|
2515
|
+
*
|
|
2516
|
+
* Note: `{ a: undefined }` and `{}` are NOT considered equal. This differs from
|
|
2517
|
+
* JSON.stringify behavior but is intentional — explicit undefined properties are
|
|
2518
|
+
* semantically distinct from absent properties.
|
|
2519
|
+
*
|
|
2520
|
+
* Set comparison is order-independent: each element in one set is matched to an
|
|
2521
|
+
* element in the other using deep equality (O(n²)).
|
|
2522
|
+
*
|
|
2523
|
+
* NaN handling: `deepEqual(NaN, NaN)` returns `false` because the comparison
|
|
2524
|
+
* uses strict equality (`===`) for primitives, and `NaN !== NaN` in JavaScript.
|
|
2525
|
+
*
|
|
2526
|
+
* Circular reference limitation: objects already visited by the traversal are
|
|
2527
|
+
* treated as non-equal. This means structurally identical circular references
|
|
2528
|
+
* (e.g. `a.self = a` vs `b.self = b`) return `false`. This is a conservative
|
|
2529
|
+
* approach that prevents infinite recursion but may produce false negatives.
|
|
2530
|
+
*/
|
|
2531
|
+
function deepEqual$1(a, b) {
|
|
2532
|
+
return deepEqualInner(a, b, /* @__PURE__ */ new WeakSet());
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
//#endregion
|
|
2536
|
+
//#region src/core/domain/diff.ts
|
|
2537
|
+
const typeOrder = {
|
|
2538
|
+
added: 0,
|
|
2539
|
+
modified: 1,
|
|
2540
|
+
deleted: 2
|
|
2541
|
+
};
|
|
2542
|
+
function buildDiffResult(entries, warnings = []) {
|
|
2543
|
+
const sorted = [...entries].sort((a, b) => typeOrder[a.type] - typeOrder[b.type]);
|
|
2544
|
+
let added = 0;
|
|
2545
|
+
let modified = 0;
|
|
2546
|
+
let deleted = 0;
|
|
2547
|
+
for (const e of sorted) if (e.type === "added") added++;
|
|
2548
|
+
else if (e.type === "modified") modified++;
|
|
2549
|
+
else deleted++;
|
|
2550
|
+
return {
|
|
2551
|
+
entries: sorted,
|
|
2552
|
+
summary: {
|
|
2553
|
+
added,
|
|
2554
|
+
modified,
|
|
2555
|
+
deleted,
|
|
2556
|
+
total: sorted.length
|
|
2557
|
+
},
|
|
2558
|
+
isEmpty: sorted.length === 0,
|
|
2559
|
+
warnings
|
|
2560
|
+
};
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
//#endregion
|
|
2564
|
+
//#region src/core/domain/action/services/diffDetector.ts
|
|
2565
|
+
function compareActions$1(local, remote) {
|
|
2566
|
+
const diffs = [];
|
|
2567
|
+
if (local.index !== remote.index) diffs.push(`index: ${remote.index} -> ${local.index}`);
|
|
2568
|
+
if (local.name !== remote.name) diffs.push(`name: "${remote.name}" -> "${local.name}"`);
|
|
2569
|
+
if (!deepEqual$1(local.destApp, remote.destApp)) diffs.push("destApp changed");
|
|
2570
|
+
if (local.filterCond !== remote.filterCond) diffs.push("filterCond changed");
|
|
2571
|
+
if (!deepEqual$1(local.mappings, remote.mappings)) if (local.mappings.length !== remote.mappings.length) diffs.push(`mappings: ${remote.mappings.length} -> ${local.mappings.length}`);
|
|
2572
|
+
else diffs.push("mappings changed");
|
|
2573
|
+
if (!deepEqual$1(local.entities, remote.entities)) diffs.push("entities changed");
|
|
2574
|
+
return diffs;
|
|
2575
|
+
}
|
|
2576
|
+
const ActionDiffDetector = { detect: (local, remote) => {
|
|
2577
|
+
const entries = [];
|
|
2578
|
+
for (const [name, localAction] of Object.entries(local.actions)) {
|
|
2579
|
+
const remoteAction = remote.actions[name];
|
|
2580
|
+
if (!remoteAction) entries.push({
|
|
2581
|
+
type: "added",
|
|
2582
|
+
actionName: name,
|
|
2583
|
+
details: `dest: ${localAction.destApp.app ?? localAction.destApp.code ?? "(unspecified)"}`
|
|
2584
|
+
});
|
|
2585
|
+
else {
|
|
2586
|
+
const diffs = compareActions$1(localAction, remoteAction);
|
|
2587
|
+
if (diffs.length > 0) entries.push({
|
|
2588
|
+
type: "modified",
|
|
2589
|
+
actionName: name,
|
|
2590
|
+
details: diffs.join(", ")
|
|
2591
|
+
});
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
for (const [name, remoteAction] of Object.entries(remote.actions)) if (!local.actions[name]) entries.push({
|
|
2595
|
+
type: "deleted",
|
|
2596
|
+
actionName: name,
|
|
2597
|
+
details: `dest: ${remoteAction.destApp.app ?? remoteAction.destApp.code ?? "(unspecified)"}`
|
|
2598
|
+
});
|
|
2599
|
+
return buildDiffResult(entries);
|
|
2600
|
+
} };
|
|
2601
|
+
|
|
2602
|
+
//#endregion
|
|
2603
|
+
//#region src/core/application/detectDiffBase.ts
|
|
2604
|
+
async function detectDiffFromConfig(config) {
|
|
2605
|
+
const [storageResult, remote] = await Promise.all([config.getStorage(), config.fetchRemote()]);
|
|
2606
|
+
if (!storageResult.exists) throw new ValidationError(ValidationErrorCode.InvalidInput, config.notFoundMessage);
|
|
2607
|
+
const local = config.parseConfig(storageResult.content);
|
|
2608
|
+
return config.detect(local, remote);
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
//#endregion
|
|
2612
|
+
//#region src/core/application/action/detectActionDiff.ts
|
|
2613
|
+
async function detectActionDiff({ container }) {
|
|
2614
|
+
return detectDiffFromConfig({
|
|
2615
|
+
getStorage: () => container.actionStorage.get(),
|
|
2616
|
+
fetchRemote: () => container.actionConfigurator.getActions(),
|
|
2617
|
+
parseConfig: parseActionConfigText,
|
|
2618
|
+
detect: (local, remote) => ActionDiffDetector.detect(local, { actions: remote.actions }),
|
|
2619
|
+
notFoundMessage: "Action config file not found"
|
|
2620
|
+
});
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
//#endregion
|
|
2624
|
+
//#region src/cli/commands/diffCommandFactory.ts
|
|
2625
|
+
function createDiffCommand(config) {
|
|
2626
|
+
async function runDiff(containerConfig) {
|
|
2627
|
+
const container = config.createContainer(containerConfig);
|
|
2628
|
+
const s = p.spinner();
|
|
2629
|
+
s.start(config.spinnerMessage);
|
|
2630
|
+
let result;
|
|
2631
|
+
try {
|
|
2632
|
+
result = await config.detectDiff({ container });
|
|
2633
|
+
} catch (error) {
|
|
2634
|
+
s.stop("Comparison failed.");
|
|
2635
|
+
throw error;
|
|
2636
|
+
}
|
|
2637
|
+
s.stop("Comparison complete.");
|
|
2638
|
+
config.printResult(result);
|
|
2639
|
+
}
|
|
2640
|
+
return define({
|
|
2641
|
+
name: "diff",
|
|
2642
|
+
description: config.description,
|
|
2643
|
+
args: config.args,
|
|
2644
|
+
run: async (ctx) => {
|
|
2645
|
+
try {
|
|
2646
|
+
const values = ctx.values;
|
|
2647
|
+
await routeMultiApp(values, {
|
|
2648
|
+
singleLegacy: async () => {
|
|
2649
|
+
await runDiff(config.resolveContainerConfig(values));
|
|
2650
|
+
},
|
|
2651
|
+
singleApp: async (app, projectConfig) => {
|
|
2652
|
+
await runDiff(config.resolveAppContainerConfig(app, projectConfig, values));
|
|
2653
|
+
},
|
|
2654
|
+
multiApp: async (plan, projectConfig) => {
|
|
2655
|
+
await runMultiAppWithFailCheck(plan, async (app) => {
|
|
2656
|
+
const containerConfig = config.resolveAppContainerConfig(app, projectConfig, values);
|
|
2657
|
+
printAppHeader(app.name, app.appId);
|
|
2658
|
+
await runDiff(containerConfig);
|
|
2659
|
+
}, config.multiAppSuccessMessage);
|
|
2660
|
+
}
|
|
2661
|
+
});
|
|
2662
|
+
} catch (error) {
|
|
2663
|
+
handleCliError(error);
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
//#endregion
|
|
2670
|
+
//#region src/cli/commands/action/diff.ts
|
|
2671
|
+
var diff_default$12 = createDiffCommand({
|
|
2672
|
+
description: "Compare local action config with remote kintone app",
|
|
2673
|
+
args: actionArgs,
|
|
2674
|
+
spinnerMessage: "Comparing action settings...",
|
|
2675
|
+
multiAppSuccessMessage: "All action diffs completed successfully.",
|
|
2676
|
+
createContainer: createActionCliContainer,
|
|
2677
|
+
detectDiff: detectActionDiff,
|
|
2678
|
+
printResult: printActionDiffResult,
|
|
2679
|
+
resolveContainerConfig: resolveActionContainerConfig,
|
|
2680
|
+
resolveAppContainerConfig: resolveActionAppContainerConfig
|
|
2681
|
+
});
|
|
2682
|
+
|
|
2410
2683
|
//#endregion
|
|
2411
2684
|
//#region src/cli/commands/action/index.ts
|
|
2412
2685
|
var action_default = define({
|
|
@@ -2414,7 +2687,8 @@ var action_default = define({
|
|
|
2414
2687
|
description: "Manage kintone action settings",
|
|
2415
2688
|
subCommands: {
|
|
2416
2689
|
apply: apply_default$12,
|
|
2417
|
-
capture: capture_default$13
|
|
2690
|
+
capture: capture_default$13,
|
|
2691
|
+
diff: diff_default$12
|
|
2418
2692
|
},
|
|
2419
2693
|
run: () => {}
|
|
2420
2694
|
});
|
|
@@ -2662,6 +2936,52 @@ var capture_default$12 = define({
|
|
|
2662
2936
|
}
|
|
2663
2937
|
});
|
|
2664
2938
|
|
|
2939
|
+
//#endregion
|
|
2940
|
+
//#region src/core/domain/adminNotes/services/diffDetector.ts
|
|
2941
|
+
function compareConfigs$2(local, remote) {
|
|
2942
|
+
const entries = [];
|
|
2943
|
+
if (local.content !== remote.content) entries.push({
|
|
2944
|
+
type: "modified",
|
|
2945
|
+
field: "content",
|
|
2946
|
+
details: "content changed"
|
|
2947
|
+
});
|
|
2948
|
+
if (local.includeInTemplateAndDuplicates !== remote.includeInTemplateAndDuplicates) entries.push({
|
|
2949
|
+
type: "modified",
|
|
2950
|
+
field: "includeInTemplateAndDuplicates",
|
|
2951
|
+
details: `${String(remote.includeInTemplateAndDuplicates)} -> ${String(local.includeInTemplateAndDuplicates)}`
|
|
2952
|
+
});
|
|
2953
|
+
return entries;
|
|
2954
|
+
}
|
|
2955
|
+
const AdminNotesDiffDetector = { detect: (local, remote) => {
|
|
2956
|
+
return buildDiffResult(compareConfigs$2(local, remote));
|
|
2957
|
+
} };
|
|
2958
|
+
|
|
2959
|
+
//#endregion
|
|
2960
|
+
//#region src/core/application/adminNotes/detectAdminNotesDiff.ts
|
|
2961
|
+
async function detectAdminNotesDiff({ container }) {
|
|
2962
|
+
return detectDiffFromConfig({
|
|
2963
|
+
getStorage: () => container.adminNotesStorage.get(),
|
|
2964
|
+
fetchRemote: () => container.adminNotesConfigurator.getAdminNotes(),
|
|
2965
|
+
parseConfig: parseAdminNotesConfigText,
|
|
2966
|
+
detect: (local, remote) => AdminNotesDiffDetector.detect(local, remote.config),
|
|
2967
|
+
notFoundMessage: "Admin notes config file not found"
|
|
2968
|
+
});
|
|
2969
|
+
}
|
|
2970
|
+
|
|
2971
|
+
//#endregion
|
|
2972
|
+
//#region src/cli/commands/admin-notes/diff.ts
|
|
2973
|
+
var diff_default$11 = createDiffCommand({
|
|
2974
|
+
description: "Compare local admin notes config with remote kintone app",
|
|
2975
|
+
args: adminNotesArgs,
|
|
2976
|
+
spinnerMessage: "Comparing admin notes...",
|
|
2977
|
+
multiAppSuccessMessage: "All admin notes diffs completed successfully.",
|
|
2978
|
+
createContainer: createAdminNotesCliContainer,
|
|
2979
|
+
detectDiff: detectAdminNotesDiff,
|
|
2980
|
+
printResult: printAdminNotesDiffResult,
|
|
2981
|
+
resolveContainerConfig: resolveAdminNotesContainerConfig,
|
|
2982
|
+
resolveAppContainerConfig: resolveAdminNotesAppContainerConfig
|
|
2983
|
+
});
|
|
2984
|
+
|
|
2665
2985
|
//#endregion
|
|
2666
2986
|
//#region src/cli/commands/admin-notes/index.ts
|
|
2667
2987
|
var admin_notes_default = define({
|
|
@@ -2669,7 +2989,8 @@ var admin_notes_default = define({
|
|
|
2669
2989
|
description: "Manage kintone admin notes",
|
|
2670
2990
|
subCommands: {
|
|
2671
2991
|
apply: apply_default$11,
|
|
2672
|
-
capture: capture_default$12
|
|
2992
|
+
capture: capture_default$12,
|
|
2993
|
+
diff: diff_default$11
|
|
2673
2994
|
},
|
|
2674
2995
|
run: () => {}
|
|
2675
2996
|
});
|
|
@@ -3016,6 +3337,84 @@ var capture_default$11 = define({
|
|
|
3016
3337
|
}
|
|
3017
3338
|
});
|
|
3018
3339
|
|
|
3340
|
+
//#endregion
|
|
3341
|
+
//#region src/core/domain/appPermission/services/diffDetector.ts
|
|
3342
|
+
const BOOLEAN_FLAGS = [
|
|
3343
|
+
"includeSubs",
|
|
3344
|
+
"appEditable",
|
|
3345
|
+
"recordViewable",
|
|
3346
|
+
"recordAddable",
|
|
3347
|
+
"recordEditable",
|
|
3348
|
+
"recordDeletable",
|
|
3349
|
+
"recordImportable",
|
|
3350
|
+
"recordExportable"
|
|
3351
|
+
];
|
|
3352
|
+
function entityKey(right) {
|
|
3353
|
+
return `${right.entity.type}:${right.entity.code}`;
|
|
3354
|
+
}
|
|
3355
|
+
function describeRight$1(right) {
|
|
3356
|
+
const flags = BOOLEAN_FLAGS.filter((f) => f !== "includeSubs" && right[f]);
|
|
3357
|
+
return flags.length > 0 ? flags.join(", ") : "no permissions";
|
|
3358
|
+
}
|
|
3359
|
+
function compareRights(local, remote) {
|
|
3360
|
+
const diffs = [];
|
|
3361
|
+
for (const flag of BOOLEAN_FLAGS) if (local[flag] !== remote[flag]) diffs.push(`${flag}: ${String(remote[flag])} -> ${String(local[flag])}`);
|
|
3362
|
+
return diffs;
|
|
3363
|
+
}
|
|
3364
|
+
const AppPermissionDiffDetector = { detect: (local, remote) => {
|
|
3365
|
+
const entries = [];
|
|
3366
|
+
const localMap = new Map(local.rights.map((r) => [entityKey(r), r]));
|
|
3367
|
+
const remoteMap = new Map(remote.rights.map((r) => [entityKey(r), r]));
|
|
3368
|
+
for (const [key, localRight] of localMap) {
|
|
3369
|
+
const remoteRight = remoteMap.get(key);
|
|
3370
|
+
if (!remoteRight) entries.push({
|
|
3371
|
+
type: "added",
|
|
3372
|
+
entityKey: key,
|
|
3373
|
+
details: describeRight$1(localRight)
|
|
3374
|
+
});
|
|
3375
|
+
else {
|
|
3376
|
+
const diffs = compareRights(localRight, remoteRight);
|
|
3377
|
+
if (diffs.length > 0) entries.push({
|
|
3378
|
+
type: "modified",
|
|
3379
|
+
entityKey: key,
|
|
3380
|
+
details: diffs.join(", ")
|
|
3381
|
+
});
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
for (const [key, remoteRight] of remoteMap) if (!localMap.has(key)) entries.push({
|
|
3385
|
+
type: "deleted",
|
|
3386
|
+
entityKey: key,
|
|
3387
|
+
details: describeRight$1(remoteRight)
|
|
3388
|
+
});
|
|
3389
|
+
return buildDiffResult(entries);
|
|
3390
|
+
} };
|
|
3391
|
+
|
|
3392
|
+
//#endregion
|
|
3393
|
+
//#region src/core/application/appPermission/detectAppPermissionDiff.ts
|
|
3394
|
+
async function detectAppPermissionDiff({ container }) {
|
|
3395
|
+
return detectDiffFromConfig({
|
|
3396
|
+
getStorage: () => container.appPermissionStorage.get(),
|
|
3397
|
+
fetchRemote: () => container.appPermissionConfigurator.getAppPermissions(),
|
|
3398
|
+
parseConfig: parseAppPermissionConfigText,
|
|
3399
|
+
detect: (local, remote) => AppPermissionDiffDetector.detect(local, { rights: remote.rights }),
|
|
3400
|
+
notFoundMessage: "App permission config file not found"
|
|
3401
|
+
});
|
|
3402
|
+
}
|
|
3403
|
+
|
|
3404
|
+
//#endregion
|
|
3405
|
+
//#region src/cli/commands/app-acl/diff.ts
|
|
3406
|
+
var diff_default$10 = createDiffCommand({
|
|
3407
|
+
description: "Compare local app permission config with remote kintone app",
|
|
3408
|
+
args: appAclArgs,
|
|
3409
|
+
spinnerMessage: "Comparing app permissions...",
|
|
3410
|
+
multiAppSuccessMessage: "All app permission diffs completed successfully.",
|
|
3411
|
+
createContainer: createAppPermissionCliContainer,
|
|
3412
|
+
detectDiff: detectAppPermissionDiff,
|
|
3413
|
+
printResult: printAppPermissionDiffResult,
|
|
3414
|
+
resolveContainerConfig: resolveAppAclContainerConfig,
|
|
3415
|
+
resolveAppContainerConfig: resolveAppAclAppContainerConfig
|
|
3416
|
+
});
|
|
3417
|
+
|
|
3019
3418
|
//#endregion
|
|
3020
3419
|
//#region src/cli/commands/app-acl/index.ts
|
|
3021
3420
|
var app_acl_default = define({
|
|
@@ -3023,7 +3422,8 @@ var app_acl_default = define({
|
|
|
3023
3422
|
description: "Manage kintone app access permissions",
|
|
3024
3423
|
subCommands: {
|
|
3025
3424
|
apply: apply_default$10,
|
|
3026
|
-
capture: capture_default$11
|
|
3425
|
+
capture: capture_default$11,
|
|
3426
|
+
diff: diff_default$10
|
|
3027
3427
|
},
|
|
3028
3428
|
run: () => {}
|
|
3029
3429
|
});
|
|
@@ -3499,6 +3899,105 @@ var apply_default$9 = define({
|
|
|
3499
3899
|
}
|
|
3500
3900
|
});
|
|
3501
3901
|
|
|
3902
|
+
//#endregion
|
|
3903
|
+
//#region src/core/domain/customization/valueObject.ts
|
|
3904
|
+
const DEFAULT_CUSTOMIZATION_SCOPE = "ALL";
|
|
3905
|
+
|
|
3906
|
+
//#endregion
|
|
3907
|
+
//#region src/core/domain/customization/services/diffDetector.ts
|
|
3908
|
+
function resourceName(resource) {
|
|
3909
|
+
if (resource.type === "URL") return resource.url;
|
|
3910
|
+
const parts = resource.path.replace(/\\/g, "/").split("/");
|
|
3911
|
+
return parts[parts.length - 1];
|
|
3912
|
+
}
|
|
3913
|
+
function remoteResourceName(resource) {
|
|
3914
|
+
if (resource.type === "URL") return resource.url;
|
|
3915
|
+
return resource.file.name;
|
|
3916
|
+
}
|
|
3917
|
+
function compareResourceLists(localResources, remoteResources, platform, resourceType, warnings) {
|
|
3918
|
+
const entries = [];
|
|
3919
|
+
const localNames = localResources.map(resourceName);
|
|
3920
|
+
const remoteNames = remoteResources.map(remoteResourceName);
|
|
3921
|
+
const localNameSet = new Set(localNames);
|
|
3922
|
+
const remoteNameSet = new Set(remoteNames);
|
|
3923
|
+
const hasDuplicates = localNames.length !== localNameSet.size || remoteNames.length !== remoteNameSet.size;
|
|
3924
|
+
if (hasDuplicates) warnings.push(`[${platform}.${resourceType}] duplicate basenames detected; diff results may be inaccurate for FILE resources`);
|
|
3925
|
+
for (const name of localNameSet) if (!remoteNameSet.has(name)) entries.push({
|
|
3926
|
+
type: "added",
|
|
3927
|
+
platform,
|
|
3928
|
+
category: resourceType,
|
|
3929
|
+
name,
|
|
3930
|
+
details: "new resource"
|
|
3931
|
+
});
|
|
3932
|
+
for (const name of remoteNameSet) if (!localNameSet.has(name)) entries.push({
|
|
3933
|
+
type: "deleted",
|
|
3934
|
+
platform,
|
|
3935
|
+
category: resourceType,
|
|
3936
|
+
name,
|
|
3937
|
+
details: "removed"
|
|
3938
|
+
});
|
|
3939
|
+
const matchedFiles = [...localNameSet].filter((n) => remoteNameSet.has(n));
|
|
3940
|
+
const hasLocalFiles = localResources.some((r) => r.type === "FILE");
|
|
3941
|
+
const hasRemoteFiles = remoteResources.some((r) => r.type === "FILE");
|
|
3942
|
+
if (matchedFiles.length > 0 && hasLocalFiles && hasRemoteFiles) warnings.push(`[${platform}.${resourceType}] FILE resources are compared by name only; content changes are not detected`);
|
|
3943
|
+
if (!hasDuplicates) {
|
|
3944
|
+
const localShared = localNames.filter((n) => remoteNameSet.has(n));
|
|
3945
|
+
const remoteShared = remoteNames.filter((n) => localNameSet.has(n));
|
|
3946
|
+
if (localShared.length > 1 && localShared.length === remoteShared.length && localShared.some((n, i) => n !== remoteShared[i])) entries.push({
|
|
3947
|
+
type: "modified",
|
|
3948
|
+
platform,
|
|
3949
|
+
category: resourceType,
|
|
3950
|
+
name: "(order)",
|
|
3951
|
+
details: "resource load order changed"
|
|
3952
|
+
});
|
|
3953
|
+
}
|
|
3954
|
+
return entries;
|
|
3955
|
+
}
|
|
3956
|
+
function comparePlatform(localJs, localCss, remote, platform, warnings) {
|
|
3957
|
+
return [...compareResourceLists(localJs, remote.js, platform, "js", warnings), ...compareResourceLists(localCss, remote.css, platform, "css", warnings)];
|
|
3958
|
+
}
|
|
3959
|
+
const CustomizationDiffDetector = { detect: (local, remote) => {
|
|
3960
|
+
const entries = [];
|
|
3961
|
+
const warnings = [];
|
|
3962
|
+
const localScope = local.scope ?? DEFAULT_CUSTOMIZATION_SCOPE;
|
|
3963
|
+
if (localScope !== remote.scope) entries.push({
|
|
3964
|
+
type: "modified",
|
|
3965
|
+
platform: "config",
|
|
3966
|
+
category: "scope",
|
|
3967
|
+
name: "scope",
|
|
3968
|
+
details: `${remote.scope} -> ${localScope}`
|
|
3969
|
+
});
|
|
3970
|
+
entries.push(...comparePlatform(local.desktop.js, local.desktop.css, remote.desktop, "desktop", warnings));
|
|
3971
|
+
entries.push(...comparePlatform(local.mobile.js, local.mobile.css, remote.mobile, "mobile", warnings));
|
|
3972
|
+
return buildDiffResult(entries, warnings);
|
|
3973
|
+
} };
|
|
3974
|
+
|
|
3975
|
+
//#endregion
|
|
3976
|
+
//#region src/core/application/customization/detectCustomizationDiff.ts
|
|
3977
|
+
async function detectCustomizationDiff({ container }) {
|
|
3978
|
+
return detectDiffFromConfig({
|
|
3979
|
+
getStorage: () => container.customizationStorage.get(),
|
|
3980
|
+
fetchRemote: () => container.customizationConfigurator.getCustomization(),
|
|
3981
|
+
parseConfig: (content) => parseConfigText(content),
|
|
3982
|
+
detect: (local, remote) => CustomizationDiffDetector.detect(local, remote),
|
|
3983
|
+
notFoundMessage: "Customization config file not found"
|
|
3984
|
+
});
|
|
3985
|
+
}
|
|
3986
|
+
|
|
3987
|
+
//#endregion
|
|
3988
|
+
//#region src/cli/commands/customize/diff.ts
|
|
3989
|
+
var diff_default$9 = createDiffCommand({
|
|
3990
|
+
description: "Compare local customization config with remote kintone app",
|
|
3991
|
+
args: customizeArgs,
|
|
3992
|
+
spinnerMessage: "Comparing customization settings...",
|
|
3993
|
+
multiAppSuccessMessage: "All customization diffs completed successfully.",
|
|
3994
|
+
createContainer: createCustomizationCliContainer,
|
|
3995
|
+
detectDiff: detectCustomizationDiff,
|
|
3996
|
+
printResult: printCustomizationDiffResult,
|
|
3997
|
+
resolveContainerConfig: resolveCustomizeConfig,
|
|
3998
|
+
resolveAppContainerConfig: resolveCustomizeAppConfig
|
|
3999
|
+
});
|
|
4000
|
+
|
|
3502
4001
|
//#endregion
|
|
3503
4002
|
//#region src/cli/commands/customize/index.ts
|
|
3504
4003
|
var customize_default = define({
|
|
@@ -3506,7 +4005,8 @@ var customize_default = define({
|
|
|
3506
4005
|
description: "Manage kintone JS/CSS customizations",
|
|
3507
4006
|
subCommands: {
|
|
3508
4007
|
apply: apply_default$9,
|
|
3509
|
-
capture: capture_default$10
|
|
4008
|
+
capture: capture_default$10,
|
|
4009
|
+
diff: diff_default$9
|
|
3510
4010
|
},
|
|
3511
4011
|
run: () => {}
|
|
3512
4012
|
});
|
|
@@ -3860,6 +4360,72 @@ var capture_default$9 = define({
|
|
|
3860
4360
|
}
|
|
3861
4361
|
});
|
|
3862
4362
|
|
|
4363
|
+
//#endregion
|
|
4364
|
+
//#region src/core/domain/fieldPermission/services/diffDetector.ts
|
|
4365
|
+
function areEntitiesEqual(a, b) {
|
|
4366
|
+
return deepEqual$1(a.entities.map((e) => ({
|
|
4367
|
+
accessibility: e.accessibility,
|
|
4368
|
+
type: e.entity.type,
|
|
4369
|
+
code: e.entity.code,
|
|
4370
|
+
includeSubs: e.includeSubs ?? false
|
|
4371
|
+
})), b.entities.map((e) => ({
|
|
4372
|
+
accessibility: e.accessibility,
|
|
4373
|
+
type: e.entity.type,
|
|
4374
|
+
code: e.entity.code,
|
|
4375
|
+
includeSubs: e.includeSubs ?? false
|
|
4376
|
+
})));
|
|
4377
|
+
}
|
|
4378
|
+
const FieldPermissionDiffDetector = { detect: (local, remote) => {
|
|
4379
|
+
const entries = [];
|
|
4380
|
+
const localMap = new Map(local.rights.map((r) => [r.code, r]));
|
|
4381
|
+
const remoteMap = new Map(remote.rights.map((r) => [r.code, r]));
|
|
4382
|
+
for (const [code, localRight] of localMap) {
|
|
4383
|
+
const remoteRight = remoteMap.get(code);
|
|
4384
|
+
if (!remoteRight) entries.push({
|
|
4385
|
+
type: "added",
|
|
4386
|
+
fieldCode: code,
|
|
4387
|
+
details: `${localRight.entities.length} entities`
|
|
4388
|
+
});
|
|
4389
|
+
else if (!areEntitiesEqual(localRight, remoteRight)) entries.push({
|
|
4390
|
+
type: "modified",
|
|
4391
|
+
fieldCode: code,
|
|
4392
|
+
details: "entities changed"
|
|
4393
|
+
});
|
|
4394
|
+
}
|
|
4395
|
+
for (const code of remoteMap.keys()) if (!localMap.has(code)) entries.push({
|
|
4396
|
+
type: "deleted",
|
|
4397
|
+
fieldCode: code,
|
|
4398
|
+
details: "removed"
|
|
4399
|
+
});
|
|
4400
|
+
return buildDiffResult(entries);
|
|
4401
|
+
} };
|
|
4402
|
+
|
|
4403
|
+
//#endregion
|
|
4404
|
+
//#region src/core/application/fieldPermission/detectFieldPermissionDiff.ts
|
|
4405
|
+
async function detectFieldPermissionDiff({ container }) {
|
|
4406
|
+
return detectDiffFromConfig({
|
|
4407
|
+
getStorage: () => container.fieldPermissionStorage.get(),
|
|
4408
|
+
fetchRemote: () => container.fieldPermissionConfigurator.getFieldPermissions(),
|
|
4409
|
+
parseConfig: parseFieldPermissionConfigText,
|
|
4410
|
+
detect: (local, remote) => FieldPermissionDiffDetector.detect(local, { rights: remote.rights }),
|
|
4411
|
+
notFoundMessage: "Field permission config file not found"
|
|
4412
|
+
});
|
|
4413
|
+
}
|
|
4414
|
+
|
|
4415
|
+
//#endregion
|
|
4416
|
+
//#region src/cli/commands/field-acl/diff.ts
|
|
4417
|
+
var diff_default$8 = createDiffCommand({
|
|
4418
|
+
description: "Compare local field permission config with remote kintone app",
|
|
4419
|
+
args: fieldAclArgs,
|
|
4420
|
+
spinnerMessage: "Comparing field permissions...",
|
|
4421
|
+
multiAppSuccessMessage: "All field permission diffs completed successfully.",
|
|
4422
|
+
createContainer: createFieldPermissionCliContainer,
|
|
4423
|
+
detectDiff: detectFieldPermissionDiff,
|
|
4424
|
+
printResult: printFieldPermissionDiffResult,
|
|
4425
|
+
resolveContainerConfig: resolveFieldAclContainerConfig,
|
|
4426
|
+
resolveAppContainerConfig: resolveFieldAclAppContainerConfig
|
|
4427
|
+
});
|
|
4428
|
+
|
|
3863
4429
|
//#endregion
|
|
3864
4430
|
//#region src/cli/commands/field-acl/index.ts
|
|
3865
4431
|
var field_acl_default = define({
|
|
@@ -3867,7 +4433,8 @@ var field_acl_default = define({
|
|
|
3867
4433
|
description: "Manage kintone field access permissions",
|
|
3868
4434
|
subCommands: {
|
|
3869
4435
|
apply: apply_default$8,
|
|
3870
|
-
capture: capture_default$9
|
|
4436
|
+
capture: capture_default$9,
|
|
4437
|
+
diff: diff_default$8
|
|
3871
4438
|
},
|
|
3872
4439
|
run: () => {}
|
|
3873
4440
|
});
|
|
@@ -5322,7 +5889,7 @@ async function saveGeneralSettings({ container, input }) {
|
|
|
5322
5889
|
|
|
5323
5890
|
//#endregion
|
|
5324
5891
|
//#region src/core/domain/notification/services/configSerializer.ts
|
|
5325
|
-
function serializeEntity(entity) {
|
|
5892
|
+
function serializeEntity$1(entity) {
|
|
5326
5893
|
return {
|
|
5327
5894
|
type: entity.type,
|
|
5328
5895
|
code: entity.code
|
|
@@ -5330,7 +5897,7 @@ function serializeEntity(entity) {
|
|
|
5330
5897
|
}
|
|
5331
5898
|
function serializeGeneralNotification(notification) {
|
|
5332
5899
|
const result = {
|
|
5333
|
-
entity: serializeEntity(notification.entity),
|
|
5900
|
+
entity: serializeEntity$1(notification.entity),
|
|
5334
5901
|
recordAdded: notification.recordAdded,
|
|
5335
5902
|
recordEdited: notification.recordEdited,
|
|
5336
5903
|
commentAdded: notification.commentAdded,
|
|
@@ -5341,7 +5908,7 @@ function serializeGeneralNotification(notification) {
|
|
|
5341
5908
|
return result;
|
|
5342
5909
|
}
|
|
5343
5910
|
function serializePerRecordTarget(target) {
|
|
5344
|
-
const result = { entity: serializeEntity(target.entity) };
|
|
5911
|
+
const result = { entity: serializeEntity$1(target.entity) };
|
|
5345
5912
|
if (target.includeSubs !== void 0) result.includeSubs = target.includeSubs;
|
|
5346
5913
|
return result;
|
|
5347
5914
|
}
|
|
@@ -5353,7 +5920,7 @@ function serializePerRecordNotification(notification) {
|
|
|
5353
5920
|
};
|
|
5354
5921
|
}
|
|
5355
5922
|
function serializeReminderTarget(target) {
|
|
5356
|
-
const result = { entity: serializeEntity(target.entity) };
|
|
5923
|
+
const result = { entity: serializeEntity$1(target.entity) };
|
|
5357
5924
|
if (target.includeSubs !== void 0) result.includeSubs = target.includeSubs;
|
|
5358
5925
|
return result;
|
|
5359
5926
|
}
|
|
@@ -6328,26 +6895,273 @@ var capture_default$8 = define({
|
|
|
6328
6895
|
});
|
|
6329
6896
|
|
|
6330
6897
|
//#endregion
|
|
6331
|
-
//#region src/
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6898
|
+
//#region src/lib/groupByKey.ts
|
|
6899
|
+
/**
|
|
6900
|
+
* Groups items by a key function into a Map where each key maps to an array of items.
|
|
6901
|
+
* Multiple items can share the same key, producing a multimap structure.
|
|
6902
|
+
*/
|
|
6903
|
+
function groupByKey(items, keyFn) {
|
|
6904
|
+
const map = /* @__PURE__ */ new Map();
|
|
6905
|
+
for (const item of items) {
|
|
6906
|
+
const key = keyFn(item);
|
|
6907
|
+
const existing = map.get(key);
|
|
6908
|
+
if (existing) existing.push(item);
|
|
6909
|
+
else map.set(key, [item]);
|
|
6910
|
+
}
|
|
6911
|
+
return map;
|
|
6912
|
+
}
|
|
6341
6913
|
|
|
6342
6914
|
//#endregion
|
|
6343
|
-
//#region src/core/domain/
|
|
6344
|
-
function
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6915
|
+
//#region src/core/domain/notification/services/diffDetector.ts
|
|
6916
|
+
function serializeEntity(entity) {
|
|
6917
|
+
return `${entity.type}:${entity.code}`;
|
|
6918
|
+
}
|
|
6919
|
+
const GENERAL_BOOLEAN_FLAGS = [
|
|
6920
|
+
"recordAdded",
|
|
6921
|
+
"recordEdited",
|
|
6922
|
+
"commentAdded",
|
|
6923
|
+
"statusChanged",
|
|
6924
|
+
"fileImported"
|
|
6925
|
+
];
|
|
6926
|
+
function compareGeneralNotification(local, remote) {
|
|
6927
|
+
const diffs = [];
|
|
6928
|
+
if ((local.includeSubs ?? false) !== (remote.includeSubs ?? false)) diffs.push(`includeSubs: ${String(remote.includeSubs ?? false)} -> ${String(local.includeSubs ?? false)}`);
|
|
6929
|
+
for (const flag of GENERAL_BOOLEAN_FLAGS) if (local[flag] !== remote[flag]) diffs.push(`${flag}: ${String(remote[flag])} -> ${String(local[flag])}`);
|
|
6930
|
+
return diffs;
|
|
6931
|
+
}
|
|
6932
|
+
function compareGeneralSection(local, remote) {
|
|
6933
|
+
const entries = [];
|
|
6934
|
+
if (local.notifyToCommenter !== remote.notifyToCommenter) entries.push({
|
|
6935
|
+
type: "modified",
|
|
6936
|
+
section: "general",
|
|
6937
|
+
name: "notifyToCommenter",
|
|
6938
|
+
details: `${String(remote.notifyToCommenter)} -> ${String(local.notifyToCommenter)}`
|
|
6939
|
+
});
|
|
6940
|
+
const localMap = new Map(local.notifications.map((n) => [serializeEntity(n.entity), n]));
|
|
6941
|
+
const remoteMap = new Map(remote.notifications.map((n) => [serializeEntity(n.entity), n]));
|
|
6942
|
+
for (const [key, localNotif] of localMap) {
|
|
6943
|
+
const remoteNotif = remoteMap.get(key);
|
|
6944
|
+
if (!remoteNotif) entries.push({
|
|
6945
|
+
type: "added",
|
|
6946
|
+
section: "general",
|
|
6947
|
+
name: key,
|
|
6948
|
+
details: "new notification"
|
|
6949
|
+
});
|
|
6950
|
+
else {
|
|
6951
|
+
const diffs = compareGeneralNotification(localNotif, remoteNotif);
|
|
6952
|
+
if (diffs.length > 0) entries.push({
|
|
6953
|
+
type: "modified",
|
|
6954
|
+
section: "general",
|
|
6955
|
+
name: key,
|
|
6956
|
+
details: diffs.join(", ")
|
|
6957
|
+
});
|
|
6958
|
+
}
|
|
6959
|
+
}
|
|
6960
|
+
for (const key of remoteMap.keys()) if (!localMap.has(key)) entries.push({
|
|
6961
|
+
type: "deleted",
|
|
6962
|
+
section: "general",
|
|
6963
|
+
name: key,
|
|
6964
|
+
details: "removed"
|
|
6965
|
+
});
|
|
6966
|
+
return entries;
|
|
6967
|
+
}
|
|
6968
|
+
/**
|
|
6969
|
+
* Groups per-record notifications by filterCond. Multiple notifications can share
|
|
6970
|
+
* the same filterCond, so notifications within a group are compared by position
|
|
6971
|
+
* (index-based matching).
|
|
6972
|
+
*/
|
|
6973
|
+
function buildPerRecordMultiMap(notifications) {
|
|
6974
|
+
return groupByKey(notifications, (n) => n.filterCond);
|
|
6975
|
+
}
|
|
6976
|
+
function perRecordLabel(notif) {
|
|
6977
|
+
return notif.title || notif.filterCond || "(empty filter)";
|
|
6978
|
+
}
|
|
6979
|
+
function describePerRecordChanges(local, remote) {
|
|
6980
|
+
const diffs = [];
|
|
6981
|
+
if (local.title !== remote.title) diffs.push("title changed");
|
|
6982
|
+
if (!deepEqual$1(local.targets, remote.targets)) diffs.push("targets changed");
|
|
6983
|
+
return diffs.length > 0 ? diffs.join(", ") : "changed";
|
|
6984
|
+
}
|
|
6985
|
+
function describeReminderChanges(local, remote) {
|
|
6986
|
+
const diffs = [];
|
|
6987
|
+
if (local.title !== remote.title) diffs.push("title changed");
|
|
6988
|
+
if (local.daysLater !== remote.daysLater) diffs.push("daysLater changed");
|
|
6989
|
+
if ((local.hoursLater ?? 0) !== (remote.hoursLater ?? 0)) diffs.push("hoursLater changed");
|
|
6990
|
+
if ((local.time ?? "") !== (remote.time ?? "")) diffs.push("time changed");
|
|
6991
|
+
if (local.filterCond !== remote.filterCond) diffs.push("filterCond changed");
|
|
6992
|
+
if (!deepEqual$1(local.targets, remote.targets)) diffs.push("targets changed");
|
|
6993
|
+
return diffs.length > 0 ? diffs.join(", ") : "changed";
|
|
6994
|
+
}
|
|
6995
|
+
function comparePerRecordSection(local, remote) {
|
|
6996
|
+
const entries = [];
|
|
6997
|
+
const localMulti = buildPerRecordMultiMap(local);
|
|
6998
|
+
const remoteMulti = buildPerRecordMultiMap(remote);
|
|
6999
|
+
for (const [key, localNotifs] of localMulti) {
|
|
7000
|
+
const remoteNotifs = remoteMulti.get(key) ?? [];
|
|
7001
|
+
const maxLen = Math.max(localNotifs.length, remoteNotifs.length);
|
|
7002
|
+
for (let i = 0; i < maxLen; i++) {
|
|
7003
|
+
const localNotif = localNotifs[i];
|
|
7004
|
+
const remoteNotif = remoteNotifs[i];
|
|
7005
|
+
if (localNotif && !remoteNotif) entries.push({
|
|
7006
|
+
type: "added",
|
|
7007
|
+
section: "perRecord",
|
|
7008
|
+
name: perRecordLabel(localNotif),
|
|
7009
|
+
details: "new notification"
|
|
7010
|
+
});
|
|
7011
|
+
else if (!localNotif && remoteNotif) entries.push({
|
|
7012
|
+
type: "deleted",
|
|
7013
|
+
section: "perRecord",
|
|
7014
|
+
name: perRecordLabel(remoteNotif),
|
|
7015
|
+
details: "removed"
|
|
7016
|
+
});
|
|
7017
|
+
else if (localNotif && remoteNotif && !deepEqual$1(localNotif, remoteNotif)) {
|
|
7018
|
+
const diffs = describePerRecordChanges(localNotif, remoteNotif);
|
|
7019
|
+
entries.push({
|
|
7020
|
+
type: "modified",
|
|
7021
|
+
section: "perRecord",
|
|
7022
|
+
name: perRecordLabel(localNotif),
|
|
7023
|
+
details: diffs
|
|
7024
|
+
});
|
|
7025
|
+
}
|
|
7026
|
+
}
|
|
7027
|
+
}
|
|
7028
|
+
for (const [key, remoteNotifs] of remoteMulti) if (!localMulti.has(key)) for (const remoteNotif of remoteNotifs) entries.push({
|
|
7029
|
+
type: "deleted",
|
|
7030
|
+
section: "perRecord",
|
|
7031
|
+
name: perRecordLabel(remoteNotif),
|
|
7032
|
+
details: "removed"
|
|
7033
|
+
});
|
|
7034
|
+
return entries;
|
|
7035
|
+
}
|
|
7036
|
+
function compareReminderSection(local, remote) {
|
|
7037
|
+
const entries = [];
|
|
7038
|
+
const localMap = new Map(local.map((n) => [n.code, n]));
|
|
7039
|
+
const remoteMap = new Map(remote.map((n) => [n.code, n]));
|
|
7040
|
+
for (const [code, localNotif] of localMap) {
|
|
7041
|
+
const remoteNotif = remoteMap.get(code);
|
|
7042
|
+
if (!remoteNotif) entries.push({
|
|
7043
|
+
type: "added",
|
|
7044
|
+
section: "reminder",
|
|
7045
|
+
name: code,
|
|
7046
|
+
details: `"${localNotif.title}"`
|
|
7047
|
+
});
|
|
7048
|
+
else if (!deepEqual$1(localNotif, remoteNotif)) entries.push({
|
|
7049
|
+
type: "modified",
|
|
7050
|
+
section: "reminder",
|
|
7051
|
+
name: code,
|
|
7052
|
+
details: describeReminderChanges(localNotif, remoteNotif)
|
|
7053
|
+
});
|
|
7054
|
+
}
|
|
7055
|
+
for (const code of remoteMap.keys()) if (!localMap.has(code)) entries.push({
|
|
7056
|
+
type: "deleted",
|
|
7057
|
+
section: "reminder",
|
|
7058
|
+
name: code,
|
|
7059
|
+
details: "removed"
|
|
7060
|
+
});
|
|
7061
|
+
return entries;
|
|
7062
|
+
}
|
|
7063
|
+
const NotificationDiffDetector = { detect: (local, remote) => {
|
|
7064
|
+
const entries = [];
|
|
7065
|
+
if (local.general && remote.general) entries.push(...compareGeneralSection(local.general, remote.general));
|
|
7066
|
+
else if (local.general && !remote.general) entries.push({
|
|
7067
|
+
type: "added",
|
|
7068
|
+
section: "general",
|
|
7069
|
+
name: "general",
|
|
7070
|
+
details: "added general notifications section"
|
|
7071
|
+
});
|
|
7072
|
+
else if (!local.general && remote.general) entries.push({
|
|
7073
|
+
type: "deleted",
|
|
7074
|
+
section: "general",
|
|
7075
|
+
name: "general",
|
|
7076
|
+
details: "removed general notifications section"
|
|
7077
|
+
});
|
|
7078
|
+
const localPerRecord = local.perRecord ?? [];
|
|
7079
|
+
const remotePerRecord = remote.perRecord ?? [];
|
|
7080
|
+
entries.push(...comparePerRecordSection(localPerRecord, remotePerRecord));
|
|
7081
|
+
if (local.reminder && remote.reminder) {
|
|
7082
|
+
entries.push(...compareReminderSection(local.reminder.notifications, remote.reminder.notifications));
|
|
7083
|
+
if (local.reminder.timezone !== remote.reminder.timezone) entries.push({
|
|
7084
|
+
type: "modified",
|
|
7085
|
+
section: "reminder",
|
|
7086
|
+
name: "timezone",
|
|
7087
|
+
details: `${remote.reminder.timezone} -> ${local.reminder.timezone}`
|
|
7088
|
+
});
|
|
7089
|
+
} else if (local.reminder && !remote.reminder) entries.push({
|
|
7090
|
+
type: "added",
|
|
7091
|
+
section: "reminder",
|
|
7092
|
+
name: "reminder",
|
|
7093
|
+
details: "added reminder notifications section"
|
|
7094
|
+
});
|
|
7095
|
+
else if (!local.reminder && remote.reminder) entries.push({
|
|
7096
|
+
type: "deleted",
|
|
7097
|
+
section: "reminder",
|
|
7098
|
+
name: "reminder",
|
|
7099
|
+
details: "removed reminder notifications section"
|
|
7100
|
+
});
|
|
7101
|
+
return buildDiffResult(entries);
|
|
7102
|
+
} };
|
|
7103
|
+
|
|
7104
|
+
//#endregion
|
|
7105
|
+
//#region src/core/application/notification/detectNotificationDiff.ts
|
|
7106
|
+
async function detectNotificationDiff({ container }) {
|
|
7107
|
+
const [storageResult, generalResult, perRecordResult, reminderResult] = await Promise.all([
|
|
7108
|
+
container.notificationStorage.get(),
|
|
7109
|
+
container.notificationConfigurator.getGeneralNotifications(),
|
|
7110
|
+
container.notificationConfigurator.getPerRecordNotifications(),
|
|
7111
|
+
container.notificationConfigurator.getReminderNotifications()
|
|
7112
|
+
]);
|
|
7113
|
+
if (!storageResult.exists) throw new ValidationError(ValidationErrorCode.InvalidInput, "Notification config file not found");
|
|
7114
|
+
const localConfig = parseNotificationConfigText(storageResult.content);
|
|
7115
|
+
const remoteConfig = {
|
|
7116
|
+
general: {
|
|
7117
|
+
notifyToCommenter: generalResult.notifyToCommenter,
|
|
7118
|
+
notifications: generalResult.notifications
|
|
7119
|
+
},
|
|
7120
|
+
perRecord: perRecordResult.notifications,
|
|
7121
|
+
reminder: {
|
|
7122
|
+
timezone: reminderResult.timezone,
|
|
7123
|
+
notifications: reminderResult.notifications
|
|
7124
|
+
}
|
|
7125
|
+
};
|
|
7126
|
+
return NotificationDiffDetector.detect(localConfig, remoteConfig);
|
|
7127
|
+
}
|
|
7128
|
+
|
|
7129
|
+
//#endregion
|
|
7130
|
+
//#region src/cli/commands/notification/diff.ts
|
|
7131
|
+
var diff_default$7 = createDiffCommand({
|
|
7132
|
+
description: "Compare local notification config with remote kintone app",
|
|
7133
|
+
args: notificationArgs,
|
|
7134
|
+
spinnerMessage: "Comparing notification settings...",
|
|
7135
|
+
multiAppSuccessMessage: "All notification diffs completed successfully.",
|
|
7136
|
+
createContainer: createNotificationCliContainer,
|
|
7137
|
+
detectDiff: detectNotificationDiff,
|
|
7138
|
+
printResult: printNotificationDiffResult,
|
|
7139
|
+
resolveContainerConfig: resolveNotificationContainerConfig,
|
|
7140
|
+
resolveAppContainerConfig: resolveNotificationAppContainerConfig
|
|
7141
|
+
});
|
|
7142
|
+
|
|
7143
|
+
//#endregion
|
|
7144
|
+
//#region src/cli/commands/notification/index.ts
|
|
7145
|
+
var notification_default = define({
|
|
7146
|
+
name: "notification",
|
|
7147
|
+
description: "Manage kintone notification settings",
|
|
7148
|
+
subCommands: {
|
|
7149
|
+
apply: apply_default$7,
|
|
7150
|
+
capture: capture_default$8,
|
|
7151
|
+
diff: diff_default$7
|
|
7152
|
+
},
|
|
7153
|
+
run: () => {}
|
|
7154
|
+
});
|
|
7155
|
+
|
|
7156
|
+
//#endregion
|
|
7157
|
+
//#region src/core/domain/plugin/services/configParser.ts
|
|
7158
|
+
function parsePluginEntry(raw, index) {
|
|
7159
|
+
if (!isRecord$1(raw)) throw new BusinessRuleError(PluginErrorCode.PlInvalidConfigStructure, `Plugin at index ${index} must be an object`);
|
|
7160
|
+
const obj = raw;
|
|
7161
|
+
if (typeof obj.id !== "string" || obj.id.length === 0) throw new BusinessRuleError(PluginErrorCode.PlEmptyPluginId, `Plugin at index ${index} must have a non-empty "id" property`);
|
|
7162
|
+
return {
|
|
7163
|
+
id: obj.id,
|
|
7164
|
+
name: typeof obj.name === "string" ? obj.name : "",
|
|
6351
7165
|
enabled: typeof obj.enabled === "boolean" ? obj.enabled : true
|
|
6352
7166
|
};
|
|
6353
7167
|
}
|
|
@@ -6497,6 +7311,64 @@ var capture_default$7 = define({
|
|
|
6497
7311
|
}
|
|
6498
7312
|
});
|
|
6499
7313
|
|
|
7314
|
+
//#endregion
|
|
7315
|
+
//#region src/core/domain/plugin/services/diffDetector.ts
|
|
7316
|
+
const PluginDiffDetector = { detect: (local, remote) => {
|
|
7317
|
+
const entries = [];
|
|
7318
|
+
const localMap = new Map(local.plugins.map((p) => [p.id, p]));
|
|
7319
|
+
const remoteMap = new Map(remote.plugins.map((p) => [p.id, p]));
|
|
7320
|
+
for (const [id, localPlugin] of localMap) {
|
|
7321
|
+
const remotePlugin = remoteMap.get(id);
|
|
7322
|
+
if (!remotePlugin) entries.push({
|
|
7323
|
+
type: "added",
|
|
7324
|
+
pluginId: id,
|
|
7325
|
+
details: `"${localPlugin.name}"`
|
|
7326
|
+
});
|
|
7327
|
+
else {
|
|
7328
|
+
const diffs = [];
|
|
7329
|
+
if (localPlugin.name !== remotePlugin.name) diffs.push(`name: "${remotePlugin.name}" -> "${localPlugin.name}"`);
|
|
7330
|
+
if (localPlugin.enabled !== remotePlugin.enabled) diffs.push(`enabled: ${String(remotePlugin.enabled)} -> ${String(localPlugin.enabled)}`);
|
|
7331
|
+
if (diffs.length > 0) entries.push({
|
|
7332
|
+
type: "modified",
|
|
7333
|
+
pluginId: id,
|
|
7334
|
+
details: diffs.join(", ")
|
|
7335
|
+
});
|
|
7336
|
+
}
|
|
7337
|
+
}
|
|
7338
|
+
for (const [id, remotePlugin] of remoteMap) if (!localMap.has(id)) entries.push({
|
|
7339
|
+
type: "deleted",
|
|
7340
|
+
pluginId: id,
|
|
7341
|
+
details: `"${remotePlugin.name}"`
|
|
7342
|
+
});
|
|
7343
|
+
return buildDiffResult(entries);
|
|
7344
|
+
} };
|
|
7345
|
+
|
|
7346
|
+
//#endregion
|
|
7347
|
+
//#region src/core/application/plugin/detectPluginDiff.ts
|
|
7348
|
+
async function detectPluginDiff({ container }) {
|
|
7349
|
+
return detectDiffFromConfig({
|
|
7350
|
+
getStorage: () => container.pluginStorage.get(),
|
|
7351
|
+
fetchRemote: () => container.pluginConfigurator.getPlugins(),
|
|
7352
|
+
parseConfig: parsePluginConfigText,
|
|
7353
|
+
detect: (local, remote) => PluginDiffDetector.detect(local, { plugins: remote.plugins }),
|
|
7354
|
+
notFoundMessage: "Plugin config file not found"
|
|
7355
|
+
});
|
|
7356
|
+
}
|
|
7357
|
+
|
|
7358
|
+
//#endregion
|
|
7359
|
+
//#region src/cli/commands/plugin/diff.ts
|
|
7360
|
+
var diff_default$6 = createDiffCommand({
|
|
7361
|
+
description: "Compare local plugin config with remote kintone app",
|
|
7362
|
+
args: pluginArgs,
|
|
7363
|
+
spinnerMessage: "Comparing plugin settings...",
|
|
7364
|
+
multiAppSuccessMessage: "All plugin diffs completed successfully.",
|
|
7365
|
+
createContainer: createPluginCliContainer,
|
|
7366
|
+
detectDiff: detectPluginDiff,
|
|
7367
|
+
printResult: printPluginDiffResult,
|
|
7368
|
+
resolveContainerConfig: resolvePluginContainerConfig,
|
|
7369
|
+
resolveAppContainerConfig: resolvePluginAppContainerConfig
|
|
7370
|
+
});
|
|
7371
|
+
|
|
6500
7372
|
//#endregion
|
|
6501
7373
|
//#region src/cli/commands/plugin/index.ts
|
|
6502
7374
|
var plugin_default = define({
|
|
@@ -6504,7 +7376,8 @@ var plugin_default = define({
|
|
|
6504
7376
|
description: "Manage kintone plugins",
|
|
6505
7377
|
subCommands: {
|
|
6506
7378
|
apply: apply_default$6,
|
|
6507
|
-
capture: capture_default$7
|
|
7379
|
+
capture: capture_default$7,
|
|
7380
|
+
diff: diff_default$6
|
|
6508
7381
|
},
|
|
6509
7382
|
run: () => {}
|
|
6510
7383
|
});
|
|
@@ -6781,7 +7654,7 @@ function compareActions(localAction, remoteAction) {
|
|
|
6781
7654
|
if (!isExecutableUserEqual(localAction.executableUser, remoteAction.executableUser)) diffs.push("executableUser changed");
|
|
6782
7655
|
return diffs;
|
|
6783
7656
|
}
|
|
6784
|
-
function compareConfigs(local, remote) {
|
|
7657
|
+
function compareConfigs$1(local, remote) {
|
|
6785
7658
|
const entries = [];
|
|
6786
7659
|
if (local.enable !== remote.enable) entries.push({
|
|
6787
7660
|
type: "modified",
|
|
@@ -6846,68 +7719,33 @@ function compareConfigs(local, remote) {
|
|
|
6846
7719
|
return entries;
|
|
6847
7720
|
}
|
|
6848
7721
|
const ProcessManagementDiffDetector = { detect: (local, remote) => {
|
|
6849
|
-
|
|
6850
|
-
const added = entries.filter((e) => e.type === "added").length;
|
|
6851
|
-
const modified = entries.filter((e) => e.type === "modified").length;
|
|
6852
|
-
const deleted = entries.filter((e) => e.type === "deleted").length;
|
|
6853
|
-
return {
|
|
6854
|
-
entries,
|
|
6855
|
-
summary: {
|
|
6856
|
-
added,
|
|
6857
|
-
modified,
|
|
6858
|
-
deleted,
|
|
6859
|
-
total: added + modified + deleted
|
|
6860
|
-
},
|
|
6861
|
-
isEmpty: entries.length === 0
|
|
6862
|
-
};
|
|
7722
|
+
return buildDiffResult(compareConfigs$1(local, remote));
|
|
6863
7723
|
} };
|
|
6864
7724
|
|
|
6865
7725
|
//#endregion
|
|
6866
7726
|
//#region src/core/application/processManagement/detectProcessManagementDiff.ts
|
|
6867
7727
|
async function detectProcessManagementDiff({ container }) {
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
7728
|
+
return detectDiffFromConfig({
|
|
7729
|
+
getStorage: () => container.processManagementStorage.get(),
|
|
7730
|
+
fetchRemote: () => container.processManagementConfigurator.getProcessManagement(),
|
|
7731
|
+
parseConfig: parseProcessManagementConfigText,
|
|
7732
|
+
detect: (local, remote) => ProcessManagementDiffDetector.detect(local, remote.config),
|
|
7733
|
+
notFoundMessage: "Process management config file not found"
|
|
7734
|
+
});
|
|
6873
7735
|
}
|
|
6874
7736
|
|
|
6875
7737
|
//#endregion
|
|
6876
7738
|
//#region src/cli/commands/process/diff.ts
|
|
6877
|
-
|
|
6878
|
-
const container = createProcessManagementCliContainer(config);
|
|
6879
|
-
const s = p.spinner();
|
|
6880
|
-
s.start("Comparing process management settings...");
|
|
6881
|
-
const result = await detectProcessManagementDiff({ container });
|
|
6882
|
-
s.stop("Comparison complete.");
|
|
6883
|
-
printProcessDiffResult(result);
|
|
6884
|
-
}
|
|
6885
|
-
var diff_default$2 = define({
|
|
6886
|
-
name: "diff",
|
|
7739
|
+
var diff_default$5 = createDiffCommand({
|
|
6887
7740
|
description: "Compare local process management settings with remote kintone app",
|
|
6888
7741
|
args: processArgs,
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
singleApp: async (app, projectConfig) => {
|
|
6897
|
-
await runDiffProcess(resolveProcessAppContainerConfig(app, projectConfig, values));
|
|
6898
|
-
},
|
|
6899
|
-
multiApp: async (plan, projectConfig) => {
|
|
6900
|
-
await runMultiAppWithFailCheck(plan, async (app) => {
|
|
6901
|
-
const config = resolveProcessAppContainerConfig(app, projectConfig, values);
|
|
6902
|
-
printAppHeader(app.name, app.appId);
|
|
6903
|
-
await runDiffProcess(config);
|
|
6904
|
-
}, "All process management diffs completed successfully.");
|
|
6905
|
-
}
|
|
6906
|
-
});
|
|
6907
|
-
} catch (error) {
|
|
6908
|
-
handleCliError(error);
|
|
6909
|
-
}
|
|
6910
|
-
}
|
|
7742
|
+
spinnerMessage: "Comparing process management settings...",
|
|
7743
|
+
multiAppSuccessMessage: "All process management diffs completed successfully.",
|
|
7744
|
+
createContainer: createProcessManagementCliContainer,
|
|
7745
|
+
detectDiff: detectProcessManagementDiff,
|
|
7746
|
+
printResult: printProcessDiffResult,
|
|
7747
|
+
resolveContainerConfig: resolveProcessContainerConfig,
|
|
7748
|
+
resolveAppContainerConfig: resolveProcessAppContainerConfig
|
|
6911
7749
|
});
|
|
6912
7750
|
|
|
6913
7751
|
//#endregion
|
|
@@ -6918,7 +7756,7 @@ var process_default = define({
|
|
|
6918
7756
|
subCommands: {
|
|
6919
7757
|
apply: apply_default$5,
|
|
6920
7758
|
capture: capture_default$6,
|
|
6921
|
-
diff: diff_default$
|
|
7759
|
+
diff: diff_default$5
|
|
6922
7760
|
},
|
|
6923
7761
|
run: () => {}
|
|
6924
7762
|
});
|
|
@@ -7113,6 +7951,104 @@ var capture_default$5 = define({
|
|
|
7113
7951
|
}
|
|
7114
7952
|
});
|
|
7115
7953
|
|
|
7954
|
+
//#endregion
|
|
7955
|
+
//#region src/core/domain/recordPermission/services/diffDetector.ts
|
|
7956
|
+
function areRightsEqual(a, b) {
|
|
7957
|
+
return deepEqual$1(a.entities.map((e) => ({
|
|
7958
|
+
type: e.entity.type,
|
|
7959
|
+
code: e.entity.code,
|
|
7960
|
+
viewable: e.viewable,
|
|
7961
|
+
editable: e.editable,
|
|
7962
|
+
deletable: e.deletable,
|
|
7963
|
+
includeSubs: e.includeSubs
|
|
7964
|
+
})), b.entities.map((e) => ({
|
|
7965
|
+
type: e.entity.type,
|
|
7966
|
+
code: e.entity.code,
|
|
7967
|
+
viewable: e.viewable,
|
|
7968
|
+
editable: e.editable,
|
|
7969
|
+
deletable: e.deletable,
|
|
7970
|
+
includeSubs: e.includeSubs
|
|
7971
|
+
})));
|
|
7972
|
+
}
|
|
7973
|
+
function describeRight(right) {
|
|
7974
|
+
const perEntity = right.entities.map((e) => {
|
|
7975
|
+
const perms = [
|
|
7976
|
+
e.viewable ? "view" : null,
|
|
7977
|
+
e.editable ? "edit" : null,
|
|
7978
|
+
e.deletable ? "delete" : null
|
|
7979
|
+
].filter(Boolean).join("/");
|
|
7980
|
+
return `${e.entity.type}:${e.entity.code}(${perms || "none"})`;
|
|
7981
|
+
});
|
|
7982
|
+
return perEntity.length > 0 ? perEntity.join(", ") : "no entities";
|
|
7983
|
+
}
|
|
7984
|
+
const RecordPermissionDiffDetector = { detect: (local, remote) => {
|
|
7985
|
+
const entries = [];
|
|
7986
|
+
const localMulti = groupByKey(local.rights, (r) => r.filterCond);
|
|
7987
|
+
const remoteMulti = groupByKey(remote.rights, (r) => r.filterCond);
|
|
7988
|
+
for (const [filterCond, localRights] of localMulti) {
|
|
7989
|
+
const remoteRights = remoteMulti.get(filterCond) ?? [];
|
|
7990
|
+
const maxLen = Math.max(localRights.length, remoteRights.length);
|
|
7991
|
+
for (let i = 0; i < maxLen; i++) {
|
|
7992
|
+
const localRight = localRights[i];
|
|
7993
|
+
const remoteRight = remoteRights[i];
|
|
7994
|
+
if (localRight && !remoteRight) entries.push({
|
|
7995
|
+
type: "added",
|
|
7996
|
+
filterCond,
|
|
7997
|
+
details: describeRight(localRight)
|
|
7998
|
+
});
|
|
7999
|
+
else if (!localRight && remoteRight) entries.push({
|
|
8000
|
+
type: "deleted",
|
|
8001
|
+
filterCond,
|
|
8002
|
+
details: describeRight(remoteRight)
|
|
8003
|
+
});
|
|
8004
|
+
else if (localRight && remoteRight) {
|
|
8005
|
+
if (!areRightsEqual(localRight, remoteRight)) {
|
|
8006
|
+
const diffs = [];
|
|
8007
|
+
if (localRight.entities.length !== remoteRight.entities.length) diffs.push(`entities: ${remoteRight.entities.length} -> ${localRight.entities.length}`);
|
|
8008
|
+
else diffs.push("entities changed");
|
|
8009
|
+
entries.push({
|
|
8010
|
+
type: "modified",
|
|
8011
|
+
filterCond,
|
|
8012
|
+
details: diffs.join(", ")
|
|
8013
|
+
});
|
|
8014
|
+
}
|
|
8015
|
+
}
|
|
8016
|
+
}
|
|
8017
|
+
}
|
|
8018
|
+
for (const [filterCond, remoteRights] of remoteMulti) if (!localMulti.has(filterCond)) for (const remoteRight of remoteRights) entries.push({
|
|
8019
|
+
type: "deleted",
|
|
8020
|
+
filterCond,
|
|
8021
|
+
details: describeRight(remoteRight)
|
|
8022
|
+
});
|
|
8023
|
+
return buildDiffResult(entries);
|
|
8024
|
+
} };
|
|
8025
|
+
|
|
8026
|
+
//#endregion
|
|
8027
|
+
//#region src/core/application/recordPermission/detectRecordPermissionDiff.ts
|
|
8028
|
+
async function detectRecordPermissionDiff({ container }) {
|
|
8029
|
+
return detectDiffFromConfig({
|
|
8030
|
+
getStorage: () => container.recordPermissionStorage.get(),
|
|
8031
|
+
fetchRemote: () => container.recordPermissionConfigurator.getRecordPermissions(),
|
|
8032
|
+
parseConfig: parseRecordPermissionConfigText,
|
|
8033
|
+
detect: (local, remote) => RecordPermissionDiffDetector.detect(local, { rights: remote.rights }),
|
|
8034
|
+
notFoundMessage: "Record permission config file not found"
|
|
8035
|
+
});
|
|
8036
|
+
}
|
|
8037
|
+
|
|
8038
|
+
//#endregion
|
|
8039
|
+
//#region src/cli/commands/record-acl/diff.ts
|
|
8040
|
+
var diff_default$4 = createDiffCommand({
|
|
8041
|
+
description: "Compare local record permission config with remote kintone app",
|
|
8042
|
+
args: recordAclArgs,
|
|
8043
|
+
spinnerMessage: "Comparing record permissions...",
|
|
8044
|
+
multiAppSuccessMessage: "All record permission diffs completed successfully.",
|
|
8045
|
+
createContainer: createRecordPermissionCliContainer,
|
|
8046
|
+
detectDiff: detectRecordPermissionDiff,
|
|
8047
|
+
printResult: printRecordPermissionDiffResult,
|
|
8048
|
+
resolveContainerConfig: resolveRecordAclContainerConfig,
|
|
8049
|
+
resolveAppContainerConfig: resolveRecordAclAppContainerConfig
|
|
8050
|
+
});
|
|
8051
|
+
|
|
7116
8052
|
//#endregion
|
|
7117
8053
|
//#region src/cli/commands/record-acl/index.ts
|
|
7118
8054
|
var record_acl_default = define({
|
|
@@ -7120,7 +8056,8 @@ var record_acl_default = define({
|
|
|
7120
8056
|
description: "Manage kintone record access permissions",
|
|
7121
8057
|
subCommands: {
|
|
7122
8058
|
apply: apply_default$4,
|
|
7123
|
-
capture: capture_default$5
|
|
8059
|
+
capture: capture_default$5,
|
|
8060
|
+
diff: diff_default$4
|
|
7124
8061
|
},
|
|
7125
8062
|
run: () => {}
|
|
7126
8063
|
});
|
|
@@ -7462,6 +8399,73 @@ var capture_default$4 = define({
|
|
|
7462
8399
|
}
|
|
7463
8400
|
});
|
|
7464
8401
|
|
|
8402
|
+
//#endregion
|
|
8403
|
+
//#region src/core/domain/report/services/diffDetector.ts
|
|
8404
|
+
function compareReports(local, remote) {
|
|
8405
|
+
const diffs = [];
|
|
8406
|
+
if (local.name !== remote.name) diffs.push(`name: "${remote.name}" -> "${local.name}"`);
|
|
8407
|
+
if (local.chartType !== remote.chartType) diffs.push(`chartType: ${remote.chartType} -> ${local.chartType}`);
|
|
8408
|
+
if ((local.chartMode ?? "") !== (remote.chartMode ?? "")) diffs.push(`chartMode: ${remote.chartMode ?? "(unset)"} -> ${local.chartMode ?? "(unset)"}`);
|
|
8409
|
+
if (local.index !== remote.index) diffs.push(`index: ${remote.index} -> ${local.index}`);
|
|
8410
|
+
if (local.filterCond !== remote.filterCond) diffs.push("filterCond changed");
|
|
8411
|
+
if (!deepEqual$1(local.groups, remote.groups)) diffs.push("groups changed");
|
|
8412
|
+
if (!deepEqual$1(local.aggregations, remote.aggregations)) diffs.push("aggregations changed");
|
|
8413
|
+
if (!deepEqual$1(local.sorts, remote.sorts)) diffs.push("sorts changed");
|
|
8414
|
+
if (!deepEqual$1(local.periodicReport ?? null, remote.periodicReport ?? null)) diffs.push("periodicReport changed");
|
|
8415
|
+
return diffs;
|
|
8416
|
+
}
|
|
8417
|
+
const ReportDiffDetector = { detect: (local, remote) => {
|
|
8418
|
+
const entries = [];
|
|
8419
|
+
for (const [name, localReport] of Object.entries(local.reports)) {
|
|
8420
|
+
const remoteReport = remote.reports[name];
|
|
8421
|
+
if (!remoteReport) entries.push({
|
|
8422
|
+
type: "added",
|
|
8423
|
+
reportName: name,
|
|
8424
|
+
details: `chartType: ${localReport.chartType}`
|
|
8425
|
+
});
|
|
8426
|
+
else {
|
|
8427
|
+
const diffs = compareReports(localReport, remoteReport);
|
|
8428
|
+
if (diffs.length > 0) entries.push({
|
|
8429
|
+
type: "modified",
|
|
8430
|
+
reportName: name,
|
|
8431
|
+
details: diffs.join(", ")
|
|
8432
|
+
});
|
|
8433
|
+
}
|
|
8434
|
+
}
|
|
8435
|
+
for (const [name, remoteReport] of Object.entries(remote.reports)) if (!local.reports[name]) entries.push({
|
|
8436
|
+
type: "deleted",
|
|
8437
|
+
reportName: name,
|
|
8438
|
+
details: `chartType: ${remoteReport.chartType}`
|
|
8439
|
+
});
|
|
8440
|
+
return buildDiffResult(entries);
|
|
8441
|
+
} };
|
|
8442
|
+
|
|
8443
|
+
//#endregion
|
|
8444
|
+
//#region src/core/application/report/detectReportDiff.ts
|
|
8445
|
+
async function detectReportDiff({ container }) {
|
|
8446
|
+
return detectDiffFromConfig({
|
|
8447
|
+
getStorage: () => container.reportStorage.get(),
|
|
8448
|
+
fetchRemote: () => container.reportConfigurator.getReports(),
|
|
8449
|
+
parseConfig: parseReportConfigText,
|
|
8450
|
+
detect: (local, remote) => ReportDiffDetector.detect(local, { reports: remote.reports }),
|
|
8451
|
+
notFoundMessage: "Report config file not found"
|
|
8452
|
+
});
|
|
8453
|
+
}
|
|
8454
|
+
|
|
8455
|
+
//#endregion
|
|
8456
|
+
//#region src/cli/commands/report/diff.ts
|
|
8457
|
+
var diff_default$3 = createDiffCommand({
|
|
8458
|
+
description: "Compare local report config with remote kintone app",
|
|
8459
|
+
args: reportArgs,
|
|
8460
|
+
spinnerMessage: "Comparing report settings...",
|
|
8461
|
+
multiAppSuccessMessage: "All report diffs completed successfully.",
|
|
8462
|
+
createContainer: createReportCliContainer,
|
|
8463
|
+
detectDiff: detectReportDiff,
|
|
8464
|
+
printResult: printReportDiffResult,
|
|
8465
|
+
resolveContainerConfig: resolveReportContainerConfig,
|
|
8466
|
+
resolveAppContainerConfig: resolveReportAppContainerConfig
|
|
8467
|
+
});
|
|
8468
|
+
|
|
7465
8469
|
//#endregion
|
|
7466
8470
|
//#region src/cli/commands/report/index.ts
|
|
7467
8471
|
var report_default = define({
|
|
@@ -7469,7 +8473,8 @@ var report_default = define({
|
|
|
7469
8473
|
description: "Manage kintone report settings",
|
|
7470
8474
|
subCommands: {
|
|
7471
8475
|
apply: apply_default$3,
|
|
7472
|
-
capture: capture_default$4
|
|
8476
|
+
capture: capture_default$4,
|
|
8477
|
+
diff: diff_default$3
|
|
7473
8478
|
},
|
|
7474
8479
|
run: () => {}
|
|
7475
8480
|
});
|
|
@@ -7521,53 +8526,8 @@ var capture_default$3 = define({
|
|
|
7521
8526
|
}
|
|
7522
8527
|
});
|
|
7523
8528
|
|
|
7524
|
-
//#endregion
|
|
7525
|
-
//#region src/core/domain/formSchema/entity.ts
|
|
7526
|
-
const FormDiff = { create: (entries) => {
|
|
7527
|
-
const summary = {
|
|
7528
|
-
added: entries.filter((e) => e.type === "added").length,
|
|
7529
|
-
modified: entries.filter((e) => e.type === "modified").length,
|
|
7530
|
-
deleted: entries.filter((e) => e.type === "deleted").length,
|
|
7531
|
-
total: entries.length
|
|
7532
|
-
};
|
|
7533
|
-
const sortOrder = {
|
|
7534
|
-
added: 0,
|
|
7535
|
-
modified: 1,
|
|
7536
|
-
deleted: 2
|
|
7537
|
-
};
|
|
7538
|
-
return {
|
|
7539
|
-
entries: [...entries].sort((a, b) => sortOrder[a.type] - sortOrder[b.type]),
|
|
7540
|
-
summary,
|
|
7541
|
-
isEmpty: entries.length === 0
|
|
7542
|
-
};
|
|
7543
|
-
} };
|
|
7544
|
-
|
|
7545
8529
|
//#endregion
|
|
7546
8530
|
//#region src/core/domain/formSchema/services/diffDetector.ts
|
|
7547
|
-
function isArrayEqual$1(a, b) {
|
|
7548
|
-
if (!Array.isArray(a) || !Array.isArray(b)) return false;
|
|
7549
|
-
if (a.length !== b.length) return false;
|
|
7550
|
-
for (let i = 0; i < a.length; i++) if (!isValueEqual(a[i], b[i])) return false;
|
|
7551
|
-
return true;
|
|
7552
|
-
}
|
|
7553
|
-
function isRecordEqual(a, b) {
|
|
7554
|
-
const keysA = Object.keys(a);
|
|
7555
|
-
const keysB = Object.keys(b);
|
|
7556
|
-
if (keysA.length !== keysB.length) return false;
|
|
7557
|
-
for (const key of keysA) {
|
|
7558
|
-
if (!Object.hasOwn(b, key)) return false;
|
|
7559
|
-
if (!isValueEqual(a[key], b[key])) return false;
|
|
7560
|
-
}
|
|
7561
|
-
return true;
|
|
7562
|
-
}
|
|
7563
|
-
function isValueEqual(a, b) {
|
|
7564
|
-
if (a === b) return true;
|
|
7565
|
-
if (a === null || b === null) return a === b;
|
|
7566
|
-
if (typeof a !== typeof b) return false;
|
|
7567
|
-
if (Array.isArray(a)) return isArrayEqual$1(a, b);
|
|
7568
|
-
if (isRecord$1(a) && isRecord$1(b)) return isRecordEqual(a, b);
|
|
7569
|
-
return false;
|
|
7570
|
-
}
|
|
7571
8531
|
function isMapEqual(a, b) {
|
|
7572
8532
|
if (a.size !== b.size) return false;
|
|
7573
8533
|
for (const [key, valA] of a) {
|
|
@@ -7579,18 +8539,8 @@ function isMapEqual(a, b) {
|
|
|
7579
8539
|
}
|
|
7580
8540
|
function isPropertiesEqual(a, b) {
|
|
7581
8541
|
if (a.type === "SUBTABLE" && b.type === "SUBTABLE") return isMapEqual(a.properties.fields, b.properties.fields);
|
|
7582
|
-
if (a.type === "REFERENCE_TABLE" && b.type === "REFERENCE_TABLE")
|
|
7583
|
-
|
|
7584
|
-
const refB = b.properties.referenceTable;
|
|
7585
|
-
return isValueEqual({
|
|
7586
|
-
...refA,
|
|
7587
|
-
displayFields: [...refA.displayFields]
|
|
7588
|
-
}, {
|
|
7589
|
-
...refB,
|
|
7590
|
-
displayFields: [...refB.displayFields]
|
|
7591
|
-
});
|
|
7592
|
-
}
|
|
7593
|
-
return isValueEqual(a.properties, b.properties);
|
|
8542
|
+
if (a.type === "REFERENCE_TABLE" && b.type === "REFERENCE_TABLE") return deepEqual$1(a.properties.referenceTable, b.properties.referenceTable);
|
|
8543
|
+
return deepEqual$1(a.properties, b.properties);
|
|
7594
8544
|
}
|
|
7595
8545
|
function isFieldEqual(a, b) {
|
|
7596
8546
|
if (a.type !== b.type) return false;
|
|
@@ -7599,31 +8549,16 @@ function isFieldEqual(a, b) {
|
|
|
7599
8549
|
if (Boolean(a.noLabel) !== Boolean(b.noLabel)) return false;
|
|
7600
8550
|
return isPropertiesEqual(a, b);
|
|
7601
8551
|
}
|
|
7602
|
-
function hasPropertiesChanged(before, after) {
|
|
7603
|
-
if (before.type === "SUBTABLE" && after.type === "SUBTABLE") return !isMapEqual(before.properties.fields, after.properties.fields);
|
|
7604
|
-
if (before.type === "REFERENCE_TABLE" && after.type === "REFERENCE_TABLE") {
|
|
7605
|
-
const refB = before.properties.referenceTable;
|
|
7606
|
-
const refA = after.properties.referenceTable;
|
|
7607
|
-
return !isValueEqual({
|
|
7608
|
-
...refB,
|
|
7609
|
-
displayFields: [...refB.displayFields]
|
|
7610
|
-
}, {
|
|
7611
|
-
...refA,
|
|
7612
|
-
displayFields: [...refA.displayFields]
|
|
7613
|
-
});
|
|
7614
|
-
}
|
|
7615
|
-
return !isValueEqual(before.properties, after.properties);
|
|
7616
|
-
}
|
|
7617
8552
|
function describeChanges$1(before, after) {
|
|
7618
8553
|
const changes = [];
|
|
7619
8554
|
if (before.type !== after.type) changes.push(`type: ${before.type} -> ${after.type}`);
|
|
7620
8555
|
if (before.label !== after.label) changes.push(`label: ${before.label} -> ${after.label}`);
|
|
7621
8556
|
if (Boolean(before.noLabel) !== Boolean(after.noLabel)) changes.push(`noLabel: ${before.noLabel ?? false} -> ${after.noLabel ?? false}`);
|
|
7622
|
-
if (
|
|
8557
|
+
if (!isPropertiesEqual(before, after)) changes.push("properties changed");
|
|
7623
8558
|
return changes.length > 0 ? changes.join(", ") : "no visible changes";
|
|
7624
8559
|
}
|
|
7625
8560
|
function isLayoutEqual(a, b) {
|
|
7626
|
-
return
|
|
8561
|
+
return deepEqual$1(a, b);
|
|
7627
8562
|
}
|
|
7628
8563
|
const DiffDetector = {
|
|
7629
8564
|
detectLayoutChanges: (schemaLayout, currentLayout) => {
|
|
@@ -7653,10 +8588,10 @@ const DiffDetector = {
|
|
|
7653
8588
|
type: "deleted",
|
|
7654
8589
|
fieldCode,
|
|
7655
8590
|
fieldLabel: currentDef.label,
|
|
7656
|
-
details: "
|
|
8591
|
+
details: "removed",
|
|
7657
8592
|
before: currentDef
|
|
7658
8593
|
});
|
|
7659
|
-
return
|
|
8594
|
+
return buildDiffResult(entries);
|
|
7660
8595
|
}
|
|
7661
8596
|
};
|
|
7662
8597
|
|
|
@@ -8153,14 +9088,20 @@ async function detectDiff({ container }) {
|
|
|
8153
9088
|
|
|
8154
9089
|
//#endregion
|
|
8155
9090
|
//#region src/cli/commands/schema/diff.ts
|
|
8156
|
-
async function runDiff
|
|
9091
|
+
async function runDiff(container) {
|
|
8157
9092
|
const s = p.spinner();
|
|
8158
9093
|
s.start("Fetching form schema...");
|
|
8159
|
-
|
|
9094
|
+
let result;
|
|
9095
|
+
try {
|
|
9096
|
+
result = await detectDiff({ container });
|
|
9097
|
+
} catch (error) {
|
|
9098
|
+
s.stop("Comparison failed.");
|
|
9099
|
+
throw error;
|
|
9100
|
+
}
|
|
8160
9101
|
s.stop("Form schema fetched.");
|
|
8161
9102
|
printDiffResult(result);
|
|
8162
9103
|
}
|
|
8163
|
-
var diff_default$
|
|
9104
|
+
var diff_default$2 = define({
|
|
8164
9105
|
name: "diff",
|
|
8165
9106
|
description: "Detect differences between schema file and current kintone form",
|
|
8166
9107
|
args: {
|
|
@@ -8171,17 +9112,17 @@ var diff_default$1 = define({
|
|
|
8171
9112
|
try {
|
|
8172
9113
|
await routeMultiApp(ctx.values, {
|
|
8173
9114
|
singleLegacy: async () => {
|
|
8174
|
-
await runDiff
|
|
9115
|
+
await runDiff(createCliContainer(resolveConfig(ctx.values)));
|
|
8175
9116
|
},
|
|
8176
9117
|
singleApp: async (app, projectConfig) => {
|
|
8177
|
-
await runDiff
|
|
9118
|
+
await runDiff(createCliContainer(resolveAppCliConfig(app, projectConfig, ctx.values)));
|
|
8178
9119
|
},
|
|
8179
9120
|
multiApp: async (plan, projectConfig) => {
|
|
8180
9121
|
await runMultiAppWithFailCheck(plan, async (app) => {
|
|
8181
9122
|
const container = createCliContainer(resolveAppCliConfig(app, projectConfig, ctx.values));
|
|
8182
9123
|
printAppHeader(app.name, app.appId);
|
|
8183
|
-
await runDiff
|
|
8184
|
-
});
|
|
9124
|
+
await runDiff(container);
|
|
9125
|
+
}, "All schema diffs completed successfully.");
|
|
8185
9126
|
}
|
|
8186
9127
|
});
|
|
8187
9128
|
} catch (error) {
|
|
@@ -8899,7 +9840,7 @@ var schema_default = define({
|
|
|
8899
9840
|
name: "schema",
|
|
8900
9841
|
description: "Manage kintone form schemas",
|
|
8901
9842
|
subCommands: {
|
|
8902
|
-
diff: diff_default$
|
|
9843
|
+
diff: diff_default$2,
|
|
8903
9844
|
migrate: migrate_default,
|
|
8904
9845
|
override: override_default,
|
|
8905
9846
|
capture: capture_default$3,
|
|
@@ -9497,6 +10438,91 @@ var capture_default$1 = define({
|
|
|
9497
10438
|
}
|
|
9498
10439
|
});
|
|
9499
10440
|
|
|
10441
|
+
//#endregion
|
|
10442
|
+
//#region src/core/domain/generalSettings/services/diffDetector.ts
|
|
10443
|
+
const DEFAULT_STRING = "";
|
|
10444
|
+
const DEFAULT_BOOLEAN = false;
|
|
10445
|
+
const DEFAULT_FIRST_MONTH = 1;
|
|
10446
|
+
function compareConfigs(local, remote) {
|
|
10447
|
+
const entries = [];
|
|
10448
|
+
function compareString(field, l, r, defaultValue, suppressValues = false) {
|
|
10449
|
+
const lv = l ?? defaultValue;
|
|
10450
|
+
const rv = r ?? defaultValue;
|
|
10451
|
+
if (lv !== rv) entries.push({
|
|
10452
|
+
type: "modified",
|
|
10453
|
+
field,
|
|
10454
|
+
details: suppressValues ? `${field} changed` : `"${rv}" -> "${lv}"`
|
|
10455
|
+
});
|
|
10456
|
+
}
|
|
10457
|
+
function compareBoolean(field, l, r, defaultValue) {
|
|
10458
|
+
const lv = l ?? defaultValue;
|
|
10459
|
+
const rv = r ?? defaultValue;
|
|
10460
|
+
if (lv !== rv) entries.push({
|
|
10461
|
+
type: "modified",
|
|
10462
|
+
field,
|
|
10463
|
+
details: `${String(rv)} -> ${String(lv)}`
|
|
10464
|
+
});
|
|
10465
|
+
}
|
|
10466
|
+
function compareNumber(field, l, r, defaultValue) {
|
|
10467
|
+
const lv = l ?? defaultValue;
|
|
10468
|
+
const rv = r ?? defaultValue;
|
|
10469
|
+
if (lv !== rv) entries.push({
|
|
10470
|
+
type: "modified",
|
|
10471
|
+
field,
|
|
10472
|
+
details: `${rv} -> ${lv}`
|
|
10473
|
+
});
|
|
10474
|
+
}
|
|
10475
|
+
function compareDeepEqual(field, l, r) {
|
|
10476
|
+
if (!deepEqual$1(l, r)) entries.push({
|
|
10477
|
+
type: "modified",
|
|
10478
|
+
field,
|
|
10479
|
+
details: `${field} changed`
|
|
10480
|
+
});
|
|
10481
|
+
}
|
|
10482
|
+
compareString("name", local.name, remote.name, DEFAULT_STRING);
|
|
10483
|
+
compareString("description", local.description, remote.description, DEFAULT_STRING, true);
|
|
10484
|
+
compareDeepEqual("icon", local.icon, remote.icon);
|
|
10485
|
+
compareString("theme", local.theme, remote.theme, DEFAULT_STRING);
|
|
10486
|
+
compareDeepEqual("titleField", local.titleField, remote.titleField);
|
|
10487
|
+
compareBoolean("enableThumbnails", local.enableThumbnails, remote.enableThumbnails, DEFAULT_BOOLEAN);
|
|
10488
|
+
compareBoolean("enableBulkDeletion", local.enableBulkDeletion, remote.enableBulkDeletion, DEFAULT_BOOLEAN);
|
|
10489
|
+
compareBoolean("enableComments", local.enableComments, remote.enableComments, DEFAULT_BOOLEAN);
|
|
10490
|
+
compareBoolean("enableDuplicateRecord", local.enableDuplicateRecord, remote.enableDuplicateRecord, DEFAULT_BOOLEAN);
|
|
10491
|
+
compareBoolean("enableInlineRecordEditing", local.enableInlineRecordEditing, remote.enableInlineRecordEditing, DEFAULT_BOOLEAN);
|
|
10492
|
+
compareDeepEqual("numberPrecision", local.numberPrecision, remote.numberPrecision);
|
|
10493
|
+
compareNumber("firstMonthOfFiscalYear", local.firstMonthOfFiscalYear, remote.firstMonthOfFiscalYear, DEFAULT_FIRST_MONTH);
|
|
10494
|
+
return entries;
|
|
10495
|
+
}
|
|
10496
|
+
const GeneralSettingsDiffDetector = { detect: (local, remote) => {
|
|
10497
|
+
return buildDiffResult(compareConfigs(local, remote));
|
|
10498
|
+
} };
|
|
10499
|
+
|
|
10500
|
+
//#endregion
|
|
10501
|
+
//#region src/core/application/generalSettings/detectGeneralSettingsDiff.ts
|
|
10502
|
+
async function detectGeneralSettingsDiff({ container }) {
|
|
10503
|
+
return detectDiffFromConfig({
|
|
10504
|
+
getStorage: () => container.generalSettingsStorage.get(),
|
|
10505
|
+
fetchRemote: () => container.generalSettingsConfigurator.getGeneralSettings(),
|
|
10506
|
+
parseConfig: parseGeneralSettingsConfigText,
|
|
10507
|
+
detect: (local, remote) => GeneralSettingsDiffDetector.detect(local, remote.config),
|
|
10508
|
+
notFoundMessage: "General settings config file not found"
|
|
10509
|
+
});
|
|
10510
|
+
}
|
|
10511
|
+
|
|
10512
|
+
//#endregion
|
|
10513
|
+
//#region src/cli/commands/settings/diff.ts
|
|
10514
|
+
var diff_default$1 = createDiffCommand({
|
|
10515
|
+
description: "Compare local general settings config with remote kintone app",
|
|
10516
|
+
args: settingsArgs,
|
|
10517
|
+
spinnerMessage: "Comparing general settings...",
|
|
10518
|
+
multiAppSuccessMessage: "All general settings diffs completed successfully.",
|
|
10519
|
+
createContainer: createGeneralSettingsCliContainer,
|
|
10520
|
+
detectDiff: detectGeneralSettingsDiff,
|
|
10521
|
+
printResult: printGeneralSettingsDiffResult,
|
|
10522
|
+
resolveContainerConfig: resolveSettingsContainerConfig,
|
|
10523
|
+
resolveAppContainerConfig: resolveSettingsAppContainerConfig
|
|
10524
|
+
});
|
|
10525
|
+
|
|
9500
10526
|
//#endregion
|
|
9501
10527
|
//#region src/cli/commands/settings/index.ts
|
|
9502
10528
|
var settings_default = define({
|
|
@@ -9504,7 +10530,8 @@ var settings_default = define({
|
|
|
9504
10530
|
description: "Manage kintone general settings",
|
|
9505
10531
|
subCommands: {
|
|
9506
10532
|
apply: apply_default$1,
|
|
9507
|
-
capture: capture_default$1
|
|
10533
|
+
capture: capture_default$1,
|
|
10534
|
+
diff: diff_default$1
|
|
9508
10535
|
},
|
|
9509
10536
|
run: () => {}
|
|
9510
10537
|
});
|
|
@@ -9693,37 +10720,21 @@ var capture_default = define({
|
|
|
9693
10720
|
|
|
9694
10721
|
//#endregion
|
|
9695
10722
|
//#region src/core/domain/view/services/diffDetector.ts
|
|
9696
|
-
function isArrayEqual(a, b) {
|
|
9697
|
-
if (a.length !== b.length) return false;
|
|
9698
|
-
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
9699
|
-
return true;
|
|
9700
|
-
}
|
|
9701
10723
|
function describeChanges(local, remote) {
|
|
9702
10724
|
const changes = [];
|
|
10725
|
+
if (local.name !== remote.name) changes.push(`name: "${remote.name}" -> "${local.name}"`);
|
|
9703
10726
|
if (local.type !== remote.type) changes.push(`type: ${remote.type} -> ${local.type}`);
|
|
10727
|
+
if ((local.builtinType ?? "") !== (remote.builtinType ?? "")) changes.push("builtinType changed");
|
|
9704
10728
|
if (local.index !== remote.index) changes.push(`index: ${remote.index} -> ${local.index}`);
|
|
9705
10729
|
if ((local.filterCond ?? "") !== (remote.filterCond ?? "")) changes.push("filterCond changed");
|
|
9706
10730
|
if ((local.sort ?? "") !== (remote.sort ?? "")) changes.push("sort changed");
|
|
9707
10731
|
if ((local.date ?? "") !== (remote.date ?? "")) changes.push("date changed");
|
|
9708
10732
|
if ((local.title ?? "") !== (remote.title ?? "")) changes.push("title changed");
|
|
9709
10733
|
if ((local.html ?? "") !== (remote.html ?? "")) changes.push("html changed");
|
|
9710
|
-
if (local.pager !== remote.pager) changes.push(`pager: ${String(remote.pager ??
|
|
10734
|
+
if ((local.pager ?? false) !== (remote.pager ?? false)) changes.push(`pager: ${String(remote.pager ?? false)} -> ${String(local.pager ?? false)}`);
|
|
9711
10735
|
if ((local.device ?? "") !== (remote.device ?? "")) changes.push("device changed");
|
|
9712
|
-
if (!
|
|
9713
|
-
return changes
|
|
9714
|
-
}
|
|
9715
|
-
function isViewEqual(local, remote) {
|
|
9716
|
-
if (local.type !== remote.type) return false;
|
|
9717
|
-
if (local.index !== remote.index) return false;
|
|
9718
|
-
if ((local.filterCond ?? "") !== (remote.filterCond ?? "")) return false;
|
|
9719
|
-
if ((local.sort ?? "") !== (remote.sort ?? "")) return false;
|
|
9720
|
-
if ((local.date ?? "") !== (remote.date ?? "")) return false;
|
|
9721
|
-
if ((local.title ?? "") !== (remote.title ?? "")) return false;
|
|
9722
|
-
if ((local.html ?? "") !== (remote.html ?? "")) return false;
|
|
9723
|
-
if (local.pager !== remote.pager) return false;
|
|
9724
|
-
if ((local.device ?? "") !== (remote.device ?? "")) return false;
|
|
9725
|
-
if (!isArrayEqual(local.fields ?? [], remote.fields ?? [])) return false;
|
|
9726
|
-
return true;
|
|
10736
|
+
if (!deepEqual$1(local.fields ?? [], remote.fields ?? [])) changes.push("fields changed");
|
|
10737
|
+
return changes;
|
|
9727
10738
|
}
|
|
9728
10739
|
const ViewDiffDetector = { detect: (localViews, remoteViews) => {
|
|
9729
10740
|
const entries = [];
|
|
@@ -9734,83 +10745,47 @@ const ViewDiffDetector = { detect: (localViews, remoteViews) => {
|
|
|
9734
10745
|
viewName: name,
|
|
9735
10746
|
details: "new view"
|
|
9736
10747
|
});
|
|
9737
|
-
else
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
|
|
10748
|
+
else {
|
|
10749
|
+
const changes = describeChanges(localView, remoteView);
|
|
10750
|
+
if (changes.length > 0) entries.push({
|
|
10751
|
+
type: "modified",
|
|
10752
|
+
viewName: name,
|
|
10753
|
+
details: changes.join(", ")
|
|
10754
|
+
});
|
|
10755
|
+
}
|
|
9742
10756
|
}
|
|
9743
10757
|
for (const name of Object.keys(remoteViews)) if (localViews[name] === void 0) entries.push({
|
|
9744
10758
|
type: "deleted",
|
|
9745
10759
|
viewName: name,
|
|
9746
|
-
details: "
|
|
10760
|
+
details: "removed"
|
|
9747
10761
|
});
|
|
9748
|
-
|
|
9749
|
-
const modified = entries.filter((e) => e.type === "modified").length;
|
|
9750
|
-
const deleted = entries.filter((e) => e.type === "deleted").length;
|
|
9751
|
-
return {
|
|
9752
|
-
entries,
|
|
9753
|
-
summary: {
|
|
9754
|
-
added,
|
|
9755
|
-
modified,
|
|
9756
|
-
deleted,
|
|
9757
|
-
total: added + modified + deleted
|
|
9758
|
-
},
|
|
9759
|
-
isEmpty: entries.length === 0
|
|
9760
|
-
};
|
|
10762
|
+
return buildDiffResult(entries);
|
|
9761
10763
|
} };
|
|
9762
10764
|
|
|
9763
10765
|
//#endregion
|
|
9764
10766
|
//#region src/core/application/view/detectViewDiff.ts
|
|
9765
10767
|
async function detectViewDiff({ container }) {
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
summary: diff.summary,
|
|
9774
|
-
isEmpty: diff.isEmpty
|
|
9775
|
-
};
|
|
10768
|
+
return detectDiffFromConfig({
|
|
10769
|
+
getStorage: () => container.viewStorage.get(),
|
|
10770
|
+
fetchRemote: () => container.viewConfigurator.getViews(),
|
|
10771
|
+
parseConfig: (content) => parseViewConfigText(content).views,
|
|
10772
|
+
detect: (views, remote) => ViewDiffDetector.detect(views, remote.views),
|
|
10773
|
+
notFoundMessage: "View config file not found"
|
|
10774
|
+
});
|
|
9776
10775
|
}
|
|
9777
10776
|
|
|
9778
10777
|
//#endregion
|
|
9779
10778
|
//#region src/cli/commands/view/diff.ts
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
const s = p.spinner();
|
|
9783
|
-
s.start("Fetching views...");
|
|
9784
|
-
const result = await detectViewDiff({ container });
|
|
9785
|
-
s.stop("Views fetched.");
|
|
9786
|
-
printViewDiffResult(result);
|
|
9787
|
-
}
|
|
9788
|
-
var diff_default = define({
|
|
9789
|
-
name: "diff",
|
|
9790
|
-
description: "Detect differences between view config file and current kintone views",
|
|
10779
|
+
var diff_default = createDiffCommand({
|
|
10780
|
+
description: "Compare local view config with remote kintone app",
|
|
9791
10781
|
args: viewArgs,
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
singleApp: async (app, projectConfig) => {
|
|
9800
|
-
await runDiff(resolveViewAppContainerConfig(app, projectConfig, values));
|
|
9801
|
-
},
|
|
9802
|
-
multiApp: async (plan, projectConfig) => {
|
|
9803
|
-
await runMultiAppWithFailCheck(plan, async (app) => {
|
|
9804
|
-
const config = resolveViewAppContainerConfig(app, projectConfig, values);
|
|
9805
|
-
printAppHeader(app.name, app.appId);
|
|
9806
|
-
await runDiff(config);
|
|
9807
|
-
});
|
|
9808
|
-
}
|
|
9809
|
-
});
|
|
9810
|
-
} catch (error) {
|
|
9811
|
-
handleCliError(error);
|
|
9812
|
-
}
|
|
9813
|
-
}
|
|
10782
|
+
spinnerMessage: "Comparing view settings...",
|
|
10783
|
+
multiAppSuccessMessage: "All view diffs completed successfully.",
|
|
10784
|
+
createContainer: createViewCliContainer,
|
|
10785
|
+
detectDiff: detectViewDiff,
|
|
10786
|
+
printResult: printViewDiffResult,
|
|
10787
|
+
resolveContainerConfig: resolveViewContainerConfig,
|
|
10788
|
+
resolveAppContainerConfig: resolveViewAppContainerConfig
|
|
9814
10789
|
});
|
|
9815
10790
|
|
|
9816
10791
|
//#endregion
|