doomain 0.1.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/LICENSE +21 -0
- package/README.md +293 -0
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +5 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +8 -0
- package/dist/commands/auth/logout/vercel.d.ts +9 -0
- package/dist/commands/auth/logout/vercel.js +35 -0
- package/dist/commands/auth/vercel.d.ts +10 -0
- package/dist/commands/auth/vercel.js +69 -0
- package/dist/commands/domains/list.d.ts +10 -0
- package/dist/commands/domains/list.js +36 -0
- package/dist/commands/link.d.ts +21 -0
- package/dist/commands/link.js +63 -0
- package/dist/commands/projects/list.d.ts +9 -0
- package/dist/commands/projects/list.js +26 -0
- package/dist/commands/providers/add.d.ts +1 -0
- package/dist/commands/providers/add.js +1 -0
- package/dist/commands/providers/connect.d.ts +15 -0
- package/dist/commands/providers/connect.js +183 -0
- package/dist/commands/providers/disconnect.d.ts +13 -0
- package/dist/commands/providers/disconnect.js +52 -0
- package/dist/commands/providers/list.d.ts +8 -0
- package/dist/commands/providers/list.js +25 -0
- package/dist/commands/providers/status.d.ts +9 -0
- package/dist/commands/providers/status.js +31 -0
- package/dist/commands/providers/verify.d.ts +11 -0
- package/dist/commands/providers/verify.js +27 -0
- package/dist/commands/schema.d.ts +11 -0
- package/dist/commands/schema.js +29 -0
- package/dist/commands/verify.d.ts +12 -0
- package/dist/commands/verify.js +36 -0
- package/dist/commands/wizard.d.ts +9 -0
- package/dist/commands/wizard.js +322 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/command-schema.d.ts +14 -0
- package/dist/lib/command-schema.js +99 -0
- package/dist/lib/config.d.ts +34 -0
- package/dist/lib/config.js +49 -0
- package/dist/lib/errors.d.ts +7 -0
- package/dist/lib/errors.js +17 -0
- package/dist/lib/flags.d.ts +6 -0
- package/dist/lib/flags.js +10 -0
- package/dist/lib/link-domain.d.ts +47 -0
- package/dist/lib/link-domain.js +336 -0
- package/dist/lib/local-vercel.d.ts +6 -0
- package/dist/lib/local-vercel.js +27 -0
- package/dist/lib/output.d.ts +36 -0
- package/dist/lib/output.js +51 -0
- package/dist/lib/providers/cloudflare/index.d.ts +26 -0
- package/dist/lib/providers/cloudflare/index.js +219 -0
- package/dist/lib/providers/core/config.d.ts +5 -0
- package/dist/lib/providers/core/config.js +33 -0
- package/dist/lib/providers/core/errors.d.ts +6 -0
- package/dist/lib/providers/core/errors.js +18 -0
- package/dist/lib/providers/core/http.d.ts +17 -0
- package/dist/lib/providers/core/http.js +43 -0
- package/dist/lib/providers/core/pagination.d.ts +12 -0
- package/dist/lib/providers/core/pagination.js +15 -0
- package/dist/lib/providers/core/planner.d.ts +19 -0
- package/dist/lib/providers/core/planner.js +79 -0
- package/dist/lib/providers/core/types.d.ts +123 -0
- package/dist/lib/providers/core/types.js +1 -0
- package/dist/lib/providers/namecheap/index.d.ts +28 -0
- package/dist/lib/providers/namecheap/index.js +289 -0
- package/dist/lib/providers/registry.d.ts +4 -0
- package/dist/lib/providers/registry.js +21 -0
- package/dist/lib/providers/spaceship/index.d.ts +22 -0
- package/dist/lib/providers/spaceship/index.js +148 -0
- package/dist/lib/providers/status.d.ts +16 -0
- package/dist/lib/providers/status.js +33 -0
- package/dist/lib/providers/types.d.ts +1 -0
- package/dist/lib/providers/types.js +1 -0
- package/dist/lib/validate.d.ts +15 -0
- package/dist/lib/validate.js +62 -0
- package/dist/lib/vercel.d.ts +32 -0
- package/dist/lib/vercel.js +131 -0
- package/oclif.manifest.json +633 -0
- package/package.json +86 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { loadConfig } from './config.js';
|
|
2
|
+
import { DoomainError } from './errors.js';
|
|
3
|
+
const VERCEL_API_URL = 'https://api.vercel.com';
|
|
4
|
+
export const VERCEL_APEX_A_RECORD = '76.76.21.21';
|
|
5
|
+
export const VERCEL_CNAME_RECORD = 'cname.vercel-dns.com';
|
|
6
|
+
export async function resolveVercelConfig() {
|
|
7
|
+
const config = await loadConfig();
|
|
8
|
+
const token = process.env.VERCEL_TOKEN || config.vercel?.token;
|
|
9
|
+
const teamId = process.env.VERCEL_TEAM_ID || config.vercel?.teamId;
|
|
10
|
+
if (!token) {
|
|
11
|
+
throw new DoomainError('MISSING_CREDENTIALS', 'Missing Vercel token. Run `doomain auth vercel` or set VERCEL_TOKEN.');
|
|
12
|
+
}
|
|
13
|
+
return { token, teamId };
|
|
14
|
+
}
|
|
15
|
+
function appendTeam(path, teamId) {
|
|
16
|
+
if (!teamId)
|
|
17
|
+
return path;
|
|
18
|
+
const separator = path.includes('?') ? '&' : '?';
|
|
19
|
+
return `${path}${separator}teamId=${encodeURIComponent(teamId)}`;
|
|
20
|
+
}
|
|
21
|
+
function apiErrorMessage(status, body) {
|
|
22
|
+
return body?.error?.message ?? `Vercel API error (${status}).`;
|
|
23
|
+
}
|
|
24
|
+
function isAlreadyAddedError(error) {
|
|
25
|
+
if (!(error instanceof DoomainError))
|
|
26
|
+
return false;
|
|
27
|
+
const details = error.details;
|
|
28
|
+
const text = `${error.message} ${details?.error?.code ?? ''}`.toLowerCase();
|
|
29
|
+
return text.includes('already') || text.includes('conflict') || text.includes('domain_already');
|
|
30
|
+
}
|
|
31
|
+
export function createVercelClient(config) {
|
|
32
|
+
async function request(path, init = {}, opts = {}) {
|
|
33
|
+
const response = await fetch(`${VERCEL_API_URL}${opts.team === false ? path : appendTeam(path, config.teamId)}`, {
|
|
34
|
+
...init,
|
|
35
|
+
headers: {
|
|
36
|
+
Authorization: `Bearer ${config.token}`,
|
|
37
|
+
'Content-Type': 'application/json',
|
|
38
|
+
...(init.headers ?? {}),
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
const body = (await response.json().catch(() => undefined));
|
|
43
|
+
throw new DoomainError('DOMAIN_LINK_FAILED', apiErrorMessage(response.status, body), body);
|
|
44
|
+
}
|
|
45
|
+
if (response.status === 204)
|
|
46
|
+
return undefined;
|
|
47
|
+
return (await response.json().catch(() => undefined));
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
async listTeams() {
|
|
51
|
+
const teamsById = new Map();
|
|
52
|
+
const seenCursors = new Set();
|
|
53
|
+
let cursor;
|
|
54
|
+
for (let page = 0; page < 25; page += 1) {
|
|
55
|
+
const query = new URLSearchParams({ limit: '100' });
|
|
56
|
+
if (cursor)
|
|
57
|
+
query.set('until', cursor);
|
|
58
|
+
const result = await request(`/v2/teams?${query.toString()}`, {}, { team: false });
|
|
59
|
+
for (const team of result.teams) {
|
|
60
|
+
teamsById.set(team.id, {
|
|
61
|
+
id: team.id,
|
|
62
|
+
name: team.name ?? null,
|
|
63
|
+
role: team.membership?.role ?? null,
|
|
64
|
+
slug: team.slug ?? team.id,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
const next = result.pagination?.next?.toString();
|
|
68
|
+
if (!next || seenCursors.has(next))
|
|
69
|
+
break;
|
|
70
|
+
seenCursors.add(next);
|
|
71
|
+
cursor = next;
|
|
72
|
+
}
|
|
73
|
+
return [...teamsById.values()].sort((a, b) => (a.name ?? a.slug).localeCompare(b.name ?? b.slug));
|
|
74
|
+
},
|
|
75
|
+
async listProjects(search) {
|
|
76
|
+
const projectsById = new Map();
|
|
77
|
+
const seenCursors = new Set();
|
|
78
|
+
let cursor;
|
|
79
|
+
for (let page = 0; page < 25; page += 1) {
|
|
80
|
+
const query = new URLSearchParams({ limit: '100' });
|
|
81
|
+
if (search)
|
|
82
|
+
query.set('search', search);
|
|
83
|
+
if (cursor)
|
|
84
|
+
query.set('from', cursor);
|
|
85
|
+
const result = await request(`/v9/projects?${query.toString()}`);
|
|
86
|
+
for (const project of result.projects) {
|
|
87
|
+
projectsById.set(project.id, {
|
|
88
|
+
id: project.id,
|
|
89
|
+
name: project.name,
|
|
90
|
+
framework: project.framework ?? null,
|
|
91
|
+
updatedAt: project.updatedAt ?? null,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const next = result.pagination?.next?.toString();
|
|
95
|
+
if (!next || seenCursors.has(next))
|
|
96
|
+
break;
|
|
97
|
+
seenCursors.add(next);
|
|
98
|
+
cursor = next;
|
|
99
|
+
}
|
|
100
|
+
return [...projectsById.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
101
|
+
},
|
|
102
|
+
async addDomainToProject(project, domain) {
|
|
103
|
+
try {
|
|
104
|
+
const raw = await request(`/v10/projects/${encodeURIComponent(project)}/domains`, {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
body: JSON.stringify({ name: domain }),
|
|
107
|
+
});
|
|
108
|
+
return { alreadyAdded: false, raw };
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
if (isAlreadyAddedError(error))
|
|
112
|
+
return { alreadyAdded: true, raw: error };
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
async getDomainConfig(domain) {
|
|
117
|
+
return request(`/v6/domains/${encodeURIComponent(domain)}/config`);
|
|
118
|
+
},
|
|
119
|
+
async getRecommendedCname(domain) {
|
|
120
|
+
const config = await this.getDomainConfig(domain).catch(() => undefined);
|
|
121
|
+
const recommended = config?.recommendedCNAME?.sort((a, b) => (a.rank ?? 999) - (b.rank ?? 999))[0];
|
|
122
|
+
return recommended?.value?.replace(/\.$/, '') || VERCEL_CNAME_RECORD;
|
|
123
|
+
},
|
|
124
|
+
async getProjectDomain(project, domain) {
|
|
125
|
+
return request(`/v9/projects/${encodeURIComponent(project)}/domains/${encodeURIComponent(domain)}`);
|
|
126
|
+
},
|
|
127
|
+
async verifyProjectDomain(project, domain) {
|
|
128
|
+
return request(`/v9/projects/${encodeURIComponent(project)}/domains/${encodeURIComponent(domain)}/verify`, { method: 'POST' });
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|