clefbase 1.3.5 → 1.3.7
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/cli-src/cli/api.js +25 -3
- package/dist/cli-src/cli/commands/deploy.js +157 -27
- package/dist/cli-src/cli/index.js +36 -8
- package/dist/cli.js +175 -41
- package/dist/hosting/index.d.ts +92 -6
- package/dist/hosting/index.d.ts.map +1 -1
- package/dist/hosting/index.js +67 -14
- package/dist/hosting/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli-src/cli/api.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Raw API calls used by the CLI.
|
|
3
|
+
* api.ts — Raw API calls used by the CLI.
|
|
4
4
|
* Written as plain fetch calls (not using HttpClient) so the CLI can be
|
|
5
5
|
* bundled independently and doesn't pull in the full SDK at runtime.
|
|
6
6
|
*/
|
|
@@ -41,6 +41,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
41
41
|
exports.CliApiError = void 0;
|
|
42
42
|
exports.listSites = listSites;
|
|
43
43
|
exports.createSite = createSite;
|
|
44
|
+
exports.deleteSite = deleteSite;
|
|
45
|
+
exports.getDnsStatus = getDnsStatus;
|
|
46
|
+
exports.reprovisionDns = reprovisionDns;
|
|
44
47
|
exports.createDeploy = createDeploy;
|
|
45
48
|
exports.uploadFileBatch = uploadFileBatch;
|
|
46
49
|
exports.finalizeDeploy = finalizeDeploy;
|
|
@@ -96,6 +99,27 @@ async function createSite(cfg, name, description) {
|
|
|
96
99
|
body: JSON.stringify({ name, description }),
|
|
97
100
|
});
|
|
98
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Delete a site.
|
|
104
|
+
*
|
|
105
|
+
* First call (confirm=false): returns { requiresConfirmation: true, dnsRecord?, message }
|
|
106
|
+
* Second call (confirm=true, deleteDns?): actually deletes
|
|
107
|
+
*/
|
|
108
|
+
async function deleteSite(cfg, siteId, opts = {}) {
|
|
109
|
+
const params = new URLSearchParams();
|
|
110
|
+
if (opts.confirm)
|
|
111
|
+
params.set("confirm", "true");
|
|
112
|
+
if (opts.deleteDns)
|
|
113
|
+
params.set("deleteDns", "true");
|
|
114
|
+
const qs = params.toString() ? `?${params}` : "";
|
|
115
|
+
return apiFetch(`${base(cfg)}/api/hosting/databases/${cfg.projectId}/sites/${siteId}${qs}`, { method: "DELETE", headers: adminHeaders(cfg) });
|
|
116
|
+
}
|
|
117
|
+
async function getDnsStatus(cfg, siteId) {
|
|
118
|
+
return apiFetch(`${base(cfg)}/api/hosting/databases/${cfg.projectId}/sites/${siteId}/dns`, { headers: adminHeaders(cfg) });
|
|
119
|
+
}
|
|
120
|
+
async function reprovisionDns(cfg, siteId) {
|
|
121
|
+
return apiFetch(`${base(cfg)}/api/hosting/databases/${cfg.projectId}/sites/${siteId}/dns/provision`, { method: "POST", headers: adminHeaders(cfg), body: JSON.stringify({}) });
|
|
122
|
+
}
|
|
99
123
|
async function createDeploy(cfg, siteId, entrypoint = "index.html") {
|
|
100
124
|
return apiFetch(`${base(cfg)}/api/hosting/databases/${cfg.projectId}/sites/${siteId}/deploys`, {
|
|
101
125
|
method: "POST",
|
|
@@ -108,7 +132,6 @@ async function uploadFileBatch(cfg, deployId, files) {
|
|
|
108
132
|
const url = `${base(cfg)}/api/hosting/databases/${cfg.projectId}/deploys/${deployId}/files/batch`;
|
|
109
133
|
let res;
|
|
110
134
|
if (typeof FormData !== "undefined") {
|
|
111
|
-
// Node 18+ native FormData: Buffer must be wrapped in Blob/File
|
|
112
135
|
const form = new FormData();
|
|
113
136
|
for (const f of files) {
|
|
114
137
|
const filename = f.path.split("/").pop() ?? f.path;
|
|
@@ -124,7 +147,6 @@ async function uploadFileBatch(cfg, deployId, files) {
|
|
|
124
147
|
});
|
|
125
148
|
}
|
|
126
149
|
else {
|
|
127
|
-
// Older Node: use form-data package which natively accepts Buffers
|
|
128
150
|
const mod = await Promise.resolve().then(() => __importStar(require("form-data")));
|
|
129
151
|
const FormDataLegacy = mod.default;
|
|
130
152
|
const form = new FormDataLegacy();
|
|
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.runDeploy = runDeploy;
|
|
7
7
|
exports.runHostingInit = runHostingInit;
|
|
8
8
|
exports.runStatus = runStatus;
|
|
9
|
+
exports.runDnsStatus = runDnsStatus;
|
|
10
|
+
exports.runDnsReprovision = runDnsReprovision;
|
|
9
11
|
const path_1 = __importDefault(require("path"));
|
|
10
12
|
const fs_1 = __importDefault(require("fs"));
|
|
11
13
|
const chalk_1 = __importDefault(require("chalk"));
|
|
@@ -65,6 +67,9 @@ function fmtBytes(n) {
|
|
|
65
67
|
return `${(n / 1024).toFixed(1)} KB`;
|
|
66
68
|
return `${(n / (1024 * 1024)).toFixed(2)} MB`;
|
|
67
69
|
}
|
|
70
|
+
function siteUrl(site) {
|
|
71
|
+
return site.customDomain ? `https://${site.customDomain}` : site.previewUrl;
|
|
72
|
+
}
|
|
68
73
|
// ─── deploy ───────────────────────────────────────────────────────────────────
|
|
69
74
|
async function runDeploy(opts) {
|
|
70
75
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -75,18 +80,24 @@ async function runDeploy(opts) {
|
|
|
75
80
|
// ── Resolve / pick a site ─────────────────────────────────────────────────
|
|
76
81
|
let siteId = opts.site ?? cfg.hosting?.siteId ?? "";
|
|
77
82
|
let siteName = cfg.hosting?.siteName ?? "";
|
|
83
|
+
let previewUrl = "";
|
|
78
84
|
if (!siteId) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
siteName =
|
|
85
|
+
const site = await pickOrCreateSite(cfg);
|
|
86
|
+
siteId = site.id;
|
|
87
|
+
siteName = site.name;
|
|
88
|
+
previewUrl = site.previewUrl;
|
|
82
89
|
cfg.hosting = {
|
|
83
90
|
siteId,
|
|
84
91
|
siteName,
|
|
92
|
+
previewUrl,
|
|
85
93
|
distDir: cfg.hosting?.distDir ?? "dist",
|
|
86
94
|
entrypoint: cfg.hosting?.entrypoint ?? "index.html",
|
|
87
95
|
};
|
|
88
96
|
(0, config_1.saveConfig)(cfg, cwd);
|
|
89
97
|
}
|
|
98
|
+
else {
|
|
99
|
+
previewUrl = cfg.hosting?.previewUrl ?? "";
|
|
100
|
+
}
|
|
90
101
|
// ── Resolve dist dir ──────────────────────────────────────────────────────
|
|
91
102
|
const distDir = opts.dir ?? cfg.hosting?.distDir ?? await promptDistDir(cwd);
|
|
92
103
|
const absDir = path_1.default.isAbsolute(distDir) ? distDir : path_1.default.join(cwd, distDir);
|
|
@@ -111,9 +122,10 @@ async function runDeploy(opts) {
|
|
|
111
122
|
}
|
|
112
123
|
// ── Summary ───────────────────────────────────────────────────────────────
|
|
113
124
|
console.log();
|
|
114
|
-
console.log(` ${chalk_1.default.bold("Site:")}
|
|
115
|
-
console.log(` ${chalk_1.default.bold("
|
|
116
|
-
console.log(` ${chalk_1.default.bold("
|
|
125
|
+
console.log(` ${chalk_1.default.bold("Site:")} ${siteName} ${chalk_1.default.dim(siteId)}`);
|
|
126
|
+
console.log(` ${chalk_1.default.bold("Preview:")} ${chalk_1.default.cyan(previewUrl || "(set after deploy)")}`);
|
|
127
|
+
console.log(` ${chalk_1.default.bold("From:")} ${path_1.default.relative(cwd, absDir)}`);
|
|
128
|
+
console.log(` ${chalk_1.default.bold("Files:")} ${files.length} ${chalk_1.default.dim("(" + fmtBytes(totalBytes) + ")")}`);
|
|
117
129
|
console.log();
|
|
118
130
|
// ── Create deploy ─────────────────────────────────────────────────────────
|
|
119
131
|
const deploySpinner = (0, ora_1.default)("Creating deploy…").start();
|
|
@@ -166,9 +178,10 @@ async function runDeploy(opts) {
|
|
|
166
178
|
process.exit(1);
|
|
167
179
|
}
|
|
168
180
|
// ── Result ────────────────────────────────────────────────────────────────
|
|
169
|
-
const url = `${cfg.serverUrl.replace(/\/+$/, "")}/hosted/${cfg.projectId}/${siteId}`;
|
|
170
181
|
console.log();
|
|
171
|
-
|
|
182
|
+
if (previewUrl) {
|
|
183
|
+
console.log(chalk_1.default.green.bold(` ✓ ${previewUrl}`));
|
|
184
|
+
}
|
|
172
185
|
console.log();
|
|
173
186
|
}
|
|
174
187
|
// ─── hosting:init ─────────────────────────────────────────────────────────────
|
|
@@ -177,9 +190,7 @@ async function runHostingInit(cwd = process.cwd()) {
|
|
|
177
190
|
console.log();
|
|
178
191
|
console.log(chalk_1.default.bold.cyan(" Hosting Setup"));
|
|
179
192
|
console.log();
|
|
180
|
-
const
|
|
181
|
-
const sites = await (0, api_1.listSites)(cfg).catch(() => []);
|
|
182
|
-
const siteName = sites.find(s => s.id === siteId)?.name ?? siteId;
|
|
193
|
+
const site = await pickOrCreateSite(cfg);
|
|
183
194
|
const { distDir } = await inquirer_1.default.prompt([{
|
|
184
195
|
type: "input", name: "distDir",
|
|
185
196
|
message: "Build output directory",
|
|
@@ -192,10 +203,20 @@ async function runHostingInit(cwd = process.cwd()) {
|
|
|
192
203
|
default: cfg.hosting?.entrypoint ?? "index.html",
|
|
193
204
|
}]);
|
|
194
205
|
cfg.services.hosting = true;
|
|
195
|
-
cfg.hosting = {
|
|
206
|
+
cfg.hosting = {
|
|
207
|
+
siteId: site.id,
|
|
208
|
+
siteName: site.name,
|
|
209
|
+
previewUrl: site.previewUrl,
|
|
210
|
+
distDir: distDir.trim(),
|
|
211
|
+
entrypoint: entrypoint.trim(),
|
|
212
|
+
};
|
|
196
213
|
(0, config_1.saveConfig)(cfg, cwd);
|
|
197
214
|
console.log();
|
|
198
|
-
console.log(chalk_1.default.green(` ✓ Linked to "${
|
|
215
|
+
console.log(chalk_1.default.green(` ✓ Linked to "${site.name}"`));
|
|
216
|
+
console.log(chalk_1.default.dim(` Preview URL: ${site.previewUrl}`));
|
|
217
|
+
if (site.dnsWarning) {
|
|
218
|
+
console.log(chalk_1.default.yellow(` ⚠ ${site.dnsWarning}`));
|
|
219
|
+
}
|
|
199
220
|
console.log(chalk_1.default.dim(" Run `clefbase deploy` to go live."));
|
|
200
221
|
console.log();
|
|
201
222
|
}
|
|
@@ -218,14 +239,67 @@ async function runStatus(cwd = process.cwd()) {
|
|
|
218
239
|
else {
|
|
219
240
|
sp.succeed("Active deploy");
|
|
220
241
|
const d = active.deploy;
|
|
221
|
-
const url = `${cfg.serverUrl.replace(/\/+$/, "")}/hosted/${cfg.projectId}/${cfg.hosting.siteId}`;
|
|
222
242
|
console.log();
|
|
223
243
|
console.log(` ${chalk_1.default.bold("Site:")} ${cfg.hosting.siteName} ${chalk_1.default.dim(cfg.hosting.siteId)}`);
|
|
224
244
|
console.log(` ${chalk_1.default.bold("Deploy:")} ${chalk_1.default.dim(d.id)}`);
|
|
225
245
|
console.log(` ${chalk_1.default.bold("Status:")} ${chalk_1.default.green(d.status)}`);
|
|
226
246
|
console.log(` ${chalk_1.default.bold("Files:")} ${d.fileCount} ${chalk_1.default.dim(fmtBytes(d.totalBytes ?? 0))}`);
|
|
227
247
|
console.log(` ${chalk_1.default.bold("Deployed:")} ${new Date(d.finishedAt ?? d.createdAt).toLocaleString()}`);
|
|
228
|
-
|
|
248
|
+
if (cfg.hosting.previewUrl) {
|
|
249
|
+
console.log(` ${chalk_1.default.bold("Preview:")} ${chalk_1.default.cyan(cfg.hosting.previewUrl)}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
sp.fail(err.message);
|
|
255
|
+
}
|
|
256
|
+
console.log();
|
|
257
|
+
}
|
|
258
|
+
// ─── hosting:dns ──────────────────────────────────────────────────────────────
|
|
259
|
+
async function runDnsStatus(cwd = process.cwd()) {
|
|
260
|
+
const cfg = (0, config_1.requireConfig)(cwd);
|
|
261
|
+
console.log();
|
|
262
|
+
console.log(chalk_1.default.bold(" DNS Status"));
|
|
263
|
+
console.log();
|
|
264
|
+
if (!cfg.hosting?.siteId) {
|
|
265
|
+
console.log(chalk_1.default.yellow(" No site linked. Run `clefbase hosting:init` first.\n"));
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const sp = (0, ora_1.default)("Checking DNS records…").start();
|
|
269
|
+
try {
|
|
270
|
+
const dns = await (0, api_1.getDnsStatus)(cfg, cfg.hosting.siteId);
|
|
271
|
+
sp.succeed("DNS checked");
|
|
272
|
+
console.log();
|
|
273
|
+
// Preview subdomain
|
|
274
|
+
console.log(` ${chalk_1.default.bold("Preview subdomain:")}`);
|
|
275
|
+
console.log(` URL: ${chalk_1.default.cyan(dns.previewUrl)}`);
|
|
276
|
+
if (dns.preview.isCorrect) {
|
|
277
|
+
console.log(` DNS: ${chalk_1.default.green("✓ Correctly configured")}`);
|
|
278
|
+
}
|
|
279
|
+
else if (dns.preview.isConflict) {
|
|
280
|
+
console.log(` DNS: ${chalk_1.default.red("✗ Conflict — " + dns.preview.message)}`);
|
|
281
|
+
console.log(chalk_1.default.dim(" Run `clefbase hosting:dns:reprovision` to fix."));
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
console.log(` DNS: ${chalk_1.default.yellow("⚠ Not yet provisioned")}`);
|
|
285
|
+
console.log(chalk_1.default.dim(" Run `clefbase hosting:dns:reprovision` to create the record."));
|
|
286
|
+
}
|
|
287
|
+
// Custom domain
|
|
288
|
+
if (dns.customDomain) {
|
|
289
|
+
console.log();
|
|
290
|
+
console.log(` ${chalk_1.default.bold("Custom domain:")}`);
|
|
291
|
+
console.log(` Domain: ${dns.customDomain.domain}`);
|
|
292
|
+
if (dns.customDomain.cnameOk) {
|
|
293
|
+
console.log(` DNS: ${chalk_1.default.green("✓ CNAME correctly points to " + dns.customDomain.cnameTarget)}`);
|
|
294
|
+
}
|
|
295
|
+
else if (dns.customDomain.conflict) {
|
|
296
|
+
console.log(` DNS: ${chalk_1.default.red("✗ Conflict — existing record points to " + dns.customDomain.cnameTarget)}`);
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
console.log(` DNS: ${chalk_1.default.yellow("⚠ CNAME not yet set")}`);
|
|
300
|
+
console.log(` Add: CNAME ${dns.customDomain.instructions.name} → ${dns.customDomain.instructions.content}`);
|
|
301
|
+
console.log(chalk_1.default.dim(` Note: ${dns.customDomain.instructions.note}`));
|
|
302
|
+
}
|
|
229
303
|
}
|
|
230
304
|
}
|
|
231
305
|
catch (err) {
|
|
@@ -233,7 +307,35 @@ async function runStatus(cwd = process.cwd()) {
|
|
|
233
307
|
}
|
|
234
308
|
console.log();
|
|
235
309
|
}
|
|
310
|
+
// ─── hosting:dns:reprovision ──────────────────────────────────────────────────
|
|
311
|
+
async function runDnsReprovision(cwd = process.cwd()) {
|
|
312
|
+
const cfg = (0, config_1.requireConfig)(cwd);
|
|
313
|
+
if (!cfg.hosting?.siteId) {
|
|
314
|
+
console.error(chalk_1.default.red("\n No site linked. Run `clefbase hosting:init` first.\n"));
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
const sp = (0, ora_1.default)(`Provisioning DNS for ${cfg.hosting.siteName}…`).start();
|
|
318
|
+
try {
|
|
319
|
+
const result = await (0, api_1.reprovisionDns)(cfg, cfg.hosting.siteId);
|
|
320
|
+
if (result.created) {
|
|
321
|
+
sp.succeed(chalk_1.default.green(`DNS record created: ${result.subdomain}`));
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
sp.succeed(chalk_1.default.dim(`DNS record already correct: ${result.subdomain}`));
|
|
325
|
+
}
|
|
326
|
+
console.log(chalk_1.default.cyan(` ${result.url}`));
|
|
327
|
+
}
|
|
328
|
+
catch (err) {
|
|
329
|
+
sp.fail(err.message);
|
|
330
|
+
}
|
|
331
|
+
console.log();
|
|
332
|
+
}
|
|
236
333
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
334
|
+
/**
|
|
335
|
+
* Interactive site picker / creator.
|
|
336
|
+
* Shows existing sites, allows creating a new one.
|
|
337
|
+
* On creation: enforces uniqueness, shows preview URL.
|
|
338
|
+
*/
|
|
237
339
|
async function pickOrCreateSite(cfg) {
|
|
238
340
|
const sp = (0, ora_1.default)("Fetching sites…").start();
|
|
239
341
|
let sites = [];
|
|
@@ -246,7 +348,10 @@ async function pickOrCreateSite(cfg) {
|
|
|
246
348
|
}
|
|
247
349
|
if (sites.length > 0) {
|
|
248
350
|
const choices = [
|
|
249
|
-
...sites.map(s => ({
|
|
351
|
+
...sites.map(s => ({
|
|
352
|
+
name: `${s.name} ${chalk_1.default.dim(s.previewUrl || s.id)}`,
|
|
353
|
+
value: s.id,
|
|
354
|
+
})),
|
|
250
355
|
{ name: chalk_1.default.cyan("+ Create a new site"), value: "__new__" },
|
|
251
356
|
];
|
|
252
357
|
const { chosen } = await inquirer_1.default.prompt([{
|
|
@@ -254,18 +359,43 @@ async function pickOrCreateSite(cfg) {
|
|
|
254
359
|
message: "Which site should receive this deploy?",
|
|
255
360
|
choices,
|
|
256
361
|
}]);
|
|
257
|
-
if (chosen !== "__new__")
|
|
258
|
-
return chosen;
|
|
362
|
+
if (chosen !== "__new__") {
|
|
363
|
+
return sites.find(s => s.id === chosen);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return createSiteInteractive(cfg);
|
|
367
|
+
}
|
|
368
|
+
/** Prompt for a new site name, handle conflict errors with retry. */
|
|
369
|
+
async function createSiteInteractive(cfg) {
|
|
370
|
+
while (true) {
|
|
371
|
+
const { name } = await inquirer_1.default.prompt([{
|
|
372
|
+
type: "input", name: "name",
|
|
373
|
+
message: "New site name (used as subdomain, e.g. my-app → my-app.cleforyx.com)",
|
|
374
|
+
validate: (v) => v.trim().length >= 2 || "Must be at least 2 characters",
|
|
375
|
+
}]);
|
|
376
|
+
const s = (0, ora_1.default)(`Creating "${name.trim()}"…`).start();
|
|
377
|
+
try {
|
|
378
|
+
const site = await (0, api_1.createSite)(cfg, name.trim());
|
|
379
|
+
s.succeed(chalk_1.default.green(`Created "${site.name}" → ${chalk_1.default.cyan(site.previewUrl)}`));
|
|
380
|
+
if (site.dnsWarning) {
|
|
381
|
+
console.log(chalk_1.default.yellow(` ⚠ ${site.dnsWarning}`));
|
|
382
|
+
}
|
|
383
|
+
return site;
|
|
384
|
+
}
|
|
385
|
+
catch (err) {
|
|
386
|
+
const message = err.message;
|
|
387
|
+
// 409 conflict — name already taken
|
|
388
|
+
if (message.toLowerCase().includes("already exists") || message.includes("409")) {
|
|
389
|
+
s.fail(chalk_1.default.red(message));
|
|
390
|
+
console.log(chalk_1.default.dim(" Please choose a different name.\n"));
|
|
391
|
+
// Loop to prompt again
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
s.fail(message);
|
|
395
|
+
throw err;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
259
398
|
}
|
|
260
|
-
const { name } = await inquirer_1.default.prompt([{
|
|
261
|
-
type: "input", name: "name",
|
|
262
|
-
message: "New site name",
|
|
263
|
-
validate: (v) => v.trim().length > 0 || "Required",
|
|
264
|
-
}]);
|
|
265
|
-
const s = (0, ora_1.default)(`Creating "${name}"…`).start();
|
|
266
|
-
const site = await (0, api_1.createSite)(cfg, name.trim());
|
|
267
|
-
s.succeed(chalk_1.default.green(`Created "${site.name}" ${chalk_1.default.dim(site.id)}`));
|
|
268
|
-
return site.id;
|
|
269
399
|
}
|
|
270
400
|
async function promptDistDir(cwd) {
|
|
271
401
|
const { dir } = await inquirer_1.default.prompt([{
|
|
@@ -79,6 +79,32 @@ program
|
|
|
79
79
|
fatal(err);
|
|
80
80
|
}
|
|
81
81
|
});
|
|
82
|
+
// ─── hosting:dns ──────────────────────────────────────────────────────────────
|
|
83
|
+
program
|
|
84
|
+
.command("hosting:dns")
|
|
85
|
+
.alias("dns")
|
|
86
|
+
.description("Show DNS status for the linked site's preview and custom domains")
|
|
87
|
+
.action(async () => {
|
|
88
|
+
try {
|
|
89
|
+
await (0, deploy_1.runDnsStatus)();
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
fatal(err);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
// ─── hosting:dns:reprovision ──────────────────────────────────────────────────
|
|
96
|
+
program
|
|
97
|
+
.command("hosting:dns:reprovision")
|
|
98
|
+
.alias("dns:reprovision")
|
|
99
|
+
.description("(Re-)provision the Cloudflare CNAME for the linked site")
|
|
100
|
+
.action(async () => {
|
|
101
|
+
try {
|
|
102
|
+
await (0, deploy_1.runDnsReprovision)();
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
fatal(err);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
82
108
|
// ─── info ─────────────────────────────────────────────────────────────────────
|
|
83
109
|
program
|
|
84
110
|
.command("info")
|
|
@@ -94,14 +120,16 @@ program
|
|
|
94
120
|
// ─── help footer ─────────────────────────────────────────────────────────────
|
|
95
121
|
program.addHelpText("after", `
|
|
96
122
|
${chalk_1.default.bold("Examples:")}
|
|
97
|
-
${chalk_1.default.cyan("clefbase init")}
|
|
98
|
-
${chalk_1.default.cyan("clefbase deploy")}
|
|
99
|
-
${chalk_1.default.cyan("clefbase deploy -d ./dist")}
|
|
100
|
-
${chalk_1.default.cyan("clefbase deploy -m \"v2 release\"")}
|
|
101
|
-
${chalk_1.default.cyan("clefbase hosting:init")}
|
|
102
|
-
${chalk_1.default.cyan("clefbase hosting:status")}
|
|
103
|
-
${chalk_1.default.cyan("clefbase hosting:sites")}
|
|
104
|
-
${chalk_1.default.cyan("clefbase
|
|
123
|
+
${chalk_1.default.cyan("clefbase init")} Set up a new project
|
|
124
|
+
${chalk_1.default.cyan("clefbase deploy")} Deploy your built site
|
|
125
|
+
${chalk_1.default.cyan("clefbase deploy -d ./dist")} Deploy from a specific directory
|
|
126
|
+
${chalk_1.default.cyan("clefbase deploy -m \"v2 release\"")} Deploy with a release note
|
|
127
|
+
${chalk_1.default.cyan("clefbase hosting:init")} Link or create a hosted site
|
|
128
|
+
${chalk_1.default.cyan("clefbase hosting:status")} Show current live deploy
|
|
129
|
+
${chalk_1.default.cyan("clefbase hosting:sites")} List all sites
|
|
130
|
+
${chalk_1.default.cyan("clefbase hosting:dns")} Show DNS status
|
|
131
|
+
${chalk_1.default.cyan("clefbase hosting:dns:reprovision")} Fix / create the preview CNAME
|
|
132
|
+
${chalk_1.default.cyan("clefbase info")} Show config & connection status
|
|
105
133
|
`);
|
|
106
134
|
program.parse(process.argv);
|
|
107
135
|
// ─── Helper ───────────────────────────────────────────────────────────────────
|
package/dist/cli.js
CHANGED
|
@@ -33736,6 +33736,18 @@ async function createSite(cfg, name, description) {
|
|
|
33736
33736
|
}
|
|
33737
33737
|
);
|
|
33738
33738
|
}
|
|
33739
|
+
async function getDnsStatus(cfg, siteId) {
|
|
33740
|
+
return apiFetch(
|
|
33741
|
+
`${base(cfg)}/api/hosting/databases/${cfg.projectId}/sites/${siteId}/dns`,
|
|
33742
|
+
{ headers: adminHeaders(cfg) }
|
|
33743
|
+
);
|
|
33744
|
+
}
|
|
33745
|
+
async function reprovisionDns(cfg, siteId) {
|
|
33746
|
+
return apiFetch(
|
|
33747
|
+
`${base(cfg)}/api/hosting/databases/${cfg.projectId}/sites/${siteId}/dns/provision`,
|
|
33748
|
+
{ method: "POST", headers: adminHeaders(cfg), body: JSON.stringify({}) }
|
|
33749
|
+
);
|
|
33750
|
+
}
|
|
33739
33751
|
async function createDeploy(cfg, siteId, entrypoint = "index.html") {
|
|
33740
33752
|
return apiFetch(
|
|
33741
33753
|
`${base(cfg)}/api/hosting/databases/${cfg.projectId}/sites/${siteId}/deploys`,
|
|
@@ -34148,17 +34160,22 @@ async function runDeploy(opts) {
|
|
|
34148
34160
|
console.log();
|
|
34149
34161
|
let siteId = opts.site ?? ((_a = cfg.hosting) == null ? void 0 : _a.siteId) ?? "";
|
|
34150
34162
|
let siteName = ((_b = cfg.hosting) == null ? void 0 : _b.siteName) ?? "";
|
|
34163
|
+
let previewUrl = "";
|
|
34151
34164
|
if (!siteId) {
|
|
34152
|
-
|
|
34153
|
-
|
|
34154
|
-
siteName =
|
|
34165
|
+
const site = await pickOrCreateSite(cfg);
|
|
34166
|
+
siteId = site.id;
|
|
34167
|
+
siteName = site.name;
|
|
34168
|
+
previewUrl = site.previewUrl;
|
|
34155
34169
|
cfg.hosting = {
|
|
34156
34170
|
siteId,
|
|
34157
34171
|
siteName,
|
|
34158
|
-
|
|
34159
|
-
|
|
34172
|
+
previewUrl,
|
|
34173
|
+
distDir: ((_c = cfg.hosting) == null ? void 0 : _c.distDir) ?? "dist",
|
|
34174
|
+
entrypoint: ((_d = cfg.hosting) == null ? void 0 : _d.entrypoint) ?? "index.html"
|
|
34160
34175
|
};
|
|
34161
34176
|
saveConfig(cfg, cwd);
|
|
34177
|
+
} else {
|
|
34178
|
+
previewUrl = ((_e = cfg.hosting) == null ? void 0 : _e.previewUrl) ?? "";
|
|
34162
34179
|
}
|
|
34163
34180
|
const distDir = opts.dir ?? ((_f = cfg.hosting) == null ? void 0 : _f.distDir) ?? await promptDistDir(cwd);
|
|
34164
34181
|
const absDir = import_path3.default.isAbsolute(distDir) ? distDir : import_path3.default.join(cwd, distDir);
|
|
@@ -34185,9 +34202,10 @@ async function runDeploy(opts) {
|
|
|
34185
34202
|
console.warn(source_default.yellow(` \u26A0 Entrypoint "${entrypoint}" not found \u2014 is your build output correct?`));
|
|
34186
34203
|
}
|
|
34187
34204
|
console.log();
|
|
34188
|
-
console.log(` ${source_default.bold("Site:")}
|
|
34189
|
-
console.log(` ${source_default.bold("
|
|
34190
|
-
console.log(` ${source_default.bold("
|
|
34205
|
+
console.log(` ${source_default.bold("Site:")} ${siteName} ${source_default.dim(siteId)}`);
|
|
34206
|
+
console.log(` ${source_default.bold("Preview:")} ${source_default.cyan(previewUrl || "(set after deploy)")}`);
|
|
34207
|
+
console.log(` ${source_default.bold("From:")} ${import_path3.default.relative(cwd, absDir)}`);
|
|
34208
|
+
console.log(` ${source_default.bold("Files:")} ${files.length} ${source_default.dim("(" + fmtBytes(totalBytes) + ")")}`);
|
|
34191
34209
|
console.log();
|
|
34192
34210
|
const deploySpinner = ora2("Creating deploy\u2026").start();
|
|
34193
34211
|
let deploy;
|
|
@@ -34231,38 +34249,47 @@ async function runDeploy(opts) {
|
|
|
34231
34249
|
finSpinner.fail(`Finalize failed: ${err.message}`);
|
|
34232
34250
|
process.exit(1);
|
|
34233
34251
|
}
|
|
34234
|
-
const url = `${cfg.serverUrl.replace(/\/+$/, "")}/hosted/${cfg.projectId}/${siteId}`;
|
|
34235
34252
|
console.log();
|
|
34236
|
-
|
|
34253
|
+
if (previewUrl) {
|
|
34254
|
+
console.log(source_default.green.bold(` \u2713 ${previewUrl}`));
|
|
34255
|
+
}
|
|
34237
34256
|
console.log();
|
|
34238
34257
|
}
|
|
34239
34258
|
async function runHostingInit(cwd = process.cwd()) {
|
|
34240
|
-
var _a, _b
|
|
34259
|
+
var _a, _b;
|
|
34241
34260
|
const cfg = requireConfig(cwd);
|
|
34242
34261
|
console.log();
|
|
34243
34262
|
console.log(source_default.bold.cyan(" Hosting Setup"));
|
|
34244
34263
|
console.log();
|
|
34245
|
-
const
|
|
34246
|
-
const sites = await listSites(cfg).catch(() => []);
|
|
34247
|
-
const siteName = ((_a = sites.find((s) => s.id === siteId)) == null ? void 0 : _a.name) ?? siteId;
|
|
34264
|
+
const site = await pickOrCreateSite(cfg);
|
|
34248
34265
|
const { distDir } = await lib_default.prompt([{
|
|
34249
34266
|
type: "input",
|
|
34250
34267
|
name: "distDir",
|
|
34251
34268
|
message: "Build output directory",
|
|
34252
|
-
default: ((
|
|
34269
|
+
default: ((_a = cfg.hosting) == null ? void 0 : _a.distDir) ?? guessDistDir2(cwd),
|
|
34253
34270
|
validate: (v) => v.trim().length > 0 || "Required"
|
|
34254
34271
|
}]);
|
|
34255
34272
|
const { entrypoint } = await lib_default.prompt([{
|
|
34256
34273
|
type: "input",
|
|
34257
34274
|
name: "entrypoint",
|
|
34258
34275
|
message: "HTML entrypoint",
|
|
34259
|
-
default: ((
|
|
34276
|
+
default: ((_b = cfg.hosting) == null ? void 0 : _b.entrypoint) ?? "index.html"
|
|
34260
34277
|
}]);
|
|
34261
34278
|
cfg.services.hosting = true;
|
|
34262
|
-
cfg.hosting = {
|
|
34279
|
+
cfg.hosting = {
|
|
34280
|
+
siteId: site.id,
|
|
34281
|
+
siteName: site.name,
|
|
34282
|
+
previewUrl: site.previewUrl,
|
|
34283
|
+
distDir: distDir.trim(),
|
|
34284
|
+
entrypoint: entrypoint.trim()
|
|
34285
|
+
};
|
|
34263
34286
|
saveConfig(cfg, cwd);
|
|
34264
34287
|
console.log();
|
|
34265
|
-
console.log(source_default.green(` \u2713 Linked to "${
|
|
34288
|
+
console.log(source_default.green(` \u2713 Linked to "${site.name}"`));
|
|
34289
|
+
console.log(source_default.dim(` Preview URL: ${site.previewUrl}`));
|
|
34290
|
+
if (site.dnsWarning) {
|
|
34291
|
+
console.log(source_default.yellow(` \u26A0 ${site.dnsWarning}`));
|
|
34292
|
+
}
|
|
34266
34293
|
console.log(source_default.dim(" Run `clefbase deploy` to go live."));
|
|
34267
34294
|
console.log();
|
|
34268
34295
|
}
|
|
@@ -34284,15 +34311,82 @@ async function runStatus(cwd = process.cwd()) {
|
|
|
34284
34311
|
} else {
|
|
34285
34312
|
sp.succeed("Active deploy");
|
|
34286
34313
|
const d = active.deploy;
|
|
34287
|
-
const url = `${cfg.serverUrl.replace(/\/+$/, "")}/hosted/${cfg.projectId}/${cfg.hosting.siteId}`;
|
|
34288
34314
|
console.log();
|
|
34289
34315
|
console.log(` ${source_default.bold("Site:")} ${cfg.hosting.siteName} ${source_default.dim(cfg.hosting.siteId)}`);
|
|
34290
34316
|
console.log(` ${source_default.bold("Deploy:")} ${source_default.dim(d.id)}`);
|
|
34291
34317
|
console.log(` ${source_default.bold("Status:")} ${source_default.green(d.status)}`);
|
|
34292
34318
|
console.log(` ${source_default.bold("Files:")} ${d.fileCount} ${source_default.dim(fmtBytes(d.totalBytes ?? 0))}`);
|
|
34293
34319
|
console.log(` ${source_default.bold("Deployed:")} ${new Date(d.finishedAt ?? d.createdAt).toLocaleString()}`);
|
|
34294
|
-
|
|
34320
|
+
if (cfg.hosting.previewUrl) {
|
|
34321
|
+
console.log(` ${source_default.bold("Preview:")} ${source_default.cyan(cfg.hosting.previewUrl)}`);
|
|
34322
|
+
}
|
|
34323
|
+
}
|
|
34324
|
+
} catch (err) {
|
|
34325
|
+
sp.fail(err.message);
|
|
34326
|
+
}
|
|
34327
|
+
console.log();
|
|
34328
|
+
}
|
|
34329
|
+
async function runDnsStatus(cwd = process.cwd()) {
|
|
34330
|
+
var _a;
|
|
34331
|
+
const cfg = requireConfig(cwd);
|
|
34332
|
+
console.log();
|
|
34333
|
+
console.log(source_default.bold(" DNS Status"));
|
|
34334
|
+
console.log();
|
|
34335
|
+
if (!((_a = cfg.hosting) == null ? void 0 : _a.siteId)) {
|
|
34336
|
+
console.log(source_default.yellow(" No site linked. Run `clefbase hosting:init` first.\n"));
|
|
34337
|
+
return;
|
|
34338
|
+
}
|
|
34339
|
+
const sp = ora2("Checking DNS records\u2026").start();
|
|
34340
|
+
try {
|
|
34341
|
+
const dns = await getDnsStatus(cfg, cfg.hosting.siteId);
|
|
34342
|
+
sp.succeed("DNS checked");
|
|
34343
|
+
console.log();
|
|
34344
|
+
console.log(` ${source_default.bold("Preview subdomain:")}`);
|
|
34345
|
+
console.log(` URL: ${source_default.cyan(dns.previewUrl)}`);
|
|
34346
|
+
if (dns.preview.isCorrect) {
|
|
34347
|
+
console.log(` DNS: ${source_default.green("\u2713 Correctly configured")}`);
|
|
34348
|
+
} else if (dns.preview.isConflict) {
|
|
34349
|
+
console.log(` DNS: ${source_default.red("\u2717 Conflict \u2014 " + dns.preview.message)}`);
|
|
34350
|
+
console.log(source_default.dim(" Run `clefbase hosting:dns:reprovision` to fix."));
|
|
34351
|
+
} else {
|
|
34352
|
+
console.log(` DNS: ${source_default.yellow("\u26A0 Not yet provisioned")}`);
|
|
34353
|
+
console.log(source_default.dim(" Run `clefbase hosting:dns:reprovision` to create the record."));
|
|
34354
|
+
}
|
|
34355
|
+
if (dns.customDomain) {
|
|
34356
|
+
console.log();
|
|
34357
|
+
console.log(` ${source_default.bold("Custom domain:")}`);
|
|
34358
|
+
console.log(` Domain: ${dns.customDomain.domain}`);
|
|
34359
|
+
if (dns.customDomain.cnameOk) {
|
|
34360
|
+
console.log(` DNS: ${source_default.green("\u2713 CNAME correctly points to " + dns.customDomain.cnameTarget)}`);
|
|
34361
|
+
} else if (dns.customDomain.conflict) {
|
|
34362
|
+
console.log(` DNS: ${source_default.red("\u2717 Conflict \u2014 existing record points to " + dns.customDomain.cnameTarget)}`);
|
|
34363
|
+
} else {
|
|
34364
|
+
console.log(` DNS: ${source_default.yellow("\u26A0 CNAME not yet set")}`);
|
|
34365
|
+
console.log(` Add: CNAME ${dns.customDomain.instructions.name} \u2192 ${dns.customDomain.instructions.content}`);
|
|
34366
|
+
console.log(source_default.dim(` Note: ${dns.customDomain.instructions.note}`));
|
|
34367
|
+
}
|
|
34368
|
+
}
|
|
34369
|
+
} catch (err) {
|
|
34370
|
+
sp.fail(err.message);
|
|
34371
|
+
}
|
|
34372
|
+
console.log();
|
|
34373
|
+
}
|
|
34374
|
+
async function runDnsReprovision(cwd = process.cwd()) {
|
|
34375
|
+
var _a;
|
|
34376
|
+
const cfg = requireConfig(cwd);
|
|
34377
|
+
if (!((_a = cfg.hosting) == null ? void 0 : _a.siteId)) {
|
|
34378
|
+
console.error(source_default.red("\n No site linked. Run `clefbase hosting:init` first.\n"));
|
|
34379
|
+
process.exit(1);
|
|
34380
|
+
}
|
|
34381
|
+
const sp = ora2(`Provisioning DNS for ${cfg.hosting.siteName}\u2026`).start();
|
|
34382
|
+
try {
|
|
34383
|
+
const result = await reprovisionDns(cfg, cfg.hosting.siteId);
|
|
34384
|
+
if (result.created) {
|
|
34385
|
+
sp.succeed(source_default.green(`DNS record created: ${result.subdomain}`));
|
|
34386
|
+
} else {
|
|
34387
|
+
sp.succeed(source_default.dim(`DNS record already correct: ${result.subdomain}`));
|
|
34295
34388
|
}
|
|
34389
|
+
console.log(source_default.cyan(` ${result.url}`));
|
|
34296
34390
|
} catch (err) {
|
|
34297
34391
|
sp.fail(err.message);
|
|
34298
34392
|
}
|
|
@@ -34309,7 +34403,10 @@ async function pickOrCreateSite(cfg) {
|
|
|
34309
34403
|
}
|
|
34310
34404
|
if (sites.length > 0) {
|
|
34311
34405
|
const choices = [
|
|
34312
|
-
...sites.map((
|
|
34406
|
+
...sites.map((s) => ({
|
|
34407
|
+
name: `${s.name} ${source_default.dim(s.previewUrl || s.id)}`,
|
|
34408
|
+
value: s.id
|
|
34409
|
+
})),
|
|
34313
34410
|
{ name: source_default.cyan("+ Create a new site"), value: "__new__" }
|
|
34314
34411
|
];
|
|
34315
34412
|
const { chosen } = await lib_default.prompt([{
|
|
@@ -34318,18 +34415,39 @@ async function pickOrCreateSite(cfg) {
|
|
|
34318
34415
|
message: "Which site should receive this deploy?",
|
|
34319
34416
|
choices
|
|
34320
34417
|
}]);
|
|
34321
|
-
if (chosen !== "__new__")
|
|
34418
|
+
if (chosen !== "__new__") {
|
|
34419
|
+
return sites.find((s) => s.id === chosen);
|
|
34420
|
+
}
|
|
34421
|
+
}
|
|
34422
|
+
return createSiteInteractive(cfg);
|
|
34423
|
+
}
|
|
34424
|
+
async function createSiteInteractive(cfg) {
|
|
34425
|
+
while (true) {
|
|
34426
|
+
const { name } = await lib_default.prompt([{
|
|
34427
|
+
type: "input",
|
|
34428
|
+
name: "name",
|
|
34429
|
+
message: "New site name (used as subdomain, e.g. my-app \u2192 my-app.cleforyx.com)",
|
|
34430
|
+
validate: (v) => v.trim().length >= 2 || "Must be at least 2 characters"
|
|
34431
|
+
}]);
|
|
34432
|
+
const s = ora2(`Creating "${name.trim()}"\u2026`).start();
|
|
34433
|
+
try {
|
|
34434
|
+
const site = await createSite(cfg, name.trim());
|
|
34435
|
+
s.succeed(source_default.green(`Created "${site.name}" \u2192 ${source_default.cyan(site.previewUrl)}`));
|
|
34436
|
+
if (site.dnsWarning) {
|
|
34437
|
+
console.log(source_default.yellow(` \u26A0 ${site.dnsWarning}`));
|
|
34438
|
+
}
|
|
34439
|
+
return site;
|
|
34440
|
+
} catch (err) {
|
|
34441
|
+
const message = err.message;
|
|
34442
|
+
if (message.toLowerCase().includes("already exists") || message.includes("409")) {
|
|
34443
|
+
s.fail(source_default.red(message));
|
|
34444
|
+
console.log(source_default.dim(" Please choose a different name.\n"));
|
|
34445
|
+
} else {
|
|
34446
|
+
s.fail(message);
|
|
34447
|
+
throw err;
|
|
34448
|
+
}
|
|
34449
|
+
}
|
|
34322
34450
|
}
|
|
34323
|
-
const { name } = await lib_default.prompt([{
|
|
34324
|
-
type: "input",
|
|
34325
|
-
name: "name",
|
|
34326
|
-
message: "New site name",
|
|
34327
|
-
validate: (v) => v.trim().length > 0 || "Required"
|
|
34328
|
-
}]);
|
|
34329
|
-
const s = ora2(`Creating "${name}"\u2026`).start();
|
|
34330
|
-
const site = await createSite(cfg, name.trim());
|
|
34331
|
-
s.succeed(source_default.green(`Created "${site.name}" ${source_default.dim(site.id)}`));
|
|
34332
|
-
return site.id;
|
|
34333
34451
|
}
|
|
34334
34452
|
async function promptDistDir(cwd) {
|
|
34335
34453
|
const { dir } = await lib_default.prompt([{
|
|
@@ -34405,7 +34523,7 @@ async function runSitesList(cwd = process.cwd()) {
|
|
|
34405
34523
|
}
|
|
34406
34524
|
|
|
34407
34525
|
// package.json
|
|
34408
|
-
var version = "1.3.
|
|
34526
|
+
var version = "1.3.7";
|
|
34409
34527
|
|
|
34410
34528
|
// src/cli/index.ts
|
|
34411
34529
|
var program2 = new Command();
|
|
@@ -34445,6 +34563,20 @@ program2.command("hosting:sites").alias("sites").description("List all hosted si
|
|
|
34445
34563
|
fatal(err);
|
|
34446
34564
|
}
|
|
34447
34565
|
});
|
|
34566
|
+
program2.command("hosting:dns").alias("dns").description("Show DNS status for the linked site's preview and custom domains").action(async () => {
|
|
34567
|
+
try {
|
|
34568
|
+
await runDnsStatus();
|
|
34569
|
+
} catch (err) {
|
|
34570
|
+
fatal(err);
|
|
34571
|
+
}
|
|
34572
|
+
});
|
|
34573
|
+
program2.command("hosting:dns:reprovision").alias("dns:reprovision").description("(Re-)provision the Cloudflare CNAME for the linked site").action(async () => {
|
|
34574
|
+
try {
|
|
34575
|
+
await runDnsReprovision();
|
|
34576
|
+
} catch (err) {
|
|
34577
|
+
fatal(err);
|
|
34578
|
+
}
|
|
34579
|
+
});
|
|
34448
34580
|
program2.command("info").description("Show project config and server connectivity").action(async () => {
|
|
34449
34581
|
try {
|
|
34450
34582
|
await runInfo();
|
|
@@ -34454,14 +34586,16 @@ program2.command("info").description("Show project config and server connectivit
|
|
|
34454
34586
|
});
|
|
34455
34587
|
program2.addHelpText("after", `
|
|
34456
34588
|
${source_default.bold("Examples:")}
|
|
34457
|
-
${source_default.cyan("clefbase init")}
|
|
34458
|
-
${source_default.cyan("clefbase deploy")}
|
|
34459
|
-
${source_default.cyan("clefbase deploy -d ./dist")}
|
|
34460
|
-
${source_default.cyan('clefbase deploy -m "v2 release"')}
|
|
34461
|
-
${source_default.cyan("clefbase hosting:init")}
|
|
34462
|
-
${source_default.cyan("clefbase hosting:status")}
|
|
34463
|
-
${source_default.cyan("clefbase hosting:sites")}
|
|
34464
|
-
${source_default.cyan("clefbase
|
|
34589
|
+
${source_default.cyan("clefbase init")} Set up a new project
|
|
34590
|
+
${source_default.cyan("clefbase deploy")} Deploy your built site
|
|
34591
|
+
${source_default.cyan("clefbase deploy -d ./dist")} Deploy from a specific directory
|
|
34592
|
+
${source_default.cyan('clefbase deploy -m "v2 release"')} Deploy with a release note
|
|
34593
|
+
${source_default.cyan("clefbase hosting:init")} Link or create a hosted site
|
|
34594
|
+
${source_default.cyan("clefbase hosting:status")} Show current live deploy
|
|
34595
|
+
${source_default.cyan("clefbase hosting:sites")} List all sites
|
|
34596
|
+
${source_default.cyan("clefbase hosting:dns")} Show DNS status
|
|
34597
|
+
${source_default.cyan("clefbase hosting:dns:reprovision")} Fix / create the preview CNAME
|
|
34598
|
+
${source_default.cyan("clefbase info")} Show config & connection status
|
|
34465
34599
|
`);
|
|
34466
34600
|
program2.parse(process.argv);
|
|
34467
34601
|
function fatal(err) {
|
package/dist/hosting/index.d.ts
CHANGED
|
@@ -5,9 +5,18 @@ export interface HostingSite {
|
|
|
5
5
|
id: string;
|
|
6
6
|
dbId: string;
|
|
7
7
|
name: string;
|
|
8
|
+
/** URL-safe slug — globally unique, used for the preview subdomain */
|
|
9
|
+
slug: string;
|
|
8
10
|
description?: string;
|
|
9
11
|
status: HostingStatus;
|
|
12
|
+
/** Auto-provisioned: {slug}.preview.cleforyx.com */
|
|
13
|
+
previewUrl: string;
|
|
14
|
+
/** Optional custom domain the user has configured */
|
|
10
15
|
customDomain?: string;
|
|
16
|
+
/** Cloudflare DNS record ID for the preview subdomain */
|
|
17
|
+
dnsRecordId?: string;
|
|
18
|
+
/** Non-fatal DNS warning set on creation if Cloudflare provisioning failed */
|
|
19
|
+
dnsWarning?: string;
|
|
11
20
|
createdAt: string;
|
|
12
21
|
updatedAt: string;
|
|
13
22
|
}
|
|
@@ -39,7 +48,10 @@ export interface DeployResult {
|
|
|
39
48
|
deploy: HostingDeploy;
|
|
40
49
|
filesUploaded: number;
|
|
41
50
|
errors: string[];
|
|
51
|
+
/** Canonical URL — custom domain if set, otherwise preview subdomain */
|
|
42
52
|
url: string;
|
|
53
|
+
/** Always the preview subdomain */
|
|
54
|
+
previewUrl: string;
|
|
43
55
|
}
|
|
44
56
|
export interface DeployOptions {
|
|
45
57
|
entrypoint?: string;
|
|
@@ -50,6 +62,32 @@ export interface DeployOptions {
|
|
|
50
62
|
/** Called after each batch with progress info. */
|
|
51
63
|
onProgress?: (uploaded: number, total: number) => void;
|
|
52
64
|
}
|
|
65
|
+
export interface DnsStatus {
|
|
66
|
+
preview: {
|
|
67
|
+
exists: boolean;
|
|
68
|
+
isCorrect: boolean;
|
|
69
|
+
isConflict: boolean;
|
|
70
|
+
message: string;
|
|
71
|
+
record?: {
|
|
72
|
+
name: string;
|
|
73
|
+
type: string;
|
|
74
|
+
content: string;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
customDomain?: {
|
|
78
|
+
domain: string;
|
|
79
|
+
cnameOk: boolean;
|
|
80
|
+
cnameTarget?: string;
|
|
81
|
+
conflict: boolean;
|
|
82
|
+
instructions: {
|
|
83
|
+
type: string;
|
|
84
|
+
name: string;
|
|
85
|
+
content: string;
|
|
86
|
+
note: string;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
previewUrl: string;
|
|
90
|
+
}
|
|
53
91
|
/**
|
|
54
92
|
* A reference to a hosted site.
|
|
55
93
|
*
|
|
@@ -57,6 +95,7 @@ export interface DeployOptions {
|
|
|
57
95
|
* const site = hosting.site("my-site-id");
|
|
58
96
|
* const result = await site.deployFiles({ "index.html": htmlBuffer, "app.js": jsBuffer });
|
|
59
97
|
* console.log(`Live at ${result.url}`);
|
|
98
|
+
* console.log(`Preview at ${result.previewUrl}`);
|
|
60
99
|
*/
|
|
61
100
|
export declare class SiteReference {
|
|
62
101
|
private readonly hosting;
|
|
@@ -82,9 +121,23 @@ export declare class SiteReference {
|
|
|
82
121
|
* message: "v1.2.0",
|
|
83
122
|
* onProgress: (done, total) => console.log(`${done}/${total}`),
|
|
84
123
|
* });
|
|
124
|
+
* console.log(`Live at ${result.url}`);
|
|
85
125
|
*/
|
|
86
126
|
deployFiles(files: Record<string, Buffer>, opts?: DeployOptions): Promise<DeployResult>;
|
|
87
|
-
/**
|
|
127
|
+
/** Check the DNS status of this site's preview + custom domains. */
|
|
128
|
+
getDnsStatus(): Promise<DnsStatus>;
|
|
129
|
+
/** Re-provision the preview DNS record (e.g. if it was accidentally deleted). */
|
|
130
|
+
reprovisionDns(): Promise<{
|
|
131
|
+
subdomain: string;
|
|
132
|
+
url: string;
|
|
133
|
+
created: boolean;
|
|
134
|
+
}>;
|
|
135
|
+
/** The preview URL for this site ({slug}.preview.cleforyx.com). */
|
|
136
|
+
get previewUrl(): string;
|
|
137
|
+
/**
|
|
138
|
+
* The public URL — custom domain if configured, else preview subdomain.
|
|
139
|
+
* Requires the site metadata; use `(await site.get())?.customDomain` to check.
|
|
140
|
+
*/
|
|
88
141
|
get url(): string;
|
|
89
142
|
}
|
|
90
143
|
/**
|
|
@@ -92,7 +145,12 @@ export declare class SiteReference {
|
|
|
92
145
|
*
|
|
93
146
|
* @example
|
|
94
147
|
* const hosting = getHosting(app);
|
|
148
|
+
*
|
|
149
|
+
* // Create a site — automatically provisions {name}.preview.cleforyx.com
|
|
95
150
|
* const site = await hosting.createSite("my-app");
|
|
151
|
+
* console.log(site.previewUrl); // https://my-app.preview.cleforyx.com
|
|
152
|
+
*
|
|
153
|
+
* // Deploy files
|
|
96
154
|
* const result = await hosting.site(site.id).deployFiles(files);
|
|
97
155
|
* console.log(result.url);
|
|
98
156
|
*/
|
|
@@ -103,18 +161,46 @@ export declare class ClefbaseHosting {
|
|
|
103
161
|
constructor(http: HttpClient, dbId: string, serverUrl: string);
|
|
104
162
|
/** List all sites for this project. */
|
|
105
163
|
listSites(): Promise<HostingSite[]>;
|
|
106
|
-
/**
|
|
164
|
+
/**
|
|
165
|
+
* Create a new hosted site.
|
|
166
|
+
*
|
|
167
|
+
* Site names must be globally unique across the platform.
|
|
168
|
+
* A CNAME record will be automatically provisioned on Cloudflare:
|
|
169
|
+
* {slug}.preview.cleforyx.com → cleforyx.com
|
|
170
|
+
*
|
|
171
|
+
* Throws a 409 ConflictError if the name is already taken.
|
|
172
|
+
*/
|
|
107
173
|
createSite(name: string, description?: string): Promise<HostingSite>;
|
|
108
|
-
/** Update site metadata. */
|
|
174
|
+
/** Update site metadata. Handles DNS rename if name changes. */
|
|
109
175
|
updateSite(siteId: string, patch: Partial<Pick<HostingSite, "name" | "description" | "status" | "customDomain">>): Promise<HostingSite>;
|
|
110
|
-
/**
|
|
111
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Begin site deletion flow.
|
|
178
|
+
*
|
|
179
|
+
* Pass `confirm: false` (or omit) to get a confirmation prompt with DNS info.
|
|
180
|
+
* Pass `confirm: true` to actually delete. Include `deleteDns: true` to also
|
|
181
|
+
* remove the Cloudflare DNS record.
|
|
182
|
+
*/
|
|
183
|
+
deleteSite(siteId: string, opts?: {
|
|
184
|
+
confirm?: boolean;
|
|
185
|
+
deleteDns?: boolean;
|
|
186
|
+
}): Promise<{
|
|
187
|
+
requiresConfirmation?: boolean;
|
|
188
|
+
dnsRecord?: object;
|
|
189
|
+
message: string;
|
|
190
|
+
deleted?: boolean;
|
|
191
|
+
}>;
|
|
112
192
|
/** Return a SiteReference for a specific site ID. */
|
|
113
193
|
site(siteId: string): SiteReference;
|
|
114
|
-
|
|
194
|
+
_previewUrl(siteId: string): string;
|
|
115
195
|
_getSite(siteId: string): Promise<HostingSite | null>;
|
|
116
196
|
_getActiveDeploy(siteId: string): Promise<HostingDeploy | null>;
|
|
117
197
|
_listDeploys(siteId: string): Promise<HostingDeploy[]>;
|
|
198
|
+
_getDnsStatus(siteId: string): Promise<DnsStatus>;
|
|
199
|
+
_reprovisionDns(siteId: string): Promise<{
|
|
200
|
+
subdomain: string;
|
|
201
|
+
url: string;
|
|
202
|
+
created: boolean;
|
|
203
|
+
}>;
|
|
118
204
|
_deployFiles(siteId: string, files: Record<string, Buffer>, opts?: DeployOptions): Promise<DeployResult>;
|
|
119
205
|
}
|
|
120
206
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hosting/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAIrC,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,CAAC;AACnD,MAAM,MAAM,YAAY,GAAI,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEvE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hosting/index.ts"],"names":[],"mappings":"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"}
|
package/dist/hosting/index.js
CHANGED
|
@@ -42,6 +42,7 @@ exports.ClefbaseHosting = exports.SiteReference = void 0;
|
|
|
42
42
|
* const site = hosting.site("my-site-id");
|
|
43
43
|
* const result = await site.deployFiles({ "index.html": htmlBuffer, "app.js": jsBuffer });
|
|
44
44
|
* console.log(`Live at ${result.url}`);
|
|
45
|
+
* console.log(`Preview at ${result.previewUrl}`);
|
|
45
46
|
*/
|
|
46
47
|
class SiteReference {
|
|
47
48
|
constructor(hosting, siteId) {
|
|
@@ -74,13 +75,29 @@ class SiteReference {
|
|
|
74
75
|
* message: "v1.2.0",
|
|
75
76
|
* onProgress: (done, total) => console.log(`${done}/${total}`),
|
|
76
77
|
* });
|
|
78
|
+
* console.log(`Live at ${result.url}`);
|
|
77
79
|
*/
|
|
78
80
|
async deployFiles(files, opts) {
|
|
79
81
|
return this.hosting._deployFiles(this.siteId, files, opts);
|
|
80
82
|
}
|
|
81
|
-
/**
|
|
83
|
+
/** Check the DNS status of this site's preview + custom domains. */
|
|
84
|
+
async getDnsStatus() {
|
|
85
|
+
return this.hosting._getDnsStatus(this.siteId);
|
|
86
|
+
}
|
|
87
|
+
/** Re-provision the preview DNS record (e.g. if it was accidentally deleted). */
|
|
88
|
+
async reprovisionDns() {
|
|
89
|
+
return this.hosting._reprovisionDns(this.siteId);
|
|
90
|
+
}
|
|
91
|
+
/** The preview URL for this site ({slug}.preview.cleforyx.com). */
|
|
92
|
+
get previewUrl() {
|
|
93
|
+
return this.hosting._previewUrl(this.siteId);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The public URL — custom domain if configured, else preview subdomain.
|
|
97
|
+
* Requires the site metadata; use `(await site.get())?.customDomain` to check.
|
|
98
|
+
*/
|
|
82
99
|
get url() {
|
|
83
|
-
return this.
|
|
100
|
+
return this.previewUrl; // SDK doesn't cache site; use DeployResult.url for canonical
|
|
84
101
|
}
|
|
85
102
|
}
|
|
86
103
|
exports.SiteReference = SiteReference;
|
|
@@ -90,7 +107,12 @@ exports.SiteReference = SiteReference;
|
|
|
90
107
|
*
|
|
91
108
|
* @example
|
|
92
109
|
* const hosting = getHosting(app);
|
|
110
|
+
*
|
|
111
|
+
* // Create a site — automatically provisions {name}.preview.cleforyx.com
|
|
93
112
|
* const site = await hosting.createSite("my-app");
|
|
113
|
+
* console.log(site.previewUrl); // https://my-app.preview.cleforyx.com
|
|
114
|
+
*
|
|
115
|
+
* // Deploy files
|
|
94
116
|
* const result = await hosting.site(site.id).deployFiles(files);
|
|
95
117
|
* console.log(result.url);
|
|
96
118
|
*/
|
|
@@ -104,24 +126,45 @@ class ClefbaseHosting {
|
|
|
104
126
|
async listSites() {
|
|
105
127
|
return this.http.get(`/databases/${this.dbId}/sites`);
|
|
106
128
|
}
|
|
107
|
-
/**
|
|
129
|
+
/**
|
|
130
|
+
* Create a new hosted site.
|
|
131
|
+
*
|
|
132
|
+
* Site names must be globally unique across the platform.
|
|
133
|
+
* A CNAME record will be automatically provisioned on Cloudflare:
|
|
134
|
+
* {slug}.preview.cleforyx.com → cleforyx.com
|
|
135
|
+
*
|
|
136
|
+
* Throws a 409 ConflictError if the name is already taken.
|
|
137
|
+
*/
|
|
108
138
|
async createSite(name, description) {
|
|
109
139
|
return this.http.post(`/databases/${this.dbId}/sites`, { name, description });
|
|
110
140
|
}
|
|
111
|
-
/** Update site metadata. */
|
|
141
|
+
/** Update site metadata. Handles DNS rename if name changes. */
|
|
112
142
|
async updateSite(siteId, patch) {
|
|
113
143
|
return this.http.patch(`/databases/${this.dbId}/sites/${siteId}`, patch);
|
|
114
144
|
}
|
|
115
|
-
/**
|
|
116
|
-
|
|
117
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Begin site deletion flow.
|
|
147
|
+
*
|
|
148
|
+
* Pass `confirm: false` (or omit) to get a confirmation prompt with DNS info.
|
|
149
|
+
* Pass `confirm: true` to actually delete. Include `deleteDns: true` to also
|
|
150
|
+
* remove the Cloudflare DNS record.
|
|
151
|
+
*/
|
|
152
|
+
async deleteSite(siteId, opts) {
|
|
153
|
+
const params = new URLSearchParams();
|
|
154
|
+
if (opts?.confirm)
|
|
155
|
+
params.set("confirm", "true");
|
|
156
|
+
if (opts?.deleteDns)
|
|
157
|
+
params.set("deleteDns", "true");
|
|
158
|
+
const qs = params.toString() ? `?${params}` : "";
|
|
159
|
+
return this.http.delete(`/databases/${this.dbId}/sites/${siteId}${qs}`);
|
|
118
160
|
}
|
|
119
161
|
/** Return a SiteReference for a specific site ID. */
|
|
120
162
|
site(siteId) {
|
|
121
163
|
return new SiteReference(this, siteId);
|
|
122
164
|
}
|
|
123
165
|
// ─── Internals ─────────────────────────────────────────────────────────────
|
|
124
|
-
|
|
166
|
+
_previewUrl(siteId) {
|
|
167
|
+
// Falls back to server URL path if site metadata isn't cached
|
|
125
168
|
return `${this.serverUrl.replace(/\/+$/, "")}/hosted/${this.dbId}/${siteId}`;
|
|
126
169
|
}
|
|
127
170
|
async _getSite(siteId) {
|
|
@@ -148,28 +191,35 @@ class ClefbaseHosting {
|
|
|
148
191
|
async _listDeploys(siteId) {
|
|
149
192
|
return this.http.get(`/databases/${this.dbId}/sites/${siteId}/deploys`);
|
|
150
193
|
}
|
|
194
|
+
async _getDnsStatus(siteId) {
|
|
195
|
+
return this.http.get(`/databases/${this.dbId}/sites/${siteId}/dns`);
|
|
196
|
+
}
|
|
197
|
+
async _reprovisionDns(siteId) {
|
|
198
|
+
return this.http.post(`/databases/${this.dbId}/sites/${siteId}/dns/provision`, {});
|
|
199
|
+
}
|
|
151
200
|
async _deployFiles(siteId, files, opts = {}) {
|
|
152
201
|
const { entrypoint = "index.html", deployedBy, message, batchSize = 20, onProgress } = opts;
|
|
153
202
|
// 1. Create pending deploy
|
|
154
203
|
const pending = await this.http.post(`/databases/${this.dbId}/sites/${siteId}/deploys`, { deployedBy, entrypoint });
|
|
204
|
+
// 2. Get site for canonical URL
|
|
205
|
+
const siteData = await this._getSite(siteId).catch(() => null);
|
|
155
206
|
const filePaths = Object.keys(files);
|
|
156
207
|
const fileBuffers = Object.values(files);
|
|
157
208
|
const errors = [];
|
|
158
209
|
let uploaded = 0;
|
|
159
|
-
//
|
|
210
|
+
// 3. Detect whether we have native FormData (Node 18+) or need form-data pkg
|
|
160
211
|
const hasNativeFormData = typeof FormData !== "undefined";
|
|
161
212
|
let FormDataLegacy;
|
|
162
213
|
if (!hasNativeFormData) {
|
|
163
214
|
const mod = await Promise.resolve().then(() => __importStar(require("form-data")));
|
|
164
215
|
FormDataLegacy = mod.default;
|
|
165
216
|
}
|
|
166
|
-
//
|
|
217
|
+
// 4. Upload in batches
|
|
167
218
|
for (let i = 0; i < filePaths.length; i += batchSize) {
|
|
168
219
|
const batchPaths = filePaths.slice(i, i + batchSize);
|
|
169
220
|
const batchBuffers = fileBuffers.slice(i, i + batchSize);
|
|
170
221
|
try {
|
|
171
222
|
if (hasNativeFormData) {
|
|
172
|
-
// Node 18+ native FormData: Buffers must be wrapped in Blob/File
|
|
173
223
|
const form = new FormData();
|
|
174
224
|
for (let j = 0; j < batchPaths.length; j++) {
|
|
175
225
|
const filename = batchPaths[j].split("/").pop() ?? batchPaths[j];
|
|
@@ -182,7 +232,6 @@ class ClefbaseHosting {
|
|
|
182
232
|
await this.http.request(`/databases/${this.dbId}/deploys/${pending.id}/files/batch`, { method: "POST", body: form, isFormData: true });
|
|
183
233
|
}
|
|
184
234
|
else {
|
|
185
|
-
// Older Node: form-data package accepts Buffers natively
|
|
186
235
|
const form = new FormDataLegacy();
|
|
187
236
|
for (let j = 0; j < batchPaths.length; j++) {
|
|
188
237
|
form.append("files[]", batchBuffers[j], {
|
|
@@ -200,13 +249,17 @@ class ClefbaseHosting {
|
|
|
200
249
|
}
|
|
201
250
|
onProgress?.(Math.min(i + batchSize, filePaths.length), filePaths.length);
|
|
202
251
|
}
|
|
203
|
-
//
|
|
252
|
+
// 5. Finalize → go live
|
|
204
253
|
const live = await this.http.post(`/databases/${this.dbId}/deploys/${pending.id}/finalize`, { message: message ?? "Deployed via clefbase SDK" });
|
|
254
|
+
const canonicalUrl = siteData?.customDomain
|
|
255
|
+
? `https://${siteData.customDomain}`
|
|
256
|
+
: siteData?.previewUrl ?? this._previewUrl(siteId);
|
|
205
257
|
return {
|
|
206
258
|
deploy: live,
|
|
207
259
|
filesUploaded: uploaded,
|
|
208
260
|
errors,
|
|
209
|
-
url:
|
|
261
|
+
url: canonicalUrl,
|
|
262
|
+
previewUrl: siteData?.previewUrl ?? this._previewUrl(siteId),
|
|
210
263
|
};
|
|
211
264
|
}
|
|
212
265
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hosting/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hosting/index.ts"],"names":[],"mappings":"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"}
|