doomain 0.1.22 → 0.1.24
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 +1 -1
- package/dist/commands/auth/clerk.js +3 -2
- package/dist/commands/auth/logout/clerk.js +3 -2
- package/dist/commands/auth/logout/vercel.js +3 -2
- package/dist/commands/auth/vercel.js +5 -4
- package/dist/commands/clerk/domains/add.js +3 -2
- package/dist/commands/dns/diagnose.js +3 -2
- package/dist/commands/dns/point.js +7 -3
- package/dist/commands/dns/remove.js +3 -2
- package/dist/commands/domains/find.js +3 -2
- package/dist/commands/domains/list.js +46 -33
- package/dist/commands/link.js +4 -3
- package/dist/commands/projects/list.js +5 -2
- package/dist/commands/providers/connect.js +14 -23
- package/dist/commands/providers/disconnect.js +3 -2
- package/dist/commands/providers/status.js +2 -1
- package/dist/commands/providers/verify.js +3 -2
- package/dist/commands/schema.js +2 -1
- package/dist/commands/update.js +2 -1
- package/dist/commands/verify.js +5 -2
- package/dist/commands/version.d.ts +5 -0
- package/dist/commands/version.js +8 -0
- package/dist/commands/wizard.js +45 -46
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/clerk-domain.d.ts +2 -1
- package/dist/lib/clerk-domain.js +122 -110
- package/dist/lib/clerk.d.ts +9 -5
- package/dist/lib/clerk.js +45 -36
- package/dist/lib/command-schema.d.ts +2 -1
- package/dist/lib/command-schema.js +16 -9
- package/dist/lib/config.d.ts +6 -4
- package/dist/lib/config.js +29 -27
- package/dist/lib/diagnose-dns.d.ts +8 -5
- package/dist/lib/diagnose-dns.js +90 -92
- package/dist/lib/dns-propagation.d.ts +5 -4
- package/dist/lib/dns-propagation.js +80 -54
- package/dist/lib/dns-reconciliation.d.ts +4 -3
- package/dist/lib/dns-reconciliation.js +52 -47
- package/dist/lib/domain-provider.d.ts +5 -1
- package/dist/lib/domain-provider.js +136 -131
- package/dist/lib/effect.d.ts +6 -0
- package/dist/lib/effect.js +20 -0
- package/dist/lib/link-domain.d.ts +3 -2
- package/dist/lib/link-domain.js +239 -218
- package/dist/lib/point-domain.d.ts +7 -4
- package/dist/lib/point-domain.js +92 -90
- package/dist/lib/providers/cloudflare/index.d.ts +9 -8
- package/dist/lib/providers/cloudflare/index.js +93 -87
- package/dist/lib/providers/core/config.d.ts +4 -1
- package/dist/lib/providers/core/config.js +17 -13
- package/dist/lib/providers/core/http.d.ts +4 -1
- package/dist/lib/providers/core/http.js +28 -18
- package/dist/lib/providers/core/pagination.d.ts +3 -2
- package/dist/lib/providers/core/pagination.js +17 -14
- package/dist/lib/providers/core/planner.d.ts +5 -4
- package/dist/lib/providers/core/planner.js +18 -15
- package/dist/lib/providers/core/types.d.ts +11 -8
- package/dist/lib/providers/hostinger/index.d.ts +9 -8
- package/dist/lib/providers/hostinger/index.js +74 -72
- package/dist/lib/providers/namecheap/index.d.ts +10 -8
- package/dist/lib/providers/namecheap/index.js +134 -109
- package/dist/lib/providers/registry.d.ts +3 -3
- package/dist/lib/providers/registry.js +7 -3
- package/dist/lib/providers/spaceship/index.d.ts +9 -8
- package/dist/lib/providers/spaceship/index.js +48 -47
- package/dist/lib/providers/status.d.ts +2 -1
- package/dist/lib/providers/status.js +41 -34
- package/dist/lib/public-ip.d.ts +2 -0
- package/dist/lib/public-ip.js +14 -0
- package/dist/lib/remove-domain.d.ts +6 -3
- package/dist/lib/remove-domain.js +83 -77
- package/dist/lib/self-update.d.ts +3 -2
- package/dist/lib/self-update.js +15 -23
- package/dist/lib/vercel-auth.d.ts +2 -1
- package/dist/lib/vercel-auth.js +21 -24
- package/dist/lib/vercel.d.ts +16 -12
- package/dist/lib/vercel.js +174 -114
- package/oclif.manifest.json +21 -1
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -438,7 +438,7 @@ The API checks configured provider accounts, tolerates failures from individual
|
|
|
438
438
|
|
|
439
439
|
## Command Reference
|
|
440
440
|
|
|
441
|
-
|
|
441
|
+
Use `doomain --help`, `doomain -h`, or `doomain help <command>` for oclif-generated help. Use `doomain --version`, `doomain -v`, or `doomain version` to print the installed version.
|
|
442
442
|
|
|
443
443
|
### `doomain`
|
|
444
444
|
|
|
@@ -2,6 +2,7 @@ import * as p from '@clack/prompts';
|
|
|
2
2
|
import { Command, Flags } from '@oclif/core';
|
|
3
3
|
import { createClerkPlatformClient } from '../../lib/clerk.js';
|
|
4
4
|
import { getConfigPath, maskSecret, updateConfig } from '../../lib/config.js';
|
|
5
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
5
6
|
import { jsonFlag } from '../../lib/flags.js';
|
|
6
7
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
7
8
|
function value(input, message) {
|
|
@@ -42,8 +43,8 @@ export default class AuthClerk extends Command {
|
|
|
42
43
|
appId = value(appId, 'Missing Clerk application id. Pass --app or set CLERK_APPLICATION_ID.');
|
|
43
44
|
if (!platformApiKey.startsWith('ak_'))
|
|
44
45
|
throw new Error('Clerk Platform API keys must start with ak_.');
|
|
45
|
-
await createClerkPlatformClient({ platformApiKey }).fetchApplication(appId);
|
|
46
|
-
await updateConfig((config) => ({ ...config, clerk: { appId, platformApiKey } }));
|
|
46
|
+
await runDoomainEffect(createClerkPlatformClient({ platformApiKey }, { transportErrorCode: 'CLERK_AUTH_FAILED' }).fetchApplication(appId));
|
|
47
|
+
await runDoomainEffect(updateConfig((config) => ({ ...config, clerk: { appId, platformApiKey } }), 'CLERK_AUTH_FAILED'));
|
|
47
48
|
out.result({ clerk: { appId, platformApiKey: maskSecret(platformApiKey) }, configPath: getConfigPath() });
|
|
48
49
|
out.success(`Clerk credentials saved to ${getConfigPath()}.`);
|
|
49
50
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
2
|
import { getConfigPath, updateConfig } from '../../../lib/config.js';
|
|
3
|
+
import { runDoomainEffect } from '../../../lib/effect.js';
|
|
3
4
|
import { jsonFlag } from '../../../lib/flags.js';
|
|
4
5
|
import { createOutput, outputError } from '../../../lib/output.js';
|
|
5
6
|
export default class AuthLogoutClerk extends Command {
|
|
@@ -10,11 +11,11 @@ export default class AuthLogoutClerk extends Command {
|
|
|
10
11
|
const out = createOutput({ json: flags.json });
|
|
11
12
|
try {
|
|
12
13
|
let removed = false;
|
|
13
|
-
await updateConfig((config) => {
|
|
14
|
+
await runDoomainEffect(updateConfig((config) => {
|
|
14
15
|
removed = config.clerk !== undefined;
|
|
15
16
|
const { clerk: _clerk, ...next } = config;
|
|
16
17
|
return next;
|
|
17
|
-
});
|
|
18
|
+
}, 'MISSING_CREDENTIALS'));
|
|
18
19
|
const environmentOverrides = ['CLERK_PLATFORM_API_KEY', 'CLERK_APPLICATION_ID'].filter((key) => process.env[key]);
|
|
19
20
|
out.result({ configPath: getConfigPath(), environmentOverrides, removed, service: 'clerk' });
|
|
20
21
|
if (environmentOverrides.length > 0)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
2
|
import { getConfigPath, updateConfig } from '../../../lib/config.js';
|
|
3
|
+
import { runDoomainEffect } from '../../../lib/effect.js';
|
|
3
4
|
import { jsonFlag } from '../../../lib/flags.js';
|
|
4
5
|
import { createOutput, outputError } from '../../../lib/output.js';
|
|
5
6
|
function envOverrides() {
|
|
@@ -16,11 +17,11 @@ export default class AuthLogoutVercel extends Command {
|
|
|
16
17
|
const out = createOutput({ json: flags.json });
|
|
17
18
|
try {
|
|
18
19
|
let removed = false;
|
|
19
|
-
await updateConfig((config) => {
|
|
20
|
+
await runDoomainEffect(updateConfig((config) => {
|
|
20
21
|
removed = config.vercel !== undefined;
|
|
21
22
|
const { vercel: _vercel, ...next } = config;
|
|
22
23
|
return next;
|
|
23
|
-
});
|
|
24
|
+
}, 'MISSING_CREDENTIALS'));
|
|
24
25
|
const overrides = envOverrides();
|
|
25
26
|
out.result({ configPath: getConfigPath(), environmentOverrides: overrides, removed, service: 'vercel' });
|
|
26
27
|
if (overrides.length > 0)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import { Command, Flags } from '@oclif/core';
|
|
3
3
|
import { getConfigPath, maskSecret, updateConfig } from '../../lib/config.js';
|
|
4
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
4
5
|
import { jsonFlag } from '../../lib/flags.js';
|
|
5
6
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
6
7
|
import { createVercelClient } from '../../lib/vercel.js';
|
|
@@ -61,7 +62,7 @@ export default class AuthVercel extends Command {
|
|
|
61
62
|
try {
|
|
62
63
|
let token = flags.token;
|
|
63
64
|
let teamId = flags['team-id'] || process.env.VERCEL_TEAM_ID?.trim() || undefined;
|
|
64
|
-
const globalTokens = token ? [] : await listGlobalVercelTokens();
|
|
65
|
+
const globalTokens = token ? [] : await runDoomainEffect(listGlobalVercelTokens());
|
|
65
66
|
if (!token) {
|
|
66
67
|
if (out.json) {
|
|
67
68
|
token = globalTokens[0]?.token;
|
|
@@ -76,7 +77,7 @@ export default class AuthVercel extends Command {
|
|
|
76
77
|
if (!out.json && teamId === undefined) {
|
|
77
78
|
const spinner = p.spinner();
|
|
78
79
|
spinner.start('Loading Vercel teams');
|
|
79
|
-
const teams = await createVercelClient({ token }).listTeams();
|
|
80
|
+
const teams = await runDoomainEffect(createVercelClient({ token }, { transportErrorCode: 'MISSING_CREDENTIALS' }).listTeams());
|
|
80
81
|
spinner.stop(`Loaded ${teams.length} Vercel team${teams.length === 1 ? '' : 's'}`);
|
|
81
82
|
const selected = await p.select({
|
|
82
83
|
message: 'Select Vercel account/team',
|
|
@@ -91,10 +92,10 @@ export default class AuthVercel extends Command {
|
|
|
91
92
|
}
|
|
92
93
|
teamId = selected === PERSONAL_ACCOUNT ? undefined : selected;
|
|
93
94
|
}
|
|
94
|
-
await updateConfig((config) => ({
|
|
95
|
+
await runDoomainEffect(updateConfig((config) => ({
|
|
95
96
|
...config,
|
|
96
97
|
vercel: { token, teamId },
|
|
97
|
-
}));
|
|
98
|
+
}), 'MISSING_CREDENTIALS'));
|
|
98
99
|
out.result({ configPath: getConfigPath(), vercel: { token: maskSecret(token), teamId } });
|
|
99
100
|
out.success(`Vercel credentials saved to ${getConfigPath()}.`);
|
|
100
101
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import { Args, Command, Flags } from '@oclif/core';
|
|
3
3
|
import { addClerkProductionDomain } from '../../../lib/clerk-domain.js';
|
|
4
|
+
import { runDoomainEffect } from '../../../lib/effect.js';
|
|
4
5
|
import { accountFlag, jsonFlag, providerFlag } from '../../../lib/flags.js';
|
|
5
6
|
import { createOutput, outputError } from '../../../lib/output.js';
|
|
6
7
|
function recordLine(record) {
|
|
@@ -61,7 +62,7 @@ export default class ClerkDomainsAdd extends Command {
|
|
|
61
62
|
}
|
|
62
63
|
spinner = out.spinner();
|
|
63
64
|
spinner.start(flags['dry-run'] ? 'Checking Clerk production setup' : 'Creating Clerk production setup');
|
|
64
|
-
const result = await addClerkProductionDomain({
|
|
65
|
+
const result = await runDoomainEffect(addClerkProductionDomain({
|
|
65
66
|
account: flags.account,
|
|
66
67
|
app: flags.app,
|
|
67
68
|
confirmDnsOverride: out.json
|
|
@@ -81,7 +82,7 @@ export default class ClerkDomainsAdd extends Command {
|
|
|
81
82
|
provider: flags.provider,
|
|
82
83
|
timeoutSeconds: flags.timeout,
|
|
83
84
|
wait: flags.wait,
|
|
84
|
-
});
|
|
85
|
+
}));
|
|
85
86
|
spinner.stop(flags['dry-run'] ? 'Clerk production setup is available' : 'Clerk production domain configured');
|
|
86
87
|
out.result(result);
|
|
87
88
|
if (!out.json) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { diagnoseDns } from '../../lib/diagnose-dns.js';
|
|
3
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
3
4
|
import { accountFlag, jsonFlag, providerFlag } from '../../lib/flags.js';
|
|
4
5
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
5
6
|
export default class DnsDiagnose extends Command {
|
|
@@ -24,13 +25,13 @@ export default class DnsDiagnose extends Command {
|
|
|
24
25
|
const spinner = out.json ? undefined : out.spinner();
|
|
25
26
|
try {
|
|
26
27
|
spinner?.start(`Diagnosing ${args.domain}`);
|
|
27
|
-
const result = await diagnoseDns({
|
|
28
|
+
const result = await runDoomainEffect(diagnoseDns({
|
|
28
29
|
account: flags.account,
|
|
29
30
|
domain: args.domain,
|
|
30
31
|
provider: flags.provider,
|
|
31
32
|
recordType: flags.type,
|
|
32
33
|
target: flags.target,
|
|
33
|
-
});
|
|
34
|
+
}));
|
|
34
35
|
spinner?.stop('DNS diagnosis complete');
|
|
35
36
|
out.result(result);
|
|
36
37
|
out.info(`Provider: ${result.provider}/${result.account} (${result.zoneDomain})`);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import { Args, Command, Flags } from '@oclif/core';
|
|
3
3
|
import { normalizeDnsValue } from '../../lib/dns-records.js';
|
|
4
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
4
5
|
import { accountFlag, jsonFlag, providerFlag } from '../../lib/flags.js';
|
|
5
6
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
6
7
|
import { pointDomain } from '../../lib/point-domain.js';
|
|
@@ -97,14 +98,17 @@ export default class DnsPoint extends Command {
|
|
|
97
98
|
spinner = out.spinner();
|
|
98
99
|
spinner.start(`Pointing ${args.domain}`);
|
|
99
100
|
}
|
|
100
|
-
const result = await pointDomain({
|
|
101
|
+
const result = await runDoomainEffect(pointDomain({
|
|
101
102
|
account: flags.account,
|
|
102
103
|
confirmDnsOverride: out.json
|
|
103
104
|
? undefined
|
|
104
105
|
: async (warning) => {
|
|
105
106
|
spinner?.stop('Existing DNS target found');
|
|
106
107
|
p.note(conflictNote(warning), 'DNS already points elsewhere');
|
|
107
|
-
const confirmed = await p.confirm({
|
|
108
|
+
const confirmed = await p.confirm({
|
|
109
|
+
message: `Override DNS for ${warning.domain}?`,
|
|
110
|
+
initialValue: false,
|
|
111
|
+
});
|
|
108
112
|
if (confirmed === true)
|
|
109
113
|
spinner?.start(`Pointing ${warning.domain}`);
|
|
110
114
|
return confirmed === true;
|
|
@@ -119,7 +123,7 @@ export default class DnsPoint extends Command {
|
|
|
119
123
|
timeoutSeconds: flags.timeout,
|
|
120
124
|
ttl: flags.ttl,
|
|
121
125
|
wait: flags.wait,
|
|
122
|
-
});
|
|
126
|
+
}));
|
|
123
127
|
if (flags['dry-run']) {
|
|
124
128
|
out.result(result);
|
|
125
129
|
if (!out.json)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import { Args, Command, Flags } from '@oclif/core';
|
|
3
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
3
4
|
import { accountFlag, jsonFlag, providerFlag } from '../../lib/flags.js';
|
|
4
5
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
5
6
|
import { removeDomain } from '../../lib/remove-domain.js';
|
|
@@ -36,7 +37,7 @@ export default class DnsRemove extends Command {
|
|
|
36
37
|
const spinner = flags['dry-run'] || out.json ? undefined : out.spinner();
|
|
37
38
|
try {
|
|
38
39
|
spinner?.start(`Inspecting ${args.domain}`);
|
|
39
|
-
const result = await removeDomain({
|
|
40
|
+
const result = await runDoomainEffect(removeDomain({
|
|
40
41
|
account: flags.account,
|
|
41
42
|
allMatching: flags['all-matching'],
|
|
42
43
|
confirmMultiple: out.json
|
|
@@ -58,7 +59,7 @@ export default class DnsRemove extends Command {
|
|
|
58
59
|
provider: flags.provider,
|
|
59
60
|
recordType: flags.type,
|
|
60
61
|
value: flags.value,
|
|
61
|
-
});
|
|
62
|
+
}));
|
|
62
63
|
spinner?.stop(result.removed === 0 ? 'No matching records found' : 'DNS records removed');
|
|
63
64
|
out.result(result);
|
|
64
65
|
if (flags['dry-run'] && !out.json)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Args, Command } from '@oclif/core';
|
|
2
|
-
import {
|
|
2
|
+
import { findDomainProviderEffect } from '../../lib/domain-provider.js';
|
|
3
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
3
4
|
import { DoomainError } from '../../lib/errors.js';
|
|
4
5
|
import { accountFlag, domainFlag, jsonFlag, providerFlag } from '../../lib/flags.js';
|
|
5
6
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
@@ -26,7 +27,7 @@ export default class DomainsFind extends Command {
|
|
|
26
27
|
const domain = flags.domain ?? args.domain;
|
|
27
28
|
if (!domain)
|
|
28
29
|
throw new DoomainError('MISSING_ARGUMENT', 'Domain is required. Pass it as an argument or use --domain.');
|
|
29
|
-
const result = await
|
|
30
|
+
const result = await runDoomainEffect(findDomainProviderEffect({ account: flags.account, domain, provider: flags.provider }));
|
|
30
31
|
const account = result.isDefaultAccount ? result.provider : `${result.provider}/${result.account}`;
|
|
31
32
|
out.info(`${result.domain} is managed by ${account} in DNS zone ${result.zoneDomain}.`);
|
|
32
33
|
for (const warning of result.warnings) {
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
import { Effect } from 'effect';
|
|
2
3
|
import { loadConfig } from '../../lib/config.js';
|
|
4
|
+
import { runDoomainEffect, trySync } from '../../lib/effect.js';
|
|
5
|
+
import { DoomainError } from '../../lib/errors.js';
|
|
3
6
|
import { accountFlag, domainFlag, jsonFlag, providerFlag } from '../../lib/flags.js';
|
|
4
7
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
5
8
|
import { DEFAULT_PROVIDER_ACCOUNT, isDefaultProviderAccount, listConfiguredProviderAccounts, normalizeProviderAccount, } from '../../lib/providers/core/config.js';
|
|
6
9
|
import { createProvider, getProviderDefinition } from '../../lib/providers/registry.js';
|
|
7
10
|
import { normalizeDomain } from '../../lib/validate.js';
|
|
8
|
-
|
|
11
|
+
function resolveZones(provider, domain) {
|
|
9
12
|
if (!domain)
|
|
10
13
|
return provider.listZones();
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
return Effect.gen(function* () {
|
|
15
|
+
const normalized = yield* trySync(() => normalizeDomain(domain), 'DOMAIN_LINK_FAILED');
|
|
16
|
+
const zone = yield* provider.getZone(normalized);
|
|
17
|
+
if (!zone) {
|
|
18
|
+
return yield* Effect.fail(new DoomainError('DOMAIN_LINK_FAILED', `${provider.name} does not have a DNS zone for ${normalized}.`));
|
|
19
|
+
}
|
|
20
|
+
return [zone];
|
|
21
|
+
});
|
|
16
22
|
}
|
|
17
23
|
export default class DomainsList extends Command {
|
|
18
24
|
static description = 'List DNS zones and records for a provider.';
|
|
@@ -26,36 +32,43 @@ export default class DomainsList extends Command {
|
|
|
26
32
|
const { flags } = await this.parse(DomainsList);
|
|
27
33
|
const out = createOutput({ json: flags.json });
|
|
28
34
|
try {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
for (const
|
|
44
|
-
const
|
|
45
|
-
results.push({
|
|
35
|
+
const { definition, results, selectedAccounts } = await runDoomainEffect(Effect.gen(function* () {
|
|
36
|
+
const config = yield* loadConfig();
|
|
37
|
+
const providerId = flags.provider ?? process.env.DOOMAIN_PROVIDER ?? config.defaults?.provider ?? 'spaceship';
|
|
38
|
+
const definition = yield* trySync(() => getProviderDefinition(providerId), 'DOMAIN_LINK_FAILED');
|
|
39
|
+
const account = flags.account
|
|
40
|
+
? yield* trySync(() => normalizeProviderAccount(flags.account), 'DOMAIN_LINK_FAILED')
|
|
41
|
+
: undefined;
|
|
42
|
+
const accounts = account
|
|
43
|
+
? [{ account, isDefaultAccount: isDefaultProviderAccount(account), providerId: definition.id }]
|
|
44
|
+
: yield* trySync(() => listConfiguredProviderAccounts(config, definition), 'DOMAIN_LINK_FAILED');
|
|
45
|
+
const selectedAccounts = accounts.length > 0
|
|
46
|
+
? accounts
|
|
47
|
+
: [{ account: DEFAULT_PROVIDER_ACCOUNT, isDefaultAccount: true, providerId: definition.id }];
|
|
48
|
+
const results = [];
|
|
49
|
+
for (const selectedAccount of selectedAccounts) {
|
|
50
|
+
const provider = yield* createProvider(definition.id, {
|
|
46
51
|
account: selectedAccount.account,
|
|
47
|
-
|
|
48
|
-
provider: provider.id,
|
|
49
|
-
records,
|
|
50
|
-
zone,
|
|
52
|
+
transportErrorCode: 'DOMAIN_LINK_FAILED',
|
|
51
53
|
});
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
const zones = yield* resolveZones(provider, flags.domain);
|
|
55
|
+
for (const zone of zones) {
|
|
56
|
+
results.push({
|
|
57
|
+
account: selectedAccount.account,
|
|
58
|
+
isDefaultAccount: selectedAccount.isDefaultAccount,
|
|
59
|
+
provider: provider.id,
|
|
60
|
+
records: yield* provider.listRecords(zone),
|
|
61
|
+
zone,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
58
64
|
}
|
|
65
|
+
return { definition, results, selectedAccounts };
|
|
66
|
+
}));
|
|
67
|
+
for (const result of results) {
|
|
68
|
+
const accountLabel = result.isDefaultAccount ? result.provider : `${result.provider}/${result.account}`;
|
|
69
|
+
out.info(`${result.zone.name} (${result.records.length} records) via ${accountLabel}`);
|
|
70
|
+
for (const record of result.records)
|
|
71
|
+
out.info(` ${record.type} ${record.name} -> ${record.value}`);
|
|
59
72
|
}
|
|
60
73
|
out.result({
|
|
61
74
|
...(selectedAccounts.length === 1
|
package/dist/commands/link.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import { Args, Command, Flags } from '@oclif/core';
|
|
3
|
+
import { runDoomainEffect } from '../lib/effect.js';
|
|
3
4
|
import { accountFlag, apexFlag, domainFlag, jsonFlag, projectFlag, providerFlag, subdomainFlag } from '../lib/flags.js';
|
|
4
5
|
import { linkDomain } from '../lib/link-domain.js';
|
|
5
6
|
import { createOutput, outputError } from '../lib/output.js';
|
|
@@ -77,7 +78,7 @@ export default class Link extends Command {
|
|
|
77
78
|
const domain = flags.domain ?? args.domain;
|
|
78
79
|
try {
|
|
79
80
|
if (flags['dry-run']) {
|
|
80
|
-
const result = await linkDomain({ ...flags, domain, dryRun: true, timeoutSeconds: flags.timeout });
|
|
81
|
+
const result = await runDoomainEffect(linkDomain({ ...flags, domain, dryRun: true, timeoutSeconds: flags.timeout }));
|
|
81
82
|
out.result(result);
|
|
82
83
|
if (!out.json) {
|
|
83
84
|
p.note(dryRunPreview(result), 'Dry run');
|
|
@@ -88,7 +89,7 @@ export default class Link extends Command {
|
|
|
88
89
|
out.intro('Doomain');
|
|
89
90
|
spinner = out.spinner();
|
|
90
91
|
spinner.start('Linking Vercel project and domain');
|
|
91
|
-
const result = await linkDomain({
|
|
92
|
+
const result = await runDoomainEffect(linkDomain({
|
|
92
93
|
...flags,
|
|
93
94
|
domain,
|
|
94
95
|
confirmDnsOverride: out.json
|
|
@@ -110,7 +111,7 @@ export default class Link extends Command {
|
|
|
110
111
|
dryRun: false,
|
|
111
112
|
progress: out.json ? undefined : ({ message }) => spinner?.message(message),
|
|
112
113
|
timeoutSeconds: flags.timeout,
|
|
113
|
-
});
|
|
114
|
+
}));
|
|
114
115
|
spinner.stop(result.vercel.verified ? 'Domain linked and verified' : 'Domain linked');
|
|
115
116
|
out.result(result);
|
|
116
117
|
out.outro(result.vercel.verified
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
2
3
|
import { jsonFlag } from '../../lib/flags.js';
|
|
3
4
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
4
5
|
import { createVercelClient, resolveVercelConfig } from '../../lib/vercel.js';
|
|
@@ -12,8 +13,10 @@ export default class ProjectsList extends Command {
|
|
|
12
13
|
const { flags } = await this.parse(ProjectsList);
|
|
13
14
|
const out = createOutput({ json: flags.json });
|
|
14
15
|
try {
|
|
15
|
-
const vercel = createVercelClient(await resolveVercelConfig())
|
|
16
|
-
|
|
16
|
+
const vercel = createVercelClient(await runDoomainEffect(resolveVercelConfig()), {
|
|
17
|
+
transportErrorCode: 'PROJECT_NOT_FOUND',
|
|
18
|
+
});
|
|
19
|
+
const projects = await runDoomainEffect(vercel.listProjects(flags.search));
|
|
17
20
|
for (const project of projects)
|
|
18
21
|
out.info(`${project.name} (${project.id})`);
|
|
19
22
|
out.result({ projects });
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import { Args, Command, Flags } from '@oclif/core';
|
|
3
3
|
import { getConfigPath, loadConfig, maskSecret, updateConfig } from '../../lib/config.js';
|
|
4
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
4
5
|
import { accountFlag, jsonFlag } from '../../lib/flags.js';
|
|
5
6
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
6
7
|
import { DEFAULT_PROVIDER_ACCOUNT, isDefaultProviderAccount, listConfiguredProviderAccounts, normalizeProviderAccount, providerAccountHasCredentials, withProviderAccountCredentials, } from '../../lib/providers/core/config.js';
|
|
7
8
|
import { getProviderDefinition, listProviderDefinitions } from '../../lib/providers/registry.js';
|
|
9
|
+
import { fetchPublicIp } from '../../lib/public-ip.js';
|
|
8
10
|
function requireString(value, message) {
|
|
9
11
|
if (typeof value === 'string' && value.trim())
|
|
10
12
|
return value.trim();
|
|
@@ -25,23 +27,6 @@ function legacyFlagValue(flags, credential) {
|
|
|
25
27
|
const value = flags[key];
|
|
26
28
|
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
27
29
|
}
|
|
28
|
-
async function fetchPublicIp() {
|
|
29
|
-
const controller = new AbortController();
|
|
30
|
-
const timeout = setTimeout(() => controller.abort(), 2000);
|
|
31
|
-
try {
|
|
32
|
-
const response = await fetch('https://api.ipify.org', { signal: controller.signal });
|
|
33
|
-
if (!response.ok)
|
|
34
|
-
return undefined;
|
|
35
|
-
const ip = (await response.text()).trim();
|
|
36
|
-
return ip || undefined;
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
finally {
|
|
42
|
-
clearTimeout(timeout);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
30
|
function credentialInitialValue(credential, detectedPublicIp) {
|
|
46
31
|
if (credential.key !== 'clientIp')
|
|
47
32
|
return undefined;
|
|
@@ -91,7 +76,7 @@ async function confirmProviderAccountOverwrite(definition, account) {
|
|
|
91
76
|
return value;
|
|
92
77
|
}
|
|
93
78
|
async function promptProvider() {
|
|
94
|
-
const config = await loadConfig();
|
|
79
|
+
const config = await runDoomainEffect(loadConfig());
|
|
95
80
|
const selected = await p.select({
|
|
96
81
|
message: 'Choose DNS provider',
|
|
97
82
|
options: listProviderDefinitions().map((definition) => ({
|
|
@@ -148,7 +133,7 @@ export default class ProvidersConnect extends Command {
|
|
|
148
133
|
if (!account)
|
|
149
134
|
return;
|
|
150
135
|
const isDefaultAccount = isDefaultProviderAccount(account);
|
|
151
|
-
const currentConfig = await loadConfig();
|
|
136
|
+
const currentConfig = await runDoomainEffect(loadConfig());
|
|
152
137
|
if (!out.json && providerAccountHasCredentials(currentConfig, definition.id, account)) {
|
|
153
138
|
const overwrite = await confirmProviderAccountOverwrite(definition, account);
|
|
154
139
|
if (!overwrite)
|
|
@@ -156,7 +141,7 @@ export default class ProvidersConnect extends Command {
|
|
|
156
141
|
}
|
|
157
142
|
const passedCredentials = parseCredentialFlags(flags.credential);
|
|
158
143
|
const credentials = {};
|
|
159
|
-
const detectedPublicIp = !out.json && usesClientIp(definition) ? await fetchPublicIp() : undefined;
|
|
144
|
+
const detectedPublicIp = !out.json && usesClientIp(definition) ? await runDoomainEffect(fetchPublicIp()) : undefined;
|
|
160
145
|
if (!out.json)
|
|
161
146
|
showSetupGuide(definition, detectedPublicIp);
|
|
162
147
|
for (const credential of definition.credentials) {
|
|
@@ -189,7 +174,13 @@ export default class ProvidersConnect extends Command {
|
|
|
189
174
|
if (!flags['no-verify']) {
|
|
190
175
|
spinner = out.json ? undefined : out.spinner();
|
|
191
176
|
spinner?.start(`Verifying ${definition.displayName} credentials`);
|
|
192
|
-
const zones = await definition
|
|
177
|
+
const zones = await runDoomainEffect(definition
|
|
178
|
+
.create({
|
|
179
|
+
credentials,
|
|
180
|
+
debug: process.env.DOOMAIN_DEBUG === '1',
|
|
181
|
+
transportErrorCode: 'MISSING_CREDENTIALS',
|
|
182
|
+
})
|
|
183
|
+
.listZones());
|
|
193
184
|
domainCount = zones.length;
|
|
194
185
|
spinner?.stop(`Verified ${definition.displayName} credentials and found ${domainCount} domain${domainCount === 1 ? '' : 's'}`);
|
|
195
186
|
spinner = undefined;
|
|
@@ -206,14 +197,14 @@ export default class ProvidersConnect extends Command {
|
|
|
206
197
|
}
|
|
207
198
|
setDefault = value;
|
|
208
199
|
}
|
|
209
|
-
await updateConfig((config) => ({
|
|
200
|
+
await runDoomainEffect(updateConfig((config) => ({
|
|
210
201
|
...config,
|
|
211
202
|
defaults: setDefault ? { ...config.defaults, provider: definition.id } : config.defaults,
|
|
212
203
|
providers: {
|
|
213
204
|
...config.providers,
|
|
214
205
|
[definition.id]: withProviderAccountCredentials(config.providers?.[definition.id], account, credentials),
|
|
215
206
|
},
|
|
216
|
-
}));
|
|
207
|
+
}), 'MISSING_CREDENTIALS'));
|
|
217
208
|
out.result({
|
|
218
209
|
account,
|
|
219
210
|
configPath: getConfigPath(),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Args, Command } from '@oclif/core';
|
|
2
2
|
import { getConfigPath, updateConfig } from '../../lib/config.js';
|
|
3
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
3
4
|
import { accountFlag, jsonFlag } from '../../lib/flags.js';
|
|
4
5
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
5
6
|
import { isDefaultProviderAccount, normalizeProviderAccount } from '../../lib/providers/core/config.js';
|
|
@@ -28,7 +29,7 @@ export default class ProvidersDisconnect extends Command {
|
|
|
28
29
|
const definition = getProviderDefinition(args.provider);
|
|
29
30
|
const account = flags.account ? normalizeProviderAccount(flags.account) : undefined;
|
|
30
31
|
let removed = false;
|
|
31
|
-
await updateConfig((config) => {
|
|
32
|
+
await runDoomainEffect(updateConfig((config) => {
|
|
32
33
|
const providers = { ...config.providers };
|
|
33
34
|
const provider = providers[definition.id];
|
|
34
35
|
if (!account) {
|
|
@@ -71,7 +72,7 @@ export default class ProvidersDisconnect extends Command {
|
|
|
71
72
|
defaults: Object.keys(defaults).length > 0 ? defaults : undefined,
|
|
72
73
|
providers: Object.keys(providers).length > 0 ? providers : undefined,
|
|
73
74
|
};
|
|
74
|
-
});
|
|
75
|
+
}, 'PROVIDER_NOT_FOUND'));
|
|
75
76
|
const overrides = envOverrides(definition);
|
|
76
77
|
out.result({
|
|
77
78
|
account,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
2
3
|
import { jsonFlag } from '../../lib/flags.js';
|
|
3
4
|
import { createOutput } from '../../lib/output.js';
|
|
4
5
|
import { listProviderStatuses } from '../../lib/providers/status.js';
|
|
@@ -22,7 +23,7 @@ export default class ProvidersStatus extends Command {
|
|
|
22
23
|
const out = createOutput({ json: flags.json });
|
|
23
24
|
const spinner = out.json || flags['no-verify'] ? undefined : out.spinner();
|
|
24
25
|
spinner?.start('Checking DNS providers');
|
|
25
|
-
const providers = await listProviderStatuses({ verify: !flags['no-verify'] });
|
|
26
|
+
const providers = await runDoomainEffect(listProviderStatuses({ verify: !flags['no-verify'] }));
|
|
26
27
|
spinner?.stop('Checked DNS providers');
|
|
27
28
|
for (const provider of providers) {
|
|
28
29
|
out.info(`${provider.displayName} (${provider.accountLabel}) - ${formatStatus(provider)}${provider.isPreferredProvider ? ' [preferred provider]' : ''}`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Args, Command } from '@oclif/core';
|
|
2
|
+
import { runDoomainEffect } from '../../lib/effect.js';
|
|
2
3
|
import { accountFlag, jsonFlag } from '../../lib/flags.js';
|
|
3
4
|
import { createOutput, outputError } from '../../lib/output.js';
|
|
4
5
|
import { isDefaultProviderAccount, normalizeProviderAccount } from '../../lib/providers/core/config.js';
|
|
@@ -17,8 +18,8 @@ export default class ProvidersVerify extends Command {
|
|
|
17
18
|
const out = createOutput({ json: flags.json });
|
|
18
19
|
try {
|
|
19
20
|
const account = normalizeProviderAccount(flags.account);
|
|
20
|
-
const provider = await createProvider(args.provider, { account });
|
|
21
|
-
const health = await provider.verifyCredentials();
|
|
21
|
+
const provider = await runDoomainEffect(createProvider(args.provider, { account, transportErrorCode: 'PROVIDER_AUTH_FAILED' }));
|
|
22
|
+
const health = await runDoomainEffect(provider.verifyCredentials());
|
|
22
23
|
out.result({ account, health, isDefaultAccount: isDefaultProviderAccount(account), provider: provider.id });
|
|
23
24
|
out.success(`${provider.name} credentials verified.`);
|
|
24
25
|
}
|
package/dist/commands/schema.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Args, Command } from '@oclif/core';
|
|
2
2
|
import { getCommandSchemaForAgents } from '../lib/command-schema.js';
|
|
3
|
+
import { runDoomainEffect } from '../lib/effect.js';
|
|
3
4
|
import { jsonFlag } from '../lib/flags.js';
|
|
4
5
|
import { createOutput, outputError } from '../lib/output.js';
|
|
5
6
|
export default class Schema extends Command {
|
|
@@ -14,7 +15,7 @@ export default class Schema extends Command {
|
|
|
14
15
|
const { args, flags } = await this.parse(Schema);
|
|
15
16
|
const out = createOutput({ json: flags.json });
|
|
16
17
|
try {
|
|
17
|
-
const schema = await getCommandSchemaForAgents(args.command);
|
|
18
|
+
const schema = await runDoomainEffect(getCommandSchemaForAgents(args.command));
|
|
18
19
|
if (!schema)
|
|
19
20
|
throw new Error(`Unknown command schema: ${args.command}`);
|
|
20
21
|
if (!out.json)
|
package/dist/commands/update.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
import { runDoomainEffect } from '../lib/effect.js';
|
|
2
3
|
import { jsonFlag } from '../lib/flags.js';
|
|
3
4
|
import { createOutput, outputError } from '../lib/output.js';
|
|
4
5
|
import { installLatestVersion } from '../lib/self-update.js';
|
|
@@ -14,7 +15,7 @@ export default class Update extends Command {
|
|
|
14
15
|
const spinner = out.spinner();
|
|
15
16
|
try {
|
|
16
17
|
spinner.start('Downloading the latest doomain version from npm');
|
|
17
|
-
const result = await installLatestVersion();
|
|
18
|
+
const result = await runDoomainEffect(installLatestVersion());
|
|
18
19
|
spinner.stop('Installed the latest doomain version');
|
|
19
20
|
out.result(result);
|
|
20
21
|
out.success('Installed the latest doomain version from npm.');
|
package/dist/commands/verify.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
import { runDoomainEffect } from '../lib/effect.js';
|
|
2
3
|
import { apexFlag, domainFlag, jsonFlag, projectFlag, subdomainFlag } from '../lib/flags.js';
|
|
3
4
|
import { detectLocalVercelProject } from '../lib/local-vercel.js';
|
|
4
5
|
import { createOutput, outputError } from '../lib/output.js';
|
|
@@ -23,8 +24,10 @@ export default class Verify extends Command {
|
|
|
23
24
|
const project = flags.project ?? detectLocalVercelProject()?.projectId;
|
|
24
25
|
if (!project)
|
|
25
26
|
throw new Error('Missing --project and no local .vercel/project.json was found.');
|
|
26
|
-
const vercel = createVercelClient(await resolveVercelConfig())
|
|
27
|
-
|
|
27
|
+
const vercel = createVercelClient(await runDoomainEffect(resolveVercelConfig()), {
|
|
28
|
+
transportErrorCode: 'DOMAIN_VERIFY_FAILED',
|
|
29
|
+
});
|
|
30
|
+
const result = await runDoomainEffect(vercel.verifyProjectDomain(project, target.fullDomain));
|
|
28
31
|
out.result({ project, domain: target.fullDomain, vercel: result });
|
|
29
32
|
out.success(`Verification requested for ${target.fullDomain}.`);
|
|
30
33
|
}
|