insta 0.1.0 → 0.1.1
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/domain.js +56 -1
- package/dist/index.js +14 -0
- package/package.json +1 -1
package/dist/commands/domain.js
CHANGED
|
@@ -92,12 +92,20 @@ export async function domainAttach(host, opts, deps) {
|
|
|
92
92
|
function domainLines(d, linked = true) {
|
|
93
93
|
const out = [`${d.domainName} ${d.status}${d.expiresAt ? ` (expires ${d.expiresAt.slice(0, 10)}${d.autorenew ? ', auto-renews' : ''})` : ''}`];
|
|
94
94
|
// Vacuously true for a domain with no hostnames, which is every domain until something attaches.
|
|
95
|
-
|
|
95
|
+
// Not while delegated: the platform fails every hostname on the way out, and refuses the attach.
|
|
96
|
+
if (linked && !d.delegated && d.hostnames.every((h) => h.state === 'failed')) {
|
|
96
97
|
const names = d.hostnames.map((h) => h.hostname);
|
|
97
98
|
// Attaching the bought name itself re-attaches its www.
|
|
98
99
|
const retry = names.includes(d.domainName) ? names.filter((h) => h !== `www.${d.domainName}`) : names;
|
|
99
100
|
out.push(` nothing serving — ${(retry.length ? retry : [d.domainName]).map((h) => `insta domain attach ${h}`).join('; ')}`);
|
|
100
101
|
}
|
|
102
|
+
// The zone answers elsewhere, so nothing published here resolves and an attach is refused. The
|
|
103
|
+
// repair is a next action, so it follows `linked` like the others: under --org it would name this org.
|
|
104
|
+
if (d.delegated) {
|
|
105
|
+
out.push(` delegated to ${d.nameservers.join(', ')}${linked ? '' : ' — attach is refused'}`);
|
|
106
|
+
if (linked)
|
|
107
|
+
out.push(` attach is refused until: insta domain nameservers reset ${d.domainName}`);
|
|
108
|
+
}
|
|
101
109
|
const w = Math.max(0, ...d.hostnames.map((x) => x.hostname.length));
|
|
102
110
|
for (const h of d.hostnames)
|
|
103
111
|
out.push(` ${h.hostname.padEnd(w)} ${h.state}${h.service ? ` → ${h.service}` : ''}${h.reason ? ` — ${h.reason}` : ''}`);
|
|
@@ -136,6 +144,53 @@ export async function domainStatus(name, opts, deps) {
|
|
|
136
144
|
for (const line of domain ? domainLines(domain, !opts.org) : orderStatusLines(order, !opts.org))
|
|
137
145
|
info(line);
|
|
138
146
|
}
|
|
147
|
+
// ---- nameservers and transferring out ----
|
|
148
|
+
const domainPath = (orgId, domainName) => `/orgs/${orgId}/domains/${encodeURIComponent(domainName)}`;
|
|
149
|
+
export async function domainNameserversSet(domainName, hosts, opts, deps) {
|
|
150
|
+
const nameservers = hosts.flatMap((h) => h.split(/[\s,]+/)).map((h) => h.replace(/\.$/, '')).filter(Boolean);
|
|
151
|
+
if (!nameservers.length)
|
|
152
|
+
die("name at least one nameserver, or `insta domain nameservers reset <domain>` to restore the registrar's own");
|
|
153
|
+
const { api, orgId } = await orgDeps(opts, deps);
|
|
154
|
+
const r = await api.request('PUT', `${domainPath(orgId, domainName)}/nameservers`, { nameservers });
|
|
155
|
+
if (opts.json)
|
|
156
|
+
return printJson(r);
|
|
157
|
+
for (const line of domainLines(r, !opts.org))
|
|
158
|
+
info(line);
|
|
159
|
+
}
|
|
160
|
+
export async function domainNameserversReset(domainName, opts, deps) {
|
|
161
|
+
const { api, orgId } = await orgDeps(opts, deps);
|
|
162
|
+
const r = await api.request('DELETE', `${domainPath(orgId, domainName)}/nameservers`);
|
|
163
|
+
if (opts.json)
|
|
164
|
+
return printJson(r);
|
|
165
|
+
for (const line of domainLines(r, !opts.org))
|
|
166
|
+
info(line);
|
|
167
|
+
}
|
|
168
|
+
export async function domainTransferLock(domainName, mode, opts, deps) {
|
|
169
|
+
if (mode !== 'on' && mode !== 'off')
|
|
170
|
+
die('mode must be on or off');
|
|
171
|
+
const locked = mode === 'on';
|
|
172
|
+
const { api, orgId } = await orgDeps(opts, deps);
|
|
173
|
+
const r = await api.request('PATCH', domainPath(orgId, domainName), { locked });
|
|
174
|
+
if (opts.json)
|
|
175
|
+
return printJson(r);
|
|
176
|
+
info(`${r.domainName} transfer lock ${r.locked ? 'on' : 'off'}`);
|
|
177
|
+
if (!r.locked) {
|
|
178
|
+
// ICANN's post-registration lock outranks this one and nothing here can waive it.
|
|
179
|
+
if (r.transferLockExpiresAt && new Date(r.transferLockExpiresAt).getTime() > Date.now()) {
|
|
180
|
+
info(` ICANN holds the registration until ${r.transferLockExpiresAt.slice(0, 10)} whatever this says`);
|
|
181
|
+
}
|
|
182
|
+
if (!opts.org)
|
|
183
|
+
info(` authorization code: insta domain transfer code ${r.domainName}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
export async function domainTransferCode(domainName, opts, deps) {
|
|
187
|
+
const { api, orgId } = await orgDeps(opts, deps);
|
|
188
|
+
const r = await api.request('POST', `${domainPath(orgId, domainName)}/auth-code`);
|
|
189
|
+
if (opts.json)
|
|
190
|
+
return printJson(r);
|
|
191
|
+
info(r.authCode);
|
|
192
|
+
}
|
|
193
|
+
// ---- records ----
|
|
139
194
|
export function recordLines(records) {
|
|
140
195
|
const w = (pick) => Math.max(...records.map((r) => pick(r).length));
|
|
141
196
|
const idW = w((r) => String(r.id)), typeW = w((r) => r.type), nameW = w((r) => r.fqdn), answerW = w((r) => r.answer), ttlW = w((r) => String(r.ttl));
|
package/dist/index.js
CHANGED
|
@@ -214,6 +214,20 @@ dom.command('list').description("Domains bought through InstaCloud in this org
|
|
|
214
214
|
dom.command('status <name>').description("A bought domain's order and attach state")
|
|
215
215
|
.option('--org <id>', "target org (default: linked project's org)").option('--json')
|
|
216
216
|
.action(guard((name, o) => domainCmd.domainStatus(name, o)));
|
|
217
|
+
const ns = dom.command('nameservers').description("Delegate a bought domain's zone to nameservers you name, or put it back on InstaCloud's registrar");
|
|
218
|
+
ns.command('set <domain> <nameservers...>').description("Delegate the zone — the nameservers must already host it. Every hostname the domain serves stops answering, unless they are the registrar's own: the records an attach published live in the zone you are leaving")
|
|
219
|
+
.option('--org <id>', "target org (default: linked project's org)").option('--json')
|
|
220
|
+
.action(guard((domain, hosts, o) => domainCmd.domainNameserversSet(domain, hosts, o)));
|
|
221
|
+
ns.command('reset <domain>').description("Put the zone back on the registrar's own nameservers; a hostname it took down is re-attached with `insta domain attach`")
|
|
222
|
+
.option('--org <id>', "target org (default: linked project's org)").option('--json')
|
|
223
|
+
.action(guard((domain, o) => domainCmd.domainNameserversReset(domain, o)));
|
|
224
|
+
const xfer = dom.command('transfer').description('Take a bought domain to another registrar — open the lock, then read the code (all three need org admin)');
|
|
225
|
+
xfer.command('lock <domain> <mode>').description("Open or close the registrar transfer lock (mode: on|off). ICANN's own 60-day lock on a new registration outranks it")
|
|
226
|
+
.option('--org <id>', "target org (default: linked project's org)").option('--json')
|
|
227
|
+
.action(guard((domain, mode, o) => domainCmd.domainTransferLock(domain, mode, o)));
|
|
228
|
+
xfer.command('code <domain>').description('The EPP authorization code the gaining registrar asks for — it moves nothing on its own')
|
|
229
|
+
.option('--org <id>', "target org (default: linked project's org)").option('--json')
|
|
230
|
+
.action(guard((domain, o) => domainCmd.domainTransferCode(domain, o)));
|
|
217
231
|
const rec = dom.command('records').description('DNS records of a bought domain — the zone InstaCloud holds at the registrar');
|
|
218
232
|
rec.command('list <domain>').description('Every record in the zone, managed ones marked')
|
|
219
233
|
.option('--org <id>', "target org (default: linked project's org)").option('--json')
|