home-hosted 0.8.1 → 0.8.2
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/AGENTS.md +4 -1
- package/dist/cli.js +170 -27
- package/dist/cli.js.map +1 -1
- package/docs/UI_CREATION.md +23 -0
- package/package.json +4 -2
- package/uis/stock/dist/assets/de-DQxDtYp2.js +1 -0
- package/uis/stock/dist/assets/es-BP0qzCTU.js +1 -0
- package/uis/stock/dist/assets/fr-DHCvxiys.js +1 -0
- package/uis/stock/dist/assets/index-C02FUAwz.js +46 -0
- package/uis/stock/dist/assets/{index-DwE9bYyS.css → index-Skf2FzpK.css} +1 -1
- package/uis/stock/dist/assets/ja-DseIeS1D.js +1 -0
- package/uis/stock/dist/assets/ko-Dcu2b6c2.js +1 -0
- package/uis/stock/dist/assets/ru-DaAAVw09.js +1 -0
- package/uis/stock/dist/assets/vi-D780h-t9.js +1 -0
- package/uis/stock/dist/assets/zh-CN-C8OC-N1b.js +1 -0
- package/uis/stock/dist/index.html +2 -2
- package/uis/stock/dist/ui.json +3 -3
- package/uis/stock/dist/assets/de-DRY6VVqP.js +0 -1
- package/uis/stock/dist/assets/es-CKPLbx5t.js +0 -1
- package/uis/stock/dist/assets/fr-CQ7_4vtN.js +0 -1
- package/uis/stock/dist/assets/index-HT6jUD-L.js +0 -46
- package/uis/stock/dist/assets/ja-bRUylgOt.js +0 -1
- package/uis/stock/dist/assets/ko-DWqbA99M.js +0 -1
- package/uis/stock/dist/assets/ru-DUFxhVp3.js +0 -1
- package/uis/stock/dist/assets/vi-B0-81iVf.js +0 -1
- package/uis/stock/dist/assets/zh-CN-CeoyD9BM.js +0 -1
package/AGENTS.md
CHANGED
|
@@ -58,6 +58,8 @@ pnpm dev # tsx-watch panel :6000 + the stock UI's Vite
|
|
|
58
58
|
pnpm dev --ui noc-console # the same, for another UI; --port/--ui-port override
|
|
59
59
|
pnpm run build # dist/cli.js + the stock UI (uis/stock/dist)
|
|
60
60
|
pnpm run build:uis # every UI under uis/, zipped into uis/dist/ (release assets)
|
|
61
|
+
pnpm run build:locales # i18n/sheets/*.csv -> the git-ignored i18n/generated/*.json (also
|
|
62
|
+
# runs on install and before every UI build)
|
|
61
63
|
pnpm run quickcheck # eslint + tsc + vue-tsc + the doc links — NOT the tests
|
|
62
64
|
pnpm exec vitest run # `pnpm test` is vitest in watch mode
|
|
63
65
|
pnpm run check # ← THE GATE: quickcheck + vitest run --coverage. Run before every
|
|
@@ -123,7 +125,8 @@ These prevent defects if broken. The *why* for the non-obvious ones is in
|
|
|
123
125
|
an old panel keeps serving, so a required field blanks the app.
|
|
124
126
|
- **UIs move together.** A change to `uis/stock` — or to a shared contract it reads — lands in every
|
|
125
127
|
other UI under `uis/`, and each altered UI raises its `ui.json` version; `scripts/stamp-uis.mjs`
|
|
126
|
-
**refuses** a commit that changed a shipped UI without raising it (`
|
|
128
|
+
**refuses** a commit that changed a shipped UI without raising it (a UI's `test/` and its own
|
|
129
|
+
`README.md` are exempt — neither is in the built asset).
|
|
127
130
|
`src/shared/**` is a UI build input, so a runtime contract needs the bump too — the hook does not
|
|
128
131
|
inspect that commit.
|
|
129
132
|
- **Paths.** `dataRoot` is state, under `dataRoot/.hh`; `projectDir` is the base for relative entry
|
package/dist/cli.js
CHANGED
|
@@ -709,7 +709,7 @@ function parseBind(value) {
|
|
|
709
709
|
const parsed = bindSchema(value);
|
|
710
710
|
return parsed instanceof type.errors ? null : parsed;
|
|
711
711
|
}
|
|
712
|
-
var bindSchema, workspaceIdSchema, workspaceSchema, workspaceCreateSchema, workspaceRenameSchema, portSchema, onPortConflictSchema, onPortConflictDefaultSchema, restartSchema, httpCheckSchema, resourcesSchema, healthSchema, stopSchema, bootstrapSchema, bootstrapOrNullSchema, labelOrNullSchema, logBufferLinesSchema, serverSchema, authSchema, telegramSchema, notificationsSchema, logsSchema, tlsSchema, hostSchema, ddnsRecordTypeSchema, ddnsAccountSchema, ddnsDomainSchema, ddnsIpv4Schema, ddnsIpv6Schema, ddnsConfigSchema, ddnsRecordStateSchema, ddnsRecordViewSchema, ddnsStatusSchema, ddnsProviderFieldSchema, ddnsProviderInfoSchema, ddnsViewSchema, ddnsCredentialsSchema, backupsSchema, controlSchema, defaultsSchema, restartPatchSchema, httpCheckPatchSchema, resourcesPatchSchema, healthPatchSchema, stopPatchSchema, authPatchSchema, telegramPatchSchema, notificationsPatchSchema, hostPatchSchema, backupsPatchSchema, logsPatchSchema, tlsPatchSchema, controlPatchSchema, defaultsPatchSchema, editableFields, serverPatchSchema, serverCreateSchema, nannySpecSchema, nannyExitSchema, nannyStateSchema, settingsPatchSchema, workspaceSettingsPatchSchema, authStatusSchema, tlsStatusSchema, proxyEngineSchema, proxyTargetSchema, proxyTlsModeSchema, proxyRouteSchema, proxyCertificateSchema, proxyCertificateStateSchema, proxyDns01Schema, proxyConfigSchema, proxyEngineSourceSchema, proxyEngineStatusSchema, proxyEngineInfoSchema, proxyRouteStatusSchema, proxyRouteViewSchema, proxyRunStateSchema, proxyStatusSchema, proxyCertificateViewSchema, proxyDnsAccountViewSchema, proxyViewSchema, proxyRoutePatchSchema, proxyPatchSchema, proxyCertificateUploadSchema, proxyEngineInstallSchema, telegramStatusSchema, telegramChatsSchema, notificationViewSchema, sessionViewSchema, loginSchema, passwordValueSchema, passwordSchema, serverStatusSchema, healthStateSchema, portStateSchema, logStreamSchema, logLineSchema, historyEventSchema, serverHistorySchema, processResourcesSchema, hostDiskSchema, hostViewSchema, backupFileSchema, backupEntrySchema, backupsViewSchema, restoreItemSchema, restorePlanSchema, backupCreateSchema, restoreRequestSchema, serverViewSchema, healthResponseSchema, controlViewSchema, uiMetaSchema, uiStatusSchema, workspaceViewSchema, appStateSchema, logQuerySchema, freePortResultSchema, logHistoryQuerySchema, logFileInfoSchema, logServerViewSchema, logServersViewSchema, notificationActionSchema, telegramTokenSchema, apiErrorSchema, tlsUploadSchema, settingsViewSchema, settingsSavedSchema, workspaceSettingsViewSchema, workspaceSettingsSavedSchema;
|
|
712
|
+
var bindSchema, workspaceIdSchema, workspaceSchema, workspaceCreateSchema, workspaceRenameSchema, portSchema, onPortConflictSchema, onPortConflictDefaultSchema, restartSchema, httpCheckSchema, resourcesSchema, healthSchema, stopSchema, bootstrapSchema, bootstrapOrNullSchema, labelOrNullSchema, logBufferLinesSchema, serverSchema, authSchema, telegramSchema, notificationsSchema, logsSchema, tlsSchema, hostSchema, ddnsRecordTypeSchema, ddnsAccountSchema, ddnsDomainSchema, ddnsIpv4Schema, ddnsIpv6Schema, ddnsConfigSchema, ddnsRecordStateSchema, ddnsRecordViewSchema, ddnsStatusSchema, ddnsProviderFieldSchema, ddnsProviderInfoSchema, ddnsViewSchema, ddnsCredentialsSchema, backupsSchema, controlSchema, defaultsSchema, restartPatchSchema, httpCheckPatchSchema, resourcesPatchSchema, healthPatchSchema, stopPatchSchema, authPatchSchema, telegramPatchSchema, notificationsPatchSchema, hostPatchSchema, backupsPatchSchema, logsPatchSchema, tlsPatchSchema, controlPatchSchema, defaultsPatchSchema, editableFields, serverPatchSchema, serverCreateSchema, nannySpecSchema, nannyExitSchema, nannyStateSchema, settingsPatchSchema, workspaceSettingsPatchSchema, authStatusSchema, tlsStatusSchema, proxyEngineSchema, proxyTargetSchema, proxyTlsModeSchema, proxyRouteSchema, proxyCertificateSchema, proxyCertificateStateSchema, proxyDns01Schema, proxyConfigSchema, proxyEngineSourceSchema, proxyEngineStatusSchema, proxyEngineInfoSchema, proxyRouteStatusSchema, proxyRouteViewSchema, proxyRunStateSchema, proxyStatusSchema, proxyCertificateViewSchema, proxyDnsAccountViewSchema, proxyViewSchema, proxyRoutePatchSchema, proxyPatchSchema, proxyCertificateUploadSchema, proxyEngineInstallSchema, telegramStatusSchema, telegramChatsSchema, notificationViewSchema, sessionViewSchema, loginSchema, passwordValueSchema, passwordSchema, serverStatusSchema, healthStateSchema, portStateSchema, logStreamSchema, logLineSchema, historyEventSchema, serverHistorySchema, processResourcesSchema, hostDiskSchema, hostViewSchema, backupFileSchema, backupEntrySchema, backupsViewSchema, restoreItemSchema, restoreSkipSchema, restorePlanSchema, backupCreateSchema, restoreRequestSchema, serverViewSchema, healthResponseSchema, controlViewSchema, uiMetaSchema, uiStatusSchema, workspaceViewSchema, appStateSchema, logQuerySchema, freePortResultSchema, logHistoryQuerySchema, logFileInfoSchema, logServerViewSchema, logServersViewSchema, notificationActionSchema, telegramTokenSchema, apiErrorSchema, tlsUploadSchema, settingsViewSchema, settingsSavedSchema, workspaceSettingsViewSchema, workspaceSettingsSavedSchema;
|
|
713
713
|
var init_contracts = __esmMin((() => {
|
|
714
714
|
bindSchema = type("\"local\" | \"lan\" | /^\\d{1,3}(?:\\.\\d{1,3}){3}$/");
|
|
715
715
|
workspaceIdSchema = type("/^[a-z0-9][a-z0-9_-]*$/");
|
|
@@ -1475,14 +1475,26 @@ maxRssBytes: "number.integer >= 0 = 0" }).onUndeclaredKey("reject");
|
|
|
1475
1475
|
backupEntrySchema = type({
|
|
1476
1476
|
/** `global:settings` | `global:secrets` | `global:tls` | `workspace:<id>`. */
|
|
1477
1477
|
"id": "string",
|
|
1478
|
+
/**
|
|
1479
|
+
* The panel's own English wording. Kept because it is what an older UI reads, and what a
|
|
1480
|
+
* single-language UI wants; a translated UI prefers the `*Key` beside it.
|
|
1481
|
+
*/
|
|
1478
1482
|
"label": "string",
|
|
1483
|
+
/** A catalog key for `label`, with its placeholder values, so a UI can render its own language. */
|
|
1484
|
+
"labelKey?": "string",
|
|
1485
|
+
"labelParams?": "Record<string, string>",
|
|
1479
1486
|
"kind": "\"settings\" | \"secrets\" | \"tls\" | \"workspace\"",
|
|
1480
1487
|
"workspaceId?": "string",
|
|
1481
1488
|
"note": "string | null",
|
|
1489
|
+
/** The same pair for `note`: the panel knows which reason it is, the UI knows the wording. */
|
|
1490
|
+
"noteKey?": "string",
|
|
1491
|
+
"noteParams?": "Record<string, string>",
|
|
1482
1492
|
/** What this entry would capture; a workspace carries several leaves. */
|
|
1483
1493
|
"items": type({
|
|
1484
1494
|
"id": "string",
|
|
1485
1495
|
"label": "string",
|
|
1496
|
+
"labelKey?": "string",
|
|
1497
|
+
"labelParams?": "Record<string, string>",
|
|
1486
1498
|
/** `settings`/`servers`/`secrets` for a workspace, `data` for a declared path. */
|
|
1487
1499
|
"kind": "\"settings\" | \"servers\" | \"secrets\" | \"data\"",
|
|
1488
1500
|
"path?": "string",
|
|
@@ -1490,6 +1502,8 @@ maxRssBytes: "number.integer >= 0 = 0" }).onUndeclaredKey("reject");
|
|
|
1490
1502
|
"origin?": "string",
|
|
1491
1503
|
"included": "boolean",
|
|
1492
1504
|
"note": "string | null",
|
|
1505
|
+
"noteKey?": "string",
|
|
1506
|
+
"noteParams?": "Record<string, string>",
|
|
1493
1507
|
"ignoreGenerated?": "boolean"
|
|
1494
1508
|
}).array()
|
|
1495
1509
|
});
|
|
@@ -1507,27 +1521,45 @@ maxRssBytes: "number.integer >= 0 = 0" }).onUndeclaredKey("reject");
|
|
|
1507
1521
|
/** A backup entry or leaf id (`workspace:<id>:servers`, `data:<path>`, ...). */
|
|
1508
1522
|
"id": "string",
|
|
1509
1523
|
"label": "string",
|
|
1524
|
+
"labelKey?": "string",
|
|
1525
|
+
"labelParams?": "Record<string, string>",
|
|
1510
1526
|
"kind": "\"settings\" | \"secrets\" | \"servers\" | \"tls\" | \"data\"",
|
|
1511
1527
|
"workspaceId?": "string",
|
|
1512
1528
|
/** false when the current instance does not declare it, or it is not in the archive. */
|
|
1513
1529
|
"restorable": "boolean",
|
|
1514
1530
|
/** Echo of the request's selection, so the checkboxes round-trip. */
|
|
1515
1531
|
"selected": "boolean",
|
|
1516
|
-
"note": "string | null"
|
|
1532
|
+
"note": "string | null",
|
|
1533
|
+
"noteKey?": "string",
|
|
1534
|
+
"noteParams?": "Record<string, string>"
|
|
1535
|
+
});
|
|
1536
|
+
restoreSkipSchema = type({
|
|
1537
|
+
"label": "string",
|
|
1538
|
+
"labelKey?": "string",
|
|
1539
|
+
"labelParams?": "Record<string, string>",
|
|
1540
|
+
/** A catalog key for the parenthesis, e.g. `not selected`; absent when there is none. */
|
|
1541
|
+
"reasonKey?": "string",
|
|
1542
|
+
"reasonParams?": "Record<string, string>"
|
|
1517
1543
|
});
|
|
1518
1544
|
restorePlanSchema = type({
|
|
1519
|
-
dryRun: "boolean",
|
|
1520
|
-
encrypted: "boolean",
|
|
1545
|
+
"dryRun": "boolean",
|
|
1546
|
+
"encrypted": "boolean",
|
|
1521
1547
|
/** The archive needs a password (none or a wrong one was supplied). */
|
|
1522
|
-
needsPassword: "boolean",
|
|
1523
|
-
items: restoreItemSchema.array(),
|
|
1524
|
-
applied: type("string[]"),
|
|
1525
|
-
|
|
1548
|
+
"needsPassword": "boolean",
|
|
1549
|
+
"items": restoreItemSchema.array(),
|
|
1550
|
+
"applied": type("string[]"),
|
|
1551
|
+
/**
|
|
1552
|
+
* The ids `applied` names, so a UI resolves each through `items` and renders its own label.
|
|
1553
|
+
* `applied` itself stays: it is what a UI with one language reads.
|
|
1554
|
+
*/
|
|
1555
|
+
"appliedIds?": type("string[]"),
|
|
1556
|
+
"skipped": type("string[]"),
|
|
1557
|
+
"skippedItems?": restoreSkipSchema.array(),
|
|
1526
1558
|
/** Only the panel's own listener needs a restart; its servers are re-read live. */
|
|
1527
|
-
restartRequired: "boolean",
|
|
1559
|
+
"restartRequired": "boolean",
|
|
1528
1560
|
/** The panel re-read the restored config within this same restore. */
|
|
1529
|
-
reloaded: "boolean",
|
|
1530
|
-
error: "string?"
|
|
1561
|
+
"reloaded": "boolean",
|
|
1562
|
+
"error": "string?"
|
|
1531
1563
|
});
|
|
1532
1564
|
backupCreateSchema = type({
|
|
1533
1565
|
/** Optional: encrypts the archive. Never stored. */
|
|
@@ -13666,11 +13698,15 @@ function resolveBackupPaths(servers, includePaths = [], vars) {
|
|
|
13666
13698
|
ignoreGenerated: entry.ignoreGenerated
|
|
13667
13699
|
};
|
|
13668
13700
|
const note = parent.path === entry.path ? `already declared by ${parent.origin}` : `covered by ${parent.path}`;
|
|
13701
|
+
const noteKey = parent.path === entry.path ? "settings.backup.noteAlreadyDeclared" : "settings.backup.noteCovered";
|
|
13702
|
+
const noteParams = parent.path === entry.path ? { origin: parent.origin } : { path: parent.path };
|
|
13669
13703
|
return {
|
|
13670
13704
|
path: entry.path,
|
|
13671
13705
|
origin: entry.origin,
|
|
13672
13706
|
included: false,
|
|
13673
13707
|
note,
|
|
13708
|
+
noteKey,
|
|
13709
|
+
noteParams,
|
|
13674
13710
|
ignoreGenerated: entry.ignoreGenerated
|
|
13675
13711
|
};
|
|
13676
13712
|
});
|
|
@@ -13927,7 +13963,9 @@ var init_backups = __esmMin((() => {
|
|
|
13927
13963
|
needsPassword: false,
|
|
13928
13964
|
items: [],
|
|
13929
13965
|
applied: [],
|
|
13966
|
+
appliedIds: [],
|
|
13930
13967
|
skipped: [],
|
|
13968
|
+
skippedItems: [],
|
|
13931
13969
|
restartRequired: false,
|
|
13932
13970
|
reloaded: false
|
|
13933
13971
|
};
|
|
@@ -13970,7 +14008,13 @@ var init_backups = __esmMin((() => {
|
|
|
13970
14008
|
names: entries.map((entry) => entry.name),
|
|
13971
14009
|
...password === null ? {} : { password }
|
|
13972
14010
|
});
|
|
13973
|
-
for (const name of extracted.skipped)
|
|
14011
|
+
for (const name of extracted.skipped) {
|
|
14012
|
+
plan.skipped.push(`${name} (symbolic link, skipped)`);
|
|
14013
|
+
plan.skippedItems.push({
|
|
14014
|
+
label: name,
|
|
14015
|
+
reasonKey: "settings.restore.reasonSymbolicLink"
|
|
14016
|
+
});
|
|
14017
|
+
}
|
|
13974
14018
|
const manifestPath = path.join(staging, MANIFEST);
|
|
13975
14019
|
if (!fs.existsSync(manifestPath)) return {
|
|
13976
14020
|
...plan,
|
|
@@ -13987,6 +14031,13 @@ var init_backups = __esmMin((() => {
|
|
|
13987
14031
|
selected: false
|
|
13988
14032
|
});
|
|
13989
14033
|
plan.skipped.push(`${item.label}${item.note === null ? "" : ` (${item.note})`}`);
|
|
14034
|
+
plan.skippedItems.push({
|
|
14035
|
+
label: item.label,
|
|
14036
|
+
...item.labelKey === void 0 ? {} : { labelKey: item.labelKey },
|
|
14037
|
+
...item.labelParams === void 0 ? {} : { labelParams: item.labelParams },
|
|
14038
|
+
reasonKey: item.noteKey ?? "settings.restore.reasonUnrestorable",
|
|
14039
|
+
...item.noteParams === void 0 ? {} : { reasonParams: item.noteParams }
|
|
14040
|
+
});
|
|
13990
14041
|
return;
|
|
13991
14042
|
}
|
|
13992
14043
|
const selected = selectedIds === null || selectedIds.has(item.id) || aliases.some((alias) => selectedIds.has(alias));
|
|
@@ -13995,14 +14046,30 @@ var init_backups = __esmMin((() => {
|
|
|
13995
14046
|
selected
|
|
13996
14047
|
});
|
|
13997
14048
|
if (selected) actions.set(item.id, apply);
|
|
13998
|
-
else
|
|
14049
|
+
else {
|
|
14050
|
+
plan.skipped.push(`${item.label} (not selected)`);
|
|
14051
|
+
plan.skippedItems.push({
|
|
14052
|
+
label: item.label,
|
|
14053
|
+
...item.labelKey === void 0 ? {} : { labelKey: item.labelKey },
|
|
14054
|
+
...item.labelParams === void 0 ? {} : { labelParams: item.labelParams },
|
|
14055
|
+
reasonKey: "settings.restore.reasonNotSelected"
|
|
14056
|
+
});
|
|
14057
|
+
}
|
|
13999
14058
|
};
|
|
14000
14059
|
const settingsText = readText(path.join(staging, "global", "settings.json"));
|
|
14001
14060
|
const parsedGlobal = readableGlobalSettings(settingsText) ? parseGlobalSettings(JSON.parse(settingsText)).config : null;
|
|
14002
|
-
if (settingsText !== null && parsedGlobal === null)
|
|
14061
|
+
if (settingsText !== null && parsedGlobal === null) {
|
|
14062
|
+
plan.skipped.push("Global settings (the archive's settings are not valid)");
|
|
14063
|
+
plan.skippedItems.push({
|
|
14064
|
+
label: "Global settings",
|
|
14065
|
+
labelKey: "settings.backup.entryGlobalSettings",
|
|
14066
|
+
reasonKey: "settings.restore.reasonInvalidSettings"
|
|
14067
|
+
});
|
|
14068
|
+
}
|
|
14003
14069
|
if (parsedGlobal !== null && settingsText !== null) addItem({
|
|
14004
14070
|
id: "global:settings",
|
|
14005
14071
|
label: "Global settings",
|
|
14072
|
+
labelKey: "settings.backup.entryGlobalSettings",
|
|
14006
14073
|
kind: "settings",
|
|
14007
14074
|
restorable: true,
|
|
14008
14075
|
note: null
|
|
@@ -14013,6 +14080,7 @@ var init_backups = __esmMin((() => {
|
|
|
14013
14080
|
if (globalSecrets !== null) addItem({
|
|
14014
14081
|
id: "global:secrets",
|
|
14015
14082
|
label: "Global secrets (password, API token)",
|
|
14083
|
+
labelKey: "settings.backup.entryGlobalSecrets",
|
|
14016
14084
|
kind: "secrets",
|
|
14017
14085
|
restorable: true,
|
|
14018
14086
|
note: null
|
|
@@ -14025,6 +14093,7 @@ var init_backups = __esmMin((() => {
|
|
|
14025
14093
|
addItem({
|
|
14026
14094
|
id: "global:tls",
|
|
14027
14095
|
label: "TLS certificate",
|
|
14096
|
+
labelKey: "settings.backup.entryTlsCertificate",
|
|
14028
14097
|
kind: "tls",
|
|
14029
14098
|
restorable: true,
|
|
14030
14099
|
note: null
|
|
@@ -14070,10 +14139,16 @@ var init_backups = __esmMin((() => {
|
|
|
14070
14139
|
addItem({
|
|
14071
14140
|
id: `workspace:${id}:${suffix}`,
|
|
14072
14141
|
label: `${id}: ${label}`,
|
|
14142
|
+
labelKey: "settings.backup.restoreItemLabel",
|
|
14143
|
+
labelParams: {
|
|
14144
|
+
workspace: id,
|
|
14145
|
+
item: suffix
|
|
14146
|
+
},
|
|
14073
14147
|
kind: suffix,
|
|
14074
14148
|
workspaceId: id,
|
|
14075
14149
|
restorable: false,
|
|
14076
|
-
note: "unknown workspace"
|
|
14150
|
+
note: "unknown workspace",
|
|
14151
|
+
noteKey: "settings.backup.noteUnknownWorkspace"
|
|
14077
14152
|
}, null);
|
|
14078
14153
|
}
|
|
14079
14154
|
continue;
|
|
@@ -14082,6 +14157,11 @@ var init_backups = __esmMin((() => {
|
|
|
14082
14157
|
if (readableWorkspaceSettings(settings)) addItem({
|
|
14083
14158
|
id: `workspace:${id}:settings`,
|
|
14084
14159
|
label: `${workspace.label}: Settings`,
|
|
14160
|
+
labelKey: "settings.backup.restoreItemLabel",
|
|
14161
|
+
labelParams: {
|
|
14162
|
+
workspace: workspace.label,
|
|
14163
|
+
item: "settings"
|
|
14164
|
+
},
|
|
14085
14165
|
kind: "settings",
|
|
14086
14166
|
workspaceId: id,
|
|
14087
14167
|
restorable: true,
|
|
@@ -14089,7 +14169,18 @@ var init_backups = __esmMin((() => {
|
|
|
14089
14169
|
}, () => {
|
|
14090
14170
|
writeFileAtomic(workspace.settingsPath, settings);
|
|
14091
14171
|
});
|
|
14092
|
-
else
|
|
14172
|
+
else {
|
|
14173
|
+
plan.skipped.push(`${workspace.label}: Settings (the archive's settings are not valid)`);
|
|
14174
|
+
plan.skippedItems.push({
|
|
14175
|
+
label: `${workspace.label}: Settings`,
|
|
14176
|
+
labelKey: "settings.backup.restoreItemLabel",
|
|
14177
|
+
labelParams: {
|
|
14178
|
+
workspace: workspace.label,
|
|
14179
|
+
item: "settings"
|
|
14180
|
+
},
|
|
14181
|
+
reasonKey: "settings.restore.reasonInvalidSettings"
|
|
14182
|
+
});
|
|
14183
|
+
}
|
|
14093
14184
|
}
|
|
14094
14185
|
if (servers !== null) {
|
|
14095
14186
|
const parsed = readableServersFile(servers);
|
|
@@ -14098,6 +14189,11 @@ var init_backups = __esmMin((() => {
|
|
|
14098
14189
|
addItem({
|
|
14099
14190
|
id: `workspace:${id}:servers`,
|
|
14100
14191
|
label: `${workspace.label}: Servers`,
|
|
14192
|
+
labelKey: "settings.backup.restoreItemLabel",
|
|
14193
|
+
labelParams: {
|
|
14194
|
+
workspace: workspace.label,
|
|
14195
|
+
item: "servers"
|
|
14196
|
+
},
|
|
14101
14197
|
kind: "servers",
|
|
14102
14198
|
workspaceId: id,
|
|
14103
14199
|
restorable: true,
|
|
@@ -14105,11 +14201,27 @@ var init_backups = __esmMin((() => {
|
|
|
14105
14201
|
}, () => {
|
|
14106
14202
|
writeFileAtomic(workspace.serversPath, servers);
|
|
14107
14203
|
});
|
|
14108
|
-
} else
|
|
14204
|
+
} else {
|
|
14205
|
+
plan.skipped.push(`${workspace.label}: Servers (the archive's servers are not valid)`);
|
|
14206
|
+
plan.skippedItems.push({
|
|
14207
|
+
label: `${workspace.label}: Servers`,
|
|
14208
|
+
labelKey: "settings.backup.restoreItemLabel",
|
|
14209
|
+
labelParams: {
|
|
14210
|
+
workspace: workspace.label,
|
|
14211
|
+
item: "servers"
|
|
14212
|
+
},
|
|
14213
|
+
reasonKey: "settings.restore.reasonInvalidServers"
|
|
14214
|
+
});
|
|
14215
|
+
}
|
|
14109
14216
|
}
|
|
14110
14217
|
if (secrets !== null) addItem({
|
|
14111
14218
|
id: `workspace:${id}:secrets`,
|
|
14112
14219
|
label: `${workspace.label}: Secrets`,
|
|
14220
|
+
labelKey: "settings.backup.restoreItemLabel",
|
|
14221
|
+
labelParams: {
|
|
14222
|
+
workspace: workspace.label,
|
|
14223
|
+
item: "secrets"
|
|
14224
|
+
},
|
|
14113
14225
|
kind: "secrets",
|
|
14114
14226
|
workspaceId: id,
|
|
14115
14227
|
restorable: true,
|
|
@@ -14179,21 +14291,27 @@ var init_backups = __esmMin((() => {
|
|
|
14179
14291
|
const declaredByBackup = archiveAll.some((candidate) => candidate.origin === origin && (workspace === void 0 || candidate.workspace === workspace));
|
|
14180
14292
|
addItem({
|
|
14181
14293
|
...base,
|
|
14182
|
-
note: declaredByBackup ? "declared by the backup's config, which is not being restored" : "not declared by this config, nor by the backup"
|
|
14294
|
+
note: declaredByBackup ? "declared by the backup's config, which is not being restored" : "not declared by this config, nor by the backup",
|
|
14295
|
+
noteKey: declaredByBackup ? "settings.backup.noteDeclaredByBackup" : "settings.backup.noteNotDeclared"
|
|
14183
14296
|
}, null, aliases);
|
|
14184
14297
|
continue;
|
|
14185
14298
|
}
|
|
14186
14299
|
if (!fs.existsSync(from)) {
|
|
14187
14300
|
addItem({
|
|
14188
14301
|
...base,
|
|
14189
|
-
note: "missing from the archive"
|
|
14302
|
+
note: "missing from the archive",
|
|
14303
|
+
noteKey: "settings.backup.noteMissingFromArchive"
|
|
14190
14304
|
}, null, aliases);
|
|
14191
14305
|
continue;
|
|
14192
14306
|
}
|
|
14193
14307
|
addItem({
|
|
14194
14308
|
...base,
|
|
14195
14309
|
restorable: true,
|
|
14196
|
-
|
|
14310
|
+
...target.path === archivedPath ? { note: null } : {
|
|
14311
|
+
note: `restored from ${archivedPath}`,
|
|
14312
|
+
noteKey: "settings.backup.noteRestoredFrom",
|
|
14313
|
+
noteParams: { path: archivedPath }
|
|
14314
|
+
}
|
|
14197
14315
|
}, () => fs.cpSync(from, target.path, {
|
|
14198
14316
|
recursive: true,
|
|
14199
14317
|
force: true,
|
|
@@ -14207,12 +14325,14 @@ var init_backups = __esmMin((() => {
|
|
|
14207
14325
|
}
|
|
14208
14326
|
if (!options.confirm) {
|
|
14209
14327
|
plan.applied = [...actions.keys()].map((id) => labelOf(plan, id));
|
|
14328
|
+
plan.appliedIds = [...actions.keys()];
|
|
14210
14329
|
return plan;
|
|
14211
14330
|
}
|
|
14212
14331
|
for (const [id, apply] of actions) {
|
|
14213
14332
|
apply();
|
|
14214
14333
|
plan.applied.push(labelOf(plan, id));
|
|
14215
14334
|
}
|
|
14335
|
+
plan.appliedIds = [...actions.keys()];
|
|
14216
14336
|
if (this.options.onRestored !== void 0 && [...actions.keys()].some((id) => RELOADABLE.test(id))) {
|
|
14217
14337
|
plan.reloaded = true;
|
|
14218
14338
|
this.options.onRestored();
|
|
@@ -14239,26 +14359,36 @@ var init_backups = __esmMin((() => {
|
|
|
14239
14359
|
}
|
|
14240
14360
|
/** Selectable entries: the three global slices, then one per workspace. */
|
|
14241
14361
|
entries(sources) {
|
|
14362
|
+
const missing = (path, key) => {
|
|
14363
|
+
const absent = this.missingNote(path);
|
|
14364
|
+
return absent === null ? { note: null } : {
|
|
14365
|
+
note: absent,
|
|
14366
|
+
noteKey: key
|
|
14367
|
+
};
|
|
14368
|
+
};
|
|
14242
14369
|
const entries = [
|
|
14243
14370
|
{
|
|
14244
14371
|
id: "global:settings",
|
|
14245
14372
|
label: "Global settings",
|
|
14373
|
+
labelKey: "settings.backup.entryGlobalSettings",
|
|
14246
14374
|
kind: "settings",
|
|
14247
|
-
|
|
14375
|
+
...missing(sources.globalSettingsPath, "settings.backup.noteMissing"),
|
|
14248
14376
|
items: []
|
|
14249
14377
|
},
|
|
14250
14378
|
{
|
|
14251
14379
|
id: "global:secrets",
|
|
14252
14380
|
label: "Global secrets (password, API token)",
|
|
14381
|
+
labelKey: "settings.backup.entryGlobalSecrets",
|
|
14253
14382
|
kind: "secrets",
|
|
14254
|
-
|
|
14383
|
+
...missing(sources.globalSecretsPath, "settings.backup.noteMissing"),
|
|
14255
14384
|
items: []
|
|
14256
14385
|
},
|
|
14257
14386
|
{
|
|
14258
14387
|
id: "global:tls",
|
|
14259
14388
|
label: "TLS certificate",
|
|
14389
|
+
labelKey: "settings.backup.entryTlsCertificate",
|
|
14260
14390
|
kind: "tls",
|
|
14261
|
-
|
|
14391
|
+
...missing(sources.tlsDir, "settings.backup.noteMissing"),
|
|
14262
14392
|
items: []
|
|
14263
14393
|
}
|
|
14264
14394
|
];
|
|
@@ -14274,27 +14404,37 @@ var init_backups = __esmMin((() => {
|
|
|
14274
14404
|
}
|
|
14275
14405
|
workspaceItems(workspace, includePaths) {
|
|
14276
14406
|
const id = workspace.id;
|
|
14407
|
+
const note = (path) => {
|
|
14408
|
+
const absent = this.missingNote(path);
|
|
14409
|
+
return absent === null ? { note: null } : {
|
|
14410
|
+
note: absent,
|
|
14411
|
+
noteKey: "settings.backup.noteMissing"
|
|
14412
|
+
};
|
|
14413
|
+
};
|
|
14277
14414
|
const items = [
|
|
14278
14415
|
{
|
|
14279
14416
|
id: `workspace:${id}:settings`,
|
|
14280
14417
|
label: "Settings",
|
|
14418
|
+
labelKey: "settings.backup.leafSettings",
|
|
14281
14419
|
kind: "settings",
|
|
14282
14420
|
included: true,
|
|
14283
|
-
note
|
|
14421
|
+
...note(workspace.settingsPath)
|
|
14284
14422
|
},
|
|
14285
14423
|
{
|
|
14286
14424
|
id: `workspace:${id}:servers`,
|
|
14287
14425
|
label: "Servers",
|
|
14426
|
+
labelKey: "settings.backup.leafServers",
|
|
14288
14427
|
kind: "servers",
|
|
14289
14428
|
included: true,
|
|
14290
|
-
note
|
|
14429
|
+
...note(workspace.serversPath)
|
|
14291
14430
|
},
|
|
14292
14431
|
{
|
|
14293
14432
|
id: `workspace:${id}:secrets`,
|
|
14294
14433
|
label: "Secrets",
|
|
14434
|
+
labelKey: "settings.backup.leafSecrets",
|
|
14295
14435
|
kind: "secrets",
|
|
14296
14436
|
included: true,
|
|
14297
|
-
note
|
|
14437
|
+
...note(workspace.secretsPath)
|
|
14298
14438
|
}
|
|
14299
14439
|
];
|
|
14300
14440
|
for (const declared of this.declaredData(workspace.servers, includePaths)) items.push({
|
|
@@ -14305,6 +14445,8 @@ var init_backups = __esmMin((() => {
|
|
|
14305
14445
|
origin: declared.origin,
|
|
14306
14446
|
included: declared.included,
|
|
14307
14447
|
note: declared.note,
|
|
14448
|
+
...declared.noteKey === void 0 ? {} : { noteKey: declared.noteKey },
|
|
14449
|
+
...declared.noteParams === void 0 ? {} : { noteParams: declared.noteParams },
|
|
14308
14450
|
ignoreGenerated: declared.ignoreGenerated
|
|
14309
14451
|
});
|
|
14310
14452
|
return items;
|
|
@@ -14320,7 +14462,8 @@ var init_backups = __esmMin((() => {
|
|
|
14320
14462
|
if (entry.included && isInside(entry.path, archiveDir)) return {
|
|
14321
14463
|
...entry,
|
|
14322
14464
|
included: false,
|
|
14323
|
-
note: "contains the backup directory"
|
|
14465
|
+
note: "contains the backup directory",
|
|
14466
|
+
noteKey: "settings.backup.noteContainsBackupDir"
|
|
14324
14467
|
};
|
|
14325
14468
|
return entry;
|
|
14326
14469
|
});
|