@aglyn/aglyn-transfer-ui 1.0.0-beta.254 → 1.0.0-beta.255
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/aglyn-transfer-ui",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.255",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-ui-jsx": "1.0.0-beta.
|
|
28
|
+
"@aglyn/aglyn": "1.0.0-beta.255",
|
|
29
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.255",
|
|
30
30
|
"@swc/helpers": "0.5.23"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
@@ -18,7 +18,6 @@ import type { PackageItemComparison, PackageItemDecision, PackageItemStatus } fr
|
|
|
18
18
|
import type { SitePackageDecisions, SitePackageDependencyChoice, SitePackageMergeChoice, SitePackagePlan, SitePackagePlanAnswer, SitePackagePlanItem } from './site-package-client';
|
|
19
19
|
import type { TransferAcknowledgementItem } from './transfer-acknowledgement-list.component';
|
|
20
20
|
import type { TransferChoiceOption } from './transfer-choice-select.component';
|
|
21
|
-
import type { TransferDiffChange } from './transfer-diff-table.component';
|
|
22
21
|
type ChipColor = 'default' | 'success' | 'warning' | 'error' | 'info';
|
|
23
22
|
export declare const PACKAGE_STATUS_WORDS: Readonly<Record<PackageItemStatus, {
|
|
24
23
|
label: string;
|
|
@@ -81,64 +80,10 @@ export declare function packageDependencyAnswer(choice: SitePackageDependencyCho
|
|
|
81
80
|
export declare function packageDependencyProblems(prompts: readonly PackageDependencyPrompt[], choices: Readonly<Record<string, SitePackageDependencyChoice>>): string[];
|
|
82
81
|
/** The answers the import route takes: only those for prompts still open, complete ones only. */
|
|
83
82
|
export declare function packageDependencyChoices(prompts: readonly PackageDependencyPrompt[], choices: Readonly<Record<string, SitePackageDependencyChoice>>): Record<string, SitePackageDependencyChoice>;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
*/
|
|
89
|
-
export declare function packageJsonDiff(before: unknown, after: unknown, limit?: number): {
|
|
90
|
-
changes: TransferDiffChange[];
|
|
91
|
-
more: number;
|
|
92
|
-
};
|
|
93
|
-
/** One top-level key of a merged item: both values and the default. */
|
|
94
|
-
export interface PackageMergeKey {
|
|
95
|
-
key: string;
|
|
96
|
-
site: unknown;
|
|
97
|
-
file: unknown;
|
|
98
|
-
/** What a merge does when the person does not say: the site's value wins when it has one. */
|
|
99
|
-
merged: SitePackageMergeChoice;
|
|
100
|
-
}
|
|
101
|
-
/** The keys of a merged item that differ, each with what a merge would keep. */
|
|
102
|
-
export declare function packageMergeKeys(site: unknown, file: unknown): PackageMergeKey[];
|
|
103
|
-
/** One record of an item's list: a document with its own `$id`. */
|
|
104
|
-
export type PackageRecord = Record<string, unknown> & {
|
|
105
|
-
$id: string;
|
|
106
|
-
};
|
|
107
|
-
/**
|
|
108
|
-
* The key of an item that holds its records — a dataset's `records`, a
|
|
109
|
-
* collection's `entries` — found by shape rather than by kind, so the kit
|
|
110
|
-
* names no kind a plugin declares: the one list, on either side, whose
|
|
111
|
-
* every element is a document with its own `$id`. The other side holds a
|
|
112
|
-
* list there too, or nothing. `null` when no key qualifies, or when more
|
|
113
|
-
* than one does and neither can be read as the item's records.
|
|
114
|
-
*/
|
|
115
|
-
export declare function packageRecordField(...contents: readonly unknown[]): string | null;
|
|
116
|
-
export type PackageRecordStatus = 'added' | 'removed' | 'changed';
|
|
117
|
-
/** One record that differs between the site and the file. */
|
|
118
|
-
export interface PackageRecordRow {
|
|
119
|
-
id: string;
|
|
120
|
-
status: PackageRecordStatus;
|
|
121
|
-
/** The site's copy; `null` for a record only the file holds. */
|
|
122
|
-
site: PackageRecord | null;
|
|
123
|
-
/** The file's copy; `null` for a record only the site holds. */
|
|
124
|
-
file: PackageRecord | null;
|
|
125
|
-
/** The fields whose values differ, for a changed record. */
|
|
126
|
-
changed: readonly string[];
|
|
127
|
-
}
|
|
128
|
-
export interface PackageRecordDiff {
|
|
129
|
-
/** The file's added and changed records in its order, then the site's removed ones. */
|
|
130
|
-
rows: PackageRecordRow[];
|
|
131
|
-
/** Every field the rows hold, `$id` aside, in the order they first appear. */
|
|
132
|
-
fields: string[];
|
|
133
|
-
counts: Record<PackageRecordStatus | 'same', number>;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Two lists of records, matched by `$id`: what the file adds, what it no
|
|
137
|
-
* longer holds, and, for a record on both sides, each field whose value
|
|
138
|
-
* differs. A record the import would leave as it is counts as `same` and
|
|
139
|
-
* has no row.
|
|
140
|
-
*/
|
|
141
|
-
export declare function packageRecordDiff(site: unknown, file: unknown): PackageRecordDiff;
|
|
83
|
+
export { packageJsonDiff, packageMergeKeys } from '@aglyn/aglyn/data-transfer/site-package-diff';
|
|
84
|
+
export type { PackageMergeKey } from '@aglyn/aglyn/data-transfer/site-package-diff';
|
|
85
|
+
export { packageRecordDiff, packageRecordField } from '@aglyn/aglyn/data-transfer/site-package-diff';
|
|
86
|
+
export type { PackageRecord, PackageRecordDiff, PackageRecordRow, PackageRecordStatus, } from '@aglyn/aglyn/data-transfer/site-package-diff';
|
|
142
87
|
/** Items by decision, in the order the review reads them. */
|
|
143
88
|
export declare function packageDecisionCounts(decisions: Readonly<Record<string, PackageItemDecision>>): Array<{
|
|
144
89
|
decision: PackageItemDecision;
|
|
@@ -152,4 +97,3 @@ export declare function packageDecisionCounts(decisions: Readonly<Record<string,
|
|
|
152
97
|
export declare function packageAcknowledgements(answer: Pick<SitePackagePlanAnswer, 'warnings' | 'warningsTotal' | 'unknownKinds' | 'notSent'>, decisions: Readonly<Record<string, PackageItemDecision>>, titleOf: (key: string) => string): TransferAcknowledgementItem[];
|
|
153
98
|
/** Everything decided, as the import route takes it. */
|
|
154
99
|
export declare function packageDecided(decisions: Readonly<Record<string, PackageItemDecision>>, prompts: readonly PackageDependencyPrompt[], dependencyChoices: Readonly<Record<string, SitePackageDependencyChoice>>, mergeChoices: Readonly<Record<string, Record<string, SitePackageMergeChoice>>>): SitePackageDecisions;
|
|
155
|
-
export {};
|
|
@@ -222,173 +222,11 @@ export function packageDependencyOptions(prompt) {
|
|
|
222
222
|
}
|
|
223
223
|
/*==========================================
|
|
224
224
|
* DIFFS
|
|
225
|
-
*=========================================*/
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Every leaf that differs between the site's item and the file's, as
|
|
232
|
-
* before → after rows: objects are walked key by key, a list or a value is
|
|
233
|
-
* compared whole. At most `limit` rows; `more` counts the rest.
|
|
234
|
-
*/ export function packageJsonDiff(before, after, limit = 200) {
|
|
235
|
-
const changes = [];
|
|
236
|
-
let more = 0;
|
|
237
|
-
const walk = (left, right, path)=>{
|
|
238
|
-
if (same(left, right)) return;
|
|
239
|
-
if (isPlain(left) && isPlain(right)) {
|
|
240
|
-
const keys = [
|
|
241
|
-
...new Set([
|
|
242
|
-
...Object.keys(left),
|
|
243
|
-
...Object.keys(right)
|
|
244
|
-
])
|
|
245
|
-
].sort();
|
|
246
|
-
for (const key of keys)walk(left[key], right[key], [
|
|
247
|
-
...path,
|
|
248
|
-
key
|
|
249
|
-
]);
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
if (changes.length >= limit) {
|
|
253
|
-
more += 1;
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
changes.push({
|
|
257
|
-
key: path.join('/') || '$',
|
|
258
|
-
label: pathLabel(path),
|
|
259
|
-
before: left,
|
|
260
|
-
after: right
|
|
261
|
-
});
|
|
262
|
-
};
|
|
263
|
-
walk(before, after, []);
|
|
264
|
-
return {
|
|
265
|
-
changes,
|
|
266
|
-
more
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
const blank = (value)=>value === undefined || value === null || value === '';
|
|
270
|
-
/** The keys of a merged item that differ, each with what a merge would keep. */ export function packageMergeKeys(site, file) {
|
|
271
|
-
const left = isPlain(site) ? site : {};
|
|
272
|
-
const right = isPlain(file) ? file : {};
|
|
273
|
-
return Object.keys(right).sort().filter((key)=>right[key] !== undefined && !same(left[key], right[key])).map((key)=>({
|
|
274
|
-
key,
|
|
275
|
-
site: left[key],
|
|
276
|
-
file: right[key],
|
|
277
|
-
merged: blank(left[key]) ? 'package' : 'site'
|
|
278
|
-
}));
|
|
279
|
-
}
|
|
280
|
-
const isRecord = (value)=>isPlain(value) && typeof value['$id'] === 'string' && value['$id'] !== '';
|
|
281
|
-
/**
|
|
282
|
-
* The key of an item that holds its records — a dataset's `records`, a
|
|
283
|
-
* collection's `entries` — found by shape rather than by kind, so the kit
|
|
284
|
-
* names no kind a plugin declares: the one list, on either side, whose
|
|
285
|
-
* every element is a document with its own `$id`. The other side holds a
|
|
286
|
-
* list there too, or nothing. `null` when no key qualifies, or when more
|
|
287
|
-
* than one does and neither can be read as the item's records.
|
|
288
|
-
*/ export function packageRecordField(...contents) {
|
|
289
|
-
const docs = contents.filter(isPlain);
|
|
290
|
-
const found = new Set();
|
|
291
|
-
for (const doc of docs){
|
|
292
|
-
for (const [key, value] of Object.entries(doc)){
|
|
293
|
-
if (Array.isArray(value) && value.length > 0 && value.every(isRecord)) found.add(key);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
const fields = [
|
|
297
|
-
...found
|
|
298
|
-
].filter((key)=>docs.every((doc)=>{
|
|
299
|
-
const value = doc[key];
|
|
300
|
-
return value === undefined || value === null || Array.isArray(value) && value.every(isRecord);
|
|
301
|
-
}));
|
|
302
|
-
return fields.length === 1 ? fields[0] : null;
|
|
303
|
-
}
|
|
304
|
-
const recordsOf = (value)=>Array.isArray(value) ? value.filter(isRecord) : [];
|
|
305
|
-
/**
|
|
306
|
-
* Two lists of records, matched by `$id`: what the file adds, what it no
|
|
307
|
-
* longer holds, and, for a record on both sides, each field whose value
|
|
308
|
-
* differs. A record the import would leave as it is counts as `same` and
|
|
309
|
-
* has no row.
|
|
310
|
-
*/ export function packageRecordDiff(site, file) {
|
|
311
|
-
const theirs = new Map(recordsOf(site).map((record)=>[
|
|
312
|
-
record.$id,
|
|
313
|
-
record
|
|
314
|
-
]));
|
|
315
|
-
const ours = recordsOf(file);
|
|
316
|
-
const seen = new Set();
|
|
317
|
-
const rows = [];
|
|
318
|
-
const counts = {
|
|
319
|
-
added: 0,
|
|
320
|
-
removed: 0,
|
|
321
|
-
changed: 0,
|
|
322
|
-
same: 0
|
|
323
|
-
};
|
|
324
|
-
for (const record of ours){
|
|
325
|
-
if (seen.has(record.$id)) continue;
|
|
326
|
-
seen.add(record.$id);
|
|
327
|
-
const existing = theirs.get(record.$id);
|
|
328
|
-
if (!existing) {
|
|
329
|
-
counts.added += 1;
|
|
330
|
-
rows.push({
|
|
331
|
-
id: record.$id,
|
|
332
|
-
status: 'added',
|
|
333
|
-
site: null,
|
|
334
|
-
file: record,
|
|
335
|
-
changed: []
|
|
336
|
-
});
|
|
337
|
-
continue;
|
|
338
|
-
}
|
|
339
|
-
const keys = [
|
|
340
|
-
...new Set([
|
|
341
|
-
...Object.keys(existing),
|
|
342
|
-
...Object.keys(record)
|
|
343
|
-
])
|
|
344
|
-
].filter((key)=>key !== '$id');
|
|
345
|
-
const changed = keys.filter((key)=>!same(existing[key], record[key]));
|
|
346
|
-
if (!changed.length) {
|
|
347
|
-
counts.same += 1;
|
|
348
|
-
continue;
|
|
349
|
-
}
|
|
350
|
-
counts.changed += 1;
|
|
351
|
-
rows.push({
|
|
352
|
-
id: record.$id,
|
|
353
|
-
status: 'changed',
|
|
354
|
-
site: existing,
|
|
355
|
-
file: record,
|
|
356
|
-
changed
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
for (const [id, record] of theirs){
|
|
360
|
-
if (seen.has(id)) continue;
|
|
361
|
-
counts.removed += 1;
|
|
362
|
-
rows.push({
|
|
363
|
-
id,
|
|
364
|
-
status: 'removed',
|
|
365
|
-
site: record,
|
|
366
|
-
file: null,
|
|
367
|
-
changed: []
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
const fields = [];
|
|
371
|
-
const listed = new Set([
|
|
372
|
-
'$id'
|
|
373
|
-
]);
|
|
374
|
-
for (const row of rows){
|
|
375
|
-
for (const record of [
|
|
376
|
-
row.file,
|
|
377
|
-
row.site
|
|
378
|
-
]){
|
|
379
|
-
for (const key of Object.keys(record != null ? record : {})){
|
|
380
|
-
if (listed.has(key)) continue;
|
|
381
|
-
listed.add(key);
|
|
382
|
-
fields.push(key);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
return {
|
|
387
|
-
rows,
|
|
388
|
-
fields,
|
|
389
|
-
counts
|
|
390
|
-
};
|
|
391
|
-
}
|
|
225
|
+
*=========================================*/ // The two comparisons live in the core, pure, so the native apps read the same definition.
|
|
226
|
+
export { packageJsonDiff, packageMergeKeys } from "@aglyn/aglyn/data-transfer/site-package-diff";
|
|
227
|
+
/*==========================================
|
|
228
|
+
* RECORDS — the comparison is the core's, pure, like the two above.
|
|
229
|
+
*=========================================*/ export { packageRecordDiff, packageRecordField } from "@aglyn/aglyn/data-transfer/site-package-diff";
|
|
392
230
|
/*==========================================
|
|
393
231
|
* REVIEW
|
|
394
232
|
*=========================================*/ /** Items by decision, in the order the review reads them. */ export function packageDecisionCounts(decisions) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../libs/aglyn-transfer-ui/src/lib/site-package-import-state.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*==========================================\n * THE PACKAGE IMPORT'S DECISIONS — pure, so every rule is specced without\n * a screen (AGL-3534).\n *\n * A decision per item comes from, in order: the person's choice for that\n * item, the default they set for its kind of change (new, changed,\n * unchanged), and the plan's proposal. Every item's decision is sent, so\n * the server never falls back on a proposal the person did not see.\n *=========================================*/\n\nimport type {\n PackageDependency,\n PackageItemComparison,\n PackageItemDecision,\n PackageItemStatus,\n} from '@aglyn/aglyn/data-transfer'\n\nimport type {\n SitePackageDecisions,\n SitePackageDependencyChoice,\n SitePackageMergeChoice,\n SitePackagePlan,\n SitePackagePlanAnswer,\n SitePackagePlanItem,\n SitePackageWarning,\n} from './site-package-client'\nimport type { TransferAcknowledgementItem } from './transfer-acknowledgement-list.component'\nimport type { TransferChoiceOption } from './transfer-choice-select.component'\nimport type { TransferDiffChange } from './transfer-diff-table.component'\nimport { countOf } from './transfer-words'\n\ntype ChipColor = 'default' | 'success' | 'warning' | 'error' | 'info'\n\nexport const PACKAGE_STATUS_WORDS: Readonly<\n Record<PackageItemStatus, { label: string; color: ChipColor }>\n> = {\n new: { label: 'New', color: 'success' },\n identical: { label: 'Already on this site', color: 'default' },\n differs: { label: 'Differs', color: 'warning' },\n missingDependency: { label: 'Needs something', color: 'error' },\n}\n\nexport const PACKAGE_DECISION_WORDS: Readonly<\n Record<PackageItemDecision, { label: string; description: string }>\n> = {\n create: { label: 'Add', description: 'Adds the file’s item to this site.' },\n replace: {\n label: 'Replace',\n description:\n 'Writes the file’s copy over this site’s. Pages, layouts and emails get it as a new version.',\n },\n keepBoth: {\n label: 'Keep both',\n description:\n 'Adds the file’s copy beside this site’s, under a new ID and address.',\n },\n skip: { label: 'Skip', description: 'Leaves this site’s item as it is.' },\n merge: {\n label: 'Merge',\n description:\n 'Keeps this site’s values and fills in what it has not set; choose key by key.',\n },\n}\n\n/** The default a person sets for each kind of change. `''` is not chosen yet. */\nexport interface PackageBulkDefaults {\n new: PackageItemDecision | ''\n differs: PackageItemDecision | ''\n identical: PackageItemDecision | ''\n}\n\n/** New items are added and unchanged ones left; a changed item waits for the person. */\nexport const INITIAL_PACKAGE_BULK_DEFAULTS: PackageBulkDefaults = {\n new: 'create',\n differs: '',\n identical: 'skip',\n}\n\n/** The choices a default for one kind of change may take. */\nexport const PACKAGE_BULK_CHOICES: Readonly<\n Record<PackageItemComparison, readonly PackageItemDecision[]>\n> = {\n new: ['create', 'skip'],\n differs: ['skip', 'replace', 'keepBoth'],\n identical: ['skip', 'replace', 'keepBoth'],\n}\n\nexport function packageDecisionOptions(\n choices: readonly PackageItemDecision[],\n): TransferChoiceOption<PackageItemDecision>[] {\n return choices.map((choice) => ({\n value: choice,\n label: PACKAGE_DECISION_WORDS[choice].label,\n description: PACKAGE_DECISION_WORDS[choice].description,\n }))\n}\n\n/** An item as a person names it. */\nexport function packageItemTitle(item: {\n name?: string\n slug?: string\n id: string\n}): string {\n return item.name || item.slug || item.id\n}\n\n/**\n * The item's decision: the person's own, then the default for its kind of\n * change, then the plan's proposal — each only when the item may take it.\n * `null` when a changed item has neither a choice nor a default.\n */\nexport function effectivePackageDecision(\n item: SitePackagePlanItem,\n overrides: Readonly<Record<string, PackageItemDecision>>,\n bulk: PackageBulkDefaults,\n): PackageItemDecision | null {\n const own = overrides[item.key]\n if (own && item.choices.includes(own)) return own\n const fallback = bulk[item.comparison]\n if (fallback && item.choices.includes(fallback)) return fallback\n if (item.comparison === 'differs') return null\n return item.proposed\n}\n\n/** Every item's decision, and the items still waiting for one. */\nexport function packageDecisions(\n plan: SitePackagePlan,\n overrides: Readonly<Record<string, PackageItemDecision>>,\n bulk: PackageBulkDefaults,\n): { decisions: Record<string, PackageItemDecision>; undecided: string[] } {\n const decisions: Record<string, PackageItemDecision> = {}\n const undecided: string[] = []\n for (const item of plan.items) {\n const decision = effectivePackageDecision(item, overrides, bulk)\n if (decision) decisions[item.key] = decision\n else undecided.push(item.key)\n }\n return { decisions, undecided }\n}\n\n/** A dependency that will exist nowhere after the import unless the person says how. */\nexport interface PackageDependencyPrompt {\n key: string\n kind: string\n id: string\n /** The package's item, when the file carries it and it is set to skip. */\n inPackage?: SitePackagePlanItem\n /** The items being written that name it. */\n neededBy: string[]\n}\n\n/**\n * The dependencies an import would leave pointing at nothing: those the file\n * carries but the person skipped (and the site does not hold), and those\n * neither the file nor the site holds — for items that are written.\n */\nexport function packageDependencyPrompts(\n plan: SitePackagePlan,\n decisions: Readonly<Record<string, PackageItemDecision>>,\n): PackageDependencyPrompt[] {\n const byKey = new Map(plan.items.map((item) => [item.key, item]))\n const written = (key: string) => {\n const decision = decisions[key]\n return Boolean(decision) && decision !== 'skip'\n }\n const prompts = new Map<string, PackageDependencyPrompt>()\n const add = (dep: PackageDependency, by: string, inPackage?: SitePackagePlanItem) => {\n const key = `${dep.kind}/${dep.id}`\n const prompt = prompts.get(key) ?? {\n key,\n kind: dep.kind,\n id: dep.id,\n ...(inPackage ? { inPackage } : {}),\n neededBy: [],\n }\n if (!prompt.neededBy.includes(by)) prompt.neededBy.push(by)\n prompts.set(key, prompt)\n }\n for (const item of plan.items) {\n if (!written(item.key)) continue\n const missing = new Set(item.missing.map((dep) => `${dep.kind}/${dep.id}`))\n for (const dep of item.deps) {\n const key = `${dep.kind}/${dep.id}`\n if (missing.has(key)) {\n add(dep, item.key)\n continue\n }\n const packaged = byKey.get(key)\n if (packaged && !written(key) && !packaged.existing) add(dep, item.key, packaged)\n }\n }\n return [...prompts.values()]\n}\n\n/** What a prompt may be answered with. */\nexport type PackageDependencyAnswer = 'import' | 'mapTo' | 'drop' | 'keep'\n\nexport function packageDependencyOptions(\n prompt: PackageDependencyPrompt,\n): TransferChoiceOption<PackageDependencyAnswer>[] {\n return [\n ...(prompt.inPackage\n ? [\n {\n value: 'import' as const,\n label: 'Import it from the file',\n description: 'Adds the file’s copy, though you set it to skip.',\n },\n ]\n : []),\n {\n value: 'mapTo',\n label: 'Use an item this site has',\n description: 'Points every reference at the item you pick.',\n },\n {\n value: 'drop',\n label: 'Remove the reference',\n description: 'The items that named it no longer do.',\n },\n {\n value: 'keep',\n label: 'Leave it pointing at nothing',\n description: 'Until an item with that ID exists on this site.',\n },\n ]\n}\n\n/** The answer in the person's words: what the select shows. */\nexport function packageDependencyAnswer(\n choice: SitePackageDependencyChoice | undefined,\n): PackageDependencyAnswer | '' {\n if (!choice) return ''\n return typeof choice === 'object' ? 'mapTo' : choice\n}\n\n/** Why the dependency step cannot be left yet, one sentence each. */\nexport function packageDependencyProblems(\n prompts: readonly PackageDependencyPrompt[],\n choices: Readonly<Record<string, SitePackageDependencyChoice>>,\n): string[] {\n const unanswered = prompts.filter((prompt) => !choices[prompt.key]).length\n const unmapped = prompts.filter((prompt) => {\n const choice = choices[prompt.key]\n return typeof choice === 'object' && !choice.mapTo\n }).length\n return [\n ...(unanswered\n ? [`Choose what to do about ${countOf(unanswered, 'missing item')}.`]\n : []),\n ...(unmapped\n ? [`Pick the item to use for ${countOf(unmapped, 'reference')}.`]\n : []),\n ]\n}\n\n/** The answers the import route takes: only those for prompts still open, complete ones only. */\nexport function packageDependencyChoices(\n prompts: readonly PackageDependencyPrompt[],\n choices: Readonly<Record<string, SitePackageDependencyChoice>>,\n): Record<string, SitePackageDependencyChoice> {\n const out: Record<string, SitePackageDependencyChoice> = {}\n for (const prompt of prompts) {\n const choice = choices[prompt.key]\n if (!choice) continue\n if (typeof choice === 'object' && !choice.mapTo) continue\n out[prompt.key] = choice\n }\n return out\n}\n\n/*==========================================\n * DIFFS\n *=========================================*/\n\nconst isPlain = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.getPrototypeOf(value) === Object.prototype\n\nconst same = (a: unknown, b: unknown) => JSON.stringify(a) === JSON.stringify(b)\n\n/** A path as a person reads it: `version › nodes › text › props`. */\nfunction pathLabel(path: readonly string[]): string {\n return path.length ? path.join(' › ') : 'Whole item'\n}\n\n/**\n * Every leaf that differs between the site's item and the file's, as\n * before → after rows: objects are walked key by key, a list or a value is\n * compared whole. At most `limit` rows; `more` counts the rest.\n */\nexport function packageJsonDiff(\n before: unknown,\n after: unknown,\n limit = 200,\n): { changes: TransferDiffChange[]; more: number } {\n const changes: TransferDiffChange[] = []\n let more = 0\n const walk = (left: unknown, right: unknown, path: string[]) => {\n if (same(left, right)) return\n if (isPlain(left) && isPlain(right)) {\n const keys = [...new Set([...Object.keys(left), ...Object.keys(right)])].sort()\n for (const key of keys) walk(left[key], right[key], [...path, key])\n return\n }\n if (changes.length >= limit) {\n more += 1\n return\n }\n changes.push({\n key: path.join('/') || '$',\n label: pathLabel(path),\n before: left,\n after: right,\n })\n }\n walk(before, after, [])\n return { changes, more }\n}\n\n/** One top-level key of a merged item: both values and the default. */\nexport interface PackageMergeKey {\n key: string\n site: unknown\n file: unknown\n /** What a merge does when the person does not say: the site's value wins when it has one. */\n merged: SitePackageMergeChoice\n}\n\nconst blank = (value: unknown) =>\n value === undefined || value === null || value === ''\n\n/** The keys of a merged item that differ, each with what a merge would keep. */\nexport function packageMergeKeys(site: unknown, file: unknown): PackageMergeKey[] {\n const left = isPlain(site) ? site : {}\n const right = isPlain(file) ? file : {}\n return Object.keys(right)\n .sort()\n .filter((key) => right[key] !== undefined && !same(left[key], right[key]))\n .map((key) => ({\n key,\n site: left[key],\n file: right[key],\n merged: blank(left[key]) ? 'package' : 'site',\n }))\n}\n\n/*==========================================\n * RECORDS\n *=========================================*/\n\n/** One record of an item's list: a document with its own `$id`. */\nexport type PackageRecord = Record<string, unknown> & { $id: string }\n\nconst isRecord = (value: unknown): value is PackageRecord =>\n isPlain(value) && typeof value['$id'] === 'string' && value['$id'] !== ''\n\n/**\n * The key of an item that holds its records — a dataset's `records`, a\n * collection's `entries` — found by shape rather than by kind, so the kit\n * names no kind a plugin declares: the one list, on either side, whose\n * every element is a document with its own `$id`. The other side holds a\n * list there too, or nothing. `null` when no key qualifies, or when more\n * than one does and neither can be read as the item's records.\n */\nexport function packageRecordField(...contents: readonly unknown[]): string | null {\n const docs = contents.filter(isPlain)\n const found = new Set<string>()\n for (const doc of docs) {\n for (const [key, value] of Object.entries(doc)) {\n if (Array.isArray(value) && value.length > 0 && value.every(isRecord)) found.add(key)\n }\n }\n const fields = [...found].filter((key) =>\n docs.every((doc) => {\n const value = doc[key]\n return value === undefined || value === null || (Array.isArray(value) && value.every(isRecord))\n }),\n )\n return fields.length === 1 ? (fields[0] as string) : null\n}\n\nexport type PackageRecordStatus = 'added' | 'removed' | 'changed'\n\n/** One record that differs between the site and the file. */\nexport interface PackageRecordRow {\n id: string\n status: PackageRecordStatus\n /** The site's copy; `null` for a record only the file holds. */\n site: PackageRecord | null\n /** The file's copy; `null` for a record only the site holds. */\n file: PackageRecord | null\n /** The fields whose values differ, for a changed record. */\n changed: readonly string[]\n}\n\nexport interface PackageRecordDiff {\n /** The file's added and changed records in its order, then the site's removed ones. */\n rows: PackageRecordRow[]\n /** Every field the rows hold, `$id` aside, in the order they first appear. */\n fields: string[]\n counts: Record<PackageRecordStatus | 'same', number>\n}\n\nconst recordsOf = (value: unknown): PackageRecord[] =>\n Array.isArray(value) ? value.filter(isRecord) : []\n\n/**\n * Two lists of records, matched by `$id`: what the file adds, what it no\n * longer holds, and, for a record on both sides, each field whose value\n * differs. A record the import would leave as it is counts as `same` and\n * has no row.\n */\nexport function packageRecordDiff(site: unknown, file: unknown): PackageRecordDiff {\n const theirs = new Map(recordsOf(site).map((record) => [record.$id, record]))\n const ours = recordsOf(file)\n const seen = new Set<string>()\n const rows: PackageRecordRow[] = []\n const counts = { added: 0, removed: 0, changed: 0, same: 0 }\n for (const record of ours) {\n if (seen.has(record.$id)) continue\n seen.add(record.$id)\n const existing = theirs.get(record.$id)\n if (!existing) {\n counts.added += 1\n rows.push({ id: record.$id, status: 'added', site: null, file: record, changed: [] })\n continue\n }\n const keys = [...new Set([...Object.keys(existing), ...Object.keys(record)])].filter((key) => key !== '$id')\n const changed = keys.filter((key) => !same(existing[key], record[key]))\n if (!changed.length) {\n counts.same += 1\n continue\n }\n counts.changed += 1\n rows.push({ id: record.$id, status: 'changed', site: existing, file: record, changed })\n }\n for (const [id, record] of theirs) {\n if (seen.has(id)) continue\n counts.removed += 1\n rows.push({ id, status: 'removed', site: record, file: null, changed: [] })\n }\n const fields: string[] = []\n const listed = new Set<string>(['$id'])\n for (const row of rows) {\n for (const record of [row.file, row.site]) {\n for (const key of Object.keys(record ?? {})) {\n if (listed.has(key)) continue\n listed.add(key)\n fields.push(key)\n }\n }\n }\n return { rows, fields, counts }\n}\n\n/*==========================================\n * REVIEW\n *=========================================*/\n\n/** Items by decision, in the order the review reads them. */\nexport function packageDecisionCounts(\n decisions: Readonly<Record<string, PackageItemDecision>>,\n): Array<{ decision: PackageItemDecision; count: number }> {\n const order: PackageItemDecision[] = ['create', 'replace', 'keepBoth', 'merge', 'skip']\n const counts = new Map<PackageItemDecision, number>()\n for (const decision of Object.values(decisions)) {\n counts.set(decision, (counts.get(decision) ?? 0) + 1)\n }\n return order\n .filter((decision) => counts.get(decision))\n .map((decision) => ({ decision, count: counts.get(decision) as number }))\n}\n\nconst WARNING_WORDS: Readonly<\n Record<SitePackageWarning['code'], { title: string; description: string }>\n> = {\n droppedReference: {\n title: 'References removed',\n description: 'These items named something this site does not hold; the reference is taken out.',\n },\n mappedReference: {\n title: 'References pointed at this site’s items',\n description: 'These items now name the item you picked instead.',\n },\n danglingReference: {\n title: 'References that point at nothing',\n description: 'These items name something this site does not hold, until it does.',\n },\n}\n\n/**\n * What the person acknowledges before Import: what is overwritten (kept\n * for undo), each class of reference warning, and — told, not asked — the\n * items this site cannot read.\n */\nexport function packageAcknowledgements(\n answer: Pick<SitePackagePlanAnswer, 'warnings' | 'warningsTotal' | 'unknownKinds' | 'notSent'>,\n decisions: Readonly<Record<string, PackageItemDecision>>,\n titleOf: (key: string) => string,\n): TransferAcknowledgementItem[] {\n const items: TransferAcknowledgementItem[] = []\n const overwritten = Object.entries(decisions).filter(\n ([, decision]) => decision === 'replace' || decision === 'merge',\n )\n if (overwritten.length) {\n items.push({\n id: 'overwrite',\n title: 'Items written over',\n description:\n 'This site’s copy is replaced or merged into. What it held is kept, and you can undo the import for seven days.',\n count: overwritten.length,\n samples: overwritten.slice(0, 5).map(([key]) => titleOf(key)),\n required: true,\n })\n }\n const byCode = new Map<SitePackageWarning['code'], SitePackageWarning[]>()\n for (const warning of answer.warnings) {\n byCode.set(warning.code, [...(byCode.get(warning.code) ?? []), warning])\n }\n for (const [code, warnings] of byCode) {\n items.push({\n id: code,\n title: WARNING_WORDS[code].title,\n description: WARNING_WORDS[code].description,\n count: warnings.length,\n samples: warnings\n .slice(0, 5)\n .map((warning) => `${titleOf(warning.item)} → ${warning.dependency}`),\n required: true,\n })\n }\n if (answer.warningsTotal > answer.warnings.length) {\n items.push({\n id: 'moreWarnings',\n title: 'More reference warnings',\n description: 'The list above shows the first of them.',\n count: answer.warningsTotal - answer.warnings.length,\n samples: [],\n required: true,\n })\n }\n if (answer.unknownKinds.length) {\n items.push({\n id: 'unknownKinds',\n title: 'Items this site cannot read',\n description: 'Switch on the plugin that keeps them to import them. They are left out.',\n count: answer.unknownKinds.length,\n samples: answer.unknownKinds.slice(0, 5),\n required: false,\n })\n }\n if (answer.notSent.length) {\n items.push({\n id: 'notSent',\n title: 'Emails this platform does not send',\n description: 'They are left out.',\n count: answer.notSent.length,\n samples: answer.notSent.slice(0, 5),\n required: false,\n })\n }\n return items\n}\n\n/** Everything decided, as the import route takes it. */\nexport function packageDecided(\n decisions: Readonly<Record<string, PackageItemDecision>>,\n prompts: readonly PackageDependencyPrompt[],\n dependencyChoices: Readonly<Record<string, SitePackageDependencyChoice>>,\n mergeChoices: Readonly<Record<string, Record<string, SitePackageMergeChoice>>>,\n): SitePackageDecisions {\n return {\n decisions: { ...decisions },\n dependencyChoices: packageDependencyChoices(prompts, dependencyChoices),\n mergeChoices: Object.fromEntries(\n Object.entries(mergeChoices).filter(\n ([key, choices]) => decisions[key] === 'merge' && Object.keys(choices).length,\n ),\n ),\n }\n}\n"],"names":["countOf","PACKAGE_STATUS_WORDS","new","label","color","identical","differs","missingDependency","PACKAGE_DECISION_WORDS","create","description","replace","keepBoth","skip","merge","INITIAL_PACKAGE_BULK_DEFAULTS","PACKAGE_BULK_CHOICES","packageDecisionOptions","choices","map","choice","value","packageItemTitle","item","name","slug","id","effectivePackageDecision","overrides","bulk","own","key","includes","fallback","comparison","proposed","packageDecisions","plan","decisions","undecided","items","decision","push","packageDependencyPrompts","byKey","Map","written","Boolean","prompts","add","dep","by","inPackage","kind","prompt","get","neededBy","set","missing","Set","deps","has","packaged","existing","values","packageDependencyOptions","packageDependencyAnswer","packageDependencyProblems","unanswered","filter","length","unmapped","mapTo","packageDependencyChoices","out","isPlain","Array","isArray","Object","getPrototypeOf","prototype","same","a","b","JSON","stringify","pathLabel","path","join","packageJsonDiff","before","after","limit","changes","more","walk","left","right","keys","sort","blank","undefined","packageMergeKeys","site","file","merged","isRecord","packageRecordField","contents","docs","found","doc","entries","every","fields","recordsOf","packageRecordDiff","theirs","record","$id","ours","seen","rows","counts","added","removed","changed","status","listed","row","packageDecisionCounts","order","count","WARNING_WORDS","droppedReference","title","mappedReference","danglingReference","packageAcknowledgements","answer","titleOf","overwritten","samples","slice","required","byCode","warning","warnings","code","dependency","warningsTotal","unknownKinds","notSent","packageDecided","dependencyChoices","mergeChoices","fromEntries"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../libs/aglyn-transfer-ui/src/lib/site-package-import-state.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*==========================================\n * THE PACKAGE IMPORT'S DECISIONS — pure, so every rule is specced without\n * a screen (AGL-3534).\n *\n * A decision per item comes from, in order: the person's choice for that\n * item, the default they set for its kind of change (new, changed,\n * unchanged), and the plan's proposal. Every item's decision is sent, so\n * the server never falls back on a proposal the person did not see.\n *=========================================*/\n\nimport type {\n PackageDependency,\n PackageItemComparison,\n PackageItemDecision,\n PackageItemStatus,\n} from '@aglyn/aglyn/data-transfer'\n\nimport type {\n SitePackageDecisions,\n SitePackageDependencyChoice,\n SitePackageMergeChoice,\n SitePackagePlan,\n SitePackagePlanAnswer,\n SitePackagePlanItem,\n SitePackageWarning,\n} from './site-package-client'\nimport type { TransferAcknowledgementItem } from './transfer-acknowledgement-list.component'\nimport type { TransferChoiceOption } from './transfer-choice-select.component'\nimport { countOf } from './transfer-words'\n\ntype ChipColor = 'default' | 'success' | 'warning' | 'error' | 'info'\n\nexport const PACKAGE_STATUS_WORDS: Readonly<\n Record<PackageItemStatus, { label: string; color: ChipColor }>\n> = {\n new: { label: 'New', color: 'success' },\n identical: { label: 'Already on this site', color: 'default' },\n differs: { label: 'Differs', color: 'warning' },\n missingDependency: { label: 'Needs something', color: 'error' },\n}\n\nexport const PACKAGE_DECISION_WORDS: Readonly<\n Record<PackageItemDecision, { label: string; description: string }>\n> = {\n create: { label: 'Add', description: 'Adds the file’s item to this site.' },\n replace: {\n label: 'Replace',\n description:\n 'Writes the file’s copy over this site’s. Pages, layouts and emails get it as a new version.',\n },\n keepBoth: {\n label: 'Keep both',\n description:\n 'Adds the file’s copy beside this site’s, under a new ID and address.',\n },\n skip: { label: 'Skip', description: 'Leaves this site’s item as it is.' },\n merge: {\n label: 'Merge',\n description:\n 'Keeps this site’s values and fills in what it has not set; choose key by key.',\n },\n}\n\n/** The default a person sets for each kind of change. `''` is not chosen yet. */\nexport interface PackageBulkDefaults {\n new: PackageItemDecision | ''\n differs: PackageItemDecision | ''\n identical: PackageItemDecision | ''\n}\n\n/** New items are added and unchanged ones left; a changed item waits for the person. */\nexport const INITIAL_PACKAGE_BULK_DEFAULTS: PackageBulkDefaults = {\n new: 'create',\n differs: '',\n identical: 'skip',\n}\n\n/** The choices a default for one kind of change may take. */\nexport const PACKAGE_BULK_CHOICES: Readonly<\n Record<PackageItemComparison, readonly PackageItemDecision[]>\n> = {\n new: ['create', 'skip'],\n differs: ['skip', 'replace', 'keepBoth'],\n identical: ['skip', 'replace', 'keepBoth'],\n}\n\nexport function packageDecisionOptions(\n choices: readonly PackageItemDecision[],\n): TransferChoiceOption<PackageItemDecision>[] {\n return choices.map((choice) => ({\n value: choice,\n label: PACKAGE_DECISION_WORDS[choice].label,\n description: PACKAGE_DECISION_WORDS[choice].description,\n }))\n}\n\n/** An item as a person names it. */\nexport function packageItemTitle(item: {\n name?: string\n slug?: string\n id: string\n}): string {\n return item.name || item.slug || item.id\n}\n\n/**\n * The item's decision: the person's own, then the default for its kind of\n * change, then the plan's proposal — each only when the item may take it.\n * `null` when a changed item has neither a choice nor a default.\n */\nexport function effectivePackageDecision(\n item: SitePackagePlanItem,\n overrides: Readonly<Record<string, PackageItemDecision>>,\n bulk: PackageBulkDefaults,\n): PackageItemDecision | null {\n const own = overrides[item.key]\n if (own && item.choices.includes(own)) return own\n const fallback = bulk[item.comparison]\n if (fallback && item.choices.includes(fallback)) return fallback\n if (item.comparison === 'differs') return null\n return item.proposed\n}\n\n/** Every item's decision, and the items still waiting for one. */\nexport function packageDecisions(\n plan: SitePackagePlan,\n overrides: Readonly<Record<string, PackageItemDecision>>,\n bulk: PackageBulkDefaults,\n): { decisions: Record<string, PackageItemDecision>; undecided: string[] } {\n const decisions: Record<string, PackageItemDecision> = {}\n const undecided: string[] = []\n for (const item of plan.items) {\n const decision = effectivePackageDecision(item, overrides, bulk)\n if (decision) decisions[item.key] = decision\n else undecided.push(item.key)\n }\n return { decisions, undecided }\n}\n\n/** A dependency that will exist nowhere after the import unless the person says how. */\nexport interface PackageDependencyPrompt {\n key: string\n kind: string\n id: string\n /** The package's item, when the file carries it and it is set to skip. */\n inPackage?: SitePackagePlanItem\n /** The items being written that name it. */\n neededBy: string[]\n}\n\n/**\n * The dependencies an import would leave pointing at nothing: those the file\n * carries but the person skipped (and the site does not hold), and those\n * neither the file nor the site holds — for items that are written.\n */\nexport function packageDependencyPrompts(\n plan: SitePackagePlan,\n decisions: Readonly<Record<string, PackageItemDecision>>,\n): PackageDependencyPrompt[] {\n const byKey = new Map(plan.items.map((item) => [item.key, item]))\n const written = (key: string) => {\n const decision = decisions[key]\n return Boolean(decision) && decision !== 'skip'\n }\n const prompts = new Map<string, PackageDependencyPrompt>()\n const add = (dep: PackageDependency, by: string, inPackage?: SitePackagePlanItem) => {\n const key = `${dep.kind}/${dep.id}`\n const prompt = prompts.get(key) ?? {\n key,\n kind: dep.kind,\n id: dep.id,\n ...(inPackage ? { inPackage } : {}),\n neededBy: [],\n }\n if (!prompt.neededBy.includes(by)) prompt.neededBy.push(by)\n prompts.set(key, prompt)\n }\n for (const item of plan.items) {\n if (!written(item.key)) continue\n const missing = new Set(item.missing.map((dep) => `${dep.kind}/${dep.id}`))\n for (const dep of item.deps) {\n const key = `${dep.kind}/${dep.id}`\n if (missing.has(key)) {\n add(dep, item.key)\n continue\n }\n const packaged = byKey.get(key)\n if (packaged && !written(key) && !packaged.existing) add(dep, item.key, packaged)\n }\n }\n return [...prompts.values()]\n}\n\n/** What a prompt may be answered with. */\nexport type PackageDependencyAnswer = 'import' | 'mapTo' | 'drop' | 'keep'\n\nexport function packageDependencyOptions(\n prompt: PackageDependencyPrompt,\n): TransferChoiceOption<PackageDependencyAnswer>[] {\n return [\n ...(prompt.inPackage\n ? [\n {\n value: 'import' as const,\n label: 'Import it from the file',\n description: 'Adds the file’s copy, though you set it to skip.',\n },\n ]\n : []),\n {\n value: 'mapTo',\n label: 'Use an item this site has',\n description: 'Points every reference at the item you pick.',\n },\n {\n value: 'drop',\n label: 'Remove the reference',\n description: 'The items that named it no longer do.',\n },\n {\n value: 'keep',\n label: 'Leave it pointing at nothing',\n description: 'Until an item with that ID exists on this site.',\n },\n ]\n}\n\n/** The answer in the person's words: what the select shows. */\nexport function packageDependencyAnswer(\n choice: SitePackageDependencyChoice | undefined,\n): PackageDependencyAnswer | '' {\n if (!choice) return ''\n return typeof choice === 'object' ? 'mapTo' : choice\n}\n\n/** Why the dependency step cannot be left yet, one sentence each. */\nexport function packageDependencyProblems(\n prompts: readonly PackageDependencyPrompt[],\n choices: Readonly<Record<string, SitePackageDependencyChoice>>,\n): string[] {\n const unanswered = prompts.filter((prompt) => !choices[prompt.key]).length\n const unmapped = prompts.filter((prompt) => {\n const choice = choices[prompt.key]\n return typeof choice === 'object' && !choice.mapTo\n }).length\n return [\n ...(unanswered\n ? [`Choose what to do about ${countOf(unanswered, 'missing item')}.`]\n : []),\n ...(unmapped\n ? [`Pick the item to use for ${countOf(unmapped, 'reference')}.`]\n : []),\n ]\n}\n\n/** The answers the import route takes: only those for prompts still open, complete ones only. */\nexport function packageDependencyChoices(\n prompts: readonly PackageDependencyPrompt[],\n choices: Readonly<Record<string, SitePackageDependencyChoice>>,\n): Record<string, SitePackageDependencyChoice> {\n const out: Record<string, SitePackageDependencyChoice> = {}\n for (const prompt of prompts) {\n const choice = choices[prompt.key]\n if (!choice) continue\n if (typeof choice === 'object' && !choice.mapTo) continue\n out[prompt.key] = choice\n }\n return out\n}\n\n/*==========================================\n * DIFFS\n *=========================================*/\n\n// The two comparisons live in the core, pure, so the native apps read the same definition.\nexport { packageJsonDiff, packageMergeKeys } from '@aglyn/aglyn/data-transfer/site-package-diff'\nexport type { PackageMergeKey } from '@aglyn/aglyn/data-transfer/site-package-diff'\n\n/*==========================================\n * RECORDS — the comparison is the core's, pure, like the two above.\n *=========================================*/\n\nexport { packageRecordDiff, packageRecordField } from '@aglyn/aglyn/data-transfer/site-package-diff'\nexport type {\n PackageRecord,\n PackageRecordDiff,\n PackageRecordRow,\n PackageRecordStatus,\n} from '@aglyn/aglyn/data-transfer/site-package-diff'\n\n/*==========================================\n * REVIEW\n *=========================================*/\n\n/** Items by decision, in the order the review reads them. */\nexport function packageDecisionCounts(\n decisions: Readonly<Record<string, PackageItemDecision>>,\n): Array<{ decision: PackageItemDecision; count: number }> {\n const order: PackageItemDecision[] = ['create', 'replace', 'keepBoth', 'merge', 'skip']\n const counts = new Map<PackageItemDecision, number>()\n for (const decision of Object.values(decisions)) {\n counts.set(decision, (counts.get(decision) ?? 0) + 1)\n }\n return order\n .filter((decision) => counts.get(decision))\n .map((decision) => ({ decision, count: counts.get(decision) as number }))\n}\n\nconst WARNING_WORDS: Readonly<\n Record<SitePackageWarning['code'], { title: string; description: string }>\n> = {\n droppedReference: {\n title: 'References removed',\n description: 'These items named something this site does not hold; the reference is taken out.',\n },\n mappedReference: {\n title: 'References pointed at this site’s items',\n description: 'These items now name the item you picked instead.',\n },\n danglingReference: {\n title: 'References that point at nothing',\n description: 'These items name something this site does not hold, until it does.',\n },\n}\n\n/**\n * What the person acknowledges before Import: what is overwritten (kept\n * for undo), each class of reference warning, and — told, not asked — the\n * items this site cannot read.\n */\nexport function packageAcknowledgements(\n answer: Pick<SitePackagePlanAnswer, 'warnings' | 'warningsTotal' | 'unknownKinds' | 'notSent'>,\n decisions: Readonly<Record<string, PackageItemDecision>>,\n titleOf: (key: string) => string,\n): TransferAcknowledgementItem[] {\n const items: TransferAcknowledgementItem[] = []\n const overwritten = Object.entries(decisions).filter(\n ([, decision]) => decision === 'replace' || decision === 'merge',\n )\n if (overwritten.length) {\n items.push({\n id: 'overwrite',\n title: 'Items written over',\n description:\n 'This site’s copy is replaced or merged into. What it held is kept, and you can undo the import for seven days.',\n count: overwritten.length,\n samples: overwritten.slice(0, 5).map(([key]) => titleOf(key)),\n required: true,\n })\n }\n const byCode = new Map<SitePackageWarning['code'], SitePackageWarning[]>()\n for (const warning of answer.warnings) {\n byCode.set(warning.code, [...(byCode.get(warning.code) ?? []), warning])\n }\n for (const [code, warnings] of byCode) {\n items.push({\n id: code,\n title: WARNING_WORDS[code].title,\n description: WARNING_WORDS[code].description,\n count: warnings.length,\n samples: warnings\n .slice(0, 5)\n .map((warning) => `${titleOf(warning.item)} → ${warning.dependency}`),\n required: true,\n })\n }\n if (answer.warningsTotal > answer.warnings.length) {\n items.push({\n id: 'moreWarnings',\n title: 'More reference warnings',\n description: 'The list above shows the first of them.',\n count: answer.warningsTotal - answer.warnings.length,\n samples: [],\n required: true,\n })\n }\n if (answer.unknownKinds.length) {\n items.push({\n id: 'unknownKinds',\n title: 'Items this site cannot read',\n description: 'Switch on the plugin that keeps them to import them. They are left out.',\n count: answer.unknownKinds.length,\n samples: answer.unknownKinds.slice(0, 5),\n required: false,\n })\n }\n if (answer.notSent.length) {\n items.push({\n id: 'notSent',\n title: 'Emails this platform does not send',\n description: 'They are left out.',\n count: answer.notSent.length,\n samples: answer.notSent.slice(0, 5),\n required: false,\n })\n }\n return items\n}\n\n/** Everything decided, as the import route takes it. */\nexport function packageDecided(\n decisions: Readonly<Record<string, PackageItemDecision>>,\n prompts: readonly PackageDependencyPrompt[],\n dependencyChoices: Readonly<Record<string, SitePackageDependencyChoice>>,\n mergeChoices: Readonly<Record<string, Record<string, SitePackageMergeChoice>>>,\n): SitePackageDecisions {\n return {\n decisions: { ...decisions },\n dependencyChoices: packageDependencyChoices(prompts, dependencyChoices),\n mergeChoices: Object.fromEntries(\n Object.entries(mergeChoices).filter(\n ([key, choices]) => decisions[key] === 'merge' && Object.keys(choices).length,\n ),\n ),\n }\n}\n"],"names":["countOf","PACKAGE_STATUS_WORDS","new","label","color","identical","differs","missingDependency","PACKAGE_DECISION_WORDS","create","description","replace","keepBoth","skip","merge","INITIAL_PACKAGE_BULK_DEFAULTS","PACKAGE_BULK_CHOICES","packageDecisionOptions","choices","map","choice","value","packageItemTitle","item","name","slug","id","effectivePackageDecision","overrides","bulk","own","key","includes","fallback","comparison","proposed","packageDecisions","plan","decisions","undecided","items","decision","push","packageDependencyPrompts","byKey","Map","written","Boolean","prompts","add","dep","by","inPackage","kind","prompt","get","neededBy","set","missing","Set","deps","has","packaged","existing","values","packageDependencyOptions","packageDependencyAnswer","packageDependencyProblems","unanswered","filter","length","unmapped","mapTo","packageDependencyChoices","out","packageJsonDiff","packageMergeKeys","packageRecordDiff","packageRecordField","packageDecisionCounts","order","counts","Object","count","WARNING_WORDS","droppedReference","title","mappedReference","danglingReference","packageAcknowledgements","answer","titleOf","overwritten","entries","samples","slice","required","byCode","warning","warnings","code","dependency","warningsTotal","unknownKinds","notSent","packageDecided","dependencyChoices","mergeChoices","fromEntries","keys"],"mappings":"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"}
|