@serve.zone/dcrouter 34.0.0 → 34.2.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_ts/index.js CHANGED
@@ -4,6 +4,7 @@ export * from './00_commitinfo_data.js';
4
4
  export { UnifiedEmailServer } from '@push.rocks/smartmta';
5
5
  // DcRouter
6
6
  import { DcRouter } from './classes.dcrouter.js';
7
+ import { runMigrateCommand } from './migrate-command.js';
7
8
  export * from './classes.dcrouter.js';
8
9
  // RADIUS module
9
10
  export * from './radius/index.js';
@@ -11,25 +12,37 @@ export * from './radius/index.js';
11
12
  export * from './remoteingress/index.js';
12
13
  // Web Push provider module
13
14
  export * from './webpush/index.js';
14
- export const runCli = async () => {
15
- const args = process.argv.slice(2);
16
- if (args.includes('--version') || args.includes('version')) {
17
- console.log(commitinfo.version);
18
- return;
19
- }
20
- if (args.includes('--help') || args.includes('-h') || args.includes('help')) {
21
- console.log(`dcrouter ${commitinfo.version}
22
-
23
- Usage:
15
+ const cliUsage = `Usage:
24
16
  dcrouter
25
17
  dcrouter --version
26
18
  dcrouter --help
19
+ dcrouter migrate --storage-path <absolute path> --to <version> [--db-name <name>] [--plan]
27
20
 
28
21
  Environment:
29
22
  DCROUTER_MODE=OCI_CONTAINER Start with OCI container configuration
30
23
  DCROUTER_DNS_BIND_INTERFACE Override the embedded DNS UDP bind address
31
24
  DATA_DIR=<path> Override the writable dcrouter data directory
32
- `);
25
+ `;
26
+ export const runCli = async () => {
27
+ const args = process.argv.slice(2);
28
+ if (args[0] === 'migrate') {
29
+ process.exitCode = await runMigrateCommand(args.slice(1));
30
+ return;
31
+ }
32
+ if (args.includes('--version') || args.includes('version')) {
33
+ console.log(commitinfo.version);
34
+ return;
35
+ }
36
+ if (args.includes('--help') || args.includes('-h') || args.includes('help')) {
37
+ console.log(`dcrouter ${commitinfo.version}\n\n${cliUsage}`);
38
+ return;
39
+ }
40
+ // Only a bare `dcrouter` starts the router: an argument this release does not know (a command
41
+ // a later release added, a typo) must never start it against the data it was meant for.
42
+ if (args.length > 0) {
43
+ console.error(`dcrouter: unknown argument${args.length > 1 ? 's' : ''} ${args.map((argArg) => `"${argArg}"`).join(' ')}; `
44
+ + `nothing was started.\n\n${cliUsage}`);
45
+ process.exitCode = 2;
33
46
  return;
34
47
  }
35
48
  let options = {};
@@ -49,4 +62,4 @@ Environment:
49
62
  process.once('SIGINT', shutdown);
50
63
  process.once('SIGTERM', shutdown);
51
64
  };
52
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckQsY0FBYyx5QkFBeUIsQ0FBQztBQUV4QyxxRUFBcUU7QUFDckUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFHMUQsV0FBVztBQUNYLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNqRCxjQUFjLHVCQUF1QixDQUFDO0FBRXRDLGdCQUFnQjtBQUNoQixjQUFjLG1CQUFtQixDQUFDO0FBRWxDLHdCQUF3QjtBQUN4QixjQUFjLDBCQUEwQixDQUFDO0FBRXpDLDJCQUEyQjtBQUMzQixjQUFjLG9CQUFvQixDQUFDO0FBS25DLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxLQUFLLElBQUksRUFBRTtJQUMvQixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVuQyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQzNELE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2hDLE9BQU87SUFDVCxDQUFDO0lBRUQsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzVFLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxVQUFVLENBQUMsT0FBTzs7Ozs7Ozs7Ozs7Q0FXN0MsQ0FBQyxDQUFDO1FBQ0MsT0FBTztJQUNULENBQUM7SUFFRCxJQUFJLE9BQU8sR0FBcUQsRUFBRSxDQUFDO0lBRW5FLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEtBQUssZUFBZSxFQUFFLENBQUM7UUFDbEQsTUFBTSxFQUFFLHFCQUFxQixFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsOEJBQThCLENBQUMsQ0FBQztRQUMvRSxPQUFPLEdBQUcscUJBQXFCLEVBQUUsQ0FBQztRQUNsQyxPQUFPLENBQUMsR0FBRyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVELE1BQU0sUUFBUSxHQUFHLElBQUksUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3ZCLE9BQU8sQ0FBQyxHQUFHLENBQUMscURBQXFELENBQUMsQ0FBQztJQUVuRSxNQUFNLFFBQVEsR0FBRyxLQUFLLElBQUksRUFBRTtRQUMxQixPQUFPLENBQUMsR0FBRyxDQUFDLDZCQUE2QixDQUFDLENBQUM7UUFDM0MsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQixDQUFDLENBQUM7SUFDRixPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNqQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztBQUNwQyxDQUFDLENBQUMifQ==
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckQsY0FBYyx5QkFBeUIsQ0FBQztBQUV4QyxxRUFBcUU7QUFDckUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFHMUQsV0FBVztBQUNYLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN6RCxjQUFjLHVCQUF1QixDQUFDO0FBRXRDLGdCQUFnQjtBQUNoQixjQUFjLG1CQUFtQixDQUFDO0FBRWxDLHdCQUF3QjtBQUN4QixjQUFjLDBCQUEwQixDQUFDO0FBRXpDLDJCQUEyQjtBQUMzQixjQUFjLG9CQUFvQixDQUFDO0FBS25DLE1BQU0sUUFBUSxHQUFHOzs7Ozs7Ozs7O0NBVWhCLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxNQUFNLEdBQUcsS0FBSyxJQUFJLEVBQUU7SUFDL0IsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFbkMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDMUIsT0FBTyxDQUFDLFFBQVEsR0FBRyxNQUFNLGlCQUFpQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxRCxPQUFPO0lBQ1QsQ0FBQztJQUVELElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDM0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEMsT0FBTztJQUNULENBQUM7SUFFRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDNUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLFVBQVUsQ0FBQyxPQUFPLE9BQU8sUUFBUSxFQUFFLENBQUMsQ0FBQztRQUM3RCxPQUFPO0lBQ1QsQ0FBQztJQUVELDhGQUE4RjtJQUM5Rix3RkFBd0Y7SUFDeEYsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3BCLE9BQU8sQ0FBQyxLQUFLLENBQ1gsNkJBQTZCLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJO2NBQzFHLDJCQUEyQixRQUFRLEVBQUUsQ0FDeEMsQ0FBQztRQUNGLE9BQU8sQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO1FBQ3JCLE9BQU87SUFDVCxDQUFDO0lBRUQsSUFBSSxPQUFPLEdBQXFELEVBQUUsQ0FBQztJQUVuRSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxLQUFLLGVBQWUsRUFBRSxDQUFDO1FBQ2xELE1BQU0sRUFBRSxxQkFBcUIsRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLDhCQUE4QixDQUFDLENBQUM7UUFDL0UsT0FBTyxHQUFHLHFCQUFxQixFQUFFLENBQUM7UUFDbEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN2QyxNQUFNLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUN2QixPQUFPLENBQUMsR0FBRyxDQUFDLHFEQUFxRCxDQUFDLENBQUM7SUFFbkUsTUFBTSxRQUFRLEdBQUcsS0FBSyxJQUFJLEVBQUU7UUFDMUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1FBQzNDLE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3RCLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEIsQ0FBQyxDQUFDO0lBQ0YsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDakMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDcEMsQ0FBQyxDQUFDIn0=
@@ -0,0 +1,44 @@
1
+ import * as plugins from './plugins.js';
2
+ import type { IDowngradeMigrationRunResult } from '../dist_ts_migrations/index.js';
3
+ /** The prefix of the one line `dcrouter migrate` ends with: the outcome as JSON. */
4
+ export declare const migrateResultLinePrefix = "DCROUTER_MIGRATE_RESULT:";
5
+ export declare const migrateCommandUsage = "Usage:\n dcrouter migrate --storage-path <absolute path> --to <version> [--db-name <name>] [--plan]\n\nWalks the data of a stopped dcrouter back to an earlier data version, running each\nstep's down handler. Forward migrations happen when dcrouter starts.\n\n --storage-path <path> The embedded database's storage root (absolute; no default)\n --to <version> The data version to walk back to, a step boundary\n --db-name <name> The database inside the root (default: dcrouter)\n --plan Report the steps the downgrade would run, change nothing\n\nThe root must not be in use: the command refuses a root a running dcrouter owns.\nThe last line of the output is DCROUTER_MIGRATE_RESULT:{json}.\n";
6
+ /** A command line `dcrouter migrate` refuses before it opens anything. */
7
+ export declare class MigrateCommandUsageError extends Error {
8
+ constructor(messageArg: string);
9
+ }
10
+ export interface IMigrateCommandOptions {
11
+ storagePath: string;
12
+ targetVersion: string;
13
+ dbName: string;
14
+ planOnly: boolean;
15
+ }
16
+ export type TMigrateCommandResult = ({
17
+ ok: true;
18
+ plan: boolean;
19
+ storagePath: string;
20
+ dbName: string;
21
+ } & IDowngradeMigrationRunResult) | {
22
+ ok: false;
23
+ error: {
24
+ name: string;
25
+ code?: string;
26
+ message: string;
27
+ };
28
+ };
29
+ /**
30
+ * The stopped-root check's bounds: the largest every input admits (smartdb readme, "Offline
31
+ * Physical Namespace Inspection"). A root over any of them is refused, never partly inspected: a
32
+ * data file over `maximumDataFileBytes` fails the whole inspection with `ERESOURCE_LIMIT`
33
+ * (nosqldb 5.7.1 `rustdb-storage/src/offline_inspection/physical_namespace_inspection.rs:760`).
34
+ */
35
+ export declare const offlineInspectionLimits: plugins.smartdb.ILocalSmartDbOfflinePhysicalNamespaceInspectionLimits;
36
+ export declare function parseMigrateArguments(argsArg: string[]): IMigrateCommandOptions;
37
+ /**
38
+ * Runs the downgrade offline: a stopped-root check first, then the engine, whose owner lock refuses
39
+ * a root a running dcrouter holds, then the reverse migration. Both handles are released before it
40
+ * returns, whatever happened.
41
+ */
42
+ export declare function runMigrateCommandOptions(optionsArg: IMigrateCommandOptions): Promise<TMigrateCommandResult>;
43
+ /** `dcrouter migrate …`; resolves to the process exit code and prints the result line last. */
44
+ export declare function runMigrateCommand(argsArg: string[]): Promise<number>;
@@ -0,0 +1,181 @@
1
+ import * as plugins from './plugins.js';
2
+ import { createDowngradeMigrationRunner, DcRouterMigrationError } from '../dist_ts_migrations/index.js';
3
+ /** The prefix of the one line `dcrouter migrate` ends with: the outcome as JSON. */
4
+ export const migrateResultLinePrefix = 'DCROUTER_MIGRATE_RESULT:';
5
+ export const migrateCommandUsage = `Usage:
6
+ dcrouter migrate --storage-path <absolute path> --to <version> [--db-name <name>] [--plan]
7
+
8
+ Walks the data of a stopped dcrouter back to an earlier data version, running each
9
+ step's down handler. Forward migrations happen when dcrouter starts.
10
+
11
+ --storage-path <path> The embedded database's storage root (absolute; no default)
12
+ --to <version> The data version to walk back to, a step boundary
13
+ --db-name <name> The database inside the root (default: dcrouter)
14
+ --plan Report the steps the downgrade would run, change nothing
15
+
16
+ The root must not be in use: the command refuses a root a running dcrouter owns.
17
+ The last line of the output is ${migrateResultLinePrefix}{json}.
18
+ `;
19
+ /** A command line `dcrouter migrate` refuses before it opens anything. */
20
+ export class MigrateCommandUsageError extends Error {
21
+ constructor(messageArg) {
22
+ super(messageArg);
23
+ this.name = 'MigrateCommandUsageError';
24
+ }
25
+ }
26
+ /**
27
+ * The stopped-root check's bounds: the largest every input admits (smartdb readme, "Offline
28
+ * Physical Namespace Inspection"). A root over any of them is refused, never partly inspected: a
29
+ * data file over `maximumDataFileBytes` fails the whole inspection with `ERESOURCE_LIMIT`
30
+ * (nosqldb 5.7.1 `rustdb-storage/src/offline_inspection/physical_namespace_inspection.rs:760`).
31
+ */
32
+ export const offlineInspectionLimits = {
33
+ maximumEntries: 100_000,
34
+ maximumDatabases: 4_096,
35
+ maximumCollections: 10_000,
36
+ maximumIndexes: 100_000,
37
+ maximumDataFileBytes: 268_435_456,
38
+ maximumWalFileBytes: 67_108_864,
39
+ maximumIndexFileBytes: 16_777_216,
40
+ maximumTotalFileBytes: 1_099_511_627_776,
41
+ maximumRecordsPerCollection: 1_000_000,
42
+ maximumRecordBytes: 17_825_792,
43
+ maximumResultBytes: 16_777_216,
44
+ };
45
+ const offlineInspectionTimeoutMs = 10 * 60_000;
46
+ export function parseMigrateArguments(argsArg) {
47
+ let storagePath;
48
+ let targetVersion;
49
+ let dbName = 'dcrouter';
50
+ let planOnly = false;
51
+ const valueOf = (indexArg, flagArg) => {
52
+ const value = argsArg[indexArg + 1];
53
+ if (value === undefined || value.startsWith('--')) {
54
+ throw new MigrateCommandUsageError(`${flagArg} needs a value.`);
55
+ }
56
+ return value;
57
+ };
58
+ for (let index = 0; index < argsArg.length; index++) {
59
+ const arg = argsArg[index];
60
+ switch (arg) {
61
+ case '--storage-path':
62
+ storagePath = valueOf(index++, arg);
63
+ break;
64
+ case '--to':
65
+ targetVersion = valueOf(index++, arg);
66
+ break;
67
+ case '--db-name':
68
+ dbName = valueOf(index++, arg);
69
+ break;
70
+ case '--plan':
71
+ planOnly = true;
72
+ break;
73
+ default:
74
+ throw new MigrateCommandUsageError(`Unknown argument "${arg}".`);
75
+ }
76
+ }
77
+ if (!storagePath)
78
+ throw new MigrateCommandUsageError('--storage-path is required.');
79
+ if (!plugins.path.isAbsolute(storagePath)) {
80
+ throw new MigrateCommandUsageError(`--storage-path must be an absolute path, not "${storagePath}".`);
81
+ }
82
+ if (!targetVersion)
83
+ throw new MigrateCommandUsageError('--to is required.');
84
+ return { storagePath: plugins.path.resolve(storagePath), targetVersion, dbName, planOnly };
85
+ }
86
+ /**
87
+ * Runs the downgrade offline: a stopped-root check first, then the engine, whose owner lock refuses
88
+ * a root a running dcrouter holds, then the reverse migration. Both handles are released before it
89
+ * returns, whatever happened.
90
+ */
91
+ export async function runMigrateCommandOptions(optionsArg) {
92
+ // Refuses a root an engine holds (the sidecar takes the shared owner lock), a root that is not a
93
+ // current SmartDB root, and any file that does not validate, before the engine is started.
94
+ const inspection = await plugins.smartdb.LocalSmartDb.inspectOfflinePhysicalNamespaces({ folderPath: optionsArg.storagePath, limits: offlineInspectionLimits }, { timeoutMs: offlineInspectionTimeoutMs });
95
+ const databaseNames = inspection.databases.map((databaseArg) => databaseArg.name);
96
+ if (!databaseNames.includes(optionsArg.dbName)) {
97
+ throw new DcRouterMigrationError(`The storage root holds no database "${optionsArg.dbName}" (it holds ${databaseNames.length > 0
98
+ ? databaseNames.map((nameArg) => `"${nameArg}"`).join(', ')
99
+ : 'none'}). Nothing was changed.`);
100
+ }
101
+ const localSmartDb = new plugins.smartdb.LocalSmartDb({ folderPath: optionsArg.storagePath });
102
+ let db;
103
+ let failure;
104
+ try {
105
+ const { connectionUri } = await localSmartDb.start();
106
+ db = new plugins.smartdata.SmartdataDb({ mongoDbUrl: connectionUri, mongoDbName: optionsArg.dbName });
107
+ await db.init();
108
+ const runner = await createDowngradeMigrationRunner(db, optionsArg.targetVersion);
109
+ const result = optionsArg.planOnly ? await runner.plan() : await runner.run();
110
+ return {
111
+ ok: true,
112
+ plan: optionsArg.planOnly,
113
+ storagePath: optionsArg.storagePath,
114
+ dbName: optionsArg.dbName,
115
+ currentVersionBefore: result.currentVersionBefore,
116
+ currentVersionAfter: result.currentVersionAfter,
117
+ targetVersion: result.targetVersion,
118
+ wasUpToDate: result.wasUpToDate,
119
+ wasFreshInstall: result.wasFreshInstall,
120
+ totalDurationMs: result.totalDurationMs,
121
+ stepsApplied: result.stepsApplied.map(({ id, fromVersion, toVersion, status }) => ({ id, fromVersion, toVersion, status })),
122
+ stepsSkipped: result.stepsSkipped.map(({ id, fromVersion, toVersion, status }) => ({ id, fromVersion, toVersion, status })),
123
+ };
124
+ }
125
+ catch (error) {
126
+ failure = { error };
127
+ throw error;
128
+ }
129
+ finally {
130
+ // Both handles are released whatever happened. A cleanup failure after a failed migration is
131
+ // reported beside it, and the migration's own error stays the one the command answers with.
132
+ const cleanupErrors = [];
133
+ for (const release of [() => db?.close(), () => localSmartDb.stop()]) {
134
+ try {
135
+ await release();
136
+ }
137
+ catch (cleanupError) {
138
+ cleanupErrors.push(cleanupError);
139
+ }
140
+ }
141
+ if (cleanupErrors.length > 0 && !failure) {
142
+ throw new AggregateError(cleanupErrors, 'dcrouter migrate could not release the database');
143
+ }
144
+ for (const cleanupError of failure ? cleanupErrors : []) {
145
+ console.error(`dcrouter migrate: releasing the database also failed: ${describeMigrateError(cleanupError).message}`);
146
+ }
147
+ }
148
+ }
149
+ const describeMigrateError = (errorArg) => {
150
+ if (!(errorArg instanceof Error))
151
+ return { name: 'Error', message: String(errorArg) };
152
+ const code = errorArg.code;
153
+ return {
154
+ name: errorArg.name,
155
+ ...(typeof code === 'string' ? { code } : {}),
156
+ message: errorArg.message,
157
+ };
158
+ };
159
+ /** `dcrouter migrate …`; resolves to the process exit code and prints the result line last. */
160
+ export async function runMigrateCommand(argsArg) {
161
+ if (argsArg.includes('--help') || argsArg.includes('-h')) {
162
+ console.log(migrateCommandUsage);
163
+ return 0;
164
+ }
165
+ let result;
166
+ let exitCode;
167
+ try {
168
+ result = await runMigrateCommandOptions(parseMigrateArguments(argsArg));
169
+ exitCode = 0;
170
+ }
171
+ catch (error) {
172
+ result = { ok: false, error: describeMigrateError(error) };
173
+ exitCode = error instanceof MigrateCommandUsageError ? 2 : 1;
174
+ console.error(`dcrouter migrate: ${result.error.message}`);
175
+ if (error instanceof MigrateCommandUsageError)
176
+ console.error(migrateCommandUsage);
177
+ }
178
+ console.log(`${migrateResultLinePrefix}${JSON.stringify(result)}`);
179
+ return exitCode;
180
+ }
181
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0ZS1jb21tYW5kLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvbWlncmF0ZS1jb21tYW5kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBR25HLG9GQUFvRjtBQUNwRixNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRywwQkFBMEIsQ0FBQztBQUVsRSxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRzs7Ozs7Ozs7Ozs7O2lDQVlGLHVCQUF1QjtDQUN2RCxDQUFDO0FBRUYsMEVBQTBFO0FBQzFFLE1BQU0sT0FBTyx3QkFBeUIsU0FBUSxLQUFLO0lBQ2pELFlBQVksVUFBa0I7UUFDNUIsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2xCLElBQUksQ0FBQyxJQUFJLEdBQUcsMEJBQTBCLENBQUM7SUFDekMsQ0FBQztDQUNGO0FBYUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBMEU7SUFDNUcsY0FBYyxFQUFFLE9BQU87SUFDdkIsZ0JBQWdCLEVBQUUsS0FBSztJQUN2QixrQkFBa0IsRUFBRSxNQUFNO0lBQzFCLGNBQWMsRUFBRSxPQUFPO0lBQ3ZCLG9CQUFvQixFQUFFLFdBQVc7SUFDakMsbUJBQW1CLEVBQUUsVUFBVTtJQUMvQixxQkFBcUIsRUFBRSxVQUFVO0lBQ2pDLHFCQUFxQixFQUFFLGlCQUFpQjtJQUN4QywyQkFBMkIsRUFBRSxTQUFTO0lBQ3RDLGtCQUFrQixFQUFFLFVBQVU7SUFDOUIsa0JBQWtCLEVBQUUsVUFBVTtDQUMvQixDQUFDO0FBQ0YsTUFBTSwwQkFBMEIsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFDO0FBRS9DLE1BQU0sVUFBVSxxQkFBcUIsQ0FBQyxPQUFpQjtJQUNyRCxJQUFJLFdBQStCLENBQUM7SUFDcEMsSUFBSSxhQUFpQyxDQUFDO0lBQ3RDLElBQUksTUFBTSxHQUFHLFVBQVUsQ0FBQztJQUN4QixJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDckIsTUFBTSxPQUFPLEdBQUcsQ0FBQyxRQUFnQixFQUFFLE9BQWUsRUFBRSxFQUFFO1FBQ3BELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDcEMsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNsRCxNQUFNLElBQUksd0JBQXdCLENBQUMsR0FBRyxPQUFPLGlCQUFpQixDQUFDLENBQUM7UUFDbEUsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQyxDQUFDO0lBQ0YsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUNwRCxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDM0IsUUFBUSxHQUFHLEVBQUUsQ0FBQztZQUNaLEtBQUssZ0JBQWdCO2dCQUNuQixXQUFXLEdBQUcsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUNwQyxNQUFNO1lBQ1IsS0FBSyxNQUFNO2dCQUNULGFBQWEsR0FBRyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUM7Z0JBQ3RDLE1BQU07WUFDUixLQUFLLFdBQVc7Z0JBQ2QsTUFBTSxHQUFHLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDL0IsTUFBTTtZQUNSLEtBQUssUUFBUTtnQkFDWCxRQUFRLEdBQUcsSUFBSSxDQUFDO2dCQUNoQixNQUFNO1lBQ1I7Z0JBQ0UsTUFBTSxJQUFJLHdCQUF3QixDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQyxDQUFDO1FBQ3JFLENBQUM7SUFDSCxDQUFDO0lBQ0QsSUFBSSxDQUFDLFdBQVc7UUFBRSxNQUFNLElBQUksd0JBQXdCLENBQUMsNkJBQTZCLENBQUMsQ0FBQztJQUNwRixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztRQUMxQyxNQUFNLElBQUksd0JBQXdCLENBQUMsaURBQWlELFdBQVcsSUFBSSxDQUFDLENBQUM7SUFDdkcsQ0FBQztJQUNELElBQUksQ0FBQyxhQUFhO1FBQUUsTUFBTSxJQUFJLHdCQUF3QixDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDNUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDO0FBQzdGLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSx3QkFBd0IsQ0FBQyxVQUFrQztJQUMvRSxpR0FBaUc7SUFDakcsMkZBQTJGO0lBQzNGLE1BQU0sVUFBVSxHQUFHLE1BQU0sT0FBTyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsZ0NBQWdDLENBQ3BGLEVBQUUsVUFBVSxFQUFFLFVBQVUsQ0FBQyxXQUFXLEVBQUUsTUFBTSxFQUFFLHVCQUF1QixFQUFFLEVBQ3ZFLEVBQUUsU0FBUyxFQUFFLDBCQUEwQixFQUFFLENBQzFDLENBQUM7SUFDRixNQUFNLGFBQWEsR0FBRyxVQUFVLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2xGLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQy9DLE1BQU0sSUFBSSxzQkFBc0IsQ0FDOUIsdUNBQXVDLFVBQVUsQ0FBQyxNQUFNLGVBQWUsYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDO1lBQzdGLENBQUMsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUMzRCxDQUFDLENBQUMsTUFBTSx5QkFBeUIsQ0FDcEMsQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLFlBQVksR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsVUFBVSxFQUFFLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQzlGLElBQUksRUFBNkMsQ0FBQztJQUNsRCxJQUFJLE9BQXVDLENBQUM7SUFDNUMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxFQUFFLGFBQWEsRUFBRSxHQUFHLE1BQU0sWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3JELEVBQUUsR0FBRyxJQUFJLE9BQU8sQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdEcsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDaEIsTUFBTSxNQUFNLEdBQUcsTUFBTSw4QkFBOEIsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ2xGLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUM5RSxPQUFPO1lBQ0wsRUFBRSxFQUFFLElBQUk7WUFDUixJQUFJLEVBQUUsVUFBVSxDQUFDLFFBQVE7WUFDekIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxXQUFXO1lBQ25DLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTTtZQUN6QixvQkFBb0IsRUFBRSxNQUFNLENBQUMsb0JBQW9CO1lBQ2pELG1CQUFtQixFQUFFLE1BQU0sQ0FBQyxtQkFBbUI7WUFDL0MsYUFBYSxFQUFFLE1BQU0sQ0FBQyxhQUFhO1lBQ25DLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVztZQUMvQixlQUFlLEVBQUUsTUFBTSxDQUFDLGVBQWU7WUFDdkMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxlQUFlO1lBQ3ZDLFlBQVksRUFBRSxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQzNILFlBQVksRUFBRSxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1NBQzVILENBQUM7SUFDSixDQUFDO0lBQUMsT0FBTyxLQUFjLEVBQUUsQ0FBQztRQUN4QixPQUFPLEdBQUcsRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUNwQixNQUFNLEtBQUssQ0FBQztJQUNkLENBQUM7WUFBUyxDQUFDO1FBQ1QsNkZBQTZGO1FBQzdGLDRGQUE0RjtRQUM1RixNQUFNLGFBQWEsR0FBYyxFQUFFLENBQUM7UUFDcEMsS0FBSyxNQUFNLE9BQU8sSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ3JFLElBQUksQ0FBQztnQkFDSCxNQUFNLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLENBQUM7WUFBQyxPQUFPLFlBQXFCLEVBQUUsQ0FBQztnQkFDL0IsYUFBYSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNuQyxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN6QyxNQUFNLElBQUksY0FBYyxDQUFDLGFBQWEsRUFBRSxpREFBaUQsQ0FBQyxDQUFDO1FBQzdGLENBQUM7UUFDRCxLQUFLLE1BQU0sWUFBWSxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUN4RCxPQUFPLENBQUMsS0FBSyxDQUFDLHlEQUF5RCxvQkFBb0IsQ0FBQyxZQUFZLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZILENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVELE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxRQUFpQixFQUFvRCxFQUFFO0lBQ25HLElBQUksQ0FBQyxDQUFDLFFBQVEsWUFBWSxLQUFLLENBQUM7UUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7SUFDdEYsTUFBTSxJQUFJLEdBQUksUUFBdUMsQ0FBQyxJQUFJLENBQUM7SUFDM0QsT0FBTztRQUNMLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSTtRQUNuQixHQUFHLENBQUMsT0FBTyxJQUFJLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDN0MsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPO0tBQzFCLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRiwrRkFBK0Y7QUFDL0YsTUFBTSxDQUFDLEtBQUssVUFBVSxpQkFBaUIsQ0FBQyxPQUFpQjtJQUN2RCxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ3pELE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNqQyxPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7SUFDRCxJQUFJLE1BQTZCLENBQUM7SUFDbEMsSUFBSSxRQUFnQixDQUFDO0lBQ3JCLElBQUksQ0FBQztRQUNILE1BQU0sR0FBRyxNQUFNLHdCQUF3QixDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDeEUsUUFBUSxHQUFHLENBQUMsQ0FBQztJQUNmLENBQUM7SUFBQyxPQUFPLEtBQWMsRUFBRSxDQUFDO1FBQ3hCLE1BQU0sR0FBRyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDM0QsUUFBUSxHQUFHLEtBQUssWUFBWSx3QkFBd0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0QsT0FBTyxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzNELElBQUksS0FBSyxZQUFZLHdCQUF3QjtZQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUNwRixDQUFDO0lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLHVCQUF1QixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25FLE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMifQ==
@@ -55,8 +55,9 @@ export { cloudflare, };
55
55
  import * as tsclass from '@tsclass/tsclass';
56
56
  export { tsclass, };
57
57
  import * as argon2 from 'argon2';
58
+ import * as bson from 'bson';
58
59
  import * as lruCache from 'lru-cache';
59
60
  import ipaddr from 'ipaddr.js';
60
61
  import * as uuid from 'uuid';
61
62
  import webpush from 'web-push';
62
- export { argon2, lruCache, ipaddr, uuid, webpush, };
63
+ export { argon2, bson, lruCache, ipaddr, uuid, webpush, };
@@ -66,9 +66,10 @@ import * as tsclass from '@tsclass/tsclass';
66
66
  export { tsclass, };
67
67
  // third party
68
68
  import * as argon2 from 'argon2';
69
+ import * as bson from 'bson';
69
70
  import * as lruCache from 'lru-cache';
70
71
  import ipaddr from 'ipaddr.js';
71
72
  import * as uuid from 'uuid';
72
73
  import webpush from 'web-push';
73
- export { argon2, lruCache, ipaddr, uuid, webpush, };
74
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYztBQUNkLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxLQUFLLE1BQU0sWUFBWSxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxjQUFjLE1BQU0sc0JBQXNCLENBQUM7QUFFdkQsT0FBTyxFQUNMLEdBQUcsRUFDSCxFQUFFLEVBQ0YsTUFBTSxFQUNOLElBQUksRUFDSixLQUFLLEVBQ0wsR0FBRyxFQUNILE1BQU0sRUFDTixFQUFFLEVBQ0YsSUFBSSxFQUNKLEdBQUcsRUFDSCxJQUFJLEVBQ0osR0FBRyxFQUNILGNBQWMsR0FDZixDQUFBO0FBRUQsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxtQkFBbUIsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEtBQUssYUFBYSxNQUFNLDJCQUEyQixDQUFDO0FBRTNELE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsYUFBYSxHQUNkLENBQUE7QUFFRCxvQkFBb0I7QUFDcEIsT0FBTyxLQUFLLFlB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
74
+ export { argon2, bson, lruCache, ipaddr, uuid, webpush, };
75
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYztBQUNkLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxLQUFLLE1BQU0sWUFBWSxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxjQUFjLE1BQU0sc0JBQXNCLENBQUM7QUFFdkQsT0FBTyxFQUNMLEdBQUcsRUFDSCxFQUFFLEVBQ0YsTUFBTSxFQUNOLElBQUksRUFDSixLQUFLLEVBQ0wsR0FBRyxFQUNILE1BQU0sRUFDTixFQUFFLEVBQ0YsSUFBSSxFQUNKLEdBQUcsRUFDSCxJQUFJLEVBQ0osR0FBRyxFQUNILGNBQWMsR0FDZixDQUFBO0FBRUQsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxtQkFBbUIsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEtBQUssYUFBYSxNQUFNLDJCQUEyQixDQUFDO0FBRTNELE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsYUFBYSxHQUNkLENBQUE7QUFFRCxvQkFBb0I7QUFDcEIsT0FBTyxLQUFLLFlB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
@@ -13,10 +13,15 @@
13
13
  * The fix is not to make the declared list editable. A list an operator can
14
14
  * simply append to is self-assertion, which is precisely the failure mode that
15
15
  * let routes claim domains nobody verified we own. Instead a zone earns
16
- * authority by *proof*: its public delegation must name our nameservers. That
17
- * proof is unforgeable by an ops-API caller — you cannot point `example.com`'s
18
- * NS records at our nameservers unless you actually control the domain — and it
19
- * is the missing comparison between the two representations.
16
+ * authority by *proof*: its delegation in the parent zone must name our
17
+ * nameservers. That proof is unforgeable by an ops-API caller — you cannot point
18
+ * `example.com`'s delegation at our nameservers unless you actually control the
19
+ * domain — and it is the missing comparison between the two representations.
20
+ *
21
+ * The proof is read from the parent zone's own servers, asked without
22
+ * recursion, never from a recursive resolver: a recursive lookup of a zone
23
+ * delegated to us but not claimed yet reaches our servers, which REFUSE it, so
24
+ * it could never prove the delegation it is supposed to prove.
20
25
  *
21
26
  * `dnsScopes` is gone entirely. There is exactly one representation of DNS
22
27
  * authority now, it lives in the database, and it is the one that carries its
@@ -37,7 +42,10 @@ export interface IDnsAuthorityZone {
37
42
  origin: TDnsAuthorityZoneOrigin;
38
43
  /** When the delegation proof was observed. */
39
44
  verifiedAt?: number;
40
- /** Nameservers observed at verification time — the evidence for the proof. */
45
+ /**
46
+ * The NS set the parent zone's servers delegated the zone to at verification
47
+ * time — the evidence for the proof.
48
+ */
41
49
  observedNameservers?: string[];
42
50
  /** Operator who performed the verification. */
43
51
  verifiedBy?: string;
@@ -62,20 +70,69 @@ export interface IDnsAuthoritySettings {
62
70
  updatedBy: string;
63
71
  }
64
72
  /**
65
- * Outcome of a delegation probe.
73
+ * Outcome of a delegation probe, decided by the parent zone's servers alone.
74
+ *
75
+ * - 'delegated': at least two of the parent's servers, reached through at least
76
+ * two different parent nameserver names, gave the identical referral for the
77
+ * zone, and its NS set names at least one of our nameservers. A referral that
78
+ * carries a DS sets `dsPresent`, and such a zone cannot be claimed.
79
+ * - 'not-delegated': the same agreement on a referral that names none of our
80
+ * nameservers, or on an authoritative "no such delegation" (NXDOMAIN or NODATA
81
+ * with the parent's SOA). Also the verdict for an unusable zone name.
82
+ * - 'undeterminable': anything less — a failed lookup, fewer than two
83
+ * conclusive answers, or any disagreement between them.
66
84
  *
67
85
  * 'undeterminable' is deliberately distinct from 'not-delegated': a resolver
68
86
  * timeout is not evidence that a zone is not ours. Conflating them would let a
69
87
  * transient network fault revoke authority, turning a blip into an outage.
70
88
  */
71
89
  export type TDnsDelegationVerdict = 'delegated' | 'not-delegated' | 'undeterminable';
90
+ /**
91
+ * How the probe classified one parent server's answer to the non-recursive
92
+ * NS query for the zone.
93
+ *
94
+ * - 'referral': RCODE 0, AA=0, an empty answer section, and an authority
95
+ * section whose NS records are all owned by the zone, with an OPT record that
96
+ * echoes DO=1 (otherwise a missing DS would prove nothing).
97
+ * - 'negative': AA=1 NXDOMAIN or NODATA with an empty answer section and the
98
+ * parent zone's SOA in the authority section.
99
+ * - 'inconclusive': everything else, including timeouts, REFUSED, any other
100
+ * AA=1 answer (a server that hosts the parent and the child zone answers for
101
+ * the child instead of referring) and referrals to any other name.
102
+ */
103
+ export type TDnsDelegationParentOutcome = 'referral' | 'negative' | 'inconclusive';
104
+ /** One parent server's answer to the non-recursive NS query for the zone. */
105
+ export interface IDnsDelegationParentAnswer {
106
+ /** The parent server the probe asked, as `ip:port` (`[ip]:port` for IPv6). */
107
+ server: string;
108
+ /** The parent nameserver name this address belongs to. */
109
+ nameserver: string;
110
+ outcome: TDnsDelegationParentOutcome;
111
+ /** The referral's NS set, lowercased, trailing-dot stripped and sorted (referral only). */
112
+ nameservers?: string[];
113
+ /** Whether the referral carried a DS RRset for the zone (referral only). */
114
+ dsPresent?: boolean;
115
+ detail: string;
116
+ }
72
117
  export interface IDnsDelegationProbe {
73
118
  zone: string;
74
119
  verdict: TDnsDelegationVerdict;
75
- /** NS records observed for the zone, lowercased and trailing-dot stripped. */
120
+ /**
121
+ * The NS set the parent zone's servers delegate the zone to, lowercased and
122
+ * trailing-dot stripped; empty when there is no agreed referral.
123
+ */
76
124
  observedNameservers: string[];
77
125
  expectedNameservers: string[];
78
126
  detail: string;
127
+ /** The parent zone whose servers were asked; absent when it was not found. */
128
+ parentZone?: string;
129
+ /**
130
+ * Whether the agreed referral carried a DS for the zone. Set on a verdict
131
+ * that rests on a referral; a `delegated` zone with a DS cannot be claimed.
132
+ */
133
+ dsPresent?: boolean;
134
+ /** Every parent server's classified answer, when parent servers were asked. */
135
+ parentAnswers?: IDnsDelegationParentAnswer[];
79
136
  }
80
137
  /** A disagreement between claimed authority and what is actually true. */
81
138
  export type TDnsAuthorityDriftKind =
@@ -13,14 +13,19 @@
13
13
  * The fix is not to make the declared list editable. A list an operator can
14
14
  * simply append to is self-assertion, which is precisely the failure mode that
15
15
  * let routes claim domains nobody verified we own. Instead a zone earns
16
- * authority by *proof*: its public delegation must name our nameservers. That
17
- * proof is unforgeable by an ops-API caller — you cannot point `example.com`'s
18
- * NS records at our nameservers unless you actually control the domain — and it
19
- * is the missing comparison between the two representations.
16
+ * authority by *proof*: its delegation in the parent zone must name our
17
+ * nameservers. That proof is unforgeable by an ops-API caller — you cannot point
18
+ * `example.com`'s delegation at our nameservers unless you actually control the
19
+ * domain — and it is the missing comparison between the two representations.
20
+ *
21
+ * The proof is read from the parent zone's own servers, asked without
22
+ * recursion, never from a recursive resolver: a recursive lookup of a zone
23
+ * delegated to us but not claimed yet reaches our servers, which REFUSE it, so
24
+ * it could never prove the delegation it is supposed to prove.
20
25
  *
21
26
  * `dnsScopes` is gone entirely. There is exactly one representation of DNS
22
27
  * authority now, it lives in the database, and it is the one that carries its
23
28
  * own evidence.
24
29
  */
25
30
  export {};
26
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG5zLWF1dGhvcml0eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX2ludGVyZmFjZXMvZGF0YS9kbnMtYXV0aG9yaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXVCRyJ9
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG5zLWF1dGhvcml0eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX2ludGVyZmFjZXMvZGF0YS9kbnMtYXV0aG9yaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNEJHIn0=
@@ -12,8 +12,9 @@ export interface IReq_GetDnsAuthority extends plugins.typedrequestInterfaces.imp
12
12
  };
13
13
  }
14
14
  /**
15
- * Probe a zone's public delegation without changing anything. Lets an operator
16
- * see the evidence before claiming authority.
15
+ * Probe a zone's delegation in its parent zone without changing anything. Lets
16
+ * an operator see the evidence (the parent zone and each parent server's
17
+ * answer) before claiming authority.
17
18
  */
18
19
  export interface IReq_ProbeDnsAuthorityZone extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_ProbeDnsAuthorityZone> {
19
20
  method: 'probeDnsAuthorityZone';
@@ -27,9 +28,10 @@ export interface IReq_ProbeDnsAuthorityZone extends plugins.typedrequestInterfac
27
28
  };
28
29
  }
29
30
  /**
30
- * Claim authority over a zone. Succeeds only when the zone's public delegation
31
- * names our nameservers; the claim is then persisted and reconciled in-process,
32
- * with no restart.
31
+ * Claim authority over a zone. Succeeds only on a `delegated` probe without a
32
+ * DS: the parent zone's servers agree that the zone is delegated to our
33
+ * nameservers and publish no DS for it. The claim is then persisted and
34
+ * reconciled in-process, with no restart.
33
35
  */
34
36
  export interface IReq_VerifyDnsAuthorityZone extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_VerifyDnsAuthorityZone> {
35
37
  method: 'verifyDnsAuthorityZone';
@@ -28,6 +28,29 @@ export interface IMigrationRunner {
28
28
  getCurrentVersion(): Promise<string | null>;
29
29
  run(): Promise<IMigrationRunResult>;
30
30
  }
31
+ /** The result of a downgrade run or plan, as `dcrouter migrate` reports it. */
32
+ export interface IDowngradeMigrationRunResult extends IMigrationRunResult {
33
+ targetVersion: string;
34
+ wasUpToDate: boolean;
35
+ stepsApplied: Array<{
36
+ id: string;
37
+ fromVersion: string;
38
+ toVersion: string;
39
+ status: string;
40
+ }>;
41
+ /** The steps a plan would run; empty after a run. */
42
+ stepsSkipped: Array<{
43
+ id: string;
44
+ fromVersion: string;
45
+ toVersion: string;
46
+ status: string;
47
+ }>;
48
+ }
49
+ export interface IDowngradeMigrationRunner extends IMigrationRunner {
50
+ run(): Promise<IDowngradeMigrationRunResult>;
51
+ /** The reverse plan, without the lock and without writing anything. */
52
+ plan(): Promise<IDowngradeMigrationRunResult>;
53
+ }
31
54
  export declare const dcRouterSchemaVersion = "34.0.0";
32
55
  export declare function createApplicationMigrationRunner(db: unknown, options?: IDcRouterMigrationOptions): Promise<IMigrationRunner>;
33
56
  export interface IDcRouterMigrationOptions {
@@ -60,3 +83,17 @@ export interface IDcRouterMigrationOptions {
60
83
  * @param targetVersion - The explicit schema or historical migration test target
61
84
  */
62
85
  export declare function createMigrationRunner(db: unknown, targetVersion: string, options?: IDcRouterMigrationOptions): Promise<IMigrationRunner>;
86
+ /**
87
+ * Create the runner `dcrouter migrate` walks the ledger back with.
88
+ *
89
+ * It registers the whole chain through `dcRouterSchemaVersion`, so smartmigration plans the
90
+ * reverse run itself: it refuses a target that is not a step boundary (`TARGET_NOT_REACHABLE`) and
91
+ * a path across a step without `.down()` (`DOWNGRADE_STEP_IRREVERSIBLE`) before any handler runs.
92
+ * `run()` and `plan()` refuse by name, before that, a database without a ledger, a ledger a newer
93
+ * dcrouter wrote and a target ahead of the ledger: a forward migration is what starting dcrouter
94
+ * does. A target equal to the ledger is the no-op a repeated downgrade is.
95
+ *
96
+ * @param db - An initialized SmartdataDb on a storage root no dcrouter is running on
97
+ * @param targetVersion - The data version to walk the ledger back to
98
+ */
99
+ export declare function createDowngradeMigrationRunner(db: unknown, targetVersion: string, options?: IDcRouterMigrationOptions): Promise<IDowngradeMigrationRunner>;