doomain 0.1.3 → 0.1.5
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/commands/wizard.js +48 -32
- package/dist/lib/errors.d.ts +1 -1
- package/dist/lib/vercel.js +10 -0
- package/oclif.manifest.json +34 -34
- package/package.json +1 -1
package/dist/commands/wizard.js
CHANGED
|
@@ -12,7 +12,6 @@ import { listGlobalVercelTokens } from '../lib/vercel-auth.js';
|
|
|
12
12
|
import { createVercelClient } from '../lib/vercel.js';
|
|
13
13
|
const PERSONAL_ACCOUNT = '__personal__';
|
|
14
14
|
const NEW_TOKEN = '__new_token__';
|
|
15
|
-
const SAVED_TOKEN = '__saved_token__';
|
|
16
15
|
function cancelIfNeeded(value) {
|
|
17
16
|
if (p.isCancel(value)) {
|
|
18
17
|
p.cancel('Cancelled');
|
|
@@ -111,23 +110,21 @@ function teamLabel(team) {
|
|
|
111
110
|
function globalTokenLabel(token) {
|
|
112
111
|
return token.source === 'environment' ? `Use ${token.label}` : `Use ${token.label} token`;
|
|
113
112
|
}
|
|
114
|
-
|
|
113
|
+
function isVercelAuthError(error) {
|
|
114
|
+
return error instanceof DoomainError && error.code === 'VERCEL_AUTH_FAILED';
|
|
115
|
+
}
|
|
116
|
+
async function promptVercelToken(globalTokens) {
|
|
115
117
|
if (globalTokens.length > 0) {
|
|
116
118
|
const selected = await p.select({
|
|
117
119
|
message: 'Vercel token',
|
|
118
120
|
options: [
|
|
119
121
|
...globalTokens.map((token, index) => ({ label: globalTokenLabel(token), value: String(index), hint: maskSecret(token.token) })),
|
|
120
|
-
...(savedToken && !globalTokens.some((token) => token.token === savedToken)
|
|
121
|
-
? [{ label: 'Use saved Doomain token', value: SAVED_TOKEN, hint: maskSecret(savedToken) }]
|
|
122
|
-
: []),
|
|
123
122
|
{ label: 'Enter a new token', value: NEW_TOKEN },
|
|
124
123
|
],
|
|
125
124
|
});
|
|
126
125
|
const resolved = cancelIfNeeded(selected);
|
|
127
126
|
if (resolved === null)
|
|
128
127
|
return null;
|
|
129
|
-
if (resolved === SAVED_TOKEN)
|
|
130
|
-
return savedToken ?? null;
|
|
131
128
|
if (resolved !== NEW_TOKEN)
|
|
132
129
|
return globalTokens[Number(resolved)]?.token ?? null;
|
|
133
130
|
}
|
|
@@ -156,39 +153,58 @@ export default class Wizard extends Command {
|
|
|
156
153
|
const config = await loadConfig();
|
|
157
154
|
const providerDefinitions = listProviderDefinitions();
|
|
158
155
|
const localProject = detectLocalVercelProject();
|
|
159
|
-
const globalVercelTokens = await listGlobalVercelTokens();
|
|
160
156
|
let vercelToken = config.vercel?.token;
|
|
161
157
|
let vercelTeamId = process.env.VERCEL_TEAM_ID || localProject?.orgId || config.vercel?.teamId;
|
|
162
158
|
const defaultProvider = process.env.DOOMAIN_PROVIDER || config.defaults?.provider;
|
|
163
159
|
const defaultDomain = process.env.DOOMAIN_DOMAIN || config.defaults?.domain;
|
|
164
|
-
|
|
165
|
-
|
|
160
|
+
let globalVercelTokens = [];
|
|
161
|
+
if (!vercelToken) {
|
|
162
|
+
globalVercelTokens = await listGlobalVercelTokens();
|
|
163
|
+
vercelToken = (await promptVercelToken(globalVercelTokens)) ?? undefined;
|
|
166
164
|
if (!vercelToken)
|
|
167
165
|
return;
|
|
168
166
|
}
|
|
169
|
-
const teamSpinner = p.spinner();
|
|
170
167
|
let teams = [];
|
|
171
|
-
|
|
172
|
-
p.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
168
|
+
while (true) {
|
|
169
|
+
const teamSpinner = p.spinner();
|
|
170
|
+
try {
|
|
171
|
+
if (process.env.VERCEL_TEAM_ID) {
|
|
172
|
+
p.log.info(`Using Vercel team ${vercelTeamId} from VERCEL_TEAM_ID.`);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
activeSpinner = teamSpinner;
|
|
176
|
+
teamSpinner.start('Loading Vercel teams');
|
|
177
|
+
teams = await createVercelClient({ token: vercelToken }).listTeams();
|
|
178
|
+
teamSpinner.stop(`Loaded ${teams.length} Vercel team${teams.length === 1 ? '' : 's'}`);
|
|
179
|
+
activeSpinner = undefined;
|
|
180
|
+
const selected = await p.select({
|
|
181
|
+
message: 'Select Vercel account/team',
|
|
182
|
+
initialValue: vercelTeamId ?? localProject?.orgId ?? PERSONAL_ACCOUNT,
|
|
183
|
+
options: [
|
|
184
|
+
{ label: 'Personal account', value: PERSONAL_ACCOUNT, hint: 'No team id' },
|
|
185
|
+
...teams.map((team) => ({ label: teamLabel(team), value: team.id, hint: team.role ?? team.slug })),
|
|
186
|
+
],
|
|
187
|
+
});
|
|
188
|
+
const resolved = cancelIfNeeded(selected);
|
|
189
|
+
if (resolved === null)
|
|
190
|
+
return;
|
|
191
|
+
vercelTeamId = resolved === PERSONAL_ACCOUNT ? undefined : resolved;
|
|
192
|
+
}
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
if (!isVercelAuthError(error) || process.env.VERCEL_TOKEN)
|
|
197
|
+
throw error;
|
|
198
|
+
activeSpinner?.error('Vercel authorization failed');
|
|
199
|
+
activeSpinner = undefined;
|
|
200
|
+
p.log.warning(error instanceof Error ? error.message : String(error));
|
|
201
|
+
if (globalVercelTokens.length === 0)
|
|
202
|
+
globalVercelTokens = await listGlobalVercelTokens();
|
|
203
|
+
globalVercelTokens = globalVercelTokens.filter((token) => token.token !== vercelToken);
|
|
204
|
+
vercelToken = (await promptVercelToken(globalVercelTokens)) ?? undefined;
|
|
205
|
+
if (!vercelToken)
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
192
208
|
}
|
|
193
209
|
const selectedTeam = teams.find((team) => team.id === vercelTeamId);
|
|
194
210
|
const teamDisplay = vercelTeamId ? teamLabel(selectedTeam ?? { id: vercelTeamId, name: null, role: null, slug: vercelTeamId }) : 'Personal account';
|
package/dist/lib/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type DoomainErrorCode = 'CONFIG_NOT_FOUND' | 'DOMAIN_LINK_FAILED' | 'DOMAIN_ALREADY_ASSIGNED' | 'DOMAIN_VERIFY_FAILED' | 'INVALID_INPUT' | 'MISSING_ARGUMENT' | 'MISSING_CREDENTIALS' | 'PROVIDER_API_ERROR' | 'PROVIDER_AUTH_FAILED' | 'PROVIDER_PERMISSION_DENIED' | 'PROVIDER_NOT_FOUND' | 'PROVIDER_RATE_LIMITED' | 'PROVIDER_RECORD_CONFLICT' | 'PROVIDER_UNSUPPORTED_RECORD' | 'PROVIDER_ZONE_AMBIGUOUS' | 'PROVIDER_ZONE_NOT_FOUND' | 'PROJECT_NOT_FOUND' | 'VERCEL_PROJECT_NOT_LINKED';
|
|
1
|
+
export type DoomainErrorCode = 'CONFIG_NOT_FOUND' | 'DOMAIN_LINK_FAILED' | 'DOMAIN_ALREADY_ASSIGNED' | 'DOMAIN_VERIFY_FAILED' | 'INVALID_INPUT' | 'MISSING_ARGUMENT' | 'MISSING_CREDENTIALS' | 'PROVIDER_API_ERROR' | 'PROVIDER_AUTH_FAILED' | 'PROVIDER_PERMISSION_DENIED' | 'PROVIDER_NOT_FOUND' | 'PROVIDER_RATE_LIMITED' | 'PROVIDER_RECORD_CONFLICT' | 'PROVIDER_UNSUPPORTED_RECORD' | 'PROVIDER_ZONE_AMBIGUOUS' | 'PROVIDER_ZONE_NOT_FOUND' | 'PROJECT_NOT_FOUND' | 'VERCEL_AUTH_FAILED' | 'VERCEL_PROJECT_NOT_LINKED';
|
|
2
2
|
export declare class DoomainError extends Error {
|
|
3
3
|
readonly code: DoomainErrorCode;
|
|
4
4
|
readonly details?: unknown;
|
package/dist/lib/vercel.js
CHANGED
|
@@ -22,6 +22,13 @@ function appendTeam(path, teamId) {
|
|
|
22
22
|
function apiErrorMessage(status, body) {
|
|
23
23
|
return body?.error?.message ?? `Vercel API error (${status}).`;
|
|
24
24
|
}
|
|
25
|
+
function vercelAuthErrorMessage(body) {
|
|
26
|
+
const message = body?.error?.message;
|
|
27
|
+
if (!message || message.toLowerCase() === 'not authorized') {
|
|
28
|
+
return 'Vercel token is not authorized. Run `vercel login` again or enter a token from https://vercel.com/account/tokens.';
|
|
29
|
+
}
|
|
30
|
+
return `Vercel authorization failed: ${message}`;
|
|
31
|
+
}
|
|
25
32
|
function isDomainConflictError(error) {
|
|
26
33
|
if (!(error instanceof DoomainError))
|
|
27
34
|
return false;
|
|
@@ -52,6 +59,9 @@ export function createVercelClient(config) {
|
|
|
52
59
|
});
|
|
53
60
|
if (!response.ok) {
|
|
54
61
|
const body = (await response.json().catch(() => undefined));
|
|
62
|
+
if (response.status === 401 || response.status === 403) {
|
|
63
|
+
throw new DoomainError('VERCEL_AUTH_FAILED', vercelAuthErrorMessage(body), body);
|
|
64
|
+
}
|
|
55
65
|
throw new DoomainError('DOMAIN_LINK_FAILED', apiErrorMessage(response.status, body), body);
|
|
56
66
|
}
|
|
57
67
|
if (response.status === 204)
|
package/oclif.manifest.json
CHANGED
|
@@ -335,6 +335,39 @@
|
|
|
335
335
|
"list.js"
|
|
336
336
|
]
|
|
337
337
|
},
|
|
338
|
+
"auth:logout:vercel": {
|
|
339
|
+
"aliases": [],
|
|
340
|
+
"args": {},
|
|
341
|
+
"description": "Remove saved Vercel credentials locally.",
|
|
342
|
+
"examples": [
|
|
343
|
+
"<%= config.bin %> <%= command.id %>",
|
|
344
|
+
"<%= config.bin %> <%= command.id %> --json"
|
|
345
|
+
],
|
|
346
|
+
"flags": {
|
|
347
|
+
"json": {
|
|
348
|
+
"description": "Output a single JSON object and never prompt.",
|
|
349
|
+
"name": "json",
|
|
350
|
+
"allowNo": false,
|
|
351
|
+
"type": "boolean"
|
|
352
|
+
}
|
|
353
|
+
},
|
|
354
|
+
"hasDynamicHelp": false,
|
|
355
|
+
"hiddenAliases": [],
|
|
356
|
+
"id": "auth:logout:vercel",
|
|
357
|
+
"pluginAlias": "doomain",
|
|
358
|
+
"pluginName": "doomain",
|
|
359
|
+
"pluginType": "core",
|
|
360
|
+
"strict": true,
|
|
361
|
+
"enableJsonFlag": false,
|
|
362
|
+
"isESM": true,
|
|
363
|
+
"relativePath": [
|
|
364
|
+
"dist",
|
|
365
|
+
"commands",
|
|
366
|
+
"auth",
|
|
367
|
+
"logout",
|
|
368
|
+
"vercel.js"
|
|
369
|
+
]
|
|
370
|
+
},
|
|
338
371
|
"providers:add": {
|
|
339
372
|
"aliases": [],
|
|
340
373
|
"args": {
|
|
@@ -594,40 +627,7 @@
|
|
|
594
627
|
"providers",
|
|
595
628
|
"verify.js"
|
|
596
629
|
]
|
|
597
|
-
},
|
|
598
|
-
"auth:logout:vercel": {
|
|
599
|
-
"aliases": [],
|
|
600
|
-
"args": {},
|
|
601
|
-
"description": "Remove saved Vercel credentials locally.",
|
|
602
|
-
"examples": [
|
|
603
|
-
"<%= config.bin %> <%= command.id %>",
|
|
604
|
-
"<%= config.bin %> <%= command.id %> --json"
|
|
605
|
-
],
|
|
606
|
-
"flags": {
|
|
607
|
-
"json": {
|
|
608
|
-
"description": "Output a single JSON object and never prompt.",
|
|
609
|
-
"name": "json",
|
|
610
|
-
"allowNo": false,
|
|
611
|
-
"type": "boolean"
|
|
612
|
-
}
|
|
613
|
-
},
|
|
614
|
-
"hasDynamicHelp": false,
|
|
615
|
-
"hiddenAliases": [],
|
|
616
|
-
"id": "auth:logout:vercel",
|
|
617
|
-
"pluginAlias": "doomain",
|
|
618
|
-
"pluginName": "doomain",
|
|
619
|
-
"pluginType": "core",
|
|
620
|
-
"strict": true,
|
|
621
|
-
"enableJsonFlag": false,
|
|
622
|
-
"isESM": true,
|
|
623
|
-
"relativePath": [
|
|
624
|
-
"dist",
|
|
625
|
-
"commands",
|
|
626
|
-
"auth",
|
|
627
|
-
"logout",
|
|
628
|
-
"vercel.js"
|
|
629
|
-
]
|
|
630
630
|
}
|
|
631
631
|
},
|
|
632
|
-
"version": "0.1.
|
|
632
|
+
"version": "0.1.5"
|
|
633
633
|
}
|