@did-btcr2/cli 0.5.1 → 0.6.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/README.md +137 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/cjs/index.js +464 -7
- package/dist/esm/src/cli.js +22 -11
- package/dist/esm/src/cli.js.map +1 -1
- package/dist/esm/src/commands/create.js +2 -1
- package/dist/esm/src/commands/create.js.map +1 -1
- package/dist/esm/src/commands/deactivate.js +8 -1
- package/dist/esm/src/commands/deactivate.js.map +1 -1
- package/dist/esm/src/commands/resolve.js +4 -1
- package/dist/esm/src/commands/resolve.js.map +1 -1
- package/dist/esm/src/commands/update.js +8 -1
- package/dist/esm/src/commands/update.js.map +1 -1
- package/dist/esm/src/config.js +142 -0
- package/dist/esm/src/config.js.map +1 -0
- package/dist/esm/src/index.js +1 -0
- package/dist/esm/src/index.js.map +1 -1
- package/dist/types/src/cli.d.ts +10 -5
- package/dist/types/src/cli.d.ts.map +1 -1
- package/dist/types/src/commands/create.d.ts +4 -4
- package/dist/types/src/commands/create.d.ts.map +1 -1
- package/dist/types/src/commands/deactivate.d.ts +4 -4
- package/dist/types/src/commands/deactivate.d.ts.map +1 -1
- package/dist/types/src/commands/resolve.d.ts +4 -4
- package/dist/types/src/commands/resolve.d.ts.map +1 -1
- package/dist/types/src/commands/update.d.ts +4 -4
- package/dist/types/src/commands/update.d.ts.map +1 -1
- package/dist/types/src/config.d.ts +131 -0
- package/dist/types/src/config.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/output.d.ts +1 -1
- package/dist/types/src/output.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +7 -0
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/cli.ts +23 -12
- package/src/commands/create.ts +7 -5
- package/src/commands/deactivate.ts +14 -4
- package/src/commands/resolve.ts +6 -4
- package/src/commands/update.ts +14 -4
- package/src/config.ts +226 -0
- package/src/index.ts +1 -0
- package/src/output.ts +1 -1
- package/src/types.ts +10 -3
- package/dist/cjs/cli.js +0 -77
- package/dist/cjs/cli.js.map +0 -1
- package/dist/cjs/commands/create.js +0 -48
- package/dist/cjs/commands/create.js.map +0 -1
- package/dist/cjs/commands/deactivate.js +0 -41
- package/dist/cjs/commands/deactivate.js.map +0 -1
- package/dist/cjs/commands/index.js +0 -5
- package/dist/cjs/commands/index.js.map +0 -1
- package/dist/cjs/commands/resolve.js +0 -43
- package/dist/cjs/commands/resolve.js.map +0 -1
- package/dist/cjs/commands/update.js +0 -39
- package/dist/cjs/commands/update.js.map +0 -1
- package/dist/cjs/error.js +0 -10
- package/dist/cjs/error.js.map +0 -1
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/output.js +0 -16
- package/dist/cjs/output.js.map +0 -1
- package/dist/cjs/types.js +0 -4
- package/dist/cjs/types.js.map +0 -1
- package/dist/cjs/version.js +0 -22
- package/dist/cjs/version.js.map +0 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { deriveNetwork, type ApiFactory } from '../config.js';
|
|
3
3
|
import { CLIError } from '../error.js';
|
|
4
4
|
import { formatResult } from '../output.js';
|
|
5
|
-
import { GlobalOptions, UpdateCommandOptions } from '../types.js';
|
|
5
|
+
import type { GlobalOptions, UpdateCommandOptions } from '../types.js';
|
|
6
6
|
|
|
7
7
|
/** The JSON Patch that marks a DID document as permanently deactivated. */
|
|
8
8
|
const DEACTIVATION_PATCH = [{ op: 'add' as const, path: '/deactivated', value: true }];
|
|
9
9
|
|
|
10
10
|
export function registerDeactivateCommand(
|
|
11
11
|
program : Command,
|
|
12
|
-
|
|
12
|
+
factory : ApiFactory,
|
|
13
13
|
globals : () => GlobalOptions,
|
|
14
14
|
): void {
|
|
15
15
|
program
|
|
@@ -47,6 +47,16 @@ export function registerDeactivateCommand(
|
|
|
47
47
|
verificationMethodId : options.verificationMethodId,
|
|
48
48
|
beaconId : options.beaconId as UpdateCommandOptions['beaconId'],
|
|
49
49
|
};
|
|
50
|
+
const did = parsed.sourceDocument?.id;
|
|
51
|
+
if (!did) {
|
|
52
|
+
throw new CLIError(
|
|
53
|
+
'Source document must contain an "id" field.',
|
|
54
|
+
'INVALID_ARGUMENT_ERROR',
|
|
55
|
+
options
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
const network = deriveNetwork(did);
|
|
59
|
+
const api = factory(network, globals());
|
|
50
60
|
const data = await api.btcr2.update(parsed);
|
|
51
61
|
const result = { action: 'deactivate' as const, data };
|
|
52
62
|
console.log(formatResult(result, globals()));
|
package/src/commands/resolve.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type { DidBtcr2Api } from '@did-btcr2/api';
|
|
2
1
|
import { Identifier } from '@did-btcr2/api';
|
|
3
|
-
import { Command } from 'commander';
|
|
2
|
+
import type { Command } from 'commander';
|
|
4
3
|
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { deriveNetwork, type ApiFactory } from '../config.js';
|
|
5
5
|
import { CLIError } from '../error.js';
|
|
6
6
|
import { formatResult } from '../output.js';
|
|
7
|
-
import { GlobalOptions, ResolveCommandOptions } from '../types.js';
|
|
7
|
+
import type { GlobalOptions, ResolveCommandOptions } from '../types.js';
|
|
8
8
|
|
|
9
9
|
export function registerResolveCommand(
|
|
10
10
|
program : Command,
|
|
11
|
-
|
|
11
|
+
factory : ApiFactory,
|
|
12
12
|
globals : () => GlobalOptions,
|
|
13
13
|
): void {
|
|
14
14
|
program
|
|
@@ -24,6 +24,8 @@ export function registerResolveCommand(
|
|
|
24
24
|
resolutionOptionsPath?: string;
|
|
25
25
|
}) => {
|
|
26
26
|
const parsed = await validateResolveOptions(options);
|
|
27
|
+
const network = deriveNetwork(parsed.identifier);
|
|
28
|
+
const api = factory(network, globals());
|
|
27
29
|
const data = await api.resolveDid(parsed.identifier, parsed.options);
|
|
28
30
|
const result = { action: 'resolve' as const, data };
|
|
29
31
|
console.log(formatResult(result, globals()));
|
package/src/commands/update.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { deriveNetwork, type ApiFactory } from '../config.js';
|
|
3
3
|
import { CLIError } from '../error.js';
|
|
4
4
|
import { formatResult } from '../output.js';
|
|
5
|
-
import { GlobalOptions, UpdateCommandOptions } from '../types.js';
|
|
5
|
+
import type { GlobalOptions, UpdateCommandOptions } from '../types.js';
|
|
6
6
|
|
|
7
7
|
export function registerUpdateCommand(
|
|
8
8
|
program : Command,
|
|
9
|
-
|
|
9
|
+
factory : ApiFactory,
|
|
10
10
|
globals : () => GlobalOptions,
|
|
11
11
|
): void {
|
|
12
12
|
program
|
|
@@ -49,6 +49,16 @@ export function registerUpdateCommand(
|
|
|
49
49
|
verificationMethodId : options.verificationMethodId,
|
|
50
50
|
beaconId : options.beaconId as UpdateCommandOptions['beaconId'],
|
|
51
51
|
};
|
|
52
|
+
const did = parsed.sourceDocument?.id;
|
|
53
|
+
if (!did) {
|
|
54
|
+
throw new CLIError(
|
|
55
|
+
'Source document must contain an "id" field.',
|
|
56
|
+
'INVALID_ARGUMENT_ERROR',
|
|
57
|
+
options
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
const network = deriveNetwork(did);
|
|
61
|
+
const api = factory(network, globals());
|
|
52
62
|
const data = await api.btcr2.update(parsed);
|
|
53
63
|
const result = { action: 'update' as const, data };
|
|
54
64
|
console.log(formatResult(result, globals()));
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { createApi, Identifier, type BitcoinApiConfig, type DidBtcr2Api } from '@did-btcr2/api';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { CLIError } from './error.js';
|
|
6
|
+
import { SUPPORTED_NETWORKS, type NetworkOption } from './types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Endpoint overrides provided via CLI flags, env vars, or config file.
|
|
10
|
+
* These override the per-network defaults from
|
|
11
|
+
* `DEFAULT_BITCOIN_NETWORK_CONFIG`.
|
|
12
|
+
*
|
|
13
|
+
* `config` and `profile` control config-file resolution and are only
|
|
14
|
+
* meaningful when passed through the full merge chain.
|
|
15
|
+
*/
|
|
16
|
+
export type ConnectionOverrides = {
|
|
17
|
+
btcRest? : string;
|
|
18
|
+
btcRpcUrl? : string;
|
|
19
|
+
btcRpcUser?: string;
|
|
20
|
+
btcRpcPass?: string;
|
|
21
|
+
casGateway?: string;
|
|
22
|
+
config? : string;
|
|
23
|
+
profile? : string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* On-disk config file schema.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```json
|
|
31
|
+
* {
|
|
32
|
+
* "profiles": {
|
|
33
|
+
* "regtest": {
|
|
34
|
+
* "btc": {
|
|
35
|
+
* "rest": "http://localhost:3000",
|
|
36
|
+
* "rpcUrl": "http://localhost:18443",
|
|
37
|
+
* "rpcUser": "polaruser",
|
|
38
|
+
* "rpcPass": "polarpass"
|
|
39
|
+
* }
|
|
40
|
+
* },
|
|
41
|
+
* "bitcoin": {
|
|
42
|
+
* "btc": { "rest": "https://my-mempool/api" },
|
|
43
|
+
* "cas": { "gateway": "https://ipfs.io" }
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export type ConfigFile = {
|
|
50
|
+
profiles?: Record<string, {
|
|
51
|
+
btc?: {
|
|
52
|
+
rest? : string;
|
|
53
|
+
rpcUrl? : string;
|
|
54
|
+
rpcUser? : string;
|
|
55
|
+
rpcPass? : string;
|
|
56
|
+
};
|
|
57
|
+
cas?: {
|
|
58
|
+
gateway?: string;
|
|
59
|
+
};
|
|
60
|
+
}>;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Factory function that creates a configured {@link DidBtcr2Api} instance.
|
|
65
|
+
*
|
|
66
|
+
* When `network` is provided, the returned API is wired to that network's
|
|
67
|
+
* default Bitcoin endpoints (mempool.space for public networks, localhost
|
|
68
|
+
* Polar for regtest). Optional `overrides` let callers replace individual
|
|
69
|
+
* endpoints on top of the defaults. When `network` is omitted, no Bitcoin
|
|
70
|
+
* or CAS is configured — suitable for offline operations like `create`.
|
|
71
|
+
*/
|
|
72
|
+
export type ApiFactory = (network?: NetworkOption, overrides?: ConnectionOverrides) => DidBtcr2Api;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Environment variable names consulted by {@link defaultApiFactory}.
|
|
76
|
+
*
|
|
77
|
+
* | Variable | Equivalent flag |
|
|
78
|
+
* |-----------------------|--------------------|
|
|
79
|
+
* | `BTCR2_BTC_REST` | `--btc-rest` |
|
|
80
|
+
* | `BTCR2_BTC_RPC_URL` | `--btc-rpc-url` |
|
|
81
|
+
* | `BTCR2_BTC_RPC_USER` | `--btc-rpc-user` |
|
|
82
|
+
* | `BTCR2_BTC_RPC_PASS` | `--btc-rpc-pass` |
|
|
83
|
+
* | `BTCR2_CAS_GATEWAY` | `--cas-gateway` |
|
|
84
|
+
*/
|
|
85
|
+
export const ENV_VARS = {
|
|
86
|
+
BTC_REST : 'BTCR2_BTC_REST',
|
|
87
|
+
BTC_RPC_URL : 'BTCR2_BTC_RPC_URL',
|
|
88
|
+
BTC_RPC_USER : 'BTCR2_BTC_RPC_USER',
|
|
89
|
+
BTC_RPC_PASS : 'BTCR2_BTC_RPC_PASS',
|
|
90
|
+
CAS_GATEWAY : 'BTCR2_CAS_GATEWAY',
|
|
91
|
+
} as const;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Reads {@link ConnectionOverrides} from environment variables.
|
|
95
|
+
* Only defined (non-empty) values are included.
|
|
96
|
+
*/
|
|
97
|
+
export function readEnvOverrides(): ConnectionOverrides {
|
|
98
|
+
const env = (key: string): string | undefined => process.env[key] || undefined;
|
|
99
|
+
return {
|
|
100
|
+
btcRest : env(ENV_VARS.BTC_REST),
|
|
101
|
+
btcRpcUrl : env(ENV_VARS.BTC_RPC_URL),
|
|
102
|
+
btcRpcUser : env(ENV_VARS.BTC_RPC_USER),
|
|
103
|
+
btcRpcPass : env(ENV_VARS.BTC_RPC_PASS),
|
|
104
|
+
casGateway : env(ENV_VARS.CAS_GATEWAY),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Default config file path following the XDG Base Directory Specification.
|
|
110
|
+
*
|
|
111
|
+
* Resolution order:
|
|
112
|
+
* 1. `$XDG_CONFIG_HOME/btcr2/config.json`
|
|
113
|
+
* 2. `%APPDATA%/btcr2/config.json` (Windows)
|
|
114
|
+
* 3. `~/.config/btcr2/config.json` (fallback)
|
|
115
|
+
*/
|
|
116
|
+
export function defaultConfigPath(): string {
|
|
117
|
+
const base = process.env.XDG_CONFIG_HOME
|
|
118
|
+
?? process.env.APPDATA
|
|
119
|
+
?? join(homedir(), '.config');
|
|
120
|
+
return join(base, 'btcr2', 'config.json');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Reads and parses a config file. Returns `undefined` if the file does
|
|
125
|
+
* not exist or cannot be parsed.
|
|
126
|
+
*/
|
|
127
|
+
export function readConfigFile(path: string): ConfigFile | undefined {
|
|
128
|
+
try {
|
|
129
|
+
const content = readFileSync(path, 'utf-8');
|
|
130
|
+
return JSON.parse(content) as ConfigFile;
|
|
131
|
+
} catch {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Extracts {@link ConnectionOverrides} from a named profile in a
|
|
138
|
+
* {@link ConfigFile}. Returns an empty object if the profile does not exist.
|
|
139
|
+
*/
|
|
140
|
+
export function profileToOverrides(
|
|
141
|
+
config : ConfigFile,
|
|
142
|
+
profileName : string,
|
|
143
|
+
): ConnectionOverrides {
|
|
144
|
+
const profile = config.profiles?.[profileName];
|
|
145
|
+
if (!profile) return {};
|
|
146
|
+
return {
|
|
147
|
+
btcRest : profile.btc?.rest,
|
|
148
|
+
btcRpcUrl : profile.btc?.rpcUrl,
|
|
149
|
+
btcRpcUser : profile.btc?.rpcUser,
|
|
150
|
+
btcRpcPass : profile.btc?.rpcPass,
|
|
151
|
+
casGateway : profile.cas?.gateway,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Default {@link ApiFactory} backed by network defaults from
|
|
157
|
+
* `@did-btcr2/bitcoin` (mempool.space for public networks, localhost for
|
|
158
|
+
* regtest).
|
|
159
|
+
*
|
|
160
|
+
* Override precedence (highest wins):
|
|
161
|
+
* CLI flags → env vars → config file profile → network defaults.
|
|
162
|
+
*
|
|
163
|
+
* When no `--profile` is given, the network name is used as the profile
|
|
164
|
+
* key (e.g. a regtest DID auto-selects the `"regtest"` profile).
|
|
165
|
+
*/
|
|
166
|
+
export function defaultApiFactory(network?: NetworkOption, overrides?: ConnectionOverrides): DidBtcr2Api {
|
|
167
|
+
if (!network) return createApi();
|
|
168
|
+
|
|
169
|
+
// Layer 1: Config file profile (lowest precedence of the three override layers)
|
|
170
|
+
const configPath = overrides?.config ?? defaultConfigPath();
|
|
171
|
+
const profileName = overrides?.profile ?? network;
|
|
172
|
+
const file = readConfigFile(configPath);
|
|
173
|
+
const fileOverrides = file ? profileToOverrides(file, profileName) : {};
|
|
174
|
+
|
|
175
|
+
// Layer 2: Environment variables
|
|
176
|
+
const env = readEnvOverrides();
|
|
177
|
+
|
|
178
|
+
// Merge: CLI flags → env vars → config file → (network defaults handled by BitcoinConnection)
|
|
179
|
+
const merged: ConnectionOverrides = {
|
|
180
|
+
btcRest : overrides?.btcRest ?? env.btcRest ?? fileOverrides.btcRest,
|
|
181
|
+
btcRpcUrl : overrides?.btcRpcUrl ?? env.btcRpcUrl ?? fileOverrides.btcRpcUrl,
|
|
182
|
+
btcRpcUser : overrides?.btcRpcUser ?? env.btcRpcUser ?? fileOverrides.btcRpcUser,
|
|
183
|
+
btcRpcPass : overrides?.btcRpcPass ?? env.btcRpcPass ?? fileOverrides.btcRpcPass,
|
|
184
|
+
casGateway : overrides?.casGateway ?? env.casGateway ?? fileOverrides.casGateway,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const btc: BitcoinApiConfig = { network };
|
|
188
|
+
|
|
189
|
+
if (merged.btcRest) {
|
|
190
|
+
btc.rest = { host: merged.btcRest };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (merged.btcRpcUrl) {
|
|
194
|
+
btc.rpc = {
|
|
195
|
+
host : merged.btcRpcUrl,
|
|
196
|
+
username : merged.btcRpcUser,
|
|
197
|
+
password : merged.btcRpcPass,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const cas = merged.casGateway ? { gateway: merged.casGateway } : undefined;
|
|
202
|
+
|
|
203
|
+
return createApi({ btc, ...(cas && { cas }) });
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Extracts and validates the Bitcoin network from a DID string.
|
|
208
|
+
*
|
|
209
|
+
* Decodes the DID via {@link Identifier.decode}, then checks that the
|
|
210
|
+
* embedded network is one of the supported values.
|
|
211
|
+
*
|
|
212
|
+
* @param did A `did:btcr2:...` identifier string.
|
|
213
|
+
* @returns The validated {@link NetworkOption}.
|
|
214
|
+
* @throws {CLIError} If the network is unsupported.
|
|
215
|
+
*/
|
|
216
|
+
export function deriveNetwork(did: string): NetworkOption {
|
|
217
|
+
const { network } = Identifier.decode(did);
|
|
218
|
+
if (!SUPPORTED_NETWORKS.includes(network as NetworkOption)) {
|
|
219
|
+
throw new CLIError(
|
|
220
|
+
`Unsupported network "${network}" in DID.`,
|
|
221
|
+
'INVALID_ARGUMENT_ERROR',
|
|
222
|
+
{ did, network }
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
return network as NetworkOption;
|
|
226
|
+
}
|
package/src/index.ts
CHANGED
package/src/output.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -36,7 +36,14 @@ export type CommandResult =
|
|
|
36
36
|
| { action: 'deactivate'; data: SignedBTCR2Update };
|
|
37
37
|
|
|
38
38
|
export interface GlobalOptions {
|
|
39
|
-
output
|
|
40
|
-
verbose
|
|
41
|
-
quiet
|
|
39
|
+
output : OutputFormat;
|
|
40
|
+
verbose : boolean;
|
|
41
|
+
quiet : boolean;
|
|
42
|
+
config? : string;
|
|
43
|
+
profile? : string;
|
|
44
|
+
btcRest? : string;
|
|
45
|
+
btcRpcUrl? : string;
|
|
46
|
+
btcRpcUser?: string;
|
|
47
|
+
btcRpcPass?: string;
|
|
48
|
+
casGateway?: string;
|
|
42
49
|
}
|
package/dist/cjs/cli.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { Command, CommanderError } from 'commander';
|
|
2
|
-
import { createApi } from '@did-btcr2/api';
|
|
3
|
-
import { registerCreateCommand, registerDeactivateCommand, registerResolveCommand, registerUpdateCommand, } from './commands/index.js';
|
|
4
|
-
import { CLIError } from './error.js';
|
|
5
|
-
import { VERSION } from './version.js';
|
|
6
|
-
/**
|
|
7
|
-
* CLI tool for the did:btcr2 method.
|
|
8
|
-
*/
|
|
9
|
-
export class DidBtcr2Cli {
|
|
10
|
-
program;
|
|
11
|
-
api;
|
|
12
|
-
/**
|
|
13
|
-
* Initializes the CLI with an optional pre-configured API instance.
|
|
14
|
-
* @param {DidBtcr2Api} api - Optional API instance. Defaults to an unconfigured instance.
|
|
15
|
-
*/
|
|
16
|
-
constructor(api = createApi()) {
|
|
17
|
-
this.api = api;
|
|
18
|
-
this.program = new Command('btcr2')
|
|
19
|
-
.version(`btcr2 ${VERSION}`, '-v, --version', 'Output the current version')
|
|
20
|
-
.description('CLI tool for the did:btcr2 method')
|
|
21
|
-
.option('-o, --output <format>', 'Output format <json|text>', 'text')
|
|
22
|
-
.option('--verbose', 'Verbose output', false)
|
|
23
|
-
.option('--quiet', 'Suppress non-essential output', false);
|
|
24
|
-
const globals = () => this.program.opts();
|
|
25
|
-
registerCreateCommand(this.program, this.api, globals);
|
|
26
|
-
registerResolveCommand(this.program, this.api, globals);
|
|
27
|
-
registerUpdateCommand(this.program, this.api, globals);
|
|
28
|
-
registerDeactivateCommand(this.program, this.api, globals);
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Runs the CLI with the provided argv or process.argv.
|
|
32
|
-
* @param {string[]} [argv] - Optional array of command-line arguments.
|
|
33
|
-
* @returns {Promise<void>} - Resolves when execution is complete.
|
|
34
|
-
*/
|
|
35
|
-
async run(argv) {
|
|
36
|
-
try {
|
|
37
|
-
const normalized = normalizeArgv(argv ?? process.argv);
|
|
38
|
-
await this.program.parseAsync(normalized, { from: 'node' });
|
|
39
|
-
if (!this.program.args.length)
|
|
40
|
-
this.program.outputHelp();
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
handleError(error);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Normalizes argv to ensure it has at least two elements.
|
|
49
|
-
* @param {string[]} argv - The original argv array.
|
|
50
|
-
* @returns {string[]} - The normalized argv array.
|
|
51
|
-
*/
|
|
52
|
-
function normalizeArgv(argv) {
|
|
53
|
-
if (argv.length >= 2)
|
|
54
|
-
return argv;
|
|
55
|
-
if (argv.length === 1)
|
|
56
|
-
return ['node', argv[0]];
|
|
57
|
-
return ['node', 'btcr2'];
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Handles errors thrown during CLI execution.
|
|
61
|
-
* @param {unknown} error - The error to handle.
|
|
62
|
-
* @returns {void}
|
|
63
|
-
*/
|
|
64
|
-
function handleError(error) {
|
|
65
|
-
if (error instanceof CommanderError &&
|
|
66
|
-
(error.code === 'commander.helpDisplayed' || error.code === 'commander.help')) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
if (error instanceof CLIError) {
|
|
70
|
-
console.error(error.message);
|
|
71
|
-
process.exitCode ??= 1;
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
console.error(error);
|
|
75
|
-
process.exitCode ??= 1;
|
|
76
|
-
}
|
|
77
|
-
//# sourceMappingURL=cli.js.map
|
package/dist/cjs/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { CLIError } from '../error.js';
|
|
2
|
-
import { formatResult } from '../output.js';
|
|
3
|
-
import { SUPPORTED_NETWORKS, } from '../types.js';
|
|
4
|
-
/** Expected byte length per identifier type: compressed secp256k1 = 33, SHA-256 hash = 32. */
|
|
5
|
-
const EXPECTED_BYTES = {
|
|
6
|
-
k: { length: 33, label: 'secp256k1 compressed public key (33 bytes)' },
|
|
7
|
-
x: { length: 32, label: 'SHA-256 hash (32 bytes)' },
|
|
8
|
-
};
|
|
9
|
-
export function registerCreateCommand(program, api, globals) {
|
|
10
|
-
program
|
|
11
|
-
.command('create')
|
|
12
|
-
.description('Create an identifier and initial DID document')
|
|
13
|
-
.requiredOption('-t, --type <type>', 'Identifier type <k|x>', 'k')
|
|
14
|
-
.requiredOption('-n, --network <network>', 'Identifier bitcoin network <bitcoin|testnet3|testnet4|signet|mutinynet|regtest>')
|
|
15
|
-
.requiredOption('-b, --bytes <bytes>', 'Genesis bytes as a hex string. ' +
|
|
16
|
-
'If type=k, MUST be secp256k1 public key. ' +
|
|
17
|
-
'If type=x, MUST be SHA-256 hash of a genesis document')
|
|
18
|
-
.action(async (options) => {
|
|
19
|
-
const parsed = validateCreateOptions(options);
|
|
20
|
-
const type = parsed.type === 'k' ? 'deterministic' : 'external';
|
|
21
|
-
const genesisBytes = Buffer.from(parsed.bytes, 'hex');
|
|
22
|
-
const data = api.createDid(type, genesisBytes, { network: parsed.network });
|
|
23
|
-
const result = { action: 'create', data };
|
|
24
|
-
console.log(formatResult(result, globals()));
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
function validateCreateOptions(options) {
|
|
28
|
-
if (!['k', 'x'].includes(options.type)) {
|
|
29
|
-
throw new CLIError('Invalid type. Must be "k" or "x".', 'INVALID_ARGUMENT_ERROR', options);
|
|
30
|
-
}
|
|
31
|
-
if (!SUPPORTED_NETWORKS.includes(options.network)) {
|
|
32
|
-
throw new CLIError('Invalid network. Must be one of "bitcoin", "testnet3", "testnet4", "signet", "mutinynet", or "regtest".', 'INVALID_ARGUMENT_ERROR', options);
|
|
33
|
-
}
|
|
34
|
-
const buf = Buffer.from(options.bytes, 'hex');
|
|
35
|
-
if (buf.length === 0) {
|
|
36
|
-
throw new CLIError('Invalid bytes. Must be a non-empty hex string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
37
|
-
}
|
|
38
|
-
const expected = EXPECTED_BYTES[options.type];
|
|
39
|
-
if (buf.length !== expected.length) {
|
|
40
|
-
throw new CLIError(`Invalid bytes length for type="${options.type}": expected ${expected.label}, got ${buf.length} bytes.`, 'INVALID_ARGUMENT_ERROR', options);
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
type: options.type,
|
|
44
|
-
network: options.network,
|
|
45
|
-
bytes: options.bytes,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=create.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { CLIError } from '../error.js';
|
|
2
|
-
import { formatResult } from '../output.js';
|
|
3
|
-
/** The JSON Patch that marks a DID document as permanently deactivated. */
|
|
4
|
-
const DEACTIVATION_PATCH = [{ op: 'add', path: '/deactivated', value: true }];
|
|
5
|
-
export function registerDeactivateCommand(program, api, globals) {
|
|
6
|
-
program
|
|
7
|
-
.command('deactivate')
|
|
8
|
-
.alias('delete')
|
|
9
|
-
.description('Deactivate the did:btcr2 identifier permanently. This is irreversible.')
|
|
10
|
-
.requiredOption('-s, --source-document <json>', 'Current DID document as JSON string', parseJsonArg('--source-document'))
|
|
11
|
-
.requiredOption('--source-version-id <number>', 'Current version ID of the DID document')
|
|
12
|
-
.requiredOption('-m, --verification-method-id <id>', 'DID document verification method ID used to sign the deactivation')
|
|
13
|
-
.requiredOption('-b, --beacon-id <json>', 'Beacon ID as a JSON string', parseJsonArg('--beacon-id'))
|
|
14
|
-
.action(async (options) => {
|
|
15
|
-
const parsed = {
|
|
16
|
-
sourceDocument: options.sourceDocument,
|
|
17
|
-
patches: DEACTIVATION_PATCH,
|
|
18
|
-
sourceVersionId: Number(options.sourceVersionId),
|
|
19
|
-
verificationMethodId: options.verificationMethodId,
|
|
20
|
-
beaconId: options.beaconId,
|
|
21
|
-
};
|
|
22
|
-
const data = await api.btcr2.update(parsed);
|
|
23
|
-
const result = { action: 'deactivate', data };
|
|
24
|
-
console.log(formatResult(result, globals()));
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Returns a commander argParser that validates JSON.
|
|
29
|
-
* Errors at parse time with a clear flag reference.
|
|
30
|
-
*/
|
|
31
|
-
function parseJsonArg(flagName) {
|
|
32
|
-
return (value) => {
|
|
33
|
-
try {
|
|
34
|
-
return JSON.parse(value);
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
throw new CLIError(`Invalid JSON for ${flagName}. Must be a valid JSON string.`, 'INVALID_ARGUMENT_ERROR', { flagName, value });
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
//# sourceMappingURL=deactivate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deactivate.js","sourceRoot":"","sources":["../../../src/commands/deactivate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,2EAA2E;AAC3E,MAAM,kBAAkB,GAAG,CAAC,EAAE,EAAE,EAAE,KAAc,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAEvF,MAAM,UAAU,yBAAyB,CACvC,OAAiB,EACjB,GAAqB,EACrB,OAA6B;IAE7B,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,KAAK,CAAC,QAAQ,CAAC;SACf,WAAW,CAAC,wEAAwE,CAAC;SACrF,cAAc,CACb,8BAA8B,EAC9B,qCAAqC,EACrC,YAAY,CAAC,mBAAmB,CAAC,CAClC;SACA,cAAc,CACb,8BAA8B,EAC9B,wCAAwC,CACzC;SACA,cAAc,CACb,mCAAmC,EACnC,mEAAmE,CACpE;SACA,cAAc,CACb,wBAAwB,EACxB,4BAA4B,EAC5B,YAAY,CAAC,aAAa,CAAC,CAC5B;SACA,MAAM,CAAC,KAAK,EAAE,OAKd,EAAE,EAAE;QACH,MAAM,MAAM,GAAyB;YACnC,cAAc,EAAS,OAAO,CAAC,cAAwD;YACvF,OAAO,EAAgB,kBAAkB;YACzC,eAAe,EAAQ,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;YACtD,oBAAoB,EAAG,OAAO,CAAC,oBAAoB;YACnD,QAAQ,EAAe,OAAO,CAAC,QAA4C;SAC5E,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,EAAE,MAAM,EAAE,YAAqB,EAAE,IAAI,EAAE,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,QAAgB;IACpC,OAAO,CAAC,KAAa,EAAW,EAAE;QAChC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,QAAQ,CAChB,oBAAoB,QAAQ,gCAAgC,EAC5D,wBAAwB,EACxB,EAAE,QAAQ,EAAE,KAAK,EAAE,CACpB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Identifier } from '@did-btcr2/api';
|
|
2
|
-
import { readFile } from 'node:fs/promises';
|
|
3
|
-
import { CLIError } from '../error.js';
|
|
4
|
-
import { formatResult } from '../output.js';
|
|
5
|
-
export function registerResolveCommand(program, api, globals) {
|
|
6
|
-
program
|
|
7
|
-
.command('resolve')
|
|
8
|
-
.alias('read')
|
|
9
|
-
.description('Resolve the DID document of the identifier.')
|
|
10
|
-
.requiredOption('-i, --identifier <identifier>', 'did:btcr2 identifier')
|
|
11
|
-
.option('-r, --resolution-options <json>', 'JSON string containing resolution options')
|
|
12
|
-
.option('-p, --resolution-options-path <path>', 'Path to a JSON file containing resolution options')
|
|
13
|
-
.action(async (options) => {
|
|
14
|
-
const parsed = await validateResolveOptions(options);
|
|
15
|
-
const data = await api.resolveDid(parsed.identifier, parsed.options);
|
|
16
|
-
const result = { action: 'resolve', data };
|
|
17
|
-
console.log(formatResult(result, globals()));
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
async function validateResolveOptions(options) {
|
|
21
|
-
// Validate identifier format early
|
|
22
|
-
Identifier.decode(options.identifier);
|
|
23
|
-
let resolutionOptions = undefined;
|
|
24
|
-
if (options.resolutionOptions) {
|
|
25
|
-
try {
|
|
26
|
-
resolutionOptions = JSON.parse(options.resolutionOptions);
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
throw new CLIError('Invalid resolution options. Must be a valid JSON string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
else if (options.resolutionOptionsPath) {
|
|
33
|
-
try {
|
|
34
|
-
const content = await readFile(options.resolutionOptionsPath, 'utf-8');
|
|
35
|
-
resolutionOptions = JSON.parse(content);
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
throw new CLIError('Invalid resolution options path. Must be a valid path to a JSON file.', 'INVALID_ARGUMENT_ERROR', options);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return { identifier: options.identifier, options: resolutionOptions };
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=resolve.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/commands/resolve.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,MAAM,UAAU,sBAAsB,CACpC,OAAiB,EACjB,GAAqB,EACrB,OAA6B;IAE7B,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,KAAK,CAAC,MAAM,CAAC;SACb,WAAW,CAAC,6CAA6C,CAAC;SAC1D,cAAc,CAAC,+BAA+B,EAAE,sBAAsB,CAAC;SACvE,MAAM,CAAC,iCAAiC,EAAE,2CAA2C,CAAC;SACtF,MAAM,CAAC,sCAAsC,EAAE,mDAAmD,CAAC;SACnG,MAAM,CAAC,KAAK,EAAE,OAId,EAAE,EAAE;QACH,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACrE,MAAM,MAAM,GAAG,EAAE,MAAM,EAAE,SAAkB,EAAE,IAAI,EAAE,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACP,CAAC;AAED,KAAK,UAAU,sBAAsB,CAAC,OAIrC;IACC,mCAAmC;IACnC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEtC,IAAI,iBAAiB,GAAG,SAAS,CAAC;IAClC,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,QAAQ,CAChB,0DAA0D,EAC1D,wBAAwB,EACxB,OAAO,CACR,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAC;YACvE,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,QAAQ,CAChB,uEAAuE,EACvE,wBAAwB,EACxB,OAAO,CACR,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AACxE,CAAC"}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { CLIError } from '../error.js';
|
|
2
|
-
import { formatResult } from '../output.js';
|
|
3
|
-
export function registerUpdateCommand(program, api, globals) {
|
|
4
|
-
program
|
|
5
|
-
.command('update')
|
|
6
|
-
.description('Update a did:btcr2 document.')
|
|
7
|
-
.requiredOption('-s, --source-document <json>', 'Source DID document as JSON string', parseJsonArg('--source-document'))
|
|
8
|
-
.requiredOption('--source-version-id <number>', 'Source version ID as a number')
|
|
9
|
-
.requiredOption('-p, --patches <json>', 'JSON Patch operations as a JSON string array', parseJsonArg('--patches'))
|
|
10
|
-
.requiredOption('-m, --verification-method-id <id>', 'DID document verification method ID')
|
|
11
|
-
.requiredOption('-b, --beacon-id <json>', 'Beacon ID as a JSON string', parseJsonArg('--beacon-id'))
|
|
12
|
-
.action(async (options) => {
|
|
13
|
-
const parsed = {
|
|
14
|
-
sourceDocument: options.sourceDocument,
|
|
15
|
-
patches: options.patches,
|
|
16
|
-
sourceVersionId: Number(options.sourceVersionId),
|
|
17
|
-
verificationMethodId: options.verificationMethodId,
|
|
18
|
-
beaconId: options.beaconId,
|
|
19
|
-
};
|
|
20
|
-
const data = await api.btcr2.update(parsed);
|
|
21
|
-
const result = { action: 'update', data };
|
|
22
|
-
console.log(formatResult(result, globals()));
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Returns a commander argParser that validates JSON.
|
|
27
|
-
* Errors at parse time with a clear flag reference.
|
|
28
|
-
*/
|
|
29
|
-
function parseJsonArg(flagName) {
|
|
30
|
-
return (value) => {
|
|
31
|
-
try {
|
|
32
|
-
return JSON.parse(value);
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
throw new CLIError(`Invalid JSON for ${flagName}. Must be a valid JSON string.`, 'INVALID_ARGUMENT_ERROR', { flagName, value });
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
//# sourceMappingURL=update.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/commands/update.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,MAAM,UAAU,qBAAqB,CACnC,OAAiB,EACjB,GAAqB,EACrB,OAA6B;IAE7B,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,8BAA8B,CAAC;SAC3C,cAAc,CACb,8BAA8B,EAC9B,oCAAoC,EACpC,YAAY,CAAC,mBAAmB,CAAC,CAClC;SACA,cAAc,CACb,8BAA8B,EAC9B,+BAA+B,CAChC;SACA,cAAc,CACb,sBAAsB,EACtB,8CAA8C,EAC9C,YAAY,CAAC,WAAW,CAAC,CAC1B;SACA,cAAc,CACb,mCAAmC,EACnC,qCAAqC,CACtC;SACA,cAAc,CACb,wBAAwB,EACxB,4BAA4B,EAC5B,YAAY,CAAC,aAAa,CAAC,CAC5B;SACA,MAAM,CAAC,KAAK,EAAE,OAMd,EAAE,EAAE;QACH,MAAM,MAAM,GAAyB;YACnC,cAAc,EAAS,OAAO,CAAC,cAAwD;YACvF,OAAO,EAAgB,OAAO,CAAC,OAA0C;YACzE,eAAe,EAAQ,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;YACtD,oBAAoB,EAAG,OAAO,CAAC,oBAAoB;YACnD,QAAQ,EAAe,OAAO,CAAC,QAA4C;SAC5E,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,EAAE,MAAM,EAAE,QAAiB,EAAE,IAAI,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,QAAgB;IACpC,OAAO,CAAC,KAAa,EAAW,EAAE;QAChC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,QAAQ,CAChB,oBAAoB,QAAQ,gCAAgC,EAC5D,wBAAwB,EACxB,EAAE,QAAQ,EAAE,KAAK,EAAE,CACpB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/cjs/error.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { DidMethodError } from '@did-btcr2/common';
|
|
2
|
-
/**
|
|
3
|
-
* Custom CLI Error class extending DidMethodError.
|
|
4
|
-
*/
|
|
5
|
-
export class CLIError extends DidMethodError {
|
|
6
|
-
constructor(message, type = 'CLIError', data) {
|
|
7
|
-
super(message, { type, name: 'CLIError', data });
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
//# sourceMappingURL=error.js.map
|