vela 0.10.14 → 0.11.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/README.md +1 -1
- package/dist/bin.js +1297 -1023
- package/dist/bin.js.map +4 -4
- package/package.json +1 -1
- package/templates/server/apply.sh +51 -11
- package/templates/server/destroy.sh +2 -2
- package/templates/server/lib.sh +38 -0
- package/templates/server/origin.sh +62 -0
package/dist/bin.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/bin.ts
|
|
4
|
-
import
|
|
4
|
+
import process38 from "node:process";
|
|
5
5
|
|
|
6
6
|
// src/lib/argv.ts
|
|
7
7
|
function normalizeArgv(argv) {
|
|
@@ -11,17 +11,17 @@ function normalizeArgv(argv) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// src/program.ts
|
|
14
|
-
import
|
|
15
|
-
import * as
|
|
16
|
-
import { Command as
|
|
14
|
+
import process37 from "node:process";
|
|
15
|
+
import * as p61 from "@clack/prompts";
|
|
16
|
+
import { Command as Command104 } from "commander";
|
|
17
17
|
import nodePath from "node:path";
|
|
18
18
|
import dotenv2 from "dotenv";
|
|
19
|
-
import
|
|
19
|
+
import pc38 from "picocolors";
|
|
20
20
|
|
|
21
21
|
// package.json
|
|
22
22
|
var package_default = {
|
|
23
23
|
name: "vela",
|
|
24
|
-
version: "0.
|
|
24
|
+
version: "0.11.0",
|
|
25
25
|
type: "module",
|
|
26
26
|
description: "A CLI for creating and updating SvelteKit projects",
|
|
27
27
|
license: "MIT",
|
|
@@ -222,15 +222,19 @@ function stubCommand(name, description, fullName) {
|
|
|
222
222
|
// src/lib/workspace.ts
|
|
223
223
|
import fs2 from "node:fs";
|
|
224
224
|
import path from "node:path";
|
|
225
|
-
import
|
|
225
|
+
import process3 from "node:process";
|
|
226
226
|
|
|
227
227
|
// src/lib/constants.ts
|
|
228
|
+
import process2 from "node:process";
|
|
228
229
|
var DATA_DIR = "data";
|
|
229
230
|
var MIGRATIONS_DIR = "migrations";
|
|
230
231
|
var PUBLIC_DIR = "(public)";
|
|
231
232
|
var APP_DIR = "(app)";
|
|
232
233
|
var LEGAL_DIR = "(legal)";
|
|
233
|
-
var API_URL = "https://velastack.dev"
|
|
234
|
+
var API_URL = (process2.env.VELA_API_URL?.trim() || "https://velastack.dev").replace(
|
|
235
|
+
/\/$/,
|
|
236
|
+
""
|
|
237
|
+
);
|
|
234
238
|
var FIXTURE_PREFIX = "vela";
|
|
235
239
|
|
|
236
240
|
// src/lib/package-json.ts
|
|
@@ -313,7 +317,7 @@ function sortKeys(obj) {
|
|
|
313
317
|
}
|
|
314
318
|
|
|
315
319
|
// src/lib/workspace.ts
|
|
316
|
-
function findWorkspaceRoot(from =
|
|
320
|
+
function findWorkspaceRoot(from = process3.cwd()) {
|
|
317
321
|
let currentDir = from;
|
|
318
322
|
while (currentDir !== path.parse(currentDir).root) {
|
|
319
323
|
if (fs2.existsSync(path.join(currentDir, "package.json"))) return currentDir;
|
|
@@ -321,11 +325,11 @@ function findWorkspaceRoot(from = process2.cwd()) {
|
|
|
321
325
|
}
|
|
322
326
|
return null;
|
|
323
327
|
}
|
|
324
|
-
function hasBackend(from =
|
|
328
|
+
function hasBackend(from = process3.cwd()) {
|
|
325
329
|
const root = findWorkspaceRoot(from);
|
|
326
330
|
return root !== null && fs2.existsSync(path.join(root, DATA_DIR));
|
|
327
331
|
}
|
|
328
|
-
function localDataDir(from =
|
|
332
|
+
function localDataDir(from = process3.cwd()) {
|
|
329
333
|
return path.join(findWorkspaceRoot(from) ?? from, DATA_DIR);
|
|
330
334
|
}
|
|
331
335
|
async function getWorkspace() {
|
|
@@ -381,7 +385,7 @@ function detectFeatures(root, { isAppMode, isPaymentsMode }) {
|
|
|
381
385
|
// src/commands/bless.ts
|
|
382
386
|
import fs13 from "node:fs";
|
|
383
387
|
import path11 from "node:path";
|
|
384
|
-
import
|
|
388
|
+
import process6 from "node:process";
|
|
385
389
|
import * as v2 from "valibot";
|
|
386
390
|
import { Command as Command2 } from "commander";
|
|
387
391
|
import * as p4 from "@clack/prompts";
|
|
@@ -482,7 +486,7 @@ function readManifest(root, name) {
|
|
|
482
486
|
// src/lib/package-manager.ts
|
|
483
487
|
import fs4 from "node:fs";
|
|
484
488
|
import path3 from "node:path";
|
|
485
|
-
import
|
|
489
|
+
import process4 from "node:process";
|
|
486
490
|
import { exec } from "tinyexec";
|
|
487
491
|
import { Option } from "commander";
|
|
488
492
|
import * as p2 from "@clack/prompts";
|
|
@@ -498,7 +502,7 @@ var installOption = new Option(
|
|
|
498
502
|
"installs dependencies with a specified package manager"
|
|
499
503
|
).choices(AGENT_NAMES);
|
|
500
504
|
function getUserAgent() {
|
|
501
|
-
const userAgent =
|
|
505
|
+
const userAgent = process4.env.npm_config_user_agent;
|
|
502
506
|
if (!userAgent) return void 0;
|
|
503
507
|
const pmSpec = userAgent.split(" ")[0];
|
|
504
508
|
const separatorPos = pmSpec.lastIndexOf("/");
|
|
@@ -508,7 +512,7 @@ function getUserAgent() {
|
|
|
508
512
|
async function packageManagerPrompt(cwd) {
|
|
509
513
|
const detected = await detect({ cwd });
|
|
510
514
|
const agent = detected?.name ?? getUserAgent();
|
|
511
|
-
if (!
|
|
515
|
+
if (!process4.stdout.isTTY) return agent;
|
|
512
516
|
const options = [
|
|
513
517
|
{ label: "None", value: void 0 },
|
|
514
518
|
...AGENT_NAMES.map((pm2) => ({ value: pm2, label: pm2 }))
|
|
@@ -520,14 +524,14 @@ async function packageManagerPrompt(cwd) {
|
|
|
520
524
|
});
|
|
521
525
|
if (p2.isCancel(pm)) {
|
|
522
526
|
p2.cancel("Operation cancelled.");
|
|
523
|
-
|
|
527
|
+
process4.exit(1);
|
|
524
528
|
}
|
|
525
529
|
return pm;
|
|
526
530
|
}
|
|
527
531
|
async function installDependencies(agent, cwd) {
|
|
528
532
|
const task = p2.taskLog({
|
|
529
533
|
title: `Installing dependencies with ${agent}...`,
|
|
530
|
-
limit: Math.ceil(
|
|
534
|
+
limit: Math.ceil(process4.stdout.rows / 2),
|
|
531
535
|
spacing: 0,
|
|
532
536
|
retainLog: true
|
|
533
537
|
});
|
|
@@ -544,7 +548,7 @@ async function installDependencies(agent, cwd) {
|
|
|
544
548
|
} catch {
|
|
545
549
|
task.error("Failed to install dependencies");
|
|
546
550
|
p2.cancel("Operation failed.");
|
|
547
|
-
|
|
551
|
+
process4.exit(2);
|
|
548
552
|
}
|
|
549
553
|
}
|
|
550
554
|
function addPnpmBuildDependencies(cwd, packageManager, allowedPackages) {
|
|
@@ -566,7 +570,7 @@ function addPnpmBuildDependencies(cwd, packageManager, allowedPackages) {
|
|
|
566
570
|
import fs5 from "node:fs";
|
|
567
571
|
import net from "node:net";
|
|
568
572
|
import path4 from "node:path";
|
|
569
|
-
import
|
|
573
|
+
import process5 from "node:process";
|
|
570
574
|
import { createRequire } from "node:module";
|
|
571
575
|
import { spawn } from "node:child_process";
|
|
572
576
|
import PocketBase from "pocketbase";
|
|
@@ -696,8 +700,8 @@ async function withPocketbase(cwd, fn, creds) {
|
|
|
696
700
|
const dir = path4.join(cwd, DATA_DIR);
|
|
697
701
|
const migrationsDir = path4.join(cwd, MIGRATIONS_DIR);
|
|
698
702
|
const host = "localhost";
|
|
699
|
-
const email3 = creds?.email ??
|
|
700
|
-
const password11 = creds?.password ??
|
|
703
|
+
const email3 = creds?.email ?? process5.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
704
|
+
const password11 = creds?.password ?? process5.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
701
705
|
if (!fs5.existsSync(dir)) {
|
|
702
706
|
throw new Error("PocketBase data directory does not exist");
|
|
703
707
|
}
|
|
@@ -791,8 +795,8 @@ function pocketbaseVersion() {
|
|
|
791
795
|
return pkg.version;
|
|
792
796
|
}
|
|
793
797
|
async function ensureSuperuser(cwd) {
|
|
794
|
-
const email3 =
|
|
795
|
-
const password11 =
|
|
798
|
+
const email3 = process5.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
799
|
+
const password11 = process5.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
796
800
|
if (!email3 || !password11) return;
|
|
797
801
|
const dir = path4.join(cwd, DATA_DIR);
|
|
798
802
|
if (!fs5.existsSync(dir)) return;
|
|
@@ -1339,7 +1343,7 @@ async function blessProject(cwdArg, options) {
|
|
|
1339
1343
|
{
|
|
1340
1344
|
onCancel: () => {
|
|
1341
1345
|
p4.cancel("Operation cancelled.");
|
|
1342
|
-
|
|
1346
|
+
process6.exit(0);
|
|
1343
1347
|
}
|
|
1344
1348
|
}
|
|
1345
1349
|
);
|
|
@@ -1556,7 +1560,7 @@ function summarize(names) {
|
|
|
1556
1560
|
return `${names.slice(0, 3).join(", ")}, and ${names.length - 3} more`;
|
|
1557
1561
|
}
|
|
1558
1562
|
function printNextSteps(projectPath, packageManager) {
|
|
1559
|
-
const relative = path11.relative(
|
|
1563
|
+
const relative = path11.relative(process6.cwd(), projectPath);
|
|
1560
1564
|
const pm = packageManager ?? getUserAgent() ?? "npm";
|
|
1561
1565
|
const nextSteps = [];
|
|
1562
1566
|
if (relative !== "") {
|
|
@@ -1582,7 +1586,7 @@ function printNextSteps(projectPath, packageManager) {
|
|
|
1582
1586
|
// src/commands/create.ts
|
|
1583
1587
|
import fs14 from "node:fs";
|
|
1584
1588
|
import path12 from "node:path";
|
|
1585
|
-
import
|
|
1589
|
+
import process7 from "node:process";
|
|
1586
1590
|
import * as v3 from "valibot";
|
|
1587
1591
|
import { Command as Command3 } from "commander";
|
|
1588
1592
|
import * as p5 from "@clack/prompts";
|
|
@@ -1604,7 +1608,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
|
|
|
1604
1608
|
projectPath,
|
|
1605
1609
|
options
|
|
1606
1610
|
);
|
|
1607
|
-
const relative = path12.relative(
|
|
1611
|
+
const relative = path12.relative(process7.cwd(), directory);
|
|
1608
1612
|
const pm = packageManager ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
|
|
1609
1613
|
const nextSteps = [];
|
|
1610
1614
|
if (relative !== "") {
|
|
@@ -1643,7 +1647,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
|
|
|
1643
1647
|
async function createProject(cwdArg, options) {
|
|
1644
1648
|
const onCancel2 = () => {
|
|
1645
1649
|
p5.cancel("Operation cancelled.");
|
|
1646
|
-
|
|
1650
|
+
process7.exit(0);
|
|
1647
1651
|
};
|
|
1648
1652
|
const template = findProjectTemplate(options.template ?? DEFAULT_TEMPLATE);
|
|
1649
1653
|
if (!template.backend && (options.email || options.password)) {
|
|
@@ -1780,7 +1784,7 @@ async function runPattern(slug2, argv, input, report4) {
|
|
|
1780
1784
|
throw new Error(`Unknown pattern: ${slug2}`);
|
|
1781
1785
|
}
|
|
1782
1786
|
const { workspaceRootDir, features } = await getWorkspace();
|
|
1783
|
-
const
|
|
1787
|
+
const log45 = p6.taskLog({ title: report4.task.title });
|
|
1784
1788
|
let result;
|
|
1785
1789
|
try {
|
|
1786
1790
|
result = await pattern.generate({
|
|
@@ -1800,11 +1804,11 @@ async function runPattern(slug2, argv, input, report4) {
|
|
|
1800
1804
|
});
|
|
1801
1805
|
return collections2;
|
|
1802
1806
|
},
|
|
1803
|
-
logger: { info: (message) =>
|
|
1807
|
+
logger: { info: (message) => log45.message(message) }
|
|
1804
1808
|
});
|
|
1805
|
-
|
|
1809
|
+
log45.success(report4.task.success);
|
|
1806
1810
|
} catch (e) {
|
|
1807
|
-
|
|
1811
|
+
log45.error(report4.task.error);
|
|
1808
1812
|
throw e;
|
|
1809
1813
|
}
|
|
1810
1814
|
const rel = (f) => toRelative(workspaceRootDir, f);
|
|
@@ -1847,6 +1851,7 @@ import pc4 from "picocolors";
|
|
|
1847
1851
|
import fs15 from "node:fs";
|
|
1848
1852
|
import os from "node:os";
|
|
1849
1853
|
import path14 from "node:path";
|
|
1854
|
+
import process8 from "node:process";
|
|
1850
1855
|
var CONFIG_DIR = path14.join(os.homedir(), ".vela");
|
|
1851
1856
|
var CONFIG_PATH = path14.join(CONFIG_DIR, "config.json");
|
|
1852
1857
|
function readConfig() {
|
|
@@ -1864,12 +1869,17 @@ function writeConfig(config) {
|
|
|
1864
1869
|
function clearConfig() {
|
|
1865
1870
|
if (fs15.existsSync(CONFIG_PATH)) fs15.unlinkSync(CONFIG_PATH);
|
|
1866
1871
|
}
|
|
1872
|
+
function readApiKey() {
|
|
1873
|
+
const fromEnv = process8.env.VELA_API_KEY?.trim();
|
|
1874
|
+
if (fromEnv) return fromEnv;
|
|
1875
|
+
return readConfig()?.apiKey ?? null;
|
|
1876
|
+
}
|
|
1867
1877
|
function requireApiKey() {
|
|
1868
|
-
const
|
|
1869
|
-
if (!
|
|
1870
|
-
throw new Error("Not logged in. Run `vela login` to login.");
|
|
1878
|
+
const apiKey = readApiKey();
|
|
1879
|
+
if (!apiKey) {
|
|
1880
|
+
throw new Error("Not logged in. Run `vela login` to login, or set VELA_API_KEY.");
|
|
1871
1881
|
}
|
|
1872
|
-
return
|
|
1882
|
+
return apiKey;
|
|
1873
1883
|
}
|
|
1874
1884
|
|
|
1875
1885
|
// src/lib/project-config.ts
|
|
@@ -2415,7 +2425,7 @@ var migration = new Command8("migration").description("generate a migration for
|
|
|
2415
2425
|
var generate = new Command9("generate").description("generate scaffolding for database models and forms").configureHelp(helpConfig).addCommand(form).addCommand(schema).addCommand(resource).addCommand(scaffold).addCommand(migration);
|
|
2416
2426
|
|
|
2417
2427
|
// src/commands/enable.ts
|
|
2418
|
-
import { Command as
|
|
2428
|
+
import { Command as Command24 } from "commander";
|
|
2419
2429
|
|
|
2420
2430
|
// src/commands/enable/auth.ts
|
|
2421
2431
|
import { Command as Command10 } from "commander";
|
|
@@ -2574,7 +2584,7 @@ var teams = new Command15("teams").description("enable team / multi-tenant suppo
|
|
|
2574
2584
|
);
|
|
2575
2585
|
|
|
2576
2586
|
// src/commands/enable/payments.ts
|
|
2577
|
-
import
|
|
2587
|
+
import process9 from "node:process";
|
|
2578
2588
|
import { Command as Command16 } from "commander";
|
|
2579
2589
|
import * as p14 from "@clack/prompts";
|
|
2580
2590
|
var PROVIDERS = [{ value: "stripe", label: "Stripe" }];
|
|
@@ -2620,12 +2630,12 @@ async function resolveProvider(value, source) {
|
|
|
2620
2630
|
});
|
|
2621
2631
|
if (p14.isCancel(selected)) {
|
|
2622
2632
|
p14.cancel("Operation cancelled.");
|
|
2623
|
-
|
|
2633
|
+
process9.exit(0);
|
|
2624
2634
|
}
|
|
2625
2635
|
return selected;
|
|
2626
2636
|
}
|
|
2627
2637
|
async function ensureWebhookSecret() {
|
|
2628
|
-
const existing =
|
|
2638
|
+
const existing = process9.env.STRIPE_WEBHOOK_SECRET;
|
|
2629
2639
|
if (existing) return existing;
|
|
2630
2640
|
p14.note(
|
|
2631
2641
|
[
|
|
@@ -2653,12 +2663,12 @@ async function ensurePriceId() {
|
|
|
2653
2663
|
});
|
|
2654
2664
|
if (p14.isCancel(value)) {
|
|
2655
2665
|
p14.cancel("Operation cancelled.");
|
|
2656
|
-
|
|
2666
|
+
process9.exit(0);
|
|
2657
2667
|
}
|
|
2658
2668
|
return (value ?? "").trim();
|
|
2659
2669
|
}
|
|
2660
2670
|
async function ensureKey(envVar, message) {
|
|
2661
|
-
const existing =
|
|
2671
|
+
const existing = process9.env[envVar];
|
|
2662
2672
|
if (existing) return existing;
|
|
2663
2673
|
return promptPassword(message);
|
|
2664
2674
|
}
|
|
@@ -2669,7 +2679,7 @@ async function promptPassword(message) {
|
|
|
2669
2679
|
});
|
|
2670
2680
|
if (p14.isCancel(value)) {
|
|
2671
2681
|
p14.cancel("Operation cancelled.");
|
|
2672
|
-
|
|
2682
|
+
process9.exit(0);
|
|
2673
2683
|
}
|
|
2674
2684
|
return value;
|
|
2675
2685
|
}
|
|
@@ -2700,14 +2710,40 @@ var subscriptions = new Command17("subscriptions").description("enable Stripe su
|
|
|
2700
2710
|
)
|
|
2701
2711
|
);
|
|
2702
2712
|
|
|
2703
|
-
// src/commands/enable/
|
|
2704
|
-
import process10 from "node:process";
|
|
2713
|
+
// src/commands/enable/notifications.ts
|
|
2705
2714
|
import { Command as Command18 } from "commander";
|
|
2715
|
+
var notifications = new Command18("notifications").description("enable in-app notifications with a bell dropdown (requires auth)").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
2716
|
+
(_opts, cmd) => runCommand(
|
|
2717
|
+
() => runPattern(
|
|
2718
|
+
"enable-notifications",
|
|
2719
|
+
cmd.args,
|
|
2720
|
+
{},
|
|
2721
|
+
{
|
|
2722
|
+
summary: "Enabled notifications.",
|
|
2723
|
+
nextSteps: [
|
|
2724
|
+
"Run `vela dev` and open any (app) page to see the bell in the header; /notifications lists them all.",
|
|
2725
|
+
"Send one from server code with `notify(locals.admin, userId, { title, body })` from $lib/server/notifications.",
|
|
2726
|
+
"Customize the bell in src/lib/components/notifications-bell.svelte and the page in src/routes/(app)/notifications/."
|
|
2727
|
+
],
|
|
2728
|
+
task: {
|
|
2729
|
+
title: "Enabling notifications",
|
|
2730
|
+
success: "Enabled notifications",
|
|
2731
|
+
error: "Failed to enable notifications"
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
),
|
|
2735
|
+
"Failed to enable notifications."
|
|
2736
|
+
)
|
|
2737
|
+
);
|
|
2738
|
+
|
|
2739
|
+
// src/commands/enable/s3.ts
|
|
2740
|
+
import process12 from "node:process";
|
|
2741
|
+
import { Command as Command19 } from "commander";
|
|
2706
2742
|
import * as p17 from "@clack/prompts";
|
|
2707
2743
|
import pc8 from "picocolors";
|
|
2708
2744
|
|
|
2709
2745
|
// src/lib/server-command.ts
|
|
2710
|
-
import
|
|
2746
|
+
import process11 from "node:process";
|
|
2711
2747
|
import * as v5 from "valibot";
|
|
2712
2748
|
import * as p15 from "@clack/prompts";
|
|
2713
2749
|
import pc5 from "picocolors";
|
|
@@ -2865,30 +2901,18 @@ function releaseId(date = /* @__PURE__ */ new Date()) {
|
|
|
2865
2901
|
return date.toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z");
|
|
2866
2902
|
}
|
|
2867
2903
|
|
|
2868
|
-
// src/lib/
|
|
2869
|
-
import
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
acceptHostKeys: v4.optional(v4.boolean())
|
|
2874
|
-
};
|
|
2875
|
-
function addSshOptions(command) {
|
|
2876
|
-
return command.option("-i, --identity <file>", "SSH private key to authenticate with").option("--ssh-port <port>", "SSH port").option("--accept-host-keys", "trust an unknown host key on first connect (CI)");
|
|
2877
|
-
}
|
|
2878
|
-
function sshOptionsFrom(options) {
|
|
2879
|
-
return {
|
|
2880
|
-
identityFile: options.identity,
|
|
2881
|
-
port: options.sshPort ? Number(options.sshPort) : void 0,
|
|
2882
|
-
acceptNewHostKeys: options.acceptHostKeys
|
|
2883
|
-
};
|
|
2884
|
-
}
|
|
2904
|
+
// src/lib/artifact.ts
|
|
2905
|
+
import fs20 from "node:fs";
|
|
2906
|
+
import path19 from "node:path";
|
|
2907
|
+
import { detect as detect4 } from "package-manager-detector";
|
|
2908
|
+
import { resolveCommand as resolveCommand4 } from "package-manager-detector/commands";
|
|
2885
2909
|
|
|
2886
2910
|
// src/lib/ssh.ts
|
|
2887
2911
|
import fs19 from "node:fs";
|
|
2888
2912
|
import os2 from "node:os";
|
|
2889
2913
|
import path18 from "node:path";
|
|
2890
2914
|
import crypto2 from "node:crypto";
|
|
2891
|
-
import
|
|
2915
|
+
import process10 from "node:process";
|
|
2892
2916
|
import { spawn as spawn2 } from "node:child_process";
|
|
2893
2917
|
var RemoteCommandError = class extends Error {
|
|
2894
2918
|
exitCode;
|
|
@@ -3166,17 +3190,17 @@ function spawnCapture(command, args, opts = {}) {
|
|
|
3166
3190
|
const child = spawn2(command, args, {
|
|
3167
3191
|
stdio,
|
|
3168
3192
|
cwd: opts.cwd,
|
|
3169
|
-
env: opts.env ? { ...
|
|
3193
|
+
env: opts.env ? { ...process10.env, ...opts.env } : void 0
|
|
3170
3194
|
});
|
|
3171
3195
|
let stdout = "";
|
|
3172
3196
|
let stderr = "";
|
|
3173
3197
|
child.stdout?.on("data", (chunk) => {
|
|
3174
3198
|
stdout += chunk;
|
|
3175
|
-
if (opts.streamStdout)
|
|
3199
|
+
if (opts.streamStdout) process10.stdout.write(chunk);
|
|
3176
3200
|
});
|
|
3177
3201
|
child.stderr?.on("data", (chunk) => {
|
|
3178
3202
|
stderr += chunk;
|
|
3179
|
-
if (opts.stream)
|
|
3203
|
+
if (opts.stream) process10.stderr.write(chunk);
|
|
3180
3204
|
});
|
|
3181
3205
|
child.on("error", reject);
|
|
3182
3206
|
child.on("close", (code) => resolve2({ stdout, stderr, exitCode: code ?? 1 }));
|
|
@@ -3186,15 +3210,108 @@ function spawnCapture(command, args, opts = {}) {
|
|
|
3186
3210
|
});
|
|
3187
3211
|
}
|
|
3188
3212
|
|
|
3213
|
+
// src/lib/artifact.ts
|
|
3214
|
+
var DEFAULT_OUTPUT_DIR = "build";
|
|
3215
|
+
var BuildError = class extends Error {
|
|
3216
|
+
};
|
|
3217
|
+
async function runBuild(cwd, buildCommand, env2) {
|
|
3218
|
+
if (buildCommand) {
|
|
3219
|
+
const result2 = await spawnCapture("bash", ["-lc", buildCommand], {
|
|
3220
|
+
cwd,
|
|
3221
|
+
stream: true,
|
|
3222
|
+
streamStdout: true,
|
|
3223
|
+
env: env2
|
|
3224
|
+
});
|
|
3225
|
+
if (result2.exitCode !== 0)
|
|
3226
|
+
throw new BuildError(`\`${buildCommand}\` exited ${result2.exitCode}.`);
|
|
3227
|
+
return;
|
|
3228
|
+
}
|
|
3229
|
+
const pm = (await detect4({ cwd }))?.name ?? "npm";
|
|
3230
|
+
const resolved = resolveCommand4(pm, "run", ["build"]);
|
|
3231
|
+
if (!resolved) throw new BuildError(`Could not work out how to run a build with ${pm}.`);
|
|
3232
|
+
const result = await spawnCapture(resolved.command, resolved.args, {
|
|
3233
|
+
cwd,
|
|
3234
|
+
stream: true,
|
|
3235
|
+
streamStdout: true,
|
|
3236
|
+
env: env2
|
|
3237
|
+
});
|
|
3238
|
+
if (result.exitCode !== 0) {
|
|
3239
|
+
throw new BuildError(
|
|
3240
|
+
`\`${resolved.command} ${resolved.args.join(" ")}\` exited ${result.exitCode}.`
|
|
3241
|
+
);
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
function collectArtifact(cwd, config = {}) {
|
|
3245
|
+
const outputDir = config.outputDir ?? DEFAULT_OUTPUT_DIR;
|
|
3246
|
+
const entries = [];
|
|
3247
|
+
const add2 = (rel, remoteDir = "") => {
|
|
3248
|
+
const localPath = path19.join(cwd, rel);
|
|
3249
|
+
if (fs20.existsSync(localPath)) entries.push({ localPath, remoteDir });
|
|
3250
|
+
};
|
|
3251
|
+
const buildPath = path19.join(cwd, outputDir);
|
|
3252
|
+
if (!fs20.existsSync(path19.join(buildPath, "index.js"))) {
|
|
3253
|
+
throw new BuildError(
|
|
3254
|
+
`No ${outputDir}/index.js after the build.
|
|
3255
|
+
|
|
3256
|
+
Deploying to a server needs @sveltejs/adapter-node. Install it and set it as
|
|
3257
|
+
the adapter in your Vite or Svelte config, then build again.`
|
|
3258
|
+
);
|
|
3259
|
+
}
|
|
3260
|
+
entries.push({ localPath: buildPath, remoteDir: "" });
|
|
3261
|
+
add2("package.json");
|
|
3262
|
+
add2("package-lock.json");
|
|
3263
|
+
add2(".npmrc");
|
|
3264
|
+
add2(MIGRATIONS_DIR);
|
|
3265
|
+
const hooks = path19.join(cwd, DATA_DIR, "hooks");
|
|
3266
|
+
if (fs20.existsSync(hooks)) entries.push({ localPath: hooks, remoteDir: "hooks" });
|
|
3267
|
+
for (const extra of config.include ?? []) add2(extra);
|
|
3268
|
+
return entries;
|
|
3269
|
+
}
|
|
3270
|
+
async function gitSha(cwd) {
|
|
3271
|
+
const result = await spawnCapture("git", ["rev-parse", "HEAD"], { cwd });
|
|
3272
|
+
return result.exitCode === 0 ? result.stdout.trim() : "";
|
|
3273
|
+
}
|
|
3274
|
+
async function currentBranch(cwd) {
|
|
3275
|
+
const result = await spawnCapture("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd });
|
|
3276
|
+
const branch = result.exitCode === 0 ? result.stdout.trim() : "";
|
|
3277
|
+
if (!branch || branch === "HEAD") {
|
|
3278
|
+
throw new Error(
|
|
3279
|
+
`No branch is checked out here${branch === "HEAD" ? " (detached HEAD)" : ""}, so \`-t preview\` has nothing to name.
|
|
3280
|
+
|
|
3281
|
+
Name it: \`-t preview:<branch>\`.`
|
|
3282
|
+
);
|
|
3283
|
+
}
|
|
3284
|
+
return branch;
|
|
3285
|
+
}
|
|
3286
|
+
|
|
3287
|
+
// src/lib/ssh-options.ts
|
|
3288
|
+
import * as v4 from "valibot";
|
|
3289
|
+
var SSH_OPTION_SCHEMA = {
|
|
3290
|
+
identity: v4.optional(v4.string()),
|
|
3291
|
+
sshPort: v4.optional(v4.string()),
|
|
3292
|
+
acceptHostKeys: v4.optional(v4.boolean())
|
|
3293
|
+
};
|
|
3294
|
+
function addSshOptions(command) {
|
|
3295
|
+
return command.option("-i, --identity <file>", "SSH private key to authenticate with").option("--ssh-port <port>", "SSH port").option("--accept-host-keys", "trust an unknown host key on first connect (CI)");
|
|
3296
|
+
}
|
|
3297
|
+
function sshOptionsFrom(options) {
|
|
3298
|
+
return {
|
|
3299
|
+
identityFile: options.identity,
|
|
3300
|
+
port: options.sshPort ? Number(options.sshPort) : void 0,
|
|
3301
|
+
acceptNewHostKeys: options.acceptHostKeys
|
|
3302
|
+
};
|
|
3303
|
+
}
|
|
3304
|
+
|
|
3189
3305
|
// src/lib/remote.ts
|
|
3190
|
-
import
|
|
3306
|
+
import path20 from "node:path";
|
|
3191
3307
|
var VELA_ROOT = "/var/lib/vela";
|
|
3192
3308
|
var VELA_ETC = "/etc/vela";
|
|
3193
3309
|
var VELA_USER = "vela";
|
|
3194
3310
|
var SCRIPTS_DIR = `${VELA_ROOT}/scripts`;
|
|
3195
3311
|
var PROVISIONED_MARKER = `${VELA_ETC}/provisioned`;
|
|
3312
|
+
var ORIGIN_FILE = `${VELA_ETC}/origin.json`;
|
|
3196
3313
|
function serverTemplatesDir() {
|
|
3197
|
-
return
|
|
3314
|
+
return path20.join(templatesDir(), "server");
|
|
3198
3315
|
}
|
|
3199
3316
|
async function syncServerScripts(session) {
|
|
3200
3317
|
await session.script(`mkdir -p "$1" && chmod 0755 "$1"`, { args: [SCRIPTS_DIR] });
|
|
@@ -3226,6 +3343,20 @@ async function readServerInfo(session) {
|
|
|
3226
3343
|
return null;
|
|
3227
3344
|
}
|
|
3228
3345
|
}
|
|
3346
|
+
async function readServerIdentity(session) {
|
|
3347
|
+
const raw = await session.readFile(ORIGIN_FILE);
|
|
3348
|
+
if (!raw) return null;
|
|
3349
|
+
try {
|
|
3350
|
+
const parsed = JSON.parse(raw);
|
|
3351
|
+
if (!parsed.serverId || !parsed.originHost || !parsed.token) return null;
|
|
3352
|
+
return { serverId: parsed.serverId, originHost: parsed.originHost, token: parsed.token };
|
|
3353
|
+
} catch {
|
|
3354
|
+
return null;
|
|
3355
|
+
}
|
|
3356
|
+
}
|
|
3357
|
+
async function writeServerIdentity(session, identity) {
|
|
3358
|
+
await session.writeFile(ORIGIN_FILE, JSON.stringify(identity, null, 2) + "\n", "0600");
|
|
3359
|
+
}
|
|
3229
3360
|
async function requireProvisioned(session) {
|
|
3230
3361
|
const info = await readServerInfo(session);
|
|
3231
3362
|
if (!info) {
|
|
@@ -3257,12 +3388,13 @@ var remotePaths = {
|
|
|
3257
3388
|
env: (instance) => `${VELA_ETC}/apps/${instance}/env`,
|
|
3258
3389
|
runtimeEnv: (instance) => `${VELA_ETC}/apps/${instance}/runtime.env`,
|
|
3259
3390
|
caddy: (instance) => `${VELA_ETC}/caddy/${instance}.caddy`,
|
|
3391
|
+
route: (instance) => `${VELA_ETC}/caddy/routes/${instance}.route`,
|
|
3260
3392
|
webUnit: (instance) => `vela-web@${instance}.service`,
|
|
3261
3393
|
pbUnit: (instance) => `vela-pb@${instance}.service`
|
|
3262
3394
|
};
|
|
3263
3395
|
|
|
3264
3396
|
// src/lib/remote-env.ts
|
|
3265
|
-
import
|
|
3397
|
+
import fs21 from "node:fs";
|
|
3266
3398
|
import dotenv from "dotenv";
|
|
3267
3399
|
var KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
3268
3400
|
function isValidKey(key) {
|
|
@@ -3310,7 +3442,7 @@ function quote(value) {
|
|
|
3310
3442
|
return `"${escaped}"`;
|
|
3311
3443
|
}
|
|
3312
3444
|
function readLocalEnvFile(file) {
|
|
3313
|
-
const parsed = dotenv.parse(
|
|
3445
|
+
const parsed = dotenv.parse(fs21.readFileSync(file));
|
|
3314
3446
|
const result = {};
|
|
3315
3447
|
for (const [key, value] of Object.entries(parsed)) {
|
|
3316
3448
|
if (isValidKey(key)) result[key] = value;
|
|
@@ -3367,6 +3499,15 @@ function parseTarget(raw, fallback) {
|
|
|
3367
3499
|
if (!value) {
|
|
3368
3500
|
return fallback === "local" ? { kind: "local" } : production();
|
|
3369
3501
|
}
|
|
3502
|
+
const lower = value.toLowerCase();
|
|
3503
|
+
if (lower === PREVIEW || lower.startsWith(`${PREVIEW}:`)) {
|
|
3504
|
+
const branch = value.slice(PREVIEW.length + 1) || void 0;
|
|
3505
|
+
return {
|
|
3506
|
+
kind: "preview",
|
|
3507
|
+
branch,
|
|
3508
|
+
envTag: branch ? branchToEnvTag(branch) : PREVIEW
|
|
3509
|
+
};
|
|
3510
|
+
}
|
|
3370
3511
|
if (SERVER_SHAPED.test(value)) {
|
|
3371
3512
|
throw new TargetError(
|
|
3372
3513
|
`${value} looks like a server, and ${bold("-t")} now selects a target rather than a machine.
|
|
@@ -3375,18 +3516,7 @@ Targets are ${bold("local")}, ${bold("production")}, or a name you choose such a
|
|
|
3375
3516
|
To point a target at a server, pass ${bold("--server")} on \`vela deploy\`.`
|
|
3376
3517
|
);
|
|
3377
3518
|
}
|
|
3378
|
-
const lower = value.toLowerCase();
|
|
3379
3519
|
if (lower === LOCAL_TARGET) return { kind: "local" };
|
|
3380
|
-
if (lower === PREVIEW || lower.startsWith(`${PREVIEW}:`)) {
|
|
3381
|
-
const branch = lower.slice(PREVIEW.length + 1) || void 0;
|
|
3382
|
-
return {
|
|
3383
|
-
kind: "preview",
|
|
3384
|
-
branch,
|
|
3385
|
-
// Held for when previews are built, so the grammar and the instance
|
|
3386
|
-
// naming cannot drift apart in the meantime.
|
|
3387
|
-
envTag: branch ? branchToEnvTag(branch) : PREVIEW
|
|
3388
|
-
};
|
|
3389
|
-
}
|
|
3390
3520
|
if (value.includes(":")) {
|
|
3391
3521
|
throw new TargetError(
|
|
3392
3522
|
`${value} is not a target. Only ${bold("preview")} takes a \`:branch\` suffix.`
|
|
@@ -3401,6 +3531,9 @@ Use lowercase letters, digits and single dashes, such as ${bold("staging")}.`
|
|
|
3401
3531
|
}
|
|
3402
3532
|
return { kind: "remote", name: lower, envTag: normalizeEnvTag(lower) };
|
|
3403
3533
|
}
|
|
3534
|
+
function bindingKey(target) {
|
|
3535
|
+
return target.kind === "preview" ? PREVIEW : target.envTag;
|
|
3536
|
+
}
|
|
3404
3537
|
function production() {
|
|
3405
3538
|
return { kind: "remote", name: PRODUCTION_TARGET, envTag: PROD_ENV };
|
|
3406
3539
|
}
|
|
@@ -3430,17 +3563,13 @@ function addTargetOptions(command, fallback) {
|
|
|
3430
3563
|
}
|
|
3431
3564
|
async function withTarget(raw, handlers, run = {}) {
|
|
3432
3565
|
const options = parseOptions(OptionsSchema, raw);
|
|
3433
|
-
|
|
3566
|
+
let target = parseTarget(options.target, "production");
|
|
3434
3567
|
const label4 = run.label ? `vela ${run.label}` : "this command";
|
|
3435
|
-
if (target.kind === "preview") {
|
|
3436
|
-
throw new Error(
|
|
3437
|
-
`Preview targets are not supported yet.
|
|
3438
|
-
|
|
3439
|
-
\`${describeTarget(target)}\` parses, but nothing deploys it: previews need wildcard
|
|
3440
|
-
DNS and certificates that \`vela provision\` does not set up yet.`
|
|
3441
|
-
);
|
|
3442
|
-
}
|
|
3443
3568
|
const { workspaceRootDir } = await getWorkspace();
|
|
3569
|
+
if (target.kind === "preview" && !target.branch) {
|
|
3570
|
+
const branch = await currentBranch(workspaceRootDir);
|
|
3571
|
+
target = { kind: "preview", branch, envTag: branchToEnvTag(branch) };
|
|
3572
|
+
}
|
|
3444
3573
|
const config = await loadDeployConfig(workspaceRootDir);
|
|
3445
3574
|
const app = resolveAppIdentity(workspaceRootDir, {
|
|
3446
3575
|
...config,
|
|
@@ -3484,30 +3613,32 @@ ${run.localHint}` : "")
|
|
|
3484
3613
|
session,
|
|
3485
3614
|
instance: instanceId(app.appId, target.envTag),
|
|
3486
3615
|
envTag: target.envTag,
|
|
3487
|
-
targetName: target
|
|
3616
|
+
targetName: describeTarget(target),
|
|
3617
|
+
target,
|
|
3488
3618
|
server: binding.server,
|
|
3489
3619
|
binding
|
|
3490
3620
|
});
|
|
3491
3621
|
});
|
|
3492
3622
|
}
|
|
3493
3623
|
async function ensureBinding(workspaceRootDir, target, request = {}) {
|
|
3494
|
-
const
|
|
3624
|
+
const key = bindingKey(target);
|
|
3625
|
+
const existing = readBinding(workspaceRootDir, key);
|
|
3495
3626
|
const moving = Boolean(request.server && existing && existing.server !== request.server);
|
|
3496
3627
|
let server = request.server ?? existing?.server;
|
|
3497
3628
|
if (!server) {
|
|
3498
3629
|
server = await promptServer(target);
|
|
3499
3630
|
}
|
|
3500
|
-
let domain = request.domain ?? existing?.domain;
|
|
3501
|
-
if (!domain && request.askDomain && !request.server) {
|
|
3631
|
+
let domain = target.kind === "preview" ? void 0 : request.domain ?? existing?.domain;
|
|
3632
|
+
if (!domain && request.askDomain && !request.server && target.kind !== "preview") {
|
|
3502
3633
|
domain = await promptDomain(target);
|
|
3503
3634
|
}
|
|
3504
3635
|
const binding = domain ? { server, domain } : { server };
|
|
3505
3636
|
if (!existing || existing.server !== server || existing.domain !== domain) {
|
|
3506
|
-
writeBinding(workspaceRootDir,
|
|
3637
|
+
writeBinding(workspaceRootDir, key, binding);
|
|
3507
3638
|
}
|
|
3508
3639
|
if (moving) {
|
|
3509
3640
|
p15.log.warn(
|
|
3510
|
-
`${pc5.cyan(target
|
|
3641
|
+
`${pc5.cyan(bindingName(target))} now points at ${pc5.cyan(server)}.
|
|
3511
3642
|
|
|
3512
3643
|
Whatever is running on ${existing.server} is left there, and this project can no
|
|
3513
3644
|
longer reach it. Remove it there first if that was not intended.`
|
|
@@ -3515,36 +3646,42 @@ longer reach it. Remove it there first if that was not intended.`
|
|
|
3515
3646
|
}
|
|
3516
3647
|
return binding;
|
|
3517
3648
|
}
|
|
3649
|
+
function bindingName(target) {
|
|
3650
|
+
return target.kind === "preview" ? "previews" : target.name;
|
|
3651
|
+
}
|
|
3518
3652
|
async function promptServer(target) {
|
|
3519
|
-
|
|
3653
|
+
const name = bindingName(target);
|
|
3654
|
+
if (!process11.stdout.isTTY || process11.env.CI) {
|
|
3520
3655
|
throw new Error(
|
|
3521
|
-
`${
|
|
3656
|
+
`${name} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet, and there is no terminal to ask on.
|
|
3522
3657
|
|
|
3523
3658
|
Pass ${pc5.cyan("--server user@host")}, or run the command once from your own machine
|
|
3524
3659
|
and commit ${pc5.cyan(".vela/project.json")}.`
|
|
3525
3660
|
);
|
|
3526
3661
|
}
|
|
3527
|
-
p15.log.info(
|
|
3662
|
+
p15.log.info(
|
|
3663
|
+
`${pc5.cyan(name)} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet.`
|
|
3664
|
+
);
|
|
3528
3665
|
const value = await p15.text({
|
|
3529
|
-
message: `Which server should ${
|
|
3666
|
+
message: `Which server should ${name} run on?`,
|
|
3530
3667
|
placeholder: "root@203.0.113.10",
|
|
3531
3668
|
validate: (input) => input?.trim() ? void 0 : "An ssh_config alias, or user@host"
|
|
3532
3669
|
});
|
|
3533
3670
|
if (p15.isCancel(value)) {
|
|
3534
3671
|
p15.cancel("Operation cancelled.");
|
|
3535
|
-
|
|
3672
|
+
process11.exit(0);
|
|
3536
3673
|
}
|
|
3537
3674
|
return value.trim();
|
|
3538
3675
|
}
|
|
3539
3676
|
async function promptDomain(target) {
|
|
3540
|
-
if (!
|
|
3677
|
+
if (!process11.stdout.isTTY || process11.env.CI) return void 0;
|
|
3541
3678
|
const value = await p15.text({
|
|
3542
3679
|
message: `Which hostname should ${target.name} be served on?`,
|
|
3543
3680
|
placeholder: "example.com \u2014 leave blank to decide later"
|
|
3544
3681
|
});
|
|
3545
3682
|
if (p15.isCancel(value)) {
|
|
3546
3683
|
p15.cancel("Operation cancelled.");
|
|
3547
|
-
|
|
3684
|
+
process11.exit(0);
|
|
3548
3685
|
}
|
|
3549
3686
|
return value.trim() || void 0;
|
|
3550
3687
|
}
|
|
@@ -3580,7 +3717,7 @@ async function withServerSession(raw, fn) {
|
|
|
3580
3717
|
if (!server) {
|
|
3581
3718
|
const { workspaceRootDir } = await getWorkspace();
|
|
3582
3719
|
const target = parseTarget(options.target, "production");
|
|
3583
|
-
if (target.kind
|
|
3720
|
+
if (target.kind === "local") {
|
|
3584
3721
|
throw new Error(`${describeTarget(target)} does not run on a server.`);
|
|
3585
3722
|
}
|
|
3586
3723
|
server = (await ensureBinding(workspaceRootDir, target, { server: options.server })).server;
|
|
@@ -3600,17 +3737,17 @@ function envFilePath(workspaceRootDir) {
|
|
|
3600
3737
|
import pc7 from "picocolors";
|
|
3601
3738
|
|
|
3602
3739
|
// src/lib/local-env.ts
|
|
3603
|
-
import
|
|
3740
|
+
import fs22 from "node:fs";
|
|
3604
3741
|
import * as p16 from "@clack/prompts";
|
|
3605
3742
|
import pc6 from "picocolors";
|
|
3606
3743
|
function readLocalEnv(envFile) {
|
|
3607
|
-
if (!
|
|
3744
|
+
if (!fs22.existsSync(envFile)) return {};
|
|
3608
3745
|
return readLocalEnvFile(envFile);
|
|
3609
3746
|
}
|
|
3610
3747
|
function editLocalEnv(envFile, edit) {
|
|
3611
|
-
const before =
|
|
3748
|
+
const before = fs22.existsSync(envFile) ? fs22.readFileSync(envFile, "utf8") : "";
|
|
3612
3749
|
const after = edit(before);
|
|
3613
|
-
if (after !== before)
|
|
3750
|
+
if (after !== before) fs22.writeFileSync(envFile, after);
|
|
3614
3751
|
}
|
|
3615
3752
|
function setLocalEnv(envFile, key, value) {
|
|
3616
3753
|
editLocalEnv(envFile, (content) => upsertEnvVar(content, key, value));
|
|
@@ -3742,8 +3879,8 @@ Set ${pc7.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc7.cyan("POCKETBASE_SUPERUS
|
|
|
3742
3879
|
}
|
|
3743
3880
|
|
|
3744
3881
|
// src/lib/s3-settings.ts
|
|
3745
|
-
import
|
|
3746
|
-
import
|
|
3882
|
+
import fs23 from "node:fs";
|
|
3883
|
+
import path21 from "node:path";
|
|
3747
3884
|
var VIRTUAL_HOSTED = [/\.amazonaws\.com$/i, /\.r2\.cloudflarestorage\.com$/i];
|
|
3748
3885
|
function defaultForcePathStyle(endpoint) {
|
|
3749
3886
|
let host;
|
|
@@ -3781,25 +3918,25 @@ async function hasLocalUploads(session, instance, workspaceRootDir) {
|
|
|
3781
3918
|
});
|
|
3782
3919
|
return result.stdout.trim().length > 0;
|
|
3783
3920
|
}
|
|
3784
|
-
return hasFile(
|
|
3921
|
+
return hasFile(path21.join(workspaceRootDir, DATA_DIR, "storage"));
|
|
3785
3922
|
}
|
|
3786
3923
|
function hasFile(dir) {
|
|
3787
3924
|
let entries;
|
|
3788
3925
|
try {
|
|
3789
|
-
entries =
|
|
3926
|
+
entries = fs23.readdirSync(dir, { withFileTypes: true });
|
|
3790
3927
|
} catch {
|
|
3791
3928
|
return false;
|
|
3792
3929
|
}
|
|
3793
3930
|
for (const entry of entries) {
|
|
3794
3931
|
if (entry.isFile()) return true;
|
|
3795
|
-
if (entry.isDirectory() && hasFile(
|
|
3932
|
+
if (entry.isDirectory() && hasFile(path21.join(dir, entry.name))) return true;
|
|
3796
3933
|
}
|
|
3797
3934
|
return false;
|
|
3798
3935
|
}
|
|
3799
3936
|
|
|
3800
3937
|
// src/commands/enable/s3.ts
|
|
3801
3938
|
var s3 = addTargetOptions(
|
|
3802
|
-
new
|
|
3939
|
+
new Command19("s3").description("enable S3 file storage").option("--backups", "configure where backups are kept, not where uploads go").option("--endpoint <url>", "S3 endpoint URL").option("--bucket <name>", "S3 bucket name").option("--region <region>", "S3 region").option("--access-key <key>", "S3 access key").option("--secret <secret>", "S3 secret key \u2014 prefer VELA_S3_SECRET").option("--force-path-style", "address the bucket in the path (MinIO, Ceph)").option("--no-force-path-style", "address the bucket as a subdomain (AWS, R2)").option("--force", "enable it even though uploads already exist on disk").configureHelp(helpConfig),
|
|
3803
3940
|
"local"
|
|
3804
3941
|
).action(
|
|
3805
3942
|
(raw) => runCommand(() => {
|
|
@@ -3865,7 +4002,7 @@ async function promptConfig(options, existing) {
|
|
|
3865
4002
|
const bucket = options.bucket ?? await text7("S3 bucket name", existing.bucket);
|
|
3866
4003
|
const region = options.region ?? await text7("S3 region", existing.region || "us-east-1");
|
|
3867
4004
|
const accessKey = options.accessKey ?? await text7("S3 access key", existing.accessKey);
|
|
3868
|
-
const secret = options.secret ??
|
|
4005
|
+
const secret = options.secret ?? process12.env.VELA_S3_SECRET ?? await password5("S3 secret key");
|
|
3869
4006
|
const forcePathStyle = options.forcePathStyle ?? await confirm3(
|
|
3870
4007
|
"Address the bucket in the path? (MinIO, Ceph and most self-hosted gateways need this)",
|
|
3871
4008
|
defaultForcePathStyle(endpoint)
|
|
@@ -3880,7 +4017,7 @@ async function text7(message, initialValue = "") {
|
|
|
3880
4017
|
});
|
|
3881
4018
|
if (p17.isCancel(value)) {
|
|
3882
4019
|
p17.cancel("Operation cancelled.");
|
|
3883
|
-
|
|
4020
|
+
process12.exit(0);
|
|
3884
4021
|
}
|
|
3885
4022
|
return value.trim();
|
|
3886
4023
|
}
|
|
@@ -3891,7 +4028,7 @@ async function password5(message) {
|
|
|
3891
4028
|
});
|
|
3892
4029
|
if (p17.isCancel(value)) {
|
|
3893
4030
|
p17.cancel("Operation cancelled.");
|
|
3894
|
-
|
|
4031
|
+
process12.exit(0);
|
|
3895
4032
|
}
|
|
3896
4033
|
return value;
|
|
3897
4034
|
}
|
|
@@ -3899,16 +4036,16 @@ async function confirm3(message, initialValue) {
|
|
|
3899
4036
|
const value = await p17.confirm({ message, initialValue });
|
|
3900
4037
|
if (p17.isCancel(value)) {
|
|
3901
4038
|
p17.cancel("Operation cancelled.");
|
|
3902
|
-
|
|
4039
|
+
process12.exit(0);
|
|
3903
4040
|
}
|
|
3904
4041
|
return value;
|
|
3905
4042
|
}
|
|
3906
4043
|
|
|
3907
4044
|
// src/commands/enable/smtp.ts
|
|
3908
|
-
import
|
|
3909
|
-
import { Command as
|
|
4045
|
+
import process13 from "node:process";
|
|
4046
|
+
import { Command as Command20 } from "commander";
|
|
3910
4047
|
import * as p18 from "@clack/prompts";
|
|
3911
|
-
var smtp = new
|
|
4048
|
+
var smtp = new Command20("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
|
|
3912
4049
|
() => runCommand(async () => {
|
|
3913
4050
|
const { workspaceRootDir } = await getWorkspace();
|
|
3914
4051
|
const config = await p18.group(
|
|
@@ -3934,7 +4071,7 @@ var smtp = new Command19("smtp").description("configure SMTP for transactional e
|
|
|
3934
4071
|
{
|
|
3935
4072
|
onCancel: () => {
|
|
3936
4073
|
p18.cancel("Operation cancelled.");
|
|
3937
|
-
|
|
4074
|
+
process13.exit(0);
|
|
3938
4075
|
}
|
|
3939
4076
|
}
|
|
3940
4077
|
);
|
|
@@ -3961,11 +4098,11 @@ var smtp = new Command19("smtp").description("configure SMTP for transactional e
|
|
|
3961
4098
|
);
|
|
3962
4099
|
|
|
3963
4100
|
// src/commands/enable/cms.ts
|
|
3964
|
-
import
|
|
3965
|
-
import { Command as
|
|
4101
|
+
import process14 from "node:process";
|
|
4102
|
+
import { Command as Command21 } from "commander";
|
|
3966
4103
|
import * as p19 from "@clack/prompts";
|
|
3967
4104
|
import pc9 from "picocolors";
|
|
3968
|
-
var cms = new
|
|
4105
|
+
var cms = new Command21("cms").description("enable an inline-editing CMS with an admin bar").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
3969
4106
|
(_opts, cmd) => runCommand(async () => {
|
|
3970
4107
|
if (!hasBackend()) {
|
|
3971
4108
|
p19.log.error(
|
|
@@ -3975,7 +4112,7 @@ Run ${pc9.cyan("vela bless")} to add a backend first.`
|
|
|
3975
4112
|
);
|
|
3976
4113
|
p19.log.message();
|
|
3977
4114
|
p19.cancel("Operation failed.");
|
|
3978
|
-
|
|
4115
|
+
process14.exitCode = 1;
|
|
3979
4116
|
return;
|
|
3980
4117
|
}
|
|
3981
4118
|
await runPattern(
|
|
@@ -4000,8 +4137,8 @@ Run ${pc9.cyan("vela bless")} to add a backend first.`
|
|
|
4000
4137
|
);
|
|
4001
4138
|
|
|
4002
4139
|
// src/commands/enable/blog.ts
|
|
4003
|
-
import { Command as
|
|
4004
|
-
var blog = new
|
|
4140
|
+
import { Command as Command22 } from "commander";
|
|
4141
|
+
var blog = new Command22("blog").description("enable an mdsvex blog with posts, tags, and RSS").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4005
4142
|
(_opts, cmd) => runCommand(
|
|
4006
4143
|
() => runPattern(
|
|
4007
4144
|
"enable-blog",
|
|
@@ -4026,8 +4163,8 @@ var blog = new Command21("blog").description("enable an mdsvex blog with posts,
|
|
|
4026
4163
|
);
|
|
4027
4164
|
|
|
4028
4165
|
// src/commands/enable/content-negotiation.ts
|
|
4029
|
-
import { Command as
|
|
4030
|
-
var contentNegotiation = new
|
|
4166
|
+
import { Command as Command23 } from "commander";
|
|
4167
|
+
var contentNegotiation = new Command23("content-negotiation").description("enable content negotiation (sveltekit-negotiate)").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4031
4168
|
(_opts, cmd) => runCommand(
|
|
4032
4169
|
() => runPattern(
|
|
4033
4170
|
"enable-content-negotiation",
|
|
@@ -4051,16 +4188,16 @@ var contentNegotiation = new Command22("content-negotiation").description("enabl
|
|
|
4051
4188
|
);
|
|
4052
4189
|
|
|
4053
4190
|
// src/commands/enable.ts
|
|
4054
|
-
var enable = new
|
|
4191
|
+
var enable = new Command24("enable").description("enable features").configureHelp(helpConfig).addCommand(auth).addCommand(api).addCommand(apiKeys).addCommand(backend).addCommand(contentNegotiation).addCommand(i18n).addCommand(teams).addCommand(payments).addCommand(subscriptions).addCommand(notifications).addCommand(s3).addCommand(smtp).addCommand(cms).addCommand(blog);
|
|
4055
4192
|
|
|
4056
4193
|
// src/commands/disable.ts
|
|
4057
|
-
import { Command as
|
|
4194
|
+
import { Command as Command35 } from "commander";
|
|
4058
4195
|
|
|
4059
4196
|
// src/commands/disable/auth.ts
|
|
4060
|
-
import { Command as
|
|
4197
|
+
import { Command as Command25 } from "commander";
|
|
4061
4198
|
|
|
4062
4199
|
// src/commands/disable/_shared.ts
|
|
4063
|
-
import
|
|
4200
|
+
import process15 from "node:process";
|
|
4064
4201
|
import * as p20 from "@clack/prompts";
|
|
4065
4202
|
async function runDisable(opts, flags, cmdArgs) {
|
|
4066
4203
|
if (!flags.yes) {
|
|
@@ -4070,14 +4207,14 @@ async function runDisable(opts, flags, cmdArgs) {
|
|
|
4070
4207
|
});
|
|
4071
4208
|
if (p20.isCancel(ok) || !ok) {
|
|
4072
4209
|
p20.cancel("Operation cancelled.");
|
|
4073
|
-
|
|
4210
|
+
process15.exit(0);
|
|
4074
4211
|
}
|
|
4075
4212
|
}
|
|
4076
4213
|
await runPattern(opts.slug, cmdArgs, { destructive: true }, opts.report);
|
|
4077
4214
|
}
|
|
4078
4215
|
|
|
4079
4216
|
// src/commands/disable/auth.ts
|
|
4080
|
-
var auth2 = new
|
|
4217
|
+
var auth2 = new Command25("auth").description("disable authentication").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4081
4218
|
(opts, cmd) => runCommand(
|
|
4082
4219
|
() => runDisable(
|
|
4083
4220
|
{
|
|
@@ -4103,8 +4240,8 @@ var auth2 = new Command24("auth").description("disable authentication").option("
|
|
|
4103
4240
|
);
|
|
4104
4241
|
|
|
4105
4242
|
// src/commands/disable/api.ts
|
|
4106
|
-
import { Command as
|
|
4107
|
-
var api2 = new
|
|
4243
|
+
import { Command as Command26 } from "commander";
|
|
4244
|
+
var api2 = new Command26("api").description("disable the REST API").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4108
4245
|
(opts, cmd) => runCommand(
|
|
4109
4246
|
() => runDisable(
|
|
4110
4247
|
{
|
|
@@ -4127,8 +4264,8 @@ var api2 = new Command25("api").description("disable the REST API").option("-y,
|
|
|
4127
4264
|
);
|
|
4128
4265
|
|
|
4129
4266
|
// src/commands/disable/api-keys.ts
|
|
4130
|
-
import { Command as
|
|
4131
|
-
var apiKeys2 = new
|
|
4267
|
+
import { Command as Command27 } from "commander";
|
|
4268
|
+
var apiKeys2 = new Command27("api-keys").description("disable API key management").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4132
4269
|
(opts, cmd) => runCommand(
|
|
4133
4270
|
() => runDisable(
|
|
4134
4271
|
{
|
|
@@ -4151,8 +4288,8 @@ var apiKeys2 = new Command26("api-keys").description("disable API key management
|
|
|
4151
4288
|
);
|
|
4152
4289
|
|
|
4153
4290
|
// src/commands/disable/backend.ts
|
|
4154
|
-
import { Command as
|
|
4155
|
-
var backend2 = new
|
|
4291
|
+
import { Command as Command28 } from "commander";
|
|
4292
|
+
var backend2 = new Command28("backend").description("disable the PocketBase backend").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4156
4293
|
(opts, cmd) => runCommand(
|
|
4157
4294
|
() => runDisable(
|
|
4158
4295
|
{
|
|
@@ -4175,8 +4312,8 @@ var backend2 = new Command27("backend").description("disable the PocketBase back
|
|
|
4175
4312
|
);
|
|
4176
4313
|
|
|
4177
4314
|
// src/commands/disable/content-negotiation.ts
|
|
4178
|
-
import { Command as
|
|
4179
|
-
var contentNegotiation2 = new
|
|
4315
|
+
import { Command as Command29 } from "commander";
|
|
4316
|
+
var contentNegotiation2 = new Command29("content-negotiation").description("disable content negotiation").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4180
4317
|
(opts, cmd) => runCommand(
|
|
4181
4318
|
() => runDisable(
|
|
4182
4319
|
{
|
|
@@ -4199,8 +4336,8 @@ var contentNegotiation2 = new Command28("content-negotiation").description("disa
|
|
|
4199
4336
|
);
|
|
4200
4337
|
|
|
4201
4338
|
// src/commands/disable/i18n.ts
|
|
4202
|
-
import { Command as
|
|
4203
|
-
var i18n2 = new
|
|
4339
|
+
import { Command as Command30 } from "commander";
|
|
4340
|
+
var i18n2 = new Command30("i18n").description("disable internationalization").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4204
4341
|
(opts, cmd) => runCommand(
|
|
4205
4342
|
() => runDisable(
|
|
4206
4343
|
{
|
|
@@ -4226,8 +4363,8 @@ var i18n2 = new Command29("i18n").description("disable internationalization").op
|
|
|
4226
4363
|
);
|
|
4227
4364
|
|
|
4228
4365
|
// src/commands/disable/teams.ts
|
|
4229
|
-
import { Command as
|
|
4230
|
-
var teams2 = new
|
|
4366
|
+
import { Command as Command31 } from "commander";
|
|
4367
|
+
var teams2 = new Command31("teams").description("disable teams").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4231
4368
|
(opts, cmd) => runCommand(
|
|
4232
4369
|
() => runDisable(
|
|
4233
4370
|
{
|
|
@@ -4253,8 +4390,8 @@ var teams2 = new Command30("teams").description("disable teams").option("-y, --y
|
|
|
4253
4390
|
);
|
|
4254
4391
|
|
|
4255
4392
|
// src/commands/disable/payments.ts
|
|
4256
|
-
import { Command as
|
|
4257
|
-
var payments2 = new
|
|
4393
|
+
import { Command as Command32 } from "commander";
|
|
4394
|
+
var payments2 = new Command32("payments").description("disable payments").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4258
4395
|
(opts, cmd) => runCommand(
|
|
4259
4396
|
() => runDisable(
|
|
4260
4397
|
{
|
|
@@ -4281,11 +4418,11 @@ var payments2 = new Command31("payments").description("disable payments").option
|
|
|
4281
4418
|
);
|
|
4282
4419
|
|
|
4283
4420
|
// src/commands/disable/s3.ts
|
|
4284
|
-
import { Command as
|
|
4421
|
+
import { Command as Command33 } from "commander";
|
|
4285
4422
|
import * as p21 from "@clack/prompts";
|
|
4286
4423
|
import pc10 from "picocolors";
|
|
4287
4424
|
var s32 = addTargetOptions(
|
|
4288
|
-
new
|
|
4425
|
+
new Command33("s3").description("disable S3 file storage").option("--backups", "keep backups on the server again, rather than uploads").configureHelp(helpConfig),
|
|
4289
4426
|
"local"
|
|
4290
4427
|
).action(
|
|
4291
4428
|
(raw) => runCommand(() => {
|
|
@@ -4314,8 +4451,8 @@ function label2(filesystem) {
|
|
|
4314
4451
|
}
|
|
4315
4452
|
|
|
4316
4453
|
// src/commands/disable/smtp.ts
|
|
4317
|
-
import { Command as
|
|
4318
|
-
var smtp2 = new
|
|
4454
|
+
import { Command as Command34 } from "commander";
|
|
4455
|
+
var smtp2 = new Command34("smtp").description("disable SMTP configuration").configureHelp(helpConfig).action(
|
|
4319
4456
|
() => runCommand(async () => {
|
|
4320
4457
|
const { workspaceRootDir } = await getWorkspace();
|
|
4321
4458
|
await withPocketbase(workspaceRootDir, async (pb) => {
|
|
@@ -4332,30 +4469,30 @@ var smtp2 = new Command33("smtp").description("disable SMTP configuration").conf
|
|
|
4332
4469
|
);
|
|
4333
4470
|
|
|
4334
4471
|
// src/commands/disable.ts
|
|
4335
|
-
var disable = new
|
|
4472
|
+
var disable = new Command35("disable").description("disable features").configureHelp(helpConfig).addCommand(auth2).addCommand(api2).addCommand(apiKeys2).addCommand(backend2).addCommand(contentNegotiation2).addCommand(i18n2).addCommand(teams2).addCommand(payments2).addCommand(s32).addCommand(smtp2);
|
|
4336
4473
|
|
|
4337
4474
|
// src/commands/destroy.ts
|
|
4338
|
-
import { Command as
|
|
4475
|
+
import { Command as Command41 } from "commander";
|
|
4339
4476
|
|
|
4340
4477
|
// src/commands/destroy/form.ts
|
|
4341
|
-
import { Command as
|
|
4478
|
+
import { Command as Command36 } from "commander";
|
|
4342
4479
|
|
|
4343
4480
|
// src/commands/destroy/_shared.ts
|
|
4344
|
-
import
|
|
4481
|
+
import process16 from "node:process";
|
|
4345
4482
|
import * as p22 from "@clack/prompts";
|
|
4346
4483
|
async function runDestroy(slug2, model, confirmMessage, report4, flags) {
|
|
4347
4484
|
if (!flags.yes) {
|
|
4348
4485
|
const ok = await p22.confirm({ message: confirmMessage, initialValue: false });
|
|
4349
4486
|
if (p22.isCancel(ok) || !ok) {
|
|
4350
4487
|
p22.cancel("Operation cancelled.");
|
|
4351
|
-
|
|
4488
|
+
process16.exit(0);
|
|
4352
4489
|
}
|
|
4353
4490
|
}
|
|
4354
4491
|
await runPattern(slug2, [model], { destructive: true, route: flags.route }, report4);
|
|
4355
4492
|
}
|
|
4356
4493
|
|
|
4357
4494
|
// src/commands/destroy/form.ts
|
|
4358
|
-
var form2 = new
|
|
4495
|
+
var form2 = new Command36("form").description("destroy a form generated by `vela generate form`").argument("<model>", "model name used when the form was generated (e.g., contact, login)").option("-y, --yes", "skip confirmation prompt").option(
|
|
4359
4496
|
"--route <route>",
|
|
4360
4497
|
"custom route the form was generated at (must match the --route used at generation)"
|
|
4361
4498
|
).allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
@@ -4379,8 +4516,8 @@ var form2 = new Command35("form").description("destroy a form generated by `vela
|
|
|
4379
4516
|
);
|
|
4380
4517
|
|
|
4381
4518
|
// src/commands/destroy/schema.ts
|
|
4382
|
-
import { Command as
|
|
4383
|
-
var schema2 = new
|
|
4519
|
+
import { Command as Command37 } from "commander";
|
|
4520
|
+
var schema2 = new Command37("schema").description("destroy a zod schema generated by `vela generate schema`").argument("<model>", "schema model name (e.g., contact, login)").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4384
4521
|
(model, opts) => runCommand(
|
|
4385
4522
|
() => runDestroy(
|
|
4386
4523
|
"destroy-schema",
|
|
@@ -4401,8 +4538,8 @@ var schema2 = new Command36("schema").description("destroy a zod schema generate
|
|
|
4401
4538
|
);
|
|
4402
4539
|
|
|
4403
4540
|
// src/commands/destroy/resource.ts
|
|
4404
|
-
import { Command as
|
|
4405
|
-
var resource2 = new
|
|
4541
|
+
import { Command as Command38 } from "commander";
|
|
4542
|
+
var resource2 = new Command38("resource").description("destroy a resource generated by `vela generate resource`").argument("<model>", "model path used when the resource was generated (e.g., contacts, articles)").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
4406
4543
|
(model, opts) => runCommand(
|
|
4407
4544
|
() => runDestroy(
|
|
4408
4545
|
"destroy-resource",
|
|
@@ -4423,8 +4560,8 @@ var resource2 = new Command37("resource").description("destroy a resource genera
|
|
|
4423
4560
|
);
|
|
4424
4561
|
|
|
4425
4562
|
// src/commands/destroy/scaffold.ts
|
|
4426
|
-
import { Command as
|
|
4427
|
-
var scaffold2 = new
|
|
4563
|
+
import { Command as Command39 } from "commander";
|
|
4564
|
+
var scaffold2 = new Command39("scaffold").description("destroy a scaffold generated by `vela generate scaffold`").argument("<model>", "model name used when the scaffold was generated (e.g., contact, todo)").option("-y, --yes", "skip confirmation prompt").option(
|
|
4428
4565
|
"--route <route>",
|
|
4429
4566
|
"custom route the scaffold was generated at (must match the --route used at generation)"
|
|
4430
4567
|
).allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
@@ -4451,12 +4588,205 @@ var scaffold2 = new Command38("scaffold").description("destroy a scaffold genera
|
|
|
4451
4588
|
);
|
|
4452
4589
|
|
|
4453
4590
|
// src/commands/destroy/deployment.ts
|
|
4454
|
-
import
|
|
4455
|
-
import { Command as
|
|
4591
|
+
import process17 from "node:process";
|
|
4592
|
+
import { Command as Command40 } from "commander";
|
|
4593
|
+
import * as p25 from "@clack/prompts";
|
|
4594
|
+
import pc13 from "picocolors";
|
|
4595
|
+
|
|
4596
|
+
// src/lib/deploy-report.ts
|
|
4597
|
+
import * as p24 from "@clack/prompts";
|
|
4598
|
+
import pc12 from "picocolors";
|
|
4599
|
+
|
|
4600
|
+
// src/lib/server-identity.ts
|
|
4456
4601
|
import * as p23 from "@clack/prompts";
|
|
4457
4602
|
import pc11 from "picocolors";
|
|
4603
|
+
|
|
4604
|
+
// src/lib/velastack-api.ts
|
|
4605
|
+
async function apiFetch(apiKey, pathAndQuery, init) {
|
|
4606
|
+
const headers = new Headers(init?.headers);
|
|
4607
|
+
headers.set("Authorization", `Bearer ${apiKey}`);
|
|
4608
|
+
if (init?.body && !headers.has("Content-Type")) {
|
|
4609
|
+
headers.set("Content-Type", "application/json");
|
|
4610
|
+
}
|
|
4611
|
+
const res = await fetch(`${API_URL}${pathAndQuery}`, { ...init, headers });
|
|
4612
|
+
if (res.status === 401) {
|
|
4613
|
+
throw new Error("API key invalid \u2014 run `vela login`");
|
|
4614
|
+
}
|
|
4615
|
+
if (res.status === 403) {
|
|
4616
|
+
const body = await res.text().catch(() => "");
|
|
4617
|
+
throw new Error(`velastack.dev refused this key (${body || "forbidden"}) \u2014 run \`vela login\``);
|
|
4618
|
+
}
|
|
4619
|
+
if (!res.ok) {
|
|
4620
|
+
const body = await res.text().catch(() => "");
|
|
4621
|
+
throw new Error(`Velastack API error (${res.status}): ${body || res.statusText}`);
|
|
4622
|
+
}
|
|
4623
|
+
return await res.json();
|
|
4624
|
+
}
|
|
4625
|
+
async function getCurrentUser(apiKey) {
|
|
4626
|
+
const data = await apiFetch(
|
|
4627
|
+
apiKey,
|
|
4628
|
+
"/api/collections/users/records?perPage=1"
|
|
4629
|
+
);
|
|
4630
|
+
const user = data.items[0];
|
|
4631
|
+
if (!user) throw new Error("No user found. Run `vela login` to login.");
|
|
4632
|
+
return user;
|
|
4633
|
+
}
|
|
4634
|
+
async function listTeams(apiKey) {
|
|
4635
|
+
const data = await apiFetch(
|
|
4636
|
+
apiKey,
|
|
4637
|
+
"/api/collections/teams/records?perPage=200"
|
|
4638
|
+
);
|
|
4639
|
+
return data.items;
|
|
4640
|
+
}
|
|
4641
|
+
async function listProjects(apiKey) {
|
|
4642
|
+
const data = await apiFetch(
|
|
4643
|
+
apiKey,
|
|
4644
|
+
"/api/collections/projects/records?perPage=200&expand=team"
|
|
4645
|
+
);
|
|
4646
|
+
return data.items;
|
|
4647
|
+
}
|
|
4648
|
+
async function createProject2(apiKey, args) {
|
|
4649
|
+
return apiFetch(apiKey, "/api/collections/projects/records", {
|
|
4650
|
+
method: "POST",
|
|
4651
|
+
body: JSON.stringify({ name: args.name, team: args.teamId, user: args.userId })
|
|
4652
|
+
});
|
|
4653
|
+
}
|
|
4654
|
+
async function registerServer(apiKey, input) {
|
|
4655
|
+
return apiFetch(apiKey, "/v1/servers", {
|
|
4656
|
+
method: "POST",
|
|
4657
|
+
body: JSON.stringify(input)
|
|
4658
|
+
});
|
|
4659
|
+
}
|
|
4660
|
+
async function startDeployment(apiKey, projectId, input) {
|
|
4661
|
+
return apiFetch(apiKey, `/v1/projects/${projectId}/deployments`, {
|
|
4662
|
+
method: "POST",
|
|
4663
|
+
body: JSON.stringify(input)
|
|
4664
|
+
});
|
|
4665
|
+
}
|
|
4666
|
+
async function finishDeployment(apiKey, projectId, deploymentId, input) {
|
|
4667
|
+
return apiFetch(apiKey, `/v1/projects/${projectId}/deployments/${deploymentId}`, {
|
|
4668
|
+
method: "PATCH",
|
|
4669
|
+
body: JSON.stringify(input)
|
|
4670
|
+
});
|
|
4671
|
+
}
|
|
4672
|
+
async function destroyEnvironment(apiKey, projectId, envTag) {
|
|
4673
|
+
return apiFetch(apiKey, `/v1/projects/${projectId}/environments/${encodeURIComponent(envTag)}`, {
|
|
4674
|
+
method: "DELETE"
|
|
4675
|
+
});
|
|
4676
|
+
}
|
|
4677
|
+
|
|
4678
|
+
// src/lib/server-identity.ts
|
|
4679
|
+
var IPV4 = /^\d{1,3}(?:\.\d{1,3}){3}$/;
|
|
4680
|
+
async function ensureServerIdentity(session, apiKey) {
|
|
4681
|
+
const existing = await readServerIdentity(session);
|
|
4682
|
+
const ip = await publicIp(session);
|
|
4683
|
+
const registered = await registerServer(apiKey, {
|
|
4684
|
+
ip,
|
|
4685
|
+
serverId: existing?.serverId,
|
|
4686
|
+
token: existing?.token
|
|
4687
|
+
});
|
|
4688
|
+
if (!existing || existing.serverId !== registered.serverId || existing.originHost !== registered.originHost || existing.token !== registered.token) {
|
|
4689
|
+
await writeServerIdentity(session, registered);
|
|
4690
|
+
if (existing) {
|
|
4691
|
+
p23.log.info(`${pc11.cyan(session.target)} was re-registered with velastack.dev.`);
|
|
4692
|
+
}
|
|
4693
|
+
}
|
|
4694
|
+
await runServerScript(session, "origin.sh");
|
|
4695
|
+
return registered;
|
|
4696
|
+
}
|
|
4697
|
+
async function publicIp(session) {
|
|
4698
|
+
const result = await session.script(
|
|
4699
|
+
`api="$1"
|
|
4700
|
+
if ip=$(curl -4fsS --max-time 10 "$api/v1/ip" 2>/dev/null); then
|
|
4701
|
+
printf '%s' "$ip"
|
|
4702
|
+
else
|
|
4703
|
+
ip -4 route get 1.1.1.1 2>/dev/null | awk '{for (i = 1; i <= NF; i++) if ($i == "src") print $(i + 1)}'
|
|
4704
|
+
fi`,
|
|
4705
|
+
{ args: [API_URL], check: false }
|
|
4706
|
+
);
|
|
4707
|
+
const raw = result.stdout.trim();
|
|
4708
|
+
let ip = raw;
|
|
4709
|
+
try {
|
|
4710
|
+
const parsed = JSON.parse(raw);
|
|
4711
|
+
if (typeof parsed.ip === "string") ip = parsed.ip;
|
|
4712
|
+
} catch {
|
|
4713
|
+
}
|
|
4714
|
+
ip = ip.trim().replace(/^::ffff:/, "");
|
|
4715
|
+
if (!IPV4.test(ip)) {
|
|
4716
|
+
throw new Error(
|
|
4717
|
+
`Could not work out the public IPv4 address of ${session.target}.
|
|
4718
|
+
|
|
4719
|
+
The server needs to reach ${API_URL} (or have a default IPv4 route) for velastack.dev
|
|
4720
|
+
to point its origin record at it.`
|
|
4721
|
+
);
|
|
4722
|
+
}
|
|
4723
|
+
return ip;
|
|
4724
|
+
}
|
|
4725
|
+
|
|
4726
|
+
// src/lib/deploy-report.ts
|
|
4727
|
+
function createDeployReporter(workspaceRootDir) {
|
|
4728
|
+
const link2 = readProjectConfig(workspaceRootDir);
|
|
4729
|
+
const apiKey = link2 ? readApiKey() : null;
|
|
4730
|
+
if (link2 && !apiKey) {
|
|
4731
|
+
p24.log.warn(
|
|
4732
|
+
`This project is linked to ${pc12.cyan(link2.projectName)} on velastack.dev, but there is no
|
|
4733
|
+
API key here, so this deploy will not be recorded. Run ${pc12.cyan("vela login")}, or set
|
|
4734
|
+
${pc12.cyan("VELA_API_KEY")}.`
|
|
4735
|
+
);
|
|
4736
|
+
}
|
|
4737
|
+
let deploymentId = null;
|
|
4738
|
+
return {
|
|
4739
|
+
enabled: Boolean(link2 && apiKey),
|
|
4740
|
+
async identifyServer(session) {
|
|
4741
|
+
if (!link2 || !apiKey) return null;
|
|
4742
|
+
try {
|
|
4743
|
+
return await ensureServerIdentity(session, apiKey);
|
|
4744
|
+
} catch (err) {
|
|
4745
|
+
warn("register this server", err);
|
|
4746
|
+
return null;
|
|
4747
|
+
}
|
|
4748
|
+
},
|
|
4749
|
+
async start(input) {
|
|
4750
|
+
if (!link2 || !apiKey) return null;
|
|
4751
|
+
try {
|
|
4752
|
+
const result = await startDeployment(apiKey, link2.projectId, input);
|
|
4753
|
+
deploymentId = result.deploymentId;
|
|
4754
|
+
return result;
|
|
4755
|
+
} catch (err) {
|
|
4756
|
+
warn("record this deploy", err);
|
|
4757
|
+
return null;
|
|
4758
|
+
}
|
|
4759
|
+
},
|
|
4760
|
+
async finish(input) {
|
|
4761
|
+
if (!link2 || !apiKey || !deploymentId) return;
|
|
4762
|
+
try {
|
|
4763
|
+
await finishDeployment(apiKey, link2.projectId, deploymentId, input);
|
|
4764
|
+
} catch (err) {
|
|
4765
|
+
warn("update this deploy", err);
|
|
4766
|
+
}
|
|
4767
|
+
}
|
|
4768
|
+
};
|
|
4769
|
+
}
|
|
4770
|
+
async function reportEnvironmentDestroyed(workspaceRootDir, envTag) {
|
|
4771
|
+
const link2 = readProjectConfig(workspaceRootDir);
|
|
4772
|
+
const apiKey = link2 ? readApiKey() : null;
|
|
4773
|
+
if (!link2 || !apiKey) return;
|
|
4774
|
+
try {
|
|
4775
|
+
await destroyEnvironment(apiKey, link2.projectId, envTag);
|
|
4776
|
+
} catch (err) {
|
|
4777
|
+
warn("retire the environment", err);
|
|
4778
|
+
}
|
|
4779
|
+
}
|
|
4780
|
+
function warn(what, err) {
|
|
4781
|
+
p24.log.warn(
|
|
4782
|
+
`velastack.dev could not ${what}.
|
|
4783
|
+
${pc12.dim(err instanceof Error ? err.message : String(err))}`
|
|
4784
|
+
);
|
|
4785
|
+
}
|
|
4786
|
+
|
|
4787
|
+
// src/commands/destroy/deployment.ts
|
|
4458
4788
|
var deployment = addTargetOptions(
|
|
4459
|
-
new
|
|
4789
|
+
new Command40("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
|
|
4460
4790
|
"production"
|
|
4461
4791
|
).option("--purge", "also delete the database and uploaded files").option("-y, --yes", "skip the confirmation prompt").action(
|
|
4462
4792
|
(raw) => runCommand(async () => {
|
|
@@ -4472,10 +4802,11 @@ var deployment = addTargetOptions(
|
|
|
4472
4802
|
args: [ctx.instance, ...options.purge ? ["--purge"] : []],
|
|
4473
4803
|
stream: true
|
|
4474
4804
|
});
|
|
4475
|
-
|
|
4476
|
-
|
|
4805
|
+
await reportEnvironmentDestroyed(ctx.workspaceRootDir, ctx.envTag);
|
|
4806
|
+
p25.log.success(
|
|
4807
|
+
`Removed ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${ctx.server}.` + (result?.purged ? "" : `
|
|
4477
4808
|
|
|
4478
|
-
The database and uploads are still in the instance's shared directory. Pass ${
|
|
4809
|
+
The database and uploads are still in the instance's shared directory. Pass ${pc13.cyan("--purge")} to delete them.`)
|
|
4479
4810
|
);
|
|
4480
4811
|
}
|
|
4481
4812
|
},
|
|
@@ -4488,35 +4819,35 @@ The database and uploads are still in the instance's shared directory. Pass ${pc
|
|
|
4488
4819
|
);
|
|
4489
4820
|
async function confirm7(appName, targetName, envTag, purge) {
|
|
4490
4821
|
if (isProd(envTag) || purge) {
|
|
4491
|
-
const answer = await
|
|
4492
|
-
message: `This removes ${
|
|
4822
|
+
const answer = await p25.text({
|
|
4823
|
+
message: `This removes ${pc13.cyan(`${appName} (${targetName})`)}${purge ? " and its database" : ""}. Type the app name to confirm`,
|
|
4493
4824
|
validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
|
|
4494
4825
|
});
|
|
4495
|
-
if (
|
|
4496
|
-
|
|
4497
|
-
|
|
4826
|
+
if (p25.isCancel(answer)) {
|
|
4827
|
+
p25.cancel("Operation cancelled.");
|
|
4828
|
+
process17.exit(0);
|
|
4498
4829
|
}
|
|
4499
4830
|
return;
|
|
4500
4831
|
}
|
|
4501
|
-
const ok = await
|
|
4832
|
+
const ok = await p25.confirm({
|
|
4502
4833
|
message: `Remove ${appName} (${targetName})?`,
|
|
4503
4834
|
initialValue: false
|
|
4504
4835
|
});
|
|
4505
|
-
if (
|
|
4506
|
-
|
|
4507
|
-
|
|
4836
|
+
if (p25.isCancel(ok) || !ok) {
|
|
4837
|
+
p25.cancel("Operation cancelled.");
|
|
4838
|
+
process17.exit(0);
|
|
4508
4839
|
}
|
|
4509
4840
|
}
|
|
4510
4841
|
|
|
4511
4842
|
// src/commands/destroy.ts
|
|
4512
|
-
var destroy = new
|
|
4843
|
+
var destroy = new Command41("destroy").description("destroy scaffolding, or a deployment").configureHelp(helpConfig).addCommand(form2).addCommand(schema2).addCommand(resource2).addCommand(scaffold2).addCommand(deployment);
|
|
4513
4844
|
|
|
4514
4845
|
// src/commands/ui.ts
|
|
4515
|
-
import { Command as
|
|
4846
|
+
import { Command as Command47 } from "commander";
|
|
4516
4847
|
|
|
4517
4848
|
// src/commands/ui/add.ts
|
|
4518
|
-
import { Command as
|
|
4519
|
-
import * as
|
|
4849
|
+
import { Command as Command42 } from "commander";
|
|
4850
|
+
import * as p26 from "@clack/prompts";
|
|
4520
4851
|
import { installComponents } from "@velastack/patterns";
|
|
4521
4852
|
|
|
4522
4853
|
// src/lib/ui-add.ts
|
|
@@ -4565,21 +4896,21 @@ function uiAddReport(requested, outcome) {
|
|
|
4565
4896
|
}
|
|
4566
4897
|
|
|
4567
4898
|
// src/commands/ui/add.ts
|
|
4568
|
-
var add = new
|
|
4899
|
+
var add = new Command42("add").description("add ui components (shadcn-svelte items and vela components such as data-table)").argument("<components...>", "the components to add").option("--overwrite", "replace components that already exist", false).configureHelp(helpConfig).action(
|
|
4569
4900
|
(components, options) => runCommand(async () => {
|
|
4570
4901
|
const { workspaceRootDir } = await getWorkspace();
|
|
4571
|
-
const
|
|
4902
|
+
const log45 = p26.taskLog({ title: "Adding UI components..." });
|
|
4572
4903
|
let outcome;
|
|
4573
4904
|
try {
|
|
4574
4905
|
outcome = await installComponents({
|
|
4575
4906
|
root: workspaceRootDir,
|
|
4576
4907
|
components,
|
|
4577
4908
|
overwrite: options.overwrite,
|
|
4578
|
-
logger: { info: (message) =>
|
|
4909
|
+
logger: { info: (message) => log45.message(message) }
|
|
4579
4910
|
});
|
|
4580
|
-
|
|
4911
|
+
log45.success("UI components ready");
|
|
4581
4912
|
} catch (e) {
|
|
4582
|
-
|
|
4913
|
+
log45.error("Could not add UI components");
|
|
4583
4914
|
throw e;
|
|
4584
4915
|
}
|
|
4585
4916
|
reportResult(uiAddReport(components, outcome));
|
|
@@ -4587,19 +4918,19 @@ var add = new Command41("add").description("add ui components (shadcn-svelte ite
|
|
|
4587
4918
|
);
|
|
4588
4919
|
|
|
4589
4920
|
// src/commands/ui/base.ts
|
|
4590
|
-
import { Command as
|
|
4591
|
-
import * as
|
|
4921
|
+
import { Command as Command43 } from "commander";
|
|
4922
|
+
import * as p27 from "@clack/prompts";
|
|
4592
4923
|
import { applyBaseColor } from "@velastack/patterns";
|
|
4593
|
-
var base = new
|
|
4924
|
+
var base = new Command43("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
|
|
4594
4925
|
(color) => runCommand(async () => {
|
|
4595
4926
|
const { workspaceRootDir } = await getWorkspace();
|
|
4596
|
-
const
|
|
4927
|
+
const log45 = p27.taskLog({ title: `Applying the ${color} palette...` });
|
|
4597
4928
|
let outcome;
|
|
4598
4929
|
try {
|
|
4599
4930
|
outcome = await applyBaseColor({ root: workspaceRootDir, color });
|
|
4600
|
-
|
|
4931
|
+
log45.success("Palette applied");
|
|
4601
4932
|
} catch (e) {
|
|
4602
|
-
|
|
4933
|
+
log45.error("Could not change the base color");
|
|
4603
4934
|
throw e;
|
|
4604
4935
|
}
|
|
4605
4936
|
reportResult({
|
|
@@ -4615,8 +4946,8 @@ var base = new Command42("base").description("change the base (gray) palette").a
|
|
|
4615
4946
|
);
|
|
4616
4947
|
|
|
4617
4948
|
// src/commands/ui/list.ts
|
|
4618
|
-
import { Command as
|
|
4619
|
-
import * as
|
|
4949
|
+
import { Command as Command44 } from "commander";
|
|
4950
|
+
import * as p28 from "@clack/prompts";
|
|
4620
4951
|
import { listComponents } from "@velastack/patterns";
|
|
4621
4952
|
|
|
4622
4953
|
// src/lib/ui-list.ts
|
|
@@ -4647,7 +4978,7 @@ function uiListReport(result) {
|
|
|
4647
4978
|
}
|
|
4648
4979
|
|
|
4649
4980
|
// src/commands/ui/list.ts
|
|
4650
|
-
var list = new
|
|
4981
|
+
var list = new Command44("list").description("list installed ui components, vela components and the style registry").option("--json", "print the result as JSON", false).configureHelp(helpConfig).action(
|
|
4651
4982
|
(options) => runCommand(async () => {
|
|
4652
4983
|
const { workspaceRootDir } = await getWorkspace();
|
|
4653
4984
|
if (options.json) {
|
|
@@ -4655,7 +4986,7 @@ var list = new Command43("list").description("list installed ui components, vela
|
|
|
4655
4986
|
console.log(JSON.stringify(result2, null, 2));
|
|
4656
4987
|
return;
|
|
4657
4988
|
}
|
|
4658
|
-
const spinner7 =
|
|
4989
|
+
const spinner7 = p28.spinner();
|
|
4659
4990
|
spinner7.start("Reading the registry...");
|
|
4660
4991
|
let result;
|
|
4661
4992
|
try {
|
|
@@ -4667,15 +4998,15 @@ var list = new Command43("list").description("list installed ui components, vela
|
|
|
4667
4998
|
spinner7.stop(`Read the ${result.style} registry`);
|
|
4668
4999
|
reportResult(uiListReport(result));
|
|
4669
5000
|
if (result.registryUnavailable) {
|
|
4670
|
-
|
|
5001
|
+
p28.log.warn(`${result.registryUnavailable}
|
|
4671
5002
|
Registry components are not listed.`);
|
|
4672
5003
|
}
|
|
4673
5004
|
}, "Failed to list UI components.")
|
|
4674
5005
|
);
|
|
4675
5006
|
|
|
4676
5007
|
// src/commands/ui/style.ts
|
|
4677
|
-
import { Command as
|
|
4678
|
-
import * as
|
|
5008
|
+
import { Command as Command45 } from "commander";
|
|
5009
|
+
import * as p29 from "@clack/prompts";
|
|
4679
5010
|
import { switchStyle } from "@velastack/patterns";
|
|
4680
5011
|
|
|
4681
5012
|
// src/lib/ui-style.ts
|
|
@@ -4701,72 +5032,72 @@ function uiStyleReport(result) {
|
|
|
4701
5032
|
}
|
|
4702
5033
|
|
|
4703
5034
|
// src/commands/ui/style.ts
|
|
4704
|
-
var style = new
|
|
5035
|
+
var style = new Command45("style").description("switch the shadcn-svelte style, re-adding its components").argument("<style>", `style to switch to (${STYLES.join(", ")})`).option("-y, --yes", "skip the confirmation prompt").option("--no-font", "keep the current font instead of applying the style's").configureHelp(helpConfig).action(
|
|
4705
5036
|
(name, options) => runCommand(async () => {
|
|
4706
5037
|
const { workspaceRootDir } = await getWorkspace();
|
|
4707
|
-
const spinner7 =
|
|
5038
|
+
const spinner7 = p29.spinner();
|
|
4708
5039
|
spinner7.start(`Reading the ${name} registry...`);
|
|
4709
|
-
let
|
|
5040
|
+
let log45;
|
|
4710
5041
|
let outcome;
|
|
4711
5042
|
try {
|
|
4712
5043
|
outcome = await switchStyle({
|
|
4713
5044
|
root: workspaceRootDir,
|
|
4714
5045
|
style: name,
|
|
4715
5046
|
font: options.font,
|
|
4716
|
-
logger: { info: (message) =>
|
|
5047
|
+
logger: { info: (message) => log45?.message(message) },
|
|
4717
5048
|
confirm: async (components) => {
|
|
4718
5049
|
spinner7.stop(`Read the ${name} registry`);
|
|
4719
5050
|
if (components.length > 0) {
|
|
4720
|
-
|
|
5051
|
+
p29.log.info(
|
|
4721
5052
|
`Re-adds ${components.length} component(s) from the ${name} registry; local edits to their files are lost:
|
|
4722
5053
|
${components.map((c) => `- ${c}`).join("\n")}`
|
|
4723
5054
|
);
|
|
4724
5055
|
} else {
|
|
4725
|
-
|
|
5056
|
+
p29.log.info(
|
|
4726
5057
|
`No installed component comes from the registry; only the config changes.`
|
|
4727
5058
|
);
|
|
4728
5059
|
}
|
|
4729
5060
|
if (!options.yes) {
|
|
4730
|
-
const ok = await
|
|
4731
|
-
if (
|
|
5061
|
+
const ok = await p29.confirm({ message: `Switch to ${name}?`, initialValue: false });
|
|
5062
|
+
if (p29.isCancel(ok) || !ok) return false;
|
|
4732
5063
|
}
|
|
4733
|
-
|
|
5064
|
+
log45 = p29.taskLog({ title: `Switching to the ${name} style...` });
|
|
4734
5065
|
return true;
|
|
4735
5066
|
}
|
|
4736
5067
|
});
|
|
4737
5068
|
} catch (e) {
|
|
4738
5069
|
spinner7.stop(`Could not switch to ${name}`);
|
|
4739
|
-
|
|
5070
|
+
log45?.error("Could not switch style");
|
|
4740
5071
|
throw e;
|
|
4741
5072
|
}
|
|
4742
5073
|
spinner7.stop(`Read the ${name} registry`);
|
|
4743
5074
|
if (outcome.status === "unchanged") {
|
|
4744
|
-
|
|
5075
|
+
p29.log.info(`Already using the ${name} style.`);
|
|
4745
5076
|
return;
|
|
4746
5077
|
}
|
|
4747
5078
|
if (outcome.status === "cancelled") {
|
|
4748
|
-
|
|
5079
|
+
p29.cancel("Operation cancelled.");
|
|
4749
5080
|
return;
|
|
4750
5081
|
}
|
|
4751
|
-
|
|
5082
|
+
log45?.success("Style switched");
|
|
4752
5083
|
reportResult(uiStyleReport(outcome));
|
|
4753
5084
|
}, "Failed to switch style.")
|
|
4754
5085
|
);
|
|
4755
5086
|
|
|
4756
5087
|
// src/commands/ui/theme.ts
|
|
4757
|
-
import { Command as
|
|
4758
|
-
import * as
|
|
5088
|
+
import { Command as Command46 } from "commander";
|
|
5089
|
+
import * as p30 from "@clack/prompts";
|
|
4759
5090
|
import { applyTheme } from "@velastack/patterns";
|
|
4760
|
-
var theme = new
|
|
5091
|
+
var theme = new Command46("theme").description("change the accent color, keeping the base palette").argument("<accent>", `accent to use (${THEMES.join(", ")})`).configureHelp(helpConfig).action(
|
|
4761
5092
|
(accent) => runCommand(async () => {
|
|
4762
5093
|
const { workspaceRootDir } = await getWorkspace();
|
|
4763
|
-
const
|
|
5094
|
+
const log45 = p30.taskLog({ title: `Applying the ${accent} accent...` });
|
|
4764
5095
|
let outcome;
|
|
4765
5096
|
try {
|
|
4766
5097
|
outcome = await applyTheme({ root: workspaceRootDir, theme: accent });
|
|
4767
|
-
|
|
5098
|
+
log45.success("Accent applied");
|
|
4768
5099
|
} catch (e) {
|
|
4769
|
-
|
|
5100
|
+
log45.error("Could not change the accent");
|
|
4770
5101
|
throw e;
|
|
4771
5102
|
}
|
|
4772
5103
|
reportResult({
|
|
@@ -4782,22 +5113,22 @@ var theme = new Command45("theme").description("change the accent color, keeping
|
|
|
4782
5113
|
);
|
|
4783
5114
|
|
|
4784
5115
|
// src/commands/ui.ts
|
|
4785
|
-
var ui = new
|
|
5116
|
+
var ui = new Command47("ui").description("generate ui components").configureHelp(helpConfig).addCommand(add).addCommand(list).addCommand(style).addCommand(base).addCommand(theme);
|
|
4786
5117
|
|
|
4787
5118
|
// src/commands/legal.ts
|
|
4788
|
-
import { Command as
|
|
5119
|
+
import { Command as Command50 } from "commander";
|
|
4789
5120
|
|
|
4790
5121
|
// src/commands/legal/terms.ts
|
|
4791
|
-
import
|
|
4792
|
-
import
|
|
4793
|
-
import { Command as
|
|
4794
|
-
import * as
|
|
5122
|
+
import fs24 from "node:fs";
|
|
5123
|
+
import path22 from "node:path";
|
|
5124
|
+
import { Command as Command48 } from "commander";
|
|
5125
|
+
import * as p32 from "@clack/prompts";
|
|
4795
5126
|
|
|
4796
5127
|
// src/commands/legal/shared.ts
|
|
4797
|
-
import
|
|
4798
|
-
import * as
|
|
5128
|
+
import process18 from "node:process";
|
|
5129
|
+
import * as p31 from "@clack/prompts";
|
|
4799
5130
|
var sharedFields = {
|
|
4800
|
-
websiteUrl: () =>
|
|
5131
|
+
websiteUrl: () => p31.text({
|
|
4801
5132
|
message: "What is your website URL?",
|
|
4802
5133
|
placeholder: "http://www.mysite.com",
|
|
4803
5134
|
validate: (value) => {
|
|
@@ -4806,7 +5137,7 @@ var sharedFields = {
|
|
|
4806
5137
|
}
|
|
4807
5138
|
}
|
|
4808
5139
|
}),
|
|
4809
|
-
websiteName: () =>
|
|
5140
|
+
websiteName: () => p31.text({
|
|
4810
5141
|
message: "What is your website name?",
|
|
4811
5142
|
placeholder: "My Site",
|
|
4812
5143
|
validate: (value) => {
|
|
@@ -4815,7 +5146,7 @@ var sharedFields = {
|
|
|
4815
5146
|
}
|
|
4816
5147
|
}
|
|
4817
5148
|
}),
|
|
4818
|
-
entityType: () =>
|
|
5149
|
+
entityType: () => p31.select({
|
|
4819
5150
|
message: "Entity type",
|
|
4820
5151
|
options: [
|
|
4821
5152
|
{
|
|
@@ -4826,7 +5157,7 @@ var sharedFields = {
|
|
|
4826
5157
|
{ value: "individual", label: "I'm an Individual" }
|
|
4827
5158
|
]
|
|
4828
5159
|
}),
|
|
4829
|
-
businessName: ({ results }) => results?.entityType === "business" ?
|
|
5160
|
+
businessName: ({ results }) => results?.entityType === "business" ? p31.text({
|
|
4830
5161
|
message: "What is the name of the business?",
|
|
4831
5162
|
placeholder: "My Company LLC",
|
|
4832
5163
|
validate: (value) => {
|
|
@@ -4835,7 +5166,7 @@ var sharedFields = {
|
|
|
4835
5166
|
}
|
|
4836
5167
|
}
|
|
4837
5168
|
}) : void 0,
|
|
4838
|
-
businessAddress: ({ results }) => results?.entityType === "business" ?
|
|
5169
|
+
businessAddress: ({ results }) => results?.entityType === "business" ? p31.text({
|
|
4839
5170
|
message: "What is the address of the business?",
|
|
4840
5171
|
placeholder: "1 Cupertino, CA 95014",
|
|
4841
5172
|
validate: (value) => {
|
|
@@ -4844,7 +5175,7 @@ var sharedFields = {
|
|
|
4844
5175
|
}
|
|
4845
5176
|
}
|
|
4846
5177
|
}) : void 0,
|
|
4847
|
-
country: () =>
|
|
5178
|
+
country: () => p31.text({
|
|
4848
5179
|
message: "Enter the country",
|
|
4849
5180
|
validate: (value) => {
|
|
4850
5181
|
if (!value) {
|
|
@@ -4852,7 +5183,7 @@ var sharedFields = {
|
|
|
4852
5183
|
}
|
|
4853
5184
|
}
|
|
4854
5185
|
}),
|
|
4855
|
-
state: () =>
|
|
5186
|
+
state: () => p31.text({
|
|
4856
5187
|
message: "Enter the state",
|
|
4857
5188
|
validate: (value) => {
|
|
4858
5189
|
if (!value) {
|
|
@@ -4862,11 +5193,11 @@ var sharedFields = {
|
|
|
4862
5193
|
})
|
|
4863
5194
|
};
|
|
4864
5195
|
var onCancel = () => {
|
|
4865
|
-
|
|
4866
|
-
|
|
5196
|
+
p31.cancel("Operation cancelled.");
|
|
5197
|
+
process18.exit(0);
|
|
4867
5198
|
};
|
|
4868
5199
|
async function contactMethods(type) {
|
|
4869
|
-
const selection = await
|
|
5200
|
+
const selection = await p31.multiselect({
|
|
4870
5201
|
message: `How can users contact you for any questions regarding your ${type === "privacy" ? "Privacy Policy" : "Terms & Conditions"}? Check all that apply`,
|
|
4871
5202
|
options: [
|
|
4872
5203
|
{ value: "email", label: "By email" },
|
|
@@ -4875,11 +5206,11 @@ async function contactMethods(type) {
|
|
|
4875
5206
|
{ value: "mail", label: "By sending post mail" }
|
|
4876
5207
|
]
|
|
4877
5208
|
});
|
|
4878
|
-
if (
|
|
5209
|
+
if (p31.isCancel(selection)) onCancel();
|
|
4879
5210
|
const contact = selection;
|
|
4880
5211
|
const details = {};
|
|
4881
5212
|
if (contact.includes("email")) {
|
|
4882
|
-
const email3 = await
|
|
5213
|
+
const email3 = await p31.text({
|
|
4883
5214
|
message: "What's the email?",
|
|
4884
5215
|
placeholder: "office@mycompany.com",
|
|
4885
5216
|
validate: (value) => {
|
|
@@ -4888,11 +5219,11 @@ async function contactMethods(type) {
|
|
|
4888
5219
|
}
|
|
4889
5220
|
}
|
|
4890
5221
|
});
|
|
4891
|
-
if (
|
|
5222
|
+
if (p31.isCancel(email3)) onCancel();
|
|
4892
5223
|
details.email = email3;
|
|
4893
5224
|
}
|
|
4894
5225
|
if (contact.includes("page")) {
|
|
4895
|
-
const page = await
|
|
5226
|
+
const page = await p31.text({
|
|
4896
5227
|
message: "What's the link?",
|
|
4897
5228
|
placeholder: "http://www.mycompany.com/contact",
|
|
4898
5229
|
validate: (value) => {
|
|
@@ -4901,11 +5232,11 @@ async function contactMethods(type) {
|
|
|
4901
5232
|
}
|
|
4902
5233
|
}
|
|
4903
5234
|
});
|
|
4904
|
-
if (
|
|
5235
|
+
if (p31.isCancel(page)) onCancel();
|
|
4905
5236
|
details.page = page;
|
|
4906
5237
|
}
|
|
4907
5238
|
if (contact.includes("phone")) {
|
|
4908
|
-
const phone = await
|
|
5239
|
+
const phone = await p31.text({
|
|
4909
5240
|
message: "What's the phone number?",
|
|
4910
5241
|
placeholder: "408.996.1010",
|
|
4911
5242
|
validate: (value) => {
|
|
@@ -4914,11 +5245,11 @@ async function contactMethods(type) {
|
|
|
4914
5245
|
}
|
|
4915
5246
|
}
|
|
4916
5247
|
});
|
|
4917
|
-
if (
|
|
5248
|
+
if (p31.isCancel(phone)) onCancel();
|
|
4918
5249
|
details.phone = phone;
|
|
4919
5250
|
}
|
|
4920
5251
|
if (contact.includes("mail")) {
|
|
4921
|
-
const address = await
|
|
5252
|
+
const address = await p31.text({
|
|
4922
5253
|
message: "What's the address?",
|
|
4923
5254
|
placeholder: "767 Fifth Avenue New York, NY 10153, United States",
|
|
4924
5255
|
validate: (value) => {
|
|
@@ -4927,7 +5258,7 @@ async function contactMethods(type) {
|
|
|
4927
5258
|
}
|
|
4928
5259
|
}
|
|
4929
5260
|
});
|
|
4930
|
-
if (
|
|
5261
|
+
if (p31.isCancel(address)) onCancel();
|
|
4931
5262
|
details.address = address;
|
|
4932
5263
|
}
|
|
4933
5264
|
return { methods: contact, details };
|
|
@@ -5323,7 +5654,7 @@ var generateTermsHtml = (answers) => {
|
|
|
5323
5654
|
};
|
|
5324
5655
|
async function termsAction() {
|
|
5325
5656
|
const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
|
|
5326
|
-
const core = await
|
|
5657
|
+
const core = await p32.group(
|
|
5327
5658
|
{
|
|
5328
5659
|
websiteUrl: sharedFields.websiteUrl,
|
|
5329
5660
|
websiteName: sharedFields.websiteName,
|
|
@@ -5335,25 +5666,25 @@ async function termsAction() {
|
|
|
5335
5666
|
},
|
|
5336
5667
|
{ onCancel }
|
|
5337
5668
|
);
|
|
5338
|
-
const accounts = await
|
|
5669
|
+
const accounts = await p32.select({
|
|
5339
5670
|
message: "Can users create accounts?",
|
|
5340
5671
|
options: [
|
|
5341
5672
|
{ value: "yes", label: "Yes, users can create accounts" },
|
|
5342
5673
|
{ value: "no", label: "No" }
|
|
5343
5674
|
]
|
|
5344
5675
|
});
|
|
5345
|
-
if (
|
|
5346
|
-
const userContent = await
|
|
5676
|
+
if (p32.isCancel(accounts)) onCancel();
|
|
5677
|
+
const userContent = await p32.select({
|
|
5347
5678
|
message: "Can users create and/or upload content (ie. text, images)?",
|
|
5348
5679
|
options: [
|
|
5349
5680
|
{ value: "yes", label: "Yes, users can create and/or upload content" },
|
|
5350
5681
|
{ value: "no", label: "No" }
|
|
5351
5682
|
]
|
|
5352
5683
|
});
|
|
5353
|
-
if (
|
|
5684
|
+
if (p32.isCancel(userContent)) onCancel();
|
|
5354
5685
|
let infringementEmail;
|
|
5355
5686
|
if (userContent === "yes") {
|
|
5356
|
-
const email3 = await
|
|
5687
|
+
const email3 = await p32.text({
|
|
5357
5688
|
message: "What's the email address where you will receive infringements notices?",
|
|
5358
5689
|
placeholder: "dmca@website.com",
|
|
5359
5690
|
validate: (value) => {
|
|
@@ -5362,10 +5693,10 @@ async function termsAction() {
|
|
|
5362
5693
|
}
|
|
5363
5694
|
}
|
|
5364
5695
|
});
|
|
5365
|
-
if (
|
|
5696
|
+
if (p32.isCancel(email3)) onCancel();
|
|
5366
5697
|
infringementEmail = email3;
|
|
5367
5698
|
}
|
|
5368
|
-
const canBuyGoods = await
|
|
5699
|
+
const canBuyGoods = await p32.select({
|
|
5369
5700
|
message: "Can users buy goods (products, items)?",
|
|
5370
5701
|
options: [
|
|
5371
5702
|
{
|
|
@@ -5375,28 +5706,28 @@ async function termsAction() {
|
|
|
5375
5706
|
{ value: "no", label: "No" }
|
|
5376
5707
|
]
|
|
5377
5708
|
});
|
|
5378
|
-
if (
|
|
5379
|
-
const subscriptions2 = await
|
|
5709
|
+
if (p32.isCancel(canBuyGoods)) onCancel();
|
|
5710
|
+
const subscriptions2 = await p32.select({
|
|
5380
5711
|
message: "Do you offer subscription plans?",
|
|
5381
5712
|
options: [
|
|
5382
5713
|
{ value: "yes", label: "Yes, we offer subscription plans" },
|
|
5383
5714
|
{ value: "no", label: "No" }
|
|
5384
5715
|
]
|
|
5385
5716
|
});
|
|
5386
|
-
if (
|
|
5717
|
+
if (p32.isCancel(subscriptions2)) onCancel();
|
|
5387
5718
|
let freeTrial;
|
|
5388
5719
|
if (subscriptions2 === "yes") {
|
|
5389
|
-
const ft = await
|
|
5720
|
+
const ft = await p32.select({
|
|
5390
5721
|
message: "Do you offer a free trial?",
|
|
5391
5722
|
options: [
|
|
5392
5723
|
{ value: "yes", label: "Yes" },
|
|
5393
5724
|
{ value: "no", label: "No" }
|
|
5394
5725
|
]
|
|
5395
5726
|
});
|
|
5396
|
-
if (
|
|
5727
|
+
if (p32.isCancel(ft)) onCancel();
|
|
5397
5728
|
freeTrial = ft;
|
|
5398
5729
|
}
|
|
5399
|
-
const exclusiveContent = await
|
|
5730
|
+
const exclusiveContent = await p32.select({
|
|
5400
5731
|
message: "Do you want to make it clear that your own content & trademarks are your exclusive property?",
|
|
5401
5732
|
options: [
|
|
5402
5733
|
{
|
|
@@ -5406,24 +5737,24 @@ async function termsAction() {
|
|
|
5406
5737
|
{ value: "no", label: "No" }
|
|
5407
5738
|
]
|
|
5408
5739
|
});
|
|
5409
|
-
if (
|
|
5410
|
-
const feedbackReuse = await
|
|
5740
|
+
if (p32.isCancel(exclusiveContent)) onCancel();
|
|
5741
|
+
const feedbackReuse = await p32.select({
|
|
5411
5742
|
message: "If users provide you feedback & suggestions, do you want to use this feedback without compensation or credits given?",
|
|
5412
5743
|
options: [
|
|
5413
5744
|
{ value: "yes", label: "Yes, we may implement any feedback or suggestions we receive" },
|
|
5414
5745
|
{ value: "no", label: "No" }
|
|
5415
5746
|
]
|
|
5416
5747
|
});
|
|
5417
|
-
if (
|
|
5418
|
-
const promotions = await
|
|
5748
|
+
if (p32.isCancel(feedbackReuse)) onCancel();
|
|
5749
|
+
const promotions = await p32.select({
|
|
5419
5750
|
message: "Do you plan to offer promotions, contests, sweepstakes?",
|
|
5420
5751
|
options: [
|
|
5421
5752
|
{ value: "yes", label: "Yes, we may offer promotions, contests, sweepstakes" },
|
|
5422
5753
|
{ value: "no", label: "No" }
|
|
5423
5754
|
]
|
|
5424
5755
|
});
|
|
5425
|
-
if (
|
|
5426
|
-
const mobileAppRaw = await
|
|
5756
|
+
if (p32.isCancel(promotions)) onCancel();
|
|
5757
|
+
const mobileAppRaw = await p32.multiselect({
|
|
5427
5758
|
message: "Is the Service distributed through any mobile app stores? Check all that apply",
|
|
5428
5759
|
options: [
|
|
5429
5760
|
{ value: "apple", label: "Apple App Store" },
|
|
@@ -5431,7 +5762,7 @@ async function termsAction() {
|
|
|
5431
5762
|
],
|
|
5432
5763
|
required: false
|
|
5433
5764
|
});
|
|
5434
|
-
if (
|
|
5765
|
+
if (p32.isCancel(mobileAppRaw)) onCancel();
|
|
5435
5766
|
const mobileApp = mobileAppRaw ?? [];
|
|
5436
5767
|
const contact = await contactMethods("terms");
|
|
5437
5768
|
const html = generateTermsHtml({
|
|
@@ -5448,22 +5779,22 @@ async function termsAction() {
|
|
|
5448
5779
|
mobileApp,
|
|
5449
5780
|
contact
|
|
5450
5781
|
});
|
|
5451
|
-
const termsPage =
|
|
5782
|
+
const termsPage = path22.join(
|
|
5452
5783
|
workspaceRootDir,
|
|
5453
5784
|
publicRoutesDir,
|
|
5454
5785
|
LEGAL_DIR,
|
|
5455
5786
|
"terms",
|
|
5456
5787
|
"+page.svelte"
|
|
5457
5788
|
);
|
|
5458
|
-
const termsPageTs =
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5789
|
+
const termsPageTs = path22.join(workspaceRootDir, publicRoutesDir, LEGAL_DIR, "terms", "+page.ts");
|
|
5790
|
+
fs24.mkdirSync(path22.dirname(termsPage), { recursive: true });
|
|
5791
|
+
fs24.writeFileSync(termsPage, html);
|
|
5792
|
+
fs24.writeFileSync(
|
|
5462
5793
|
termsPageTs,
|
|
5463
5794
|
pageMetaTagsLoader("Terms of Service", `Terms of Service for ${core.websiteName}`)
|
|
5464
5795
|
);
|
|
5465
|
-
const relativeTermsPage =
|
|
5466
|
-
const relativeTermsPageTs =
|
|
5796
|
+
const relativeTermsPage = path22.relative(workspaceRootDir, termsPage);
|
|
5797
|
+
const relativeTermsPageTs = path22.relative(workspaceRootDir, termsPageTs);
|
|
5467
5798
|
reportResult({
|
|
5468
5799
|
summary: "Generated placeholder terms and conditions.",
|
|
5469
5800
|
filesCreated: [relativeTermsPage, relativeTermsPageTs],
|
|
@@ -5474,13 +5805,13 @@ async function termsAction() {
|
|
|
5474
5805
|
]
|
|
5475
5806
|
});
|
|
5476
5807
|
}
|
|
5477
|
-
var terms = new
|
|
5808
|
+
var terms = new Command48("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
|
|
5478
5809
|
|
|
5479
5810
|
// src/commands/legal/privacy.ts
|
|
5480
|
-
import
|
|
5481
|
-
import
|
|
5482
|
-
import { Command as
|
|
5483
|
-
import * as
|
|
5811
|
+
import fs25 from "node:fs";
|
|
5812
|
+
import path23 from "node:path";
|
|
5813
|
+
import { Command as Command49 } from "commander";
|
|
5814
|
+
import * as p33 from "@clack/prompts";
|
|
5484
5815
|
var mapLabels = {
|
|
5485
5816
|
personalInfo: {
|
|
5486
5817
|
email: "Email address",
|
|
@@ -5898,12 +6229,12 @@ var generatePrivacyHtml = (answers) => {
|
|
|
5898
6229
|
return `<section data-role="content">${sections.join("")}</section>`;
|
|
5899
6230
|
};
|
|
5900
6231
|
async function promptWithCustom(message, options, customMessage) {
|
|
5901
|
-
const selection = await
|
|
5902
|
-
if (
|
|
6232
|
+
const selection = await p33.multiselect({ message, options });
|
|
6233
|
+
if (p33.isCancel(selection)) onCancel();
|
|
5903
6234
|
const values = selection;
|
|
5904
6235
|
if (values.includes("custom")) {
|
|
5905
|
-
const custom = await
|
|
5906
|
-
if (
|
|
6236
|
+
const custom = await p33.text({ message: customMessage });
|
|
6237
|
+
if (p33.isCancel(custom)) onCancel();
|
|
5907
6238
|
const idx = values.indexOf("custom");
|
|
5908
6239
|
if (idx !== -1) values.splice(idx, 1);
|
|
5909
6240
|
if (custom) values.push(String(custom));
|
|
@@ -5912,7 +6243,7 @@ async function promptWithCustom(message, options, customMessage) {
|
|
|
5912
6243
|
}
|
|
5913
6244
|
async function privacyAction() {
|
|
5914
6245
|
const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
|
|
5915
|
-
const core = await
|
|
6246
|
+
const core = await p33.group(
|
|
5916
6247
|
{
|
|
5917
6248
|
websiteUrl: sharedFields.websiteUrl,
|
|
5918
6249
|
websiteName: sharedFields.websiteName,
|
|
@@ -5924,7 +6255,7 @@ async function privacyAction() {
|
|
|
5924
6255
|
},
|
|
5925
6256
|
{ onCancel }
|
|
5926
6257
|
);
|
|
5927
|
-
const personalInfo = await
|
|
6258
|
+
const personalInfo = await p33.multiselect({
|
|
5928
6259
|
message: "What kind of personal information do you collect from users? Check all that apply",
|
|
5929
6260
|
options: [
|
|
5930
6261
|
{ value: "email", label: "Email address" },
|
|
@@ -5939,16 +6270,16 @@ async function privacyAction() {
|
|
|
5939
6270
|
],
|
|
5940
6271
|
required: false
|
|
5941
6272
|
});
|
|
5942
|
-
if (
|
|
6273
|
+
if (p33.isCancel(personalInfo)) onCancel();
|
|
5943
6274
|
const contact = await contactMethods("privacy");
|
|
5944
|
-
const tracking = await
|
|
6275
|
+
const tracking = await p33.select({
|
|
5945
6276
|
message: "Do you use tracking and/or analytics tools, such as Google Analytics?",
|
|
5946
6277
|
options: [
|
|
5947
6278
|
{ value: "yes", label: "Yes, we use Google Analytics or other related tools" },
|
|
5948
6279
|
{ value: "no", label: "No" }
|
|
5949
6280
|
]
|
|
5950
6281
|
});
|
|
5951
|
-
if (
|
|
6282
|
+
if (p33.isCancel(tracking)) onCancel();
|
|
5952
6283
|
let trackingTools;
|
|
5953
6284
|
if (tracking === "yes") {
|
|
5954
6285
|
trackingTools = await promptWithCustom(
|
|
@@ -5967,7 +6298,7 @@ async function privacyAction() {
|
|
|
5967
6298
|
"Enter your custom tracking/analytics tool name"
|
|
5968
6299
|
);
|
|
5969
6300
|
}
|
|
5970
|
-
const sendEmails = await
|
|
6301
|
+
const sendEmails = await p33.select({
|
|
5971
6302
|
message: "Do you send emails to users?",
|
|
5972
6303
|
options: [
|
|
5973
6304
|
{
|
|
@@ -5977,7 +6308,7 @@ async function privacyAction() {
|
|
|
5977
6308
|
{ value: "no", label: "No" }
|
|
5978
6309
|
]
|
|
5979
6310
|
});
|
|
5980
|
-
if (
|
|
6311
|
+
if (p33.isCancel(sendEmails)) onCancel();
|
|
5981
6312
|
let emailPlatforms;
|
|
5982
6313
|
if (sendEmails === "yes") {
|
|
5983
6314
|
emailPlatforms = await promptWithCustom(
|
|
@@ -5992,14 +6323,14 @@ async function privacyAction() {
|
|
|
5992
6323
|
"Enter your custom email platform"
|
|
5993
6324
|
);
|
|
5994
6325
|
}
|
|
5995
|
-
const showAds = await
|
|
6326
|
+
const showAds = await p33.select({
|
|
5996
6327
|
message: "Do you show ads?",
|
|
5997
6328
|
options: [
|
|
5998
6329
|
{ value: "yes", label: "Yes, we show ads" },
|
|
5999
6330
|
{ value: "no", label: "No" }
|
|
6000
6331
|
]
|
|
6001
6332
|
});
|
|
6002
|
-
if (
|
|
6333
|
+
if (p33.isCancel(showAds)) onCancel();
|
|
6003
6334
|
let adsPlatforms;
|
|
6004
6335
|
if (showAds === "yes") {
|
|
6005
6336
|
adsPlatforms = await promptWithCustom(
|
|
@@ -6022,7 +6353,7 @@ async function privacyAction() {
|
|
|
6022
6353
|
"Enter your custom ads platform"
|
|
6023
6354
|
);
|
|
6024
6355
|
}
|
|
6025
|
-
const canPay = await
|
|
6356
|
+
const canPay = await p33.select({
|
|
6026
6357
|
message: "Can users pay for products or services?",
|
|
6027
6358
|
options: [
|
|
6028
6359
|
{ value: "yes", label: "Yes, users can pay for our products/services" },
|
|
@@ -6032,7 +6363,7 @@ async function privacyAction() {
|
|
|
6032
6363
|
}
|
|
6033
6364
|
]
|
|
6034
6365
|
});
|
|
6035
|
-
if (
|
|
6366
|
+
if (p33.isCancel(canPay)) onCancel();
|
|
6036
6367
|
let paymentProcessors;
|
|
6037
6368
|
if (canPay === "yes") {
|
|
6038
6369
|
paymentProcessors = await promptWithCustom(
|
|
@@ -6063,14 +6394,14 @@ async function privacyAction() {
|
|
|
6063
6394
|
"Enter your custom payment processor/method"
|
|
6064
6395
|
);
|
|
6065
6396
|
}
|
|
6066
|
-
const remarketing = await
|
|
6397
|
+
const remarketing = await p33.select({
|
|
6067
6398
|
message: "Do you use remarketing services for marketing & advertising purposes?",
|
|
6068
6399
|
options: [
|
|
6069
6400
|
{ value: "yes", label: "Yes, we use remarketing services to advertise our business" },
|
|
6070
6401
|
{ value: "no", label: "No" }
|
|
6071
6402
|
]
|
|
6072
6403
|
});
|
|
6073
|
-
if (
|
|
6404
|
+
if (p33.isCancel(remarketing)) onCancel();
|
|
6074
6405
|
let remarketingPlatforms;
|
|
6075
6406
|
if (remarketing === "yes") {
|
|
6076
6407
|
remarketingPlatforms = await promptWithCustom(
|
|
@@ -6089,7 +6420,7 @@ async function privacyAction() {
|
|
|
6089
6420
|
"Enter your custom remarketing platform"
|
|
6090
6421
|
);
|
|
6091
6422
|
}
|
|
6092
|
-
const providersRaw = await
|
|
6423
|
+
const providersRaw = await p33.multiselect({
|
|
6093
6424
|
message: "Select if you use any of the following providers",
|
|
6094
6425
|
options: [
|
|
6095
6426
|
{ value: "recaptcha", label: "Invisible reCAPTCHA" },
|
|
@@ -6100,16 +6431,16 @@ async function privacyAction() {
|
|
|
6100
6431
|
],
|
|
6101
6432
|
required: false
|
|
6102
6433
|
});
|
|
6103
|
-
if (
|
|
6434
|
+
if (p33.isCancel(providersRaw)) onCancel();
|
|
6104
6435
|
const providers = providersRaw;
|
|
6105
6436
|
if (providers.includes("custom")) {
|
|
6106
|
-
const custom = await
|
|
6107
|
-
if (
|
|
6437
|
+
const custom = await p33.text({ message: "Enter your custom provider" });
|
|
6438
|
+
if (p33.isCancel(custom)) onCancel();
|
|
6108
6439
|
const idx = providers.indexOf("custom");
|
|
6109
6440
|
if (idx !== -1) providers.splice(idx, 1);
|
|
6110
6441
|
if (custom) providers.push(String(custom));
|
|
6111
6442
|
}
|
|
6112
|
-
const usStates = await
|
|
6443
|
+
const usStates = await p33.select({
|
|
6113
6444
|
message: "Include U.S. state privacy rights (CCPA/CPRA, VCDPA, CPA, CTDPA, UCPA, TX, OR, etc.)?",
|
|
6114
6445
|
options: [
|
|
6115
6446
|
{
|
|
@@ -6120,55 +6451,55 @@ async function privacyAction() {
|
|
|
6120
6451
|
],
|
|
6121
6452
|
initialValue: "yes"
|
|
6122
6453
|
});
|
|
6123
|
-
if (
|
|
6124
|
-
const gdpr = await
|
|
6454
|
+
if (p33.isCancel(usStates)) onCancel();
|
|
6455
|
+
const gdpr = await p33.select({
|
|
6125
6456
|
message: "Do you want your Privacy Policy to include GDPR / UK GDPR wording?",
|
|
6126
6457
|
options: [
|
|
6127
6458
|
{ value: "yes", label: "Yes. Include GDPR rights for EEA, UK, and Swiss residents" },
|
|
6128
6459
|
{ value: "no", label: "No" }
|
|
6129
6460
|
]
|
|
6130
6461
|
});
|
|
6131
|
-
if (
|
|
6462
|
+
if (p33.isCancel(gdpr)) onCancel();
|
|
6132
6463
|
let facebookFanPage = "no";
|
|
6133
6464
|
const facebookDetails = { name: "", url: "" };
|
|
6134
6465
|
if (gdpr === "yes") {
|
|
6135
|
-
const fan = await
|
|
6466
|
+
const fan = await p33.select({
|
|
6136
6467
|
message: "Do you have a Facebook Fan Page?",
|
|
6137
6468
|
options: [
|
|
6138
6469
|
{ value: "yes", label: "Yes, we have a Facebook Fan Page" },
|
|
6139
6470
|
{ value: "no", label: "No" }
|
|
6140
6471
|
]
|
|
6141
6472
|
});
|
|
6142
|
-
if (
|
|
6473
|
+
if (p33.isCancel(fan)) onCancel();
|
|
6143
6474
|
facebookFanPage = fan;
|
|
6144
6475
|
if (facebookFanPage === "yes") {
|
|
6145
|
-
const name = await
|
|
6476
|
+
const name = await p33.text({
|
|
6146
6477
|
message: "What is the name of the Facebook Fan Page?",
|
|
6147
6478
|
placeholder: "My Facebook Page"
|
|
6148
6479
|
});
|
|
6149
|
-
if (
|
|
6480
|
+
if (p33.isCancel(name)) onCancel();
|
|
6150
6481
|
facebookDetails.name = name;
|
|
6151
|
-
const url = await
|
|
6482
|
+
const url = await p33.text({
|
|
6152
6483
|
message: "What is the URL of the Facebook Fan Page?",
|
|
6153
6484
|
placeholder: "https://facebook.com/my-facebook-page"
|
|
6154
6485
|
});
|
|
6155
|
-
if (
|
|
6486
|
+
if (p33.isCancel(url)) onCancel();
|
|
6156
6487
|
facebookDetails.url = url;
|
|
6157
6488
|
}
|
|
6158
6489
|
}
|
|
6159
|
-
const kids = await
|
|
6490
|
+
const kids = await p33.select({
|
|
6160
6491
|
message: "Do you collect information from kids under the age of 13?",
|
|
6161
6492
|
options: [
|
|
6162
6493
|
{ value: "yes", label: "Yes. We collect information from children under the age of 13" },
|
|
6163
6494
|
{ value: "no", label: "No" }
|
|
6164
6495
|
]
|
|
6165
6496
|
});
|
|
6166
|
-
if (
|
|
6167
|
-
const retention = await
|
|
6497
|
+
if (p33.isCancel(kids)) onCancel();
|
|
6498
|
+
const retention = await p33.text({
|
|
6168
6499
|
message: "How long do you retain personal information? (leave blank for default wording)",
|
|
6169
6500
|
placeholder: "e.g. 12 months after account closure"
|
|
6170
6501
|
});
|
|
6171
|
-
if (
|
|
6502
|
+
if (p33.isCancel(retention)) onCancel();
|
|
6172
6503
|
const html = generatePrivacyHtml({
|
|
6173
6504
|
core,
|
|
6174
6505
|
personalInfo: personalInfo ?? [],
|
|
@@ -6191,28 +6522,28 @@ async function privacyAction() {
|
|
|
6191
6522
|
kids,
|
|
6192
6523
|
retention
|
|
6193
6524
|
});
|
|
6194
|
-
const privacyPage =
|
|
6525
|
+
const privacyPage = path23.join(
|
|
6195
6526
|
workspaceRootDir,
|
|
6196
6527
|
publicRoutesDir,
|
|
6197
6528
|
LEGAL_DIR,
|
|
6198
6529
|
"privacy",
|
|
6199
6530
|
"+page.svelte"
|
|
6200
6531
|
);
|
|
6201
|
-
const privacyPageTs =
|
|
6532
|
+
const privacyPageTs = path23.join(
|
|
6202
6533
|
workspaceRootDir,
|
|
6203
6534
|
publicRoutesDir,
|
|
6204
6535
|
LEGAL_DIR,
|
|
6205
6536
|
"privacy",
|
|
6206
6537
|
"+page.ts"
|
|
6207
6538
|
);
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6539
|
+
fs25.mkdirSync(path23.dirname(privacyPage), { recursive: true });
|
|
6540
|
+
fs25.writeFileSync(privacyPage, html);
|
|
6541
|
+
fs25.writeFileSync(
|
|
6211
6542
|
privacyPageTs,
|
|
6212
6543
|
pageMetaTagsLoader("Privacy Policy", `Privacy Policy for ${core.websiteName}`)
|
|
6213
6544
|
);
|
|
6214
|
-
const relativePrivacyPage =
|
|
6215
|
-
const relativePrivacyPageTs =
|
|
6545
|
+
const relativePrivacyPage = path23.relative(workspaceRootDir, privacyPage);
|
|
6546
|
+
const relativePrivacyPageTs = path23.relative(workspaceRootDir, privacyPageTs);
|
|
6216
6547
|
reportResult({
|
|
6217
6548
|
summary: "Generated placeholder privacy policy.",
|
|
6218
6549
|
filesCreated: [relativePrivacyPage, relativePrivacyPageTs],
|
|
@@ -6223,20 +6554,20 @@ async function privacyAction() {
|
|
|
6223
6554
|
]
|
|
6224
6555
|
});
|
|
6225
6556
|
}
|
|
6226
|
-
var privacy = new
|
|
6557
|
+
var privacy = new Command49("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
|
|
6227
6558
|
|
|
6228
6559
|
// src/commands/legal.ts
|
|
6229
|
-
var legal = new
|
|
6560
|
+
var legal = new Command50("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
|
|
6230
6561
|
|
|
6231
6562
|
// src/commands/fixtures.ts
|
|
6232
|
-
import { Command as
|
|
6563
|
+
import { Command as Command56 } from "commander";
|
|
6233
6564
|
|
|
6234
6565
|
// src/commands/fixtures/load.ts
|
|
6235
|
-
import { Command as
|
|
6566
|
+
import { Command as Command51 } from "commander";
|
|
6236
6567
|
|
|
6237
6568
|
// src/lib/data.ts
|
|
6238
|
-
import
|
|
6239
|
-
import
|
|
6569
|
+
import fs26 from "node:fs";
|
|
6570
|
+
import path24 from "node:path";
|
|
6240
6571
|
import { ClientResponseError } from "pocketbase";
|
|
6241
6572
|
|
|
6242
6573
|
// src/lib/collections.ts
|
|
@@ -6273,14 +6604,14 @@ function dependencyOrder(collections2, startingCollectionId) {
|
|
|
6273
6604
|
|
|
6274
6605
|
// src/lib/data.ts
|
|
6275
6606
|
function dataDir(cwd, kind) {
|
|
6276
|
-
return
|
|
6607
|
+
return path24.join(cwd, DATA_DIR, kind);
|
|
6277
6608
|
}
|
|
6278
6609
|
function getDataFiles(cwd, kind) {
|
|
6279
6610
|
const dir = dataDir(cwd, kind);
|
|
6280
|
-
if (!
|
|
6281
|
-
return
|
|
6611
|
+
if (!fs26.existsSync(dir)) return [];
|
|
6612
|
+
return fs26.readdirSync(dir).filter((file) => file.endsWith(".json")).sort((a, b) => a.localeCompare(b)).map((file) => ({
|
|
6282
6613
|
collectionName: file.replace(/\.json$/i, "").replace(/^\d+[-_]?/, ""),
|
|
6283
|
-
filePath:
|
|
6614
|
+
filePath: path24.join(dir, file)
|
|
6284
6615
|
}));
|
|
6285
6616
|
}
|
|
6286
6617
|
function getSeedFiles(cwd) {
|
|
@@ -6290,7 +6621,7 @@ function getFixtureFiles(cwd) {
|
|
|
6290
6621
|
return getDataFiles(cwd, "fixtures");
|
|
6291
6622
|
}
|
|
6292
6623
|
function readRecords(filePath) {
|
|
6293
|
-
return JSON.parse(
|
|
6624
|
+
return JSON.parse(fs26.readFileSync(filePath, "utf8"));
|
|
6294
6625
|
}
|
|
6295
6626
|
function readSeedIds(cwd) {
|
|
6296
6627
|
const ids = /* @__PURE__ */ new Map();
|
|
@@ -6327,7 +6658,7 @@ function describeError(e) {
|
|
|
6327
6658
|
return e instanceof Error ? e.message : String(e);
|
|
6328
6659
|
}
|
|
6329
6660
|
function label3(cwd, filePath, count) {
|
|
6330
|
-
return `${
|
|
6661
|
+
return `${path24.relative(cwd, filePath)} (${count} records)`;
|
|
6331
6662
|
}
|
|
6332
6663
|
async function createRecords(pb, kind, cwd, { collectionName, filePath }) {
|
|
6333
6664
|
const records = readRecords(filePath);
|
|
@@ -6335,7 +6666,7 @@ async function createRecords(pb, kind, cwd, { collectionName, filePath }) {
|
|
|
6335
6666
|
try {
|
|
6336
6667
|
await pb.collection(collectionName).create(record);
|
|
6337
6668
|
} catch (e) {
|
|
6338
|
-
throw new DataLoadError(kind,
|
|
6669
|
+
throw new DataLoadError(kind, path24.relative(cwd, filePath), index, e);
|
|
6339
6670
|
}
|
|
6340
6671
|
}
|
|
6341
6672
|
return records.length;
|
|
@@ -6422,7 +6753,7 @@ async function hasLoadedFixtures(pb) {
|
|
|
6422
6753
|
}
|
|
6423
6754
|
|
|
6424
6755
|
// src/commands/fixtures/load.ts
|
|
6425
|
-
var load = new
|
|
6756
|
+
var load = new Command51("load").description("load fixtures into the database").configureHelp(helpConfig).action(
|
|
6426
6757
|
() => runCommand(async () => {
|
|
6427
6758
|
const { workspaceRootDir } = await getWorkspace();
|
|
6428
6759
|
let loaded = [];
|
|
@@ -6448,8 +6779,8 @@ var load = new Command50("load").description("load fixtures into the database").
|
|
|
6448
6779
|
);
|
|
6449
6780
|
|
|
6450
6781
|
// src/commands/fixtures/clear.ts
|
|
6451
|
-
import { Command as
|
|
6452
|
-
var clear = new
|
|
6782
|
+
import { Command as Command52 } from "commander";
|
|
6783
|
+
var clear = new Command52("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
|
|
6453
6784
|
() => runCommand(async () => {
|
|
6454
6785
|
const { workspaceRootDir } = await getWorkspace();
|
|
6455
6786
|
let cleared = [];
|
|
@@ -6478,8 +6809,8 @@ var clear = new Command51("clear").description("clear loaded fixtures").configur
|
|
|
6478
6809
|
);
|
|
6479
6810
|
|
|
6480
6811
|
// src/commands/fixtures/reset.ts
|
|
6481
|
-
import { Command as
|
|
6482
|
-
var reset = new
|
|
6812
|
+
import { Command as Command53 } from "commander";
|
|
6813
|
+
var reset = new Command53("reset").description("clear and reload fixtures").configureHelp(helpConfig).action(
|
|
6483
6814
|
() => runCommand(async () => {
|
|
6484
6815
|
const { workspaceRootDir } = await getWorkspace();
|
|
6485
6816
|
let cleared = [];
|
|
@@ -6509,10 +6840,10 @@ var reset = new Command52("reset").description("clear and reload fixtures").conf
|
|
|
6509
6840
|
);
|
|
6510
6841
|
|
|
6511
6842
|
// src/commands/fixtures/generate.ts
|
|
6512
|
-
import
|
|
6513
|
-
import
|
|
6514
|
-
import { Command as
|
|
6515
|
-
import * as
|
|
6843
|
+
import fs27 from "node:fs";
|
|
6844
|
+
import path25 from "node:path";
|
|
6845
|
+
import { Command as Command54, InvalidArgumentError } from "commander";
|
|
6846
|
+
import * as p34 from "@clack/prompts";
|
|
6516
6847
|
import { annotate } from "annotate-json-schema";
|
|
6517
6848
|
import { createGenerator } from "json-schema-faker";
|
|
6518
6849
|
import { faker } from "@faker-js/faker";
|
|
@@ -6547,9 +6878,9 @@ async function loadCollections(pb) {
|
|
|
6547
6878
|
}
|
|
6548
6879
|
async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
6549
6880
|
const fixturesDir = dataDir(workspaceRootDir, "fixtures");
|
|
6550
|
-
|
|
6551
|
-
for (const file of
|
|
6552
|
-
if (file.endsWith(".json"))
|
|
6881
|
+
fs27.mkdirSync(fixturesDir, { recursive: true });
|
|
6882
|
+
for (const file of fs27.readdirSync(fixturesDir)) {
|
|
6883
|
+
if (file.endsWith(".json")) fs27.unlinkSync(path25.join(fixturesDir, file));
|
|
6553
6884
|
}
|
|
6554
6885
|
if (opts.seed !== void 0) faker.seed(opts.seed);
|
|
6555
6886
|
const generator = createGenerator({
|
|
@@ -6616,13 +6947,13 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
|
6616
6947
|
items.push(record);
|
|
6617
6948
|
}
|
|
6618
6949
|
const filename = `${padZeros(fileIndex, 2)}-${collection.name}.json`;
|
|
6619
|
-
|
|
6620
|
-
writtenFiles.push(`${
|
|
6950
|
+
fs27.writeFileSync(path25.join(fixturesDir, filename), JSON.stringify(items, null, 2));
|
|
6951
|
+
writtenFiles.push(`${path25.join(DATA_DIR, "fixtures", filename)} (${items.length} records)`);
|
|
6621
6952
|
fileIndex++;
|
|
6622
6953
|
}
|
|
6623
6954
|
return { writtenFiles, warnings };
|
|
6624
6955
|
}
|
|
6625
|
-
var generate2 = new
|
|
6956
|
+
var generate2 = new Command54("generate").description("generate fixture data").option("-c, --count <count>", "number of records per collection", parseCount, 10).option("-s, --seed <seed>", "seed for deterministic output", parseSeed).option("-f, --force", "overwrite existing fixture files and clear loaded fixtures").configureHelp(helpConfig).action(
|
|
6626
6957
|
(opts) => runCommand(async () => {
|
|
6627
6958
|
const { workspaceRootDir } = await getWorkspace();
|
|
6628
6959
|
const existing = getFixtureFiles(workspaceRootDir);
|
|
@@ -6651,7 +6982,7 @@ var generate2 = new Command53("generate").description("generate fixture data").o
|
|
|
6651
6982
|
seed: opts.seed
|
|
6652
6983
|
});
|
|
6653
6984
|
});
|
|
6654
|
-
for (const warning of result.warnings)
|
|
6985
|
+
for (const warning of result.warnings) p34.log.warn(warning);
|
|
6655
6986
|
if (result.writtenFiles.length === 0) {
|
|
6656
6987
|
reportResult({
|
|
6657
6988
|
summary: "No eligible collections found to generate fixtures for.",
|
|
@@ -6675,8 +7006,8 @@ var generate2 = new Command53("generate").description("generate fixture data").o
|
|
|
6675
7006
|
);
|
|
6676
7007
|
|
|
6677
7008
|
// src/commands/fixtures/regen.ts
|
|
6678
|
-
import { Command as
|
|
6679
|
-
import * as
|
|
7009
|
+
import { Command as Command55, InvalidArgumentError as InvalidArgumentError2 } from "commander";
|
|
7010
|
+
import * as p35 from "@clack/prompts";
|
|
6680
7011
|
function parseCount2(value) {
|
|
6681
7012
|
const n = parseInt(value, 10);
|
|
6682
7013
|
if (!Number.isFinite(n) || n <= 0 || n > 999) {
|
|
@@ -6691,7 +7022,7 @@ function parseSeed2(value) {
|
|
|
6691
7022
|
}
|
|
6692
7023
|
return n;
|
|
6693
7024
|
}
|
|
6694
|
-
var regen = new
|
|
7025
|
+
var regen = new Command55("regen").description("clear the database, regenerate fixture files, and reload them").option("-c, --count <count>", "number of records per collection", parseCount2, 10).option("-s, --seed <seed>", "seed for deterministic output", parseSeed2).configureHelp(helpConfig).action(
|
|
6695
7026
|
(opts) => runCommand(async () => {
|
|
6696
7027
|
const { workspaceRootDir } = await getWorkspace();
|
|
6697
7028
|
let cleared = [];
|
|
@@ -6705,7 +7036,7 @@ var regen = new Command54("regen").description("clear the database, regenerate f
|
|
|
6705
7036
|
});
|
|
6706
7037
|
loaded = await loadFixtures(pb, workspaceRootDir);
|
|
6707
7038
|
});
|
|
6708
|
-
for (const warning of result.warnings)
|
|
7039
|
+
for (const warning of result.warnings) p35.log.warn(warning);
|
|
6709
7040
|
reportResult({
|
|
6710
7041
|
summary: `Regenerated fixtures (${loaded.length} collection(s) reloaded).`,
|
|
6711
7042
|
filesCreated: result.writtenFiles,
|
|
@@ -6720,14 +7051,14 @@ var regen = new Command54("regen").description("clear the database, regenerate f
|
|
|
6720
7051
|
);
|
|
6721
7052
|
|
|
6722
7053
|
// src/commands/fixtures.ts
|
|
6723
|
-
var fixtures = new
|
|
7054
|
+
var fixtures = new Command56("fixtures").description("manage fixture data").configureHelp(helpConfig).addCommand(generate2).addCommand(load).addCommand(clear).addCommand(reset).addCommand(regen);
|
|
6724
7055
|
|
|
6725
7056
|
// src/commands/seeds.ts
|
|
6726
|
-
import { Command as
|
|
7057
|
+
import { Command as Command60 } from "commander";
|
|
6727
7058
|
|
|
6728
7059
|
// src/commands/seeds/load.ts
|
|
6729
|
-
import { Command as
|
|
6730
|
-
var load2 = new
|
|
7060
|
+
import { Command as Command57 } from "commander";
|
|
7061
|
+
var load2 = new Command57("load").description("load seeds into the database").option("-f, --force", "load even if target collections already have records").configureHelp(helpConfig).action(
|
|
6731
7062
|
(opts) => runCommand(async () => {
|
|
6732
7063
|
const { workspaceRootDir } = await getWorkspace();
|
|
6733
7064
|
const seedFiles = getSeedFiles(workspaceRootDir);
|
|
@@ -6764,9 +7095,9 @@ var load2 = new Command56("load").description("load seeds into the database").op
|
|
|
6764
7095
|
);
|
|
6765
7096
|
|
|
6766
7097
|
// src/commands/seeds/save.ts
|
|
6767
|
-
import
|
|
6768
|
-
import
|
|
6769
|
-
import { Command as
|
|
7098
|
+
import fs28 from "node:fs";
|
|
7099
|
+
import path26 from "node:path";
|
|
7100
|
+
import { Command as Command58 } from "commander";
|
|
6770
7101
|
var padZeros2 = (num, length) => num.toString().padStart(length, "0");
|
|
6771
7102
|
function filterSystemFields(record, systemFieldNames) {
|
|
6772
7103
|
const out = {};
|
|
@@ -6777,7 +7108,7 @@ function filterSystemFields(record, systemFieldNames) {
|
|
|
6777
7108
|
}
|
|
6778
7109
|
return out;
|
|
6779
7110
|
}
|
|
6780
|
-
var save = new
|
|
7111
|
+
var save = new Command58("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
|
|
6781
7112
|
(opts) => runCommand(async () => {
|
|
6782
7113
|
const { workspaceRootDir } = await getWorkspace();
|
|
6783
7114
|
const seedsPath = dataDir(workspaceRootDir, "seeds");
|
|
@@ -6785,10 +7116,10 @@ var save = new Command57("save").description("save the current data as seeds").o
|
|
|
6785
7116
|
if (existing.length > 0 && !opts.force) {
|
|
6786
7117
|
throw new Error("Existing seed files found in data/seeds. Pass --force to overwrite.");
|
|
6787
7118
|
}
|
|
6788
|
-
|
|
7119
|
+
fs28.mkdirSync(seedsPath, { recursive: true });
|
|
6789
7120
|
if (opts.force) {
|
|
6790
|
-
for (const file of
|
|
6791
|
-
if (file.endsWith(".json"))
|
|
7121
|
+
for (const file of fs28.readdirSync(seedsPath)) {
|
|
7122
|
+
if (file.endsWith(".json")) fs28.unlinkSync(path26.join(seedsPath, file));
|
|
6792
7123
|
}
|
|
6793
7124
|
}
|
|
6794
7125
|
const saved = [];
|
|
@@ -6817,13 +7148,13 @@ var save = new Command57("save").description("save the current data as seeds").o
|
|
|
6817
7148
|
const filtered = records.map(
|
|
6818
7149
|
(r) => filterSystemFields(r, systemFieldNames)
|
|
6819
7150
|
);
|
|
6820
|
-
const relativeSeedPath =
|
|
7151
|
+
const relativeSeedPath = path26.join(
|
|
6821
7152
|
DATA_DIR,
|
|
6822
7153
|
"seeds",
|
|
6823
7154
|
`${padZeros2(count, 2)}-${collectionName}.json`
|
|
6824
7155
|
);
|
|
6825
|
-
const seedPath =
|
|
6826
|
-
|
|
7156
|
+
const seedPath = path26.join(workspaceRootDir, relativeSeedPath);
|
|
7157
|
+
fs28.writeFileSync(seedPath, JSON.stringify(filtered, null, 2));
|
|
6827
7158
|
saved.push(`${relativeSeedPath} (${filtered.length} records)`);
|
|
6828
7159
|
count++;
|
|
6829
7160
|
}
|
|
@@ -6849,8 +7180,8 @@ var save = new Command57("save").description("save the current data as seeds").o
|
|
|
6849
7180
|
);
|
|
6850
7181
|
|
|
6851
7182
|
// src/commands/seeds/clear.ts
|
|
6852
|
-
import { Command as
|
|
6853
|
-
var clear2 = new
|
|
7183
|
+
import { Command as Command59 } from "commander";
|
|
7184
|
+
var clear2 = new Command59("clear").description("clear seeded records").configureHelp(helpConfig).action(
|
|
6854
7185
|
() => runCommand(async () => {
|
|
6855
7186
|
const { workspaceRootDir } = await getWorkspace();
|
|
6856
7187
|
const seedFiles = getSeedFiles(workspaceRootDir);
|
|
@@ -6881,23 +7212,23 @@ var clear2 = new Command58("clear").description("clear seeded records").configur
|
|
|
6881
7212
|
);
|
|
6882
7213
|
|
|
6883
7214
|
// src/commands/seeds.ts
|
|
6884
|
-
var seeds = new
|
|
7215
|
+
var seeds = new Command60("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
|
|
6885
7216
|
|
|
6886
7217
|
// src/commands/signup.ts
|
|
6887
|
-
import { Command as
|
|
6888
|
-
import * as
|
|
7218
|
+
import { Command as Command62 } from "commander";
|
|
7219
|
+
import * as p37 from "@clack/prompts";
|
|
6889
7220
|
import makeFetchCookie2 from "fetch-cookie";
|
|
6890
7221
|
|
|
6891
7222
|
// src/commands/login.ts
|
|
6892
7223
|
import os3 from "node:os";
|
|
6893
|
-
import { Command as
|
|
6894
|
-
import * as
|
|
7224
|
+
import { Command as Command61 } from "commander";
|
|
7225
|
+
import * as p36 from "@clack/prompts";
|
|
6895
7226
|
import makeFetchCookie from "fetch-cookie";
|
|
6896
|
-
var login = new
|
|
7227
|
+
var login = new Command61("login").description("login to velastack.dev").configureHelp(helpConfig).action(
|
|
6897
7228
|
() => runCommand(async () => {
|
|
6898
|
-
const { email: email3, password: password11 } = await
|
|
6899
|
-
email: () =>
|
|
6900
|
-
password: () =>
|
|
7229
|
+
const { email: email3, password: password11 } = await p36.group({
|
|
7230
|
+
email: () => p36.text({ message: "Email" }),
|
|
7231
|
+
password: () => p36.password({ message: "Password" })
|
|
6901
7232
|
});
|
|
6902
7233
|
const fetchCookie = makeFetchCookie(fetch);
|
|
6903
7234
|
const loginRes = await fetchCookie(`${API_URL}/login`, {
|
|
@@ -6919,7 +7250,7 @@ var login = new Command60("login").description("login to velastack.dev").configu
|
|
|
6919
7250
|
}
|
|
6920
7251
|
const apiKey = await issueApiKey(fetchCookie);
|
|
6921
7252
|
writeConfig({ apiKey });
|
|
6922
|
-
|
|
7253
|
+
p36.log.success("Logged in to velastack.dev");
|
|
6923
7254
|
}, "Failed to login.")
|
|
6924
7255
|
);
|
|
6925
7256
|
async function issueApiKey(fetchCookie) {
|
|
@@ -6960,12 +7291,12 @@ function extractApiKey(cookie) {
|
|
|
6960
7291
|
}
|
|
6961
7292
|
|
|
6962
7293
|
// src/commands/signup.ts
|
|
6963
|
-
var signup = new
|
|
7294
|
+
var signup = new Command62("signup").description("signup to velastack.dev").configureHelp(helpConfig).action(
|
|
6964
7295
|
() => runCommand(async () => {
|
|
6965
|
-
const { email: email3, password: password11, passwordConfirm } = await
|
|
6966
|
-
email: () =>
|
|
6967
|
-
password: () =>
|
|
6968
|
-
passwordConfirm: () =>
|
|
7296
|
+
const { email: email3, password: password11, passwordConfirm } = await p37.group({
|
|
7297
|
+
email: () => p37.text({ message: "Email" }),
|
|
7298
|
+
password: () => p37.password({ message: "Password" }),
|
|
7299
|
+
passwordConfirm: () => p37.password({ message: "Confirm password" })
|
|
6969
7300
|
});
|
|
6970
7301
|
if (password11 !== passwordConfirm) {
|
|
6971
7302
|
throw new Error("Passwords do not match.");
|
|
@@ -6989,33 +7320,33 @@ var signup = new Command61("signup").description("signup to velastack.dev").conf
|
|
|
6989
7320
|
}
|
|
6990
7321
|
const apiKey = await issueApiKey(fetchCookie);
|
|
6991
7322
|
writeConfig({ apiKey });
|
|
6992
|
-
|
|
6993
|
-
|
|
7323
|
+
p37.log.success("Signed up to velastack.dev");
|
|
7324
|
+
p37.log.info("Check your email for a confirmation link.");
|
|
6994
7325
|
}, "Failed to signup.")
|
|
6995
7326
|
);
|
|
6996
7327
|
|
|
6997
7328
|
// src/commands/logout.ts
|
|
6998
|
-
import { Command as
|
|
6999
|
-
import * as
|
|
7000
|
-
var logout = new
|
|
7329
|
+
import { Command as Command63 } from "commander";
|
|
7330
|
+
import * as p38 from "@clack/prompts";
|
|
7331
|
+
var logout = new Command63("logout").alias("signout").description("logout from velastack.dev").configureHelp(helpConfig).action(
|
|
7001
7332
|
() => runCommand(() => {
|
|
7002
7333
|
if (!readConfig()) {
|
|
7003
|
-
|
|
7334
|
+
p38.log.info("Not logged in");
|
|
7004
7335
|
return;
|
|
7005
7336
|
}
|
|
7006
7337
|
clearConfig();
|
|
7007
|
-
|
|
7338
|
+
p38.log.success("Logged out of velastack.dev");
|
|
7008
7339
|
})
|
|
7009
7340
|
);
|
|
7010
7341
|
|
|
7011
7342
|
// src/commands/whoami.ts
|
|
7012
|
-
import { Command as
|
|
7013
|
-
import * as
|
|
7014
|
-
var whoami = new
|
|
7343
|
+
import { Command as Command64 } from "commander";
|
|
7344
|
+
import * as p39 from "@clack/prompts";
|
|
7345
|
+
var whoami = new Command64("whoami").description("show the current user").configureHelp(helpConfig).action(
|
|
7015
7346
|
() => runCommand(async () => {
|
|
7016
7347
|
const apiKey = readConfig()?.apiKey;
|
|
7017
7348
|
if (!apiKey) {
|
|
7018
|
-
|
|
7349
|
+
p39.log.info("Not logged in. Run `vela login` to login.");
|
|
7019
7350
|
return;
|
|
7020
7351
|
}
|
|
7021
7352
|
const res = await fetch(`${API_URL}/api/collections/users/records`, {
|
|
@@ -7023,31 +7354,31 @@ var whoami = new Command63("whoami").description("show the current user").config
|
|
|
7023
7354
|
});
|
|
7024
7355
|
const data = await res.json();
|
|
7025
7356
|
if (!data.items.length) throw new Error("No user found. Run `vela login` to login.");
|
|
7026
|
-
|
|
7357
|
+
p39.log.success(`Logged in as ${data.items[0].email}`);
|
|
7027
7358
|
})
|
|
7028
7359
|
);
|
|
7029
7360
|
|
|
7030
7361
|
// src/commands/migrate.ts
|
|
7031
|
-
import { Command as
|
|
7362
|
+
import { Command as Command70 } from "commander";
|
|
7032
7363
|
|
|
7033
7364
|
// src/commands/migrate/up.ts
|
|
7034
|
-
import { Command as
|
|
7365
|
+
import { Command as Command65 } from "commander";
|
|
7035
7366
|
|
|
7036
7367
|
// src/lib/migrate.ts
|
|
7037
|
-
import
|
|
7038
|
-
import
|
|
7368
|
+
import path27 from "node:path";
|
|
7369
|
+
import process19 from "node:process";
|
|
7039
7370
|
import { x as x2 } from "tinyexec";
|
|
7040
7371
|
async function runPocketbaseMigrate(args) {
|
|
7041
|
-
const cwd =
|
|
7372
|
+
const cwd = process19.cwd();
|
|
7042
7373
|
const { getBinaryPath } = await import("pocketbase-server");
|
|
7043
7374
|
const binaryPath = getBinaryPath();
|
|
7044
7375
|
await x2(
|
|
7045
7376
|
binaryPath,
|
|
7046
7377
|
[
|
|
7047
7378
|
"--dir",
|
|
7048
|
-
|
|
7379
|
+
path27.join(cwd, DATA_DIR),
|
|
7049
7380
|
"--migrationsDir",
|
|
7050
|
-
|
|
7381
|
+
path27.join(cwd, MIGRATIONS_DIR),
|
|
7051
7382
|
"migrate",
|
|
7052
7383
|
...args
|
|
7053
7384
|
],
|
|
@@ -7070,10 +7401,10 @@ async function runMigrateUp() {
|
|
|
7070
7401
|
]
|
|
7071
7402
|
});
|
|
7072
7403
|
}
|
|
7073
|
-
var up = new
|
|
7404
|
+
var up = new Command65("up").description("apply all pending migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations."));
|
|
7074
7405
|
|
|
7075
7406
|
// src/commands/migrate/down.ts
|
|
7076
|
-
import { Command as
|
|
7407
|
+
import { Command as Command66, InvalidArgumentError as InvalidArgumentError3 } from "commander";
|
|
7077
7408
|
function parseSteps(value) {
|
|
7078
7409
|
const n = parseInt(value, 10);
|
|
7079
7410
|
if (!Number.isFinite(n) || n <= 0) {
|
|
@@ -7081,7 +7412,7 @@ function parseSteps(value) {
|
|
|
7081
7412
|
}
|
|
7082
7413
|
return n;
|
|
7083
7414
|
}
|
|
7084
|
-
var down = new
|
|
7415
|
+
var down = new Command66("down").alias("rollback").description("revert the last N applied migrations").argument("[number]", "how many migrations to revert", parseSteps, 1).configureHelp(helpConfig).action(
|
|
7085
7416
|
(n) => runCommand(async () => {
|
|
7086
7417
|
await runPocketbaseMigrate(["down", String(n)]);
|
|
7087
7418
|
reportResult({
|
|
@@ -7095,20 +7426,20 @@ var down = new Command65("down").alias("rollback").description("revert the last
|
|
|
7095
7426
|
);
|
|
7096
7427
|
|
|
7097
7428
|
// src/commands/migrate/create.ts
|
|
7098
|
-
import
|
|
7099
|
-
import
|
|
7100
|
-
import
|
|
7101
|
-
import { Command as
|
|
7102
|
-
var create2 = new
|
|
7429
|
+
import fs29 from "node:fs";
|
|
7430
|
+
import path28 from "node:path";
|
|
7431
|
+
import process20 from "node:process";
|
|
7432
|
+
import { Command as Command67 } from "commander";
|
|
7433
|
+
var create2 = new Command67("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
|
|
7103
7434
|
(name) => runCommand(async () => {
|
|
7104
|
-
const cwd =
|
|
7435
|
+
const cwd = process20.cwd();
|
|
7105
7436
|
const before = listMigrationFiles(cwd);
|
|
7106
7437
|
await runPocketbaseMigrate(["create", name]);
|
|
7107
7438
|
const after = listMigrationFiles(cwd);
|
|
7108
7439
|
const added = [...after].filter((f) => !before.has(f));
|
|
7109
7440
|
reportResult({
|
|
7110
7441
|
summary: `Created blank migration ${name}.`,
|
|
7111
|
-
filesCreated: added.map((f) =>
|
|
7442
|
+
filesCreated: added.map((f) => path28.join(MIGRATIONS_DIR, f)),
|
|
7112
7443
|
nextSteps: [
|
|
7113
7444
|
`Open the new file in ${MIGRATIONS_DIR}/ and fill in the up/down handlers.`,
|
|
7114
7445
|
"Run `vela migrate up` to apply the migration once the handlers are written."
|
|
@@ -7117,19 +7448,19 @@ var create2 = new Command66("create").alias("new").description("create a new bla
|
|
|
7117
7448
|
}, "Failed to create migration.")
|
|
7118
7449
|
);
|
|
7119
7450
|
function listMigrationFiles(cwd) {
|
|
7120
|
-
const dir =
|
|
7121
|
-
if (!
|
|
7122
|
-
return new Set(
|
|
7451
|
+
const dir = path28.join(cwd, MIGRATIONS_DIR);
|
|
7452
|
+
if (!fs29.existsSync(dir)) return /* @__PURE__ */ new Set();
|
|
7453
|
+
return new Set(fs29.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
|
|
7123
7454
|
}
|
|
7124
7455
|
|
|
7125
7456
|
// src/commands/migrate/collections.ts
|
|
7126
|
-
import
|
|
7127
|
-
import
|
|
7128
|
-
import
|
|
7129
|
-
import { Command as
|
|
7130
|
-
var collections = new
|
|
7457
|
+
import fs30 from "node:fs";
|
|
7458
|
+
import path29 from "node:path";
|
|
7459
|
+
import process21 from "node:process";
|
|
7460
|
+
import { Command as Command68 } from "commander";
|
|
7461
|
+
var collections = new Command68("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
|
|
7131
7462
|
() => runCommand(async () => {
|
|
7132
|
-
const cwd =
|
|
7463
|
+
const cwd = process21.cwd();
|
|
7133
7464
|
const before = listMigrationFiles2(cwd);
|
|
7134
7465
|
await runPocketbaseMigrate(["collections"]);
|
|
7135
7466
|
const after = listMigrationFiles2(cwd);
|
|
@@ -7142,7 +7473,7 @@ var collections = new Command67("collections").alias("snapshot").description("sn
|
|
|
7142
7473
|
}
|
|
7143
7474
|
reportResult({
|
|
7144
7475
|
summary: "Snapshotted local collections into a new migration.",
|
|
7145
|
-
filesCreated: added.map((f) =>
|
|
7476
|
+
filesCreated: added.map((f) => path29.join(MIGRATIONS_DIR, f)),
|
|
7146
7477
|
nextSteps: [
|
|
7147
7478
|
`Review the generated snapshot in ${MIGRATIONS_DIR}/.`,
|
|
7148
7479
|
"Commit the snapshot so teammates pick up the new schema.",
|
|
@@ -7152,14 +7483,14 @@ var collections = new Command67("collections").alias("snapshot").description("sn
|
|
|
7152
7483
|
}, "Failed to snapshot collections.")
|
|
7153
7484
|
);
|
|
7154
7485
|
function listMigrationFiles2(cwd) {
|
|
7155
|
-
const dir =
|
|
7156
|
-
if (!
|
|
7157
|
-
return new Set(
|
|
7486
|
+
const dir = path29.join(cwd, MIGRATIONS_DIR);
|
|
7487
|
+
if (!fs30.existsSync(dir)) return /* @__PURE__ */ new Set();
|
|
7488
|
+
return new Set(fs30.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
|
|
7158
7489
|
}
|
|
7159
7490
|
|
|
7160
7491
|
// src/commands/migrate/history-sync.ts
|
|
7161
|
-
import { Command as
|
|
7162
|
-
var historySync = new
|
|
7492
|
+
import { Command as Command69 } from "commander";
|
|
7493
|
+
var historySync = new Command69("history-sync").description("drop _migrations rows whose files no longer exist").configureHelp(helpConfig).action(
|
|
7163
7494
|
() => runCommand(async () => {
|
|
7164
7495
|
await runPocketbaseMigrate(["history-sync"]);
|
|
7165
7496
|
reportResult({
|
|
@@ -7170,23 +7501,23 @@ var historySync = new Command68("history-sync").description("drop _migrations ro
|
|
|
7170
7501
|
);
|
|
7171
7502
|
|
|
7172
7503
|
// src/commands/migrate.ts
|
|
7173
|
-
var migrate = new
|
|
7504
|
+
var migrate = new Command70("migrate").description("manage database migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations.")).addCommand(up).addCommand(down).addCommand(create2).addCommand(collections).addCommand(historySync);
|
|
7174
7505
|
|
|
7175
7506
|
// src/commands/dev.ts
|
|
7176
|
-
import
|
|
7177
|
-
import
|
|
7178
|
-
import
|
|
7507
|
+
import fs31 from "node:fs";
|
|
7508
|
+
import path31 from "node:path";
|
|
7509
|
+
import process23 from "node:process";
|
|
7179
7510
|
import { performance } from "node:perf_hooks";
|
|
7180
|
-
import { Command as
|
|
7181
|
-
import
|
|
7511
|
+
import { Command as Command71, InvalidArgumentError as InvalidArgumentError4 } from "commander";
|
|
7512
|
+
import pc15 from "picocolors";
|
|
7182
7513
|
import PocketBase4 from "pocketbase";
|
|
7183
7514
|
|
|
7184
7515
|
// src/lib/vite.ts
|
|
7185
|
-
import
|
|
7186
|
-
import
|
|
7516
|
+
import path30 from "node:path";
|
|
7517
|
+
import process22 from "node:process";
|
|
7187
7518
|
import { createRequire as createRequire2 } from "node:module";
|
|
7188
7519
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
7189
|
-
import
|
|
7520
|
+
import pc14 from "picocolors";
|
|
7190
7521
|
var REQUIRED_VITE_MAJOR = 8;
|
|
7191
7522
|
function viteVersionError(version) {
|
|
7192
7523
|
const major = Number.parseInt(version, 10);
|
|
@@ -7202,18 +7533,18 @@ function viteVersionError(version) {
|
|
|
7202
7533
|
}
|
|
7203
7534
|
function resolveProjectVite(cwd) {
|
|
7204
7535
|
try {
|
|
7205
|
-
return createRequire2(
|
|
7536
|
+
return createRequire2(path30.join(cwd, "package.json")).resolve("vite");
|
|
7206
7537
|
} catch {
|
|
7207
7538
|
return null;
|
|
7208
7539
|
}
|
|
7209
7540
|
}
|
|
7210
|
-
async function loadVite(cwd =
|
|
7541
|
+
async function loadVite(cwd = process22.cwd()) {
|
|
7211
7542
|
const entry = resolveProjectVite(cwd);
|
|
7212
7543
|
const vite = entry ? await import(pathToFileURL2(entry).href) : await import("vite");
|
|
7213
7544
|
const error = viteVersionError(vite.version);
|
|
7214
7545
|
if (error) {
|
|
7215
|
-
console.error(`${
|
|
7216
|
-
|
|
7546
|
+
console.error(`${pc14.redBright("\u2717")} ${error}`);
|
|
7547
|
+
process22.exit(1);
|
|
7217
7548
|
}
|
|
7218
7549
|
return vite;
|
|
7219
7550
|
}
|
|
@@ -7226,39 +7557,39 @@ function parsePort(value) {
|
|
|
7226
7557
|
}
|
|
7227
7558
|
return port;
|
|
7228
7559
|
}
|
|
7229
|
-
var dev = new
|
|
7230
|
-
const cwd =
|
|
7231
|
-
|
|
7560
|
+
var dev = new Command71("dev").description("start the development server").option("--open [path]", "open the app in a browser once the server is ready").option("--host [host]", "expose the server on the network").option("--port <port>", "port to listen on", parsePort).option("--strictPort", "exit if the port is already in use instead of taking the next one").option("--cors", "enable CORS").option("--force", "re-bundle dependencies, ignoring the optimizer cache").configureHelp(helpConfig).action(async (options) => {
|
|
7561
|
+
const cwd = process23.cwd();
|
|
7562
|
+
process23.env.VELA_DATA_DIR ??= localDataDir(cwd);
|
|
7232
7563
|
const startTime = performance.now();
|
|
7233
7564
|
const { createServer, version } = await loadVite(cwd);
|
|
7234
|
-
const viteMetadataDir =
|
|
7235
|
-
const viteMetadataFile =
|
|
7565
|
+
const viteMetadataDir = path31.join(cwd, "node_modules", ".vite");
|
|
7566
|
+
const viteMetadataFile = path31.join(viteMetadataDir, "_pocketbase_metadata.json");
|
|
7236
7567
|
let pbProc;
|
|
7237
7568
|
const backend3 = hasBackend(cwd);
|
|
7238
|
-
const needsStart = backend3 && !
|
|
7569
|
+
const needsStart = backend3 && !process23.env.POCKETBASE_URL;
|
|
7239
7570
|
const cleanup = () => {
|
|
7240
7571
|
if (pbProc?.pid) pbProc.kill();
|
|
7241
|
-
if (
|
|
7572
|
+
if (fs31.existsSync(viteMetadataFile)) fs31.rmSync(viteMetadataFile);
|
|
7242
7573
|
};
|
|
7243
7574
|
if (needsStart) {
|
|
7244
|
-
const dataDir2 =
|
|
7575
|
+
const dataDir2 = path31.join(cwd, DATA_DIR);
|
|
7245
7576
|
const started = await startPocketbaseServe({
|
|
7246
7577
|
dataDir: dataDir2,
|
|
7247
7578
|
migrationsDir: MIGRATIONS_DIR,
|
|
7248
|
-
hooksDir:
|
|
7579
|
+
hooksDir: path31.join(dataDir2, "hooks"),
|
|
7249
7580
|
dev: true,
|
|
7250
7581
|
stdio: "pipe"
|
|
7251
7582
|
});
|
|
7252
7583
|
pbProc = started.proc;
|
|
7253
|
-
|
|
7254
|
-
pbProc.stdout?.pipe(
|
|
7255
|
-
pbProc.stderr?.pipe(
|
|
7584
|
+
process23.env.POCKETBASE_URL = started.url;
|
|
7585
|
+
pbProc.stdout?.pipe(process23.stdout);
|
|
7586
|
+
pbProc.stderr?.pipe(process23.stderr);
|
|
7256
7587
|
pbProc.on("error", (err) => console.error("PocketBase error:", err));
|
|
7257
7588
|
pbProc.on("exit", (code) => console.log(`PocketBase exited with code ${code}`));
|
|
7258
|
-
|
|
7259
|
-
|
|
7589
|
+
process23.on("exit", cleanup);
|
|
7590
|
+
process23.on("SIGINT", () => {
|
|
7260
7591
|
cleanup();
|
|
7261
|
-
|
|
7592
|
+
process23.exit(0);
|
|
7262
7593
|
});
|
|
7263
7594
|
}
|
|
7264
7595
|
const serverOptions = {};
|
|
@@ -7276,31 +7607,31 @@ var dev = new Command70("dev").description("start the development server").optio
|
|
|
7276
7607
|
if (!backend3) return;
|
|
7277
7608
|
const { address, port: vitePort } = server.httpServer.address();
|
|
7278
7609
|
const viteHost = address === "::1" ? "localhost" : address;
|
|
7279
|
-
await
|
|
7280
|
-
await
|
|
7610
|
+
await fs31.promises.mkdir(viteMetadataDir, { recursive: true });
|
|
7611
|
+
await fs31.promises.writeFile(
|
|
7281
7612
|
viteMetadataFile,
|
|
7282
7613
|
JSON.stringify({
|
|
7283
|
-
pocketbaseUrl:
|
|
7614
|
+
pocketbaseUrl: process23.env.POCKETBASE_URL,
|
|
7284
7615
|
vitePort,
|
|
7285
7616
|
viteHost
|
|
7286
7617
|
})
|
|
7287
7618
|
);
|
|
7288
|
-
const pb = new PocketBase4(
|
|
7619
|
+
const pb = new PocketBase4(process23.env.POCKETBASE_URL);
|
|
7289
7620
|
await pb.collection("_superusers").authWithPassword(
|
|
7290
|
-
|
|
7291
|
-
|
|
7621
|
+
process23.env.POCKETBASE_SUPERUSER_EMAIL,
|
|
7622
|
+
process23.env.POCKETBASE_SUPERUSER_PASSWORD
|
|
7292
7623
|
);
|
|
7293
7624
|
await pb.settings.update({ meta: { appURL: `http://${viteHost}:${vitePort}` } });
|
|
7294
7625
|
await startWatchingTypes(cwd, pb);
|
|
7295
7626
|
});
|
|
7296
7627
|
await server.listen();
|
|
7297
|
-
const hasExistingLogs =
|
|
7298
|
-
const startupDurationString =
|
|
7299
|
-
`ready in ${
|
|
7628
|
+
const hasExistingLogs = process23.stdout.bytesWritten > 0 || process23.stderr.bytesWritten > 0;
|
|
7629
|
+
const startupDurationString = pc15.dim(
|
|
7630
|
+
`ready in ${pc15.reset(pc15.bold(Math.ceil(performance.now() - startTime)))} ms`
|
|
7300
7631
|
);
|
|
7301
7632
|
server.config.logger.info(
|
|
7302
7633
|
`
|
|
7303
|
-
${
|
|
7634
|
+
${pc15.green(`${pc15.bold("VITE")} v${version}`)} ${startupDurationString}
|
|
7304
7635
|
`,
|
|
7305
7636
|
{ clear: !hasExistingLogs }
|
|
7306
7637
|
);
|
|
@@ -7309,18 +7640,18 @@ var dev = new Command70("dev").description("start the development server").optio
|
|
|
7309
7640
|
});
|
|
7310
7641
|
async function startWatchingTypes(cwd, pb) {
|
|
7311
7642
|
const { processTypes } = await import("@velastack/pocketbase-codegen");
|
|
7312
|
-
const typesDir =
|
|
7313
|
-
const pocketbaseDir =
|
|
7314
|
-
const pocketbaseTypes =
|
|
7643
|
+
const typesDir = path31.resolve(cwd, ".svelte-kit", "types");
|
|
7644
|
+
const pocketbaseDir = path31.join(typesDir, "pocketbase");
|
|
7645
|
+
const pocketbaseTypes = path31.join(pocketbaseDir, "$types.d.ts");
|
|
7315
7646
|
const regenerate = () => processTypes(pb, typesDir).catch(() => {
|
|
7316
7647
|
});
|
|
7317
7648
|
await regenerate();
|
|
7318
7649
|
void (async () => {
|
|
7319
7650
|
for (; ; ) {
|
|
7320
7651
|
try {
|
|
7321
|
-
await
|
|
7322
|
-
for await (const event of
|
|
7323
|
-
if (event.eventType === "rename" && event.filename === "$types.d.ts" && !
|
|
7652
|
+
await fs31.promises.mkdir(pocketbaseDir, { recursive: true });
|
|
7653
|
+
for await (const event of fs31.promises.watch(pocketbaseDir)) {
|
|
7654
|
+
if (event.eventType === "rename" && event.filename === "$types.d.ts" && !fs31.existsSync(pocketbaseTypes)) {
|
|
7324
7655
|
setTimeout(regenerate, 100);
|
|
7325
7656
|
}
|
|
7326
7657
|
}
|
|
@@ -7332,15 +7663,15 @@ async function startWatchingTypes(cwd, pb) {
|
|
|
7332
7663
|
}
|
|
7333
7664
|
|
|
7334
7665
|
// src/commands/build.ts
|
|
7335
|
-
import
|
|
7336
|
-
import
|
|
7337
|
-
import
|
|
7338
|
-
import { Command as
|
|
7339
|
-
import * as
|
|
7340
|
-
import
|
|
7666
|
+
import fs32 from "node:fs";
|
|
7667
|
+
import path32 from "node:path";
|
|
7668
|
+
import process25 from "node:process";
|
|
7669
|
+
import { Command as Command72 } from "commander";
|
|
7670
|
+
import * as p40 from "@clack/prompts";
|
|
7671
|
+
import pc16 from "picocolors";
|
|
7341
7672
|
import { x as x3 } from "tinyexec";
|
|
7342
|
-
import { detect as
|
|
7343
|
-
import { resolveCommand as
|
|
7673
|
+
import { detect as detect5 } from "package-manager-detector";
|
|
7674
|
+
import { resolveCommand as resolveCommand5 } from "package-manager-detector/commands";
|
|
7344
7675
|
|
|
7345
7676
|
// src/lib/build-env.ts
|
|
7346
7677
|
function applyBuildEnv(cwd, env2 = process.env) {
|
|
@@ -7349,10 +7680,10 @@ function applyBuildEnv(cwd, env2 = process.env) {
|
|
|
7349
7680
|
}
|
|
7350
7681
|
|
|
7351
7682
|
// src/lib/origin.ts
|
|
7352
|
-
import
|
|
7683
|
+
import process24 from "node:process";
|
|
7353
7684
|
function resolveOrigin(workspaceRootDir, envTag, config = {}) {
|
|
7354
7685
|
return normalizeOrigin(
|
|
7355
|
-
|
|
7686
|
+
process24.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
|
|
7356
7687
|
);
|
|
7357
7688
|
}
|
|
7358
7689
|
function normalizeOrigin(value) {
|
|
@@ -7366,39 +7697,42 @@ function normalizeOrigin(value) {
|
|
|
7366
7697
|
return null;
|
|
7367
7698
|
}
|
|
7368
7699
|
}
|
|
7700
|
+
function splitHosts(value) {
|
|
7701
|
+
return (value ?? "").split(",").map((host) => host.trim()).filter(Boolean);
|
|
7702
|
+
}
|
|
7369
7703
|
|
|
7370
7704
|
// src/commands/build.ts
|
|
7371
|
-
var PRERENDERED_DIR =
|
|
7372
|
-
var build = new
|
|
7373
|
-
const cwd =
|
|
7705
|
+
var PRERENDERED_DIR = path32.join(".svelte-kit", "output", "prerendered");
|
|
7706
|
+
var build = new Command72("build").description("build the app").configureHelp(helpConfig).option("-t, --target <target>", "which copy of the app to build for", PRODUCTION_TARGET).action(async (options) => {
|
|
7707
|
+
const cwd = process25.cwd();
|
|
7374
7708
|
applyBuildEnv(cwd);
|
|
7375
7709
|
const origin = await originForBuild(cwd, options.target);
|
|
7376
|
-
if (origin)
|
|
7710
|
+
if (origin) process25.env.VELA_ORIGIN = origin;
|
|
7377
7711
|
let pbProc;
|
|
7378
|
-
const needsStart = hasBackend(cwd) && !
|
|
7712
|
+
const needsStart = hasBackend(cwd) && !process25.env.POCKETBASE_URL;
|
|
7379
7713
|
const cleanup = () => {
|
|
7380
7714
|
if (pbProc?.pid) pbProc.kill();
|
|
7381
7715
|
};
|
|
7382
7716
|
if (needsStart) {
|
|
7383
7717
|
await ensureSuperuser(cwd);
|
|
7384
|
-
const dataDir2 =
|
|
7718
|
+
const dataDir2 = path32.join(cwd, DATA_DIR);
|
|
7385
7719
|
const started = await startPocketbaseServe({
|
|
7386
7720
|
dataDir: dataDir2,
|
|
7387
7721
|
migrationsDir: MIGRATIONS_DIR,
|
|
7388
|
-
hooksDir:
|
|
7722
|
+
hooksDir: path32.join(dataDir2, "hooks"),
|
|
7389
7723
|
dev: true
|
|
7390
7724
|
});
|
|
7391
7725
|
pbProc = started.proc;
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7726
|
+
process25.env.POCKETBASE_URL = started.url;
|
|
7727
|
+
process25.on("exit", cleanup);
|
|
7728
|
+
process25.on("SIGINT", () => {
|
|
7395
7729
|
cleanup();
|
|
7396
|
-
|
|
7730
|
+
process25.exit(0);
|
|
7397
7731
|
});
|
|
7398
7732
|
}
|
|
7399
7733
|
try {
|
|
7400
|
-
const pm = (await
|
|
7401
|
-
const resolved =
|
|
7734
|
+
const pm = (await detect5({ cwd }))?.name ?? "npm";
|
|
7735
|
+
const resolved = resolveCommand5(pm, "execute", ["vite", "build"]);
|
|
7402
7736
|
const args = resolved.args.slice();
|
|
7403
7737
|
if (pm === "npm") args.unshift("--yes");
|
|
7404
7738
|
await x3(resolved.command, args, {
|
|
@@ -7415,7 +7749,8 @@ async function originForBuild(cwd, target) {
|
|
|
7415
7749
|
if (!workspaceRootDir) return null;
|
|
7416
7750
|
try {
|
|
7417
7751
|
const parsed = parseTarget(target, PRODUCTION_TARGET);
|
|
7418
|
-
if (parsed.kind
|
|
7752
|
+
if (parsed.kind === "local") return null;
|
|
7753
|
+
if (parsed.kind === "preview") return resolveOrigin(workspaceRootDir, bindingKey(parsed), {});
|
|
7419
7754
|
const config = await loadDeployConfig(workspaceRootDir);
|
|
7420
7755
|
return resolveOrigin(workspaceRootDir, parsed.envTag, config);
|
|
7421
7756
|
} catch {
|
|
@@ -7423,50 +7758,50 @@ async function originForBuild(cwd, target) {
|
|
|
7423
7758
|
}
|
|
7424
7759
|
}
|
|
7425
7760
|
function warnIfPrerendered(cwd) {
|
|
7426
|
-
const dir =
|
|
7427
|
-
if (!
|
|
7428
|
-
|
|
7761
|
+
const dir = path32.join(cwd, PRERENDERED_DIR);
|
|
7762
|
+
if (!fs32.existsSync(dir) || fs32.readdirSync(dir).length === 0) return;
|
|
7763
|
+
p40.log.warn(
|
|
7429
7764
|
`Prerendered pages were built with no domain configured, so their canonical
|
|
7430
7765
|
links point at SvelteKit's placeholder host rather than at this site.
|
|
7431
7766
|
|
|
7432
|
-
Set one with ${
|
|
7767
|
+
Set one with ${pc16.cyan("vela deploy --domain example.com")}, or pass ${pc16.cyan("VELA_ORIGIN")}.`
|
|
7433
7768
|
);
|
|
7434
7769
|
}
|
|
7435
7770
|
|
|
7436
7771
|
// src/commands/preview.ts
|
|
7437
|
-
import
|
|
7438
|
-
import
|
|
7439
|
-
import { Command as
|
|
7772
|
+
import path33 from "node:path";
|
|
7773
|
+
import process26 from "node:process";
|
|
7774
|
+
import { Command as Command73 } from "commander";
|
|
7440
7775
|
import { x as x4 } from "tinyexec";
|
|
7441
|
-
import { detect as
|
|
7442
|
-
import { resolveCommand as
|
|
7443
|
-
var preview = new
|
|
7444
|
-
const cwd =
|
|
7445
|
-
|
|
7776
|
+
import { detect as detect6 } from "package-manager-detector";
|
|
7777
|
+
import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
|
|
7778
|
+
var preview = new Command73("preview").description("preview the built app").configureHelp(helpConfig).action(async () => {
|
|
7779
|
+
const cwd = process26.cwd();
|
|
7780
|
+
process26.env.VELA_DATA_DIR ??= localDataDir(cwd);
|
|
7446
7781
|
let pbProc;
|
|
7447
|
-
const needsStart = hasBackend(cwd) && !
|
|
7782
|
+
const needsStart = hasBackend(cwd) && !process26.env.POCKETBASE_URL;
|
|
7448
7783
|
const cleanup = () => {
|
|
7449
7784
|
if (pbProc?.pid) pbProc.kill();
|
|
7450
7785
|
};
|
|
7451
7786
|
if (needsStart) {
|
|
7452
|
-
const dataDir2 =
|
|
7787
|
+
const dataDir2 = path33.join(cwd, DATA_DIR);
|
|
7453
7788
|
const started = await startPocketbaseServe({
|
|
7454
7789
|
dataDir: dataDir2,
|
|
7455
7790
|
migrationsDir: MIGRATIONS_DIR,
|
|
7456
|
-
hooksDir:
|
|
7791
|
+
hooksDir: path33.join(dataDir2, "hooks"),
|
|
7457
7792
|
dev: true
|
|
7458
7793
|
});
|
|
7459
7794
|
pbProc = started.proc;
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7795
|
+
process26.env.POCKETBASE_URL = started.url;
|
|
7796
|
+
process26.on("exit", cleanup);
|
|
7797
|
+
process26.on("SIGINT", () => {
|
|
7463
7798
|
cleanup();
|
|
7464
|
-
|
|
7799
|
+
process26.exit(0);
|
|
7465
7800
|
});
|
|
7466
7801
|
}
|
|
7467
7802
|
try {
|
|
7468
|
-
const pm = (await
|
|
7469
|
-
const resolved =
|
|
7803
|
+
const pm = (await detect6({ cwd }))?.name ?? "npm";
|
|
7804
|
+
const resolved = resolveCommand6(pm, "execute", ["vite", "preview"]);
|
|
7470
7805
|
const args = resolved.args.slice();
|
|
7471
7806
|
if (pm === "npm") args.unshift("--yes");
|
|
7472
7807
|
await x4(resolved.command, args, {
|
|
@@ -7479,12 +7814,12 @@ var preview = new Command72("preview").description("preview the built app").conf
|
|
|
7479
7814
|
});
|
|
7480
7815
|
|
|
7481
7816
|
// src/commands/sync.ts
|
|
7482
|
-
import
|
|
7483
|
-
import { Command as
|
|
7484
|
-
var sync = new
|
|
7817
|
+
import path34 from "node:path";
|
|
7818
|
+
import { Command as Command74 } from "commander";
|
|
7819
|
+
var sync = new Command74("sync").description("sync types from the database").configureHelp(helpConfig).action(
|
|
7485
7820
|
() => runCommand(async () => {
|
|
7486
7821
|
const { workspaceRootDir } = await getWorkspace();
|
|
7487
|
-
const typesDir =
|
|
7822
|
+
const typesDir = path34.join(workspaceRootDir, ".svelte-kit", "types");
|
|
7488
7823
|
const { processTypes } = await import("@velastack/pocketbase-codegen");
|
|
7489
7824
|
await withPocketbase(workspaceRootDir, async (pb) => {
|
|
7490
7825
|
await processTypes(pb, typesDir);
|
|
@@ -7494,9 +7829,9 @@ var sync = new Command73("sync").description("sync types from the database").con
|
|
|
7494
7829
|
);
|
|
7495
7830
|
|
|
7496
7831
|
// src/commands/provision.ts
|
|
7497
|
-
import { Command as
|
|
7498
|
-
import * as
|
|
7499
|
-
import
|
|
7832
|
+
import { Command as Command75 } from "commander";
|
|
7833
|
+
import * as p41 from "@clack/prompts";
|
|
7834
|
+
import pc17 from "picocolors";
|
|
7500
7835
|
import * as v6 from "valibot";
|
|
7501
7836
|
var OptionsSchema2 = v6.object({
|
|
7502
7837
|
...SSH_OPTION_SCHEMA,
|
|
@@ -7504,24 +7839,24 @@ var OptionsSchema2 = v6.object({
|
|
|
7504
7839
|
nodeMajor: v6.optional(v6.string())
|
|
7505
7840
|
});
|
|
7506
7841
|
var provision = addSshOptions(
|
|
7507
|
-
new
|
|
7842
|
+
new Command75("provision").description("prepare a server to host vela apps").argument("<target>", "SSH target \u2014 an alias from ~/.ssh/config, or user@host").configureHelp(helpConfig)
|
|
7508
7843
|
).option("--pb-version <version>", "PocketBase version to install").option("--node-major <version>", "Node.js major version to install", "22").action(
|
|
7509
7844
|
(target, raw) => runCommand(async () => {
|
|
7510
7845
|
const options = parseOptions(OptionsSchema2, raw);
|
|
7511
7846
|
const pbVersion = options.pbVersion ?? pocketbaseVersion();
|
|
7512
|
-
|
|
7513
|
-
|
|
7847
|
+
p41.intro(pc17.bgCyan(pc17.black(" vela provision ")));
|
|
7848
|
+
p41.log.info(`Target ${pc17.cyan(target)}`);
|
|
7514
7849
|
await withSsh(target, sshOptionsFrom(options), async (session) => {
|
|
7515
7850
|
await session.detectElevation();
|
|
7516
7851
|
const existing = await readServerInfo(session);
|
|
7517
7852
|
if (existing) {
|
|
7518
|
-
|
|
7853
|
+
p41.log.info(
|
|
7519
7854
|
`Already provisioned by vela ${existing.cliVersion} on ${existing.provisionedAt}. Bringing it up to date.`
|
|
7520
7855
|
);
|
|
7521
7856
|
}
|
|
7522
|
-
|
|
7857
|
+
p41.log.step("Uploading server scripts");
|
|
7523
7858
|
await syncServerScripts(session);
|
|
7524
|
-
|
|
7859
|
+
p41.log.step("Running provision");
|
|
7525
7860
|
const result = await runServerScript(session, "provision.sh", {
|
|
7526
7861
|
args: [
|
|
7527
7862
|
"--pb-version",
|
|
@@ -7533,7 +7868,7 @@ var provision = addSshOptions(
|
|
|
7533
7868
|
],
|
|
7534
7869
|
stream: true
|
|
7535
7870
|
});
|
|
7536
|
-
|
|
7871
|
+
p41.log.success(
|
|
7537
7872
|
`${target} is ready.
|
|
7538
7873
|
|
|
7539
7874
|
Node ${result?.node ?? "installed"}
|
|
@@ -7541,36 +7876,36 @@ var provision = addSshOptions(
|
|
|
7541
7876
|
PocketBase ${result?.pocketbase ?? pbVersion}`
|
|
7542
7877
|
);
|
|
7543
7878
|
});
|
|
7544
|
-
|
|
7879
|
+
p41.outro(`Deploy with ${pc17.cyan(`vela deploy --server ${target}`)}`);
|
|
7545
7880
|
}, "Failed to provision.")
|
|
7546
7881
|
);
|
|
7547
7882
|
|
|
7548
7883
|
// src/commands/deploy.ts
|
|
7549
7884
|
import path36 from "node:path";
|
|
7550
7885
|
import fs34 from "node:fs";
|
|
7551
|
-
import { Command as
|
|
7552
|
-
import * as
|
|
7553
|
-
import
|
|
7886
|
+
import { Command as Command76, Option as Option2 } from "commander";
|
|
7887
|
+
import * as p42 from "@clack/prompts";
|
|
7888
|
+
import pc18 from "picocolors";
|
|
7554
7889
|
import * as v7 from "valibot";
|
|
7555
7890
|
|
|
7556
7891
|
// src/lib/pocketbase-settings.ts
|
|
7557
|
-
import
|
|
7558
|
-
import
|
|
7559
|
-
import
|
|
7892
|
+
import fs33 from "node:fs";
|
|
7893
|
+
import path35 from "node:path";
|
|
7894
|
+
import process27 from "node:process";
|
|
7560
7895
|
import PocketBase5 from "pocketbase";
|
|
7561
7896
|
var COPIED_KEYS = ["appName", "senderName", "senderAddress"];
|
|
7562
7897
|
async function readLocalMeta(cwd) {
|
|
7563
|
-
const dataDir2 =
|
|
7564
|
-
if (!
|
|
7565
|
-
const email3 =
|
|
7566
|
-
const password11 =
|
|
7898
|
+
const dataDir2 = path35.join(cwd, DATA_DIR);
|
|
7899
|
+
if (!fs33.existsSync(dataDir2)) return null;
|
|
7900
|
+
const email3 = process27.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
7901
|
+
const password11 = process27.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
7567
7902
|
if (!email3 || !password11) return null;
|
|
7568
7903
|
let proc;
|
|
7569
7904
|
try {
|
|
7570
7905
|
const started = await startPocketbaseServe({
|
|
7571
7906
|
dataDir: dataDir2,
|
|
7572
7907
|
migrationsDir: MIGRATIONS_DIR,
|
|
7573
|
-
hooksDir:
|
|
7908
|
+
hooksDir: path35.join(dataDir2, "hooks")
|
|
7574
7909
|
});
|
|
7575
7910
|
proc = started.proc;
|
|
7576
7911
|
const pb = new PocketBase5(started.url);
|
|
@@ -7611,72 +7946,6 @@ async function seedRemoteMeta(session, instance, local, appURL) {
|
|
|
7611
7946
|
return Object.keys(patch);
|
|
7612
7947
|
}
|
|
7613
7948
|
|
|
7614
|
-
// src/lib/artifact.ts
|
|
7615
|
-
import fs33 from "node:fs";
|
|
7616
|
-
import path35 from "node:path";
|
|
7617
|
-
import { detect as detect6 } from "package-manager-detector";
|
|
7618
|
-
import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
|
|
7619
|
-
var DEFAULT_OUTPUT_DIR = "build";
|
|
7620
|
-
var BuildError = class extends Error {
|
|
7621
|
-
};
|
|
7622
|
-
async function runBuild(cwd, buildCommand, env2) {
|
|
7623
|
-
if (buildCommand) {
|
|
7624
|
-
const result2 = await spawnCapture("bash", ["-lc", buildCommand], {
|
|
7625
|
-
cwd,
|
|
7626
|
-
stream: true,
|
|
7627
|
-
streamStdout: true,
|
|
7628
|
-
env: env2
|
|
7629
|
-
});
|
|
7630
|
-
if (result2.exitCode !== 0)
|
|
7631
|
-
throw new BuildError(`\`${buildCommand}\` exited ${result2.exitCode}.`);
|
|
7632
|
-
return;
|
|
7633
|
-
}
|
|
7634
|
-
const pm = (await detect6({ cwd }))?.name ?? "npm";
|
|
7635
|
-
const resolved = resolveCommand6(pm, "run", ["build"]);
|
|
7636
|
-
if (!resolved) throw new BuildError(`Could not work out how to run a build with ${pm}.`);
|
|
7637
|
-
const result = await spawnCapture(resolved.command, resolved.args, {
|
|
7638
|
-
cwd,
|
|
7639
|
-
stream: true,
|
|
7640
|
-
streamStdout: true,
|
|
7641
|
-
env: env2
|
|
7642
|
-
});
|
|
7643
|
-
if (result.exitCode !== 0) {
|
|
7644
|
-
throw new BuildError(
|
|
7645
|
-
`\`${resolved.command} ${resolved.args.join(" ")}\` exited ${result.exitCode}.`
|
|
7646
|
-
);
|
|
7647
|
-
}
|
|
7648
|
-
}
|
|
7649
|
-
function collectArtifact(cwd, config = {}) {
|
|
7650
|
-
const outputDir = config.outputDir ?? DEFAULT_OUTPUT_DIR;
|
|
7651
|
-
const entries = [];
|
|
7652
|
-
const add2 = (rel, remoteDir = "") => {
|
|
7653
|
-
const localPath = path35.join(cwd, rel);
|
|
7654
|
-
if (fs33.existsSync(localPath)) entries.push({ localPath, remoteDir });
|
|
7655
|
-
};
|
|
7656
|
-
const buildPath = path35.join(cwd, outputDir);
|
|
7657
|
-
if (!fs33.existsSync(path35.join(buildPath, "index.js"))) {
|
|
7658
|
-
throw new BuildError(
|
|
7659
|
-
`No ${outputDir}/index.js after the build.
|
|
7660
|
-
|
|
7661
|
-
Deploying to a server needs @sveltejs/adapter-node. Install it and set it as
|
|
7662
|
-
the adapter in your Vite or Svelte config, then build again.`
|
|
7663
|
-
);
|
|
7664
|
-
}
|
|
7665
|
-
entries.push({ localPath: buildPath, remoteDir: "" });
|
|
7666
|
-
add2("package.json");
|
|
7667
|
-
add2("package-lock.json");
|
|
7668
|
-
add2(".npmrc");
|
|
7669
|
-
add2(MIGRATIONS_DIR);
|
|
7670
|
-
const hooks = path35.join(cwd, DATA_DIR, "hooks");
|
|
7671
|
-
if (fs33.existsSync(hooks)) entries.push({ localPath: hooks, remoteDir: "hooks" });
|
|
7672
|
-
for (const extra of config.include ?? []) add2(extra);
|
|
7673
|
-
return entries;
|
|
7674
|
-
}
|
|
7675
|
-
async function gitSha(cwd) {
|
|
7676
|
-
const result = await spawnCapture("git", ["rev-parse", "HEAD"], { cwd });
|
|
7677
|
-
return result.exitCode === 0 ? result.stdout.trim() : "";
|
|
7678
|
-
}
|
|
7679
|
-
|
|
7680
7949
|
// src/commands/deploy.ts
|
|
7681
7950
|
var OptionsSchema3 = v7.object({
|
|
7682
7951
|
...SSH_OPTION_SCHEMA,
|
|
@@ -7690,7 +7959,7 @@ var OptionsSchema3 = v7.object({
|
|
|
7690
7959
|
build: v7.optional(v7.boolean())
|
|
7691
7960
|
});
|
|
7692
7961
|
var deploy = addTargetOptions(
|
|
7693
|
-
new
|
|
7962
|
+
new Command76("deploy").description("deploy the app").configureHelp(helpConfig),
|
|
7694
7963
|
"production"
|
|
7695
7964
|
).option("--project <name>", "override the project name").option("--domain <hosts>", "hostname(s) to serve on, comma separated").option("--health-path <path>", "path the health check requests").option("--keep <count>", "how many old releases to keep on the server").option("--pb-version <version>", "PocketBase version to run").option("--no-build", "deploy the existing build output without rebuilding").addOption(
|
|
7696
7965
|
new Option2(
|
|
@@ -7706,119 +7975,172 @@ var deploy = addTargetOptions(
|
|
|
7706
7975
|
const options = parseOptions(OptionsSchema3, raw);
|
|
7707
7976
|
const backend3 = hasBackend();
|
|
7708
7977
|
const release = releaseId();
|
|
7709
|
-
|
|
7978
|
+
p42.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
|
|
7710
7979
|
await withTarget(
|
|
7711
7980
|
raw,
|
|
7712
7981
|
{
|
|
7713
7982
|
remote: async (ctx) => {
|
|
7714
7983
|
const { session, instance, workspaceRootDir, config } = ctx;
|
|
7715
|
-
|
|
7716
|
-
`${
|
|
7984
|
+
p42.log.info(
|
|
7985
|
+
`${pc18.cyan(ctx.appName)} ${pc18.dim("\u2192")} ${pc18.cyan(ctx.targetName)} ${pc18.dim(`(${ctx.server})`)}`
|
|
7717
7986
|
);
|
|
7718
7987
|
const [existing] = await readInstanceStates(session, instance);
|
|
7719
|
-
const
|
|
7988
|
+
const isPreview = ctx.target.kind === "preview";
|
|
7989
|
+
const configured = options.domain ?? (isPreview ? existing?.domain : ctx.binding.domain ?? config.deploy?.domain ?? existing?.domain) ?? "";
|
|
7720
7990
|
const askedForRemoteDb = options.remoteDb ?? config.deploy?.buildAgainstRemote;
|
|
7721
7991
|
const remoteDb = askedForRemoteDb ?? Boolean(existing?.pbPort);
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7992
|
+
const sha = await gitSha(workspaceRootDir);
|
|
7993
|
+
const reporter = createDeployReporter(workspaceRootDir);
|
|
7994
|
+
const server = await reporter.identifyServer(session);
|
|
7995
|
+
const started = await reporter.start({
|
|
7996
|
+
target: ctx.target.kind === "preview" ? "preview" : ctx.targetName,
|
|
7997
|
+
env_tag: ctx.envTag,
|
|
7998
|
+
branch: ctx.target.kind === "preview" ? ctx.target.branch : void 0,
|
|
7999
|
+
git_sha: sha || void 0,
|
|
8000
|
+
hostnames: splitHosts(configured),
|
|
8001
|
+
server: server ? { id: server.serverId, token: server.token } : void 0
|
|
8002
|
+
});
|
|
8003
|
+
const directHosts = [
|
|
8004
|
+
.../* @__PURE__ */ new Set([...splitHosts(configured), ...started?.environment.direct ?? []])
|
|
8005
|
+
];
|
|
8006
|
+
const managedHosts = started?.environment.managed ?? [];
|
|
8007
|
+
const domain = directHosts.join(",");
|
|
8008
|
+
const managed = managedHosts.join(",");
|
|
8009
|
+
const primaryHost = directHosts[0] ?? managedHosts[0] ?? "";
|
|
8010
|
+
const primaryUrl = started?.environment.primaryUrl || normalizeOrigin(primaryHost) || "";
|
|
8011
|
+
if (isPreview && !primaryHost) {
|
|
8012
|
+
throw new Error(
|
|
8013
|
+
`Nothing routes to this preview.
|
|
8014
|
+
|
|
8015
|
+
Previews get a free velastack.app hostname from velastack.dev: ${pc18.cyan("vela link")} the
|
|
8016
|
+
project and ${pc18.cyan("vela login")} (or set ${pc18.cyan("VELA_API_KEY")}). Or pass ${pc18.cyan("--domain <host>")}
|
|
8017
|
+
with DNS of your own pointing at ${ctx.server}.`
|
|
8018
|
+
);
|
|
8019
|
+
}
|
|
8020
|
+
let result = null;
|
|
8021
|
+
try {
|
|
8022
|
+
if (options.build !== false) {
|
|
8023
|
+
const origin = normalizeOrigin(process.env.VELA_ORIGIN ?? primaryUrl);
|
|
8024
|
+
let buildEnv = origin ? { VELA_ORIGIN: origin } : {};
|
|
8025
|
+
let tunnel = null;
|
|
8026
|
+
if (backend3 && remoteDb) {
|
|
8027
|
+
try {
|
|
8028
|
+
tunnel = await openDatabaseTunnel(session, instance, existing);
|
|
8029
|
+
} catch (err) {
|
|
8030
|
+
if (askedForRemoteDb) throw err;
|
|
8031
|
+
p42.log.warn(
|
|
8032
|
+
`Could not build against the ${pc18.cyan(ctx.targetName)} database, using a local one instead.
|
|
8033
|
+
${pc18.dim(String(err))}`
|
|
8034
|
+
);
|
|
8035
|
+
}
|
|
8036
|
+
}
|
|
8037
|
+
if (tunnel) {
|
|
8038
|
+
buildEnv = { ...buildEnv, ...tunnel.env };
|
|
8039
|
+
p42.log.info(
|
|
8040
|
+
`Building against the ${pc18.cyan(ctx.targetName)} database on ${ctx.server} ${pc18.dim(`(port ${tunnel.pbPort})`)}`
|
|
7734
8041
|
);
|
|
8042
|
+
} else if (backend3) {
|
|
8043
|
+
await ensureSuperuser(workspaceRootDir);
|
|
8044
|
+
}
|
|
8045
|
+
p42.log.step("Building");
|
|
8046
|
+
try {
|
|
8047
|
+
await runBuild(workspaceRootDir, config.deploy?.buildCommand, buildEnv);
|
|
8048
|
+
} finally {
|
|
8049
|
+
if (tunnel) await tunnel.close();
|
|
7735
8050
|
}
|
|
7736
8051
|
}
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
8052
|
+
const entries = collectArtifact(workspaceRootDir, config.deploy ?? {});
|
|
8053
|
+
p42.log.step(`Uploading release ${pc18.dim(release)}`);
|
|
8054
|
+
await uploadRelease(session, instance, release, entries);
|
|
8055
|
+
p42.log.step("Activating");
|
|
8056
|
+
result = await runServerScript(session, "apply.sh", {
|
|
8057
|
+
args: [
|
|
8058
|
+
instance,
|
|
8059
|
+
release,
|
|
8060
|
+
"--name",
|
|
8061
|
+
ctx.appName,
|
|
8062
|
+
"--app-id",
|
|
8063
|
+
ctx.appId,
|
|
8064
|
+
"--env",
|
|
8065
|
+
ctx.envTag,
|
|
8066
|
+
"--domain",
|
|
8067
|
+
domain,
|
|
8068
|
+
"--managed",
|
|
8069
|
+
managed,
|
|
8070
|
+
"--health-path",
|
|
8071
|
+
options.healthPath ?? config.deploy?.healthCheckPath ?? "/",
|
|
8072
|
+
"--keep",
|
|
8073
|
+
options.keep ?? String(config.deploy?.keepReleases ?? 5),
|
|
8074
|
+
"--backend",
|
|
8075
|
+
backend3 ? "1" : "0",
|
|
8076
|
+
"--pb-version",
|
|
8077
|
+
options.pbVersion ?? config.deploy?.pocketbaseVersion ?? pocketbaseVersion(),
|
|
8078
|
+
"--git-sha",
|
|
8079
|
+
sha
|
|
8080
|
+
],
|
|
8081
|
+
stream: true
|
|
8082
|
+
});
|
|
8083
|
+
} catch (err) {
|
|
8084
|
+
await reporter.finish({
|
|
8085
|
+
status: "failed",
|
|
8086
|
+
error: err instanceof Error ? err.message : String(err)
|
|
8087
|
+
});
|
|
8088
|
+
throw err;
|
|
7751
8089
|
}
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
const result = await runServerScript(session, "apply.sh", {
|
|
7758
|
-
args: [
|
|
7759
|
-
instance,
|
|
7760
|
-
release,
|
|
7761
|
-
"--name",
|
|
7762
|
-
ctx.appName,
|
|
7763
|
-
"--app-id",
|
|
7764
|
-
ctx.appId,
|
|
7765
|
-
"--env",
|
|
7766
|
-
ctx.envTag,
|
|
7767
|
-
"--domain",
|
|
7768
|
-
domain,
|
|
7769
|
-
"--health-path",
|
|
7770
|
-
options.healthPath ?? config.deploy?.healthCheckPath ?? "/",
|
|
7771
|
-
"--keep",
|
|
7772
|
-
options.keep ?? String(config.deploy?.keepReleases ?? 5),
|
|
7773
|
-
"--backend",
|
|
7774
|
-
backend3 ? "1" : "0",
|
|
7775
|
-
"--pb-version",
|
|
7776
|
-
options.pbVersion ?? config.deploy?.pocketbaseVersion ?? pocketbaseVersion(),
|
|
7777
|
-
"--git-sha",
|
|
7778
|
-
sha
|
|
7779
|
-
],
|
|
7780
|
-
stream: true
|
|
7781
|
-
});
|
|
7782
|
-
writeBinding(workspaceRootDir, ctx.envTag, {
|
|
7783
|
-
server: ctx.server,
|
|
7784
|
-
domain: domain || void 0
|
|
7785
|
-
});
|
|
8090
|
+
writeBinding(
|
|
8091
|
+
workspaceRootDir,
|
|
8092
|
+
bindingKey(ctx.target),
|
|
8093
|
+
isPreview ? { server: ctx.server } : { server: ctx.server, domain: domain || void 0 }
|
|
8094
|
+
);
|
|
7786
8095
|
if (!existing) await reportEmptyEnvironment(session, instance, workspaceRootDir);
|
|
7787
8096
|
const url = result?.url ?? "";
|
|
7788
|
-
|
|
7789
|
-
|
|
8097
|
+
await reporter.finish({
|
|
8098
|
+
status: "deployed",
|
|
8099
|
+
release,
|
|
8100
|
+
// Without a host the server answers with a loopback URL, which
|
|
8101
|
+
// is nothing to link to from a dashboard.
|
|
8102
|
+
url: primaryHost ? url : void 0
|
|
8103
|
+
});
|
|
8104
|
+
const redirects = started?.environment.redirects ?? [];
|
|
8105
|
+
p42.log.success(
|
|
8106
|
+
`Deployed ${pc18.cyan(ctx.appName)} ${pc18.dim(release)}
|
|
7790
8107
|
|
|
7791
8108
|
URL ${url}
|
|
7792
|
-
|
|
8109
|
+
` + (redirects.length ? ` Also ${redirects.map((h) => `https://${h}`).join(", ")} ${pc18.dim("(redirects here)")}
|
|
8110
|
+
` : "") + ` Port ${result?.webPort ?? "?"}${backend3 ? ` (PocketBase ${result?.pbPort ?? "?"})` : ""}`
|
|
7793
8111
|
);
|
|
8112
|
+
if (managed && managed !== existing?.managed) {
|
|
8113
|
+
p42.log.info(`${pc18.cyan(managed)} goes live within a minute.`);
|
|
8114
|
+
}
|
|
7794
8115
|
if (result?.superuserCreated) {
|
|
7795
8116
|
await copyLocalBranding(
|
|
7796
8117
|
session,
|
|
7797
8118
|
instance,
|
|
7798
8119
|
workspaceRootDir,
|
|
7799
|
-
|
|
8120
|
+
primaryHost ? result?.url ?? "" : ""
|
|
7800
8121
|
);
|
|
7801
|
-
|
|
8122
|
+
p42.log.info(
|
|
7802
8123
|
`Created the PocketBase superuser this app authenticates as.
|
|
7803
8124
|
|
|
7804
8125
|
Its credentials are stored in the environment on the server. To use
|
|
7805
|
-
your own instead, ${
|
|
8126
|
+
your own instead, ${pc18.cyan("vela env set POCKETBASE_SUPERUSER_PASSWORD")}
|
|
7806
8127
|
and deploy again.`
|
|
7807
8128
|
);
|
|
7808
|
-
} else if (backend3 &&
|
|
7809
|
-
await reportAppURLDrift(session, instance,
|
|
8129
|
+
} else if (backend3 && primaryHost) {
|
|
8130
|
+
await reportAppURLDrift(session, instance, primaryHost);
|
|
7810
8131
|
}
|
|
7811
|
-
if (!
|
|
7812
|
-
|
|
8132
|
+
if (!primaryHost) {
|
|
8133
|
+
p42.log.warn(
|
|
7813
8134
|
`No domain configured, so nothing is proxied to this app yet.
|
|
7814
|
-
Redeploy with ${
|
|
8135
|
+
Redeploy with ${pc18.cyan("--domain example.com")} once DNS points at ${ctx.server}` + (reporter.enabled ? "" : `,
|
|
8136
|
+
or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
|
|
7815
8137
|
);
|
|
7816
8138
|
}
|
|
7817
8139
|
}
|
|
7818
8140
|
},
|
|
7819
8141
|
{ project: options.project, askDomain: true, label: "deploy" }
|
|
7820
8142
|
);
|
|
7821
|
-
|
|
8143
|
+
p42.outro(`${pc18.cyan("vela status")} to see what is running`);
|
|
7822
8144
|
}, "Failed to deploy.")
|
|
7823
8145
|
);
|
|
7824
8146
|
async function reportAppURLDrift(session, instance, domain) {
|
|
@@ -7826,8 +8148,8 @@ async function reportAppURLDrift(session, instance, domain) {
|
|
|
7826
8148
|
if (!expected) return;
|
|
7827
8149
|
const current = await readRemoteAppURL(session, instance);
|
|
7828
8150
|
if (!current || normalizeOrigin(current) === expected) return;
|
|
7829
|
-
|
|
7830
|
-
`This app's PocketBase ${
|
|
8151
|
+
p42.log.warn(
|
|
8152
|
+
`This app's PocketBase ${pc18.cyan("appURL")} is ${pc18.dim(current)}, but it is served on ${pc18.dim(expected)}.
|
|
7831
8153
|
|
|
7832
8154
|
Emails and anything else PocketBase links to will use the former. Update it in
|
|
7833
8155
|
the admin panel if that is not deliberate.`
|
|
@@ -7841,17 +8163,17 @@ async function copyLocalBranding(session, instance, workspaceRootDir, appURL) {
|
|
|
7841
8163
|
if (copied.length === 0) return;
|
|
7842
8164
|
const outcome = await restartInstance(session, instance);
|
|
7843
8165
|
if (outcome.deployed && !outcome.restarted) {
|
|
7844
|
-
|
|
8166
|
+
p42.log.warn(
|
|
7845
8167
|
`Copied ${copied.join(", ")}, but the app did not restart to pick them up.
|
|
7846
|
-
${
|
|
8168
|
+
${pc18.dim(outcome.error ?? "")}`
|
|
7847
8169
|
);
|
|
7848
8170
|
return;
|
|
7849
8171
|
}
|
|
7850
|
-
|
|
8172
|
+
p42.log.success(`Copied ${copied.join(", ")} from this project's database`);
|
|
7851
8173
|
} catch (err) {
|
|
7852
|
-
|
|
8174
|
+
p42.log.warn(
|
|
7853
8175
|
`Could not copy this project's PocketBase settings across.
|
|
7854
|
-
Set them in the admin panel instead. ${
|
|
8176
|
+
Set them in the admin panel instead. ${pc18.dim(String(err))}`
|
|
7855
8177
|
);
|
|
7856
8178
|
}
|
|
7857
8179
|
}
|
|
@@ -7883,13 +8205,13 @@ Set them with \`vela env set POCKETBASE_SUPERUSER_EMAIL\` and \`vela env set POC
|
|
|
7883
8205
|
|
|
7884
8206
|
They are what \`--remote-db\` renders the build as. The usual cause is a password
|
|
7885
8207
|
changed in the PocketBase admin panel, which leaves the database and
|
|
7886
|
-
${
|
|
8208
|
+
${pc18.cyan(`/etc/vela/apps/${instance}/env`)} disagreeing.
|
|
7887
8209
|
|
|
7888
8210
|
Point the environment at the password the database has:
|
|
7889
|
-
${
|
|
8211
|
+
${pc18.cyan("vela env set POCKETBASE_SUPERUSER_PASSWORD")}
|
|
7890
8212
|
|
|
7891
8213
|
or build against a throwaway local database instead:
|
|
7892
|
-
${
|
|
8214
|
+
${pc18.cyan("vela deploy --no-remote-db")}`
|
|
7893
8215
|
);
|
|
7894
8216
|
}
|
|
7895
8217
|
return {
|
|
@@ -7942,75 +8264,26 @@ async function reportEmptyEnvironment(session, instance, workspaceRootDir) {
|
|
|
7942
8264
|
const remote = await readRemoteEnv(session, instance);
|
|
7943
8265
|
if (Object.keys(remote).length > 0) return;
|
|
7944
8266
|
if (!fs34.existsSync(path36.join(workspaceRootDir, ".env"))) return;
|
|
7945
|
-
|
|
8267
|
+
p42.log.warn(
|
|
7946
8268
|
`This app has no production environment variables yet.
|
|
7947
8269
|
|
|
7948
|
-
Local ${
|
|
7949
|
-
${
|
|
8270
|
+
Local ${pc18.cyan(".env")} values are not uploaded by a deploy. Set them with
|
|
8271
|
+
${pc18.cyan("vela env set KEY")}, or copy a file across with ${pc18.cyan("vela env import .env.production")}.`
|
|
7950
8272
|
);
|
|
7951
8273
|
}
|
|
7952
8274
|
|
|
7953
8275
|
// src/commands/link.ts
|
|
7954
8276
|
import path37 from "node:path";
|
|
7955
|
-
import
|
|
7956
|
-
import { Command as
|
|
7957
|
-
import * as
|
|
7958
|
-
|
|
7959
|
-
// src/lib/velastack-api.ts
|
|
7960
|
-
async function apiFetch(apiKey, pathAndQuery, init) {
|
|
7961
|
-
const headers = new Headers(init?.headers);
|
|
7962
|
-
headers.set("Authorization", `Bearer ${apiKey}`);
|
|
7963
|
-
if (init?.body && !headers.has("Content-Type")) {
|
|
7964
|
-
headers.set("Content-Type", "application/json");
|
|
7965
|
-
}
|
|
7966
|
-
const res = await fetch(`${API_URL}${pathAndQuery}`, { ...init, headers });
|
|
7967
|
-
if (res.status === 401 || res.status === 403) {
|
|
7968
|
-
throw new Error("API key invalid \u2014 run `vela login`");
|
|
7969
|
-
}
|
|
7970
|
-
if (!res.ok) {
|
|
7971
|
-
const body = await res.text().catch(() => "");
|
|
7972
|
-
throw new Error(`Velastack API error (${res.status}): ${body || res.statusText}`);
|
|
7973
|
-
}
|
|
7974
|
-
return await res.json();
|
|
7975
|
-
}
|
|
7976
|
-
async function getCurrentUser(apiKey) {
|
|
7977
|
-
const data = await apiFetch(
|
|
7978
|
-
apiKey,
|
|
7979
|
-
"/api/collections/users/records?perPage=1"
|
|
7980
|
-
);
|
|
7981
|
-
const user = data.items[0];
|
|
7982
|
-
if (!user) throw new Error("No user found. Run `vela login` to login.");
|
|
7983
|
-
return user;
|
|
7984
|
-
}
|
|
7985
|
-
async function listTeams(apiKey) {
|
|
7986
|
-
const data = await apiFetch(
|
|
7987
|
-
apiKey,
|
|
7988
|
-
"/api/collections/teams/records?perPage=200"
|
|
7989
|
-
);
|
|
7990
|
-
return data.items;
|
|
7991
|
-
}
|
|
7992
|
-
async function listProjects(apiKey) {
|
|
7993
|
-
const data = await apiFetch(
|
|
7994
|
-
apiKey,
|
|
7995
|
-
"/api/collections/projects/records?perPage=200&expand=team"
|
|
7996
|
-
);
|
|
7997
|
-
return data.items;
|
|
7998
|
-
}
|
|
7999
|
-
async function createProject2(apiKey, args) {
|
|
8000
|
-
return apiFetch(apiKey, "/api/collections/projects/records", {
|
|
8001
|
-
method: "POST",
|
|
8002
|
-
body: JSON.stringify({ name: args.name, team: args.teamId, user: args.userId })
|
|
8003
|
-
});
|
|
8004
|
-
}
|
|
8005
|
-
|
|
8006
|
-
// src/commands/link.ts
|
|
8277
|
+
import process28 from "node:process";
|
|
8278
|
+
import { Command as Command77 } from "commander";
|
|
8279
|
+
import * as p43 from "@clack/prompts";
|
|
8007
8280
|
var CREATE_NEW = "__new__";
|
|
8008
|
-
var link = new
|
|
8281
|
+
var link = new Command77("link").description("link this project to a velastack.dev project").configureHelp(helpConfig).action(() => runCommand(linkProject, "Failed to link the project."));
|
|
8009
8282
|
async function linkProject() {
|
|
8010
8283
|
const { workspaceRootDir } = await getWorkspace();
|
|
8011
8284
|
const existing = readProjectConfig(workspaceRootDir);
|
|
8012
8285
|
if (existing) {
|
|
8013
|
-
|
|
8286
|
+
p43.log.success(`Linked to ${existing.projectName}.`);
|
|
8014
8287
|
return;
|
|
8015
8288
|
}
|
|
8016
8289
|
const apiKey = requireApiKey();
|
|
@@ -8037,10 +8310,10 @@ async function linkProject() {
|
|
|
8037
8310
|
projectName = created.name;
|
|
8038
8311
|
}
|
|
8039
8312
|
writeProjectConfig(workspaceRootDir, { projectId, teamId, projectName });
|
|
8040
|
-
|
|
8313
|
+
p43.log.success(`Linked to ${projectName}.`);
|
|
8041
8314
|
}
|
|
8042
8315
|
async function pickExistingProject(projects) {
|
|
8043
|
-
const choice = await
|
|
8316
|
+
const choice = await p43.select({
|
|
8044
8317
|
message: "Select a project",
|
|
8045
8318
|
options: [
|
|
8046
8319
|
...projects.map((pr) => ({
|
|
@@ -8050,39 +8323,39 @@ async function pickExistingProject(projects) {
|
|
|
8050
8323
|
{ value: CREATE_NEW, label: "Create a new project" }
|
|
8051
8324
|
]
|
|
8052
8325
|
});
|
|
8053
|
-
if (
|
|
8054
|
-
|
|
8055
|
-
|
|
8326
|
+
if (p43.isCancel(choice)) {
|
|
8327
|
+
p43.cancel("Operation cancelled.");
|
|
8328
|
+
process28.exit(0);
|
|
8056
8329
|
}
|
|
8057
8330
|
return choice;
|
|
8058
8331
|
}
|
|
8059
8332
|
async function pickTeam(teams3) {
|
|
8060
8333
|
if (teams3.length === 1) return teams3[0];
|
|
8061
|
-
const choice = await
|
|
8334
|
+
const choice = await p43.select({
|
|
8062
8335
|
message: "Select a team",
|
|
8063
8336
|
options: teams3.map((team) => ({
|
|
8064
8337
|
value: team.id,
|
|
8065
8338
|
label: team.is_personal ? `${team.name} (personal)` : team.name
|
|
8066
8339
|
}))
|
|
8067
8340
|
});
|
|
8068
|
-
if (
|
|
8069
|
-
|
|
8070
|
-
|
|
8341
|
+
if (p43.isCancel(choice)) {
|
|
8342
|
+
p43.cancel("Operation cancelled.");
|
|
8343
|
+
process28.exit(0);
|
|
8071
8344
|
}
|
|
8072
8345
|
return teams3.find((team) => team.id === choice);
|
|
8073
8346
|
}
|
|
8074
8347
|
async function promptProjectName(workspaceRootDir) {
|
|
8075
8348
|
const defaultValue = defaultProjectName2(workspaceRootDir);
|
|
8076
|
-
const value = await
|
|
8349
|
+
const value = await p43.text({
|
|
8077
8350
|
message: "Project name",
|
|
8078
8351
|
defaultValue,
|
|
8079
8352
|
initialValue: defaultValue,
|
|
8080
8353
|
placeholder: defaultValue,
|
|
8081
8354
|
validate: (v9) => !v9?.trim() ? "Required" : void 0
|
|
8082
8355
|
});
|
|
8083
|
-
if (
|
|
8084
|
-
|
|
8085
|
-
|
|
8356
|
+
if (p43.isCancel(value)) {
|
|
8357
|
+
p43.cancel("Operation cancelled.");
|
|
8358
|
+
process28.exit(0);
|
|
8086
8359
|
}
|
|
8087
8360
|
return value.trim();
|
|
8088
8361
|
}
|
|
@@ -8097,14 +8370,14 @@ function defaultProjectName2(workspaceRootDir) {
|
|
|
8097
8370
|
}
|
|
8098
8371
|
|
|
8099
8372
|
// src/commands/env.ts
|
|
8100
|
-
import { Command as
|
|
8373
|
+
import { Command as Command82 } from "commander";
|
|
8101
8374
|
|
|
8102
8375
|
// src/commands/env/list.ts
|
|
8103
|
-
import { Command as
|
|
8104
|
-
import * as
|
|
8105
|
-
import
|
|
8376
|
+
import { Command as Command78 } from "commander";
|
|
8377
|
+
import * as p44 from "@clack/prompts";
|
|
8378
|
+
import pc19 from "picocolors";
|
|
8106
8379
|
var envList = addTargetOptions(
|
|
8107
|
-
new
|
|
8380
|
+
new Command78("list").description("list environment variable names").configureHelp(helpConfig),
|
|
8108
8381
|
"local"
|
|
8109
8382
|
).action(
|
|
8110
8383
|
(raw) => runCommand(
|
|
@@ -8126,23 +8399,23 @@ var envList = addTargetOptions(
|
|
|
8126
8399
|
);
|
|
8127
8400
|
function report(keys, where) {
|
|
8128
8401
|
if (keys.length === 0) {
|
|
8129
|
-
|
|
8402
|
+
p44.log.info(`No environment variables configured ${pc19.dim(`(${where})`)}.`);
|
|
8130
8403
|
return;
|
|
8131
8404
|
}
|
|
8132
|
-
|
|
8133
|
-
`Environment ${
|
|
8405
|
+
p44.log.info(
|
|
8406
|
+
`Environment ${pc19.dim(`(${where})`)}
|
|
8134
8407
|
|
|
8135
8408
|
` + keys.sort().map((key) => ` ${key}`).join("\n")
|
|
8136
8409
|
);
|
|
8137
8410
|
}
|
|
8138
8411
|
|
|
8139
8412
|
// src/commands/env/set.ts
|
|
8140
|
-
import
|
|
8141
|
-
import { Command as
|
|
8142
|
-
import * as
|
|
8143
|
-
import
|
|
8413
|
+
import process29 from "node:process";
|
|
8414
|
+
import { Command as Command79 } from "commander";
|
|
8415
|
+
import * as p45 from "@clack/prompts";
|
|
8416
|
+
import pc20 from "picocolors";
|
|
8144
8417
|
var envSet = addTargetOptions(
|
|
8145
|
-
new
|
|
8418
|
+
new Command79("set").description("set an environment variable").argument("<key>", "variable name").argument("[value]", "value \u2014 prompted for, without echo, when omitted").configureHelp(helpConfig),
|
|
8146
8419
|
"local"
|
|
8147
8420
|
).action(
|
|
8148
8421
|
(key, value, raw) => runCommand(
|
|
@@ -8152,14 +8425,14 @@ var envSet = addTargetOptions(
|
|
|
8152
8425
|
local: async (ctx) => {
|
|
8153
8426
|
const resolved = await resolveValue(key, value);
|
|
8154
8427
|
setLocalEnv(ctx.envFile, key, resolved);
|
|
8155
|
-
|
|
8428
|
+
p45.log.success(`${key} updated ${pc20.dim("(local)")}`);
|
|
8156
8429
|
await applyLocalEnvChange(ctx, [key]);
|
|
8157
8430
|
},
|
|
8158
8431
|
remote: async (ctx) => {
|
|
8159
8432
|
const resolved = await resolveValue(key, value);
|
|
8160
8433
|
const env2 = await readRemoteEnv(ctx.session, ctx.instance);
|
|
8161
8434
|
await writeRemoteEnv(ctx.session, ctx.instance, { ...env2, [key]: resolved });
|
|
8162
|
-
|
|
8435
|
+
p45.log.success(`${key} updated ${pc20.dim(`(${ctx.targetName})`)}`);
|
|
8163
8436
|
await applyEnvRestart(ctx, [key]);
|
|
8164
8437
|
}
|
|
8165
8438
|
},
|
|
@@ -8173,23 +8446,23 @@ async function resolveValue(key, value) {
|
|
|
8173
8446
|
return value ?? await promptValue(key);
|
|
8174
8447
|
}
|
|
8175
8448
|
async function promptValue(key) {
|
|
8176
|
-
const value = await
|
|
8177
|
-
message: `Value for ${
|
|
8449
|
+
const value = await p45.password({
|
|
8450
|
+
message: `Value for ${pc20.cyan(key)}`,
|
|
8178
8451
|
validate: (input) => !input?.length ? "Required" : void 0
|
|
8179
8452
|
});
|
|
8180
|
-
if (
|
|
8181
|
-
|
|
8182
|
-
|
|
8453
|
+
if (p45.isCancel(value)) {
|
|
8454
|
+
p45.cancel("Operation cancelled.");
|
|
8455
|
+
process29.exit(0);
|
|
8183
8456
|
}
|
|
8184
8457
|
return value;
|
|
8185
8458
|
}
|
|
8186
8459
|
|
|
8187
8460
|
// src/commands/env/unset.ts
|
|
8188
|
-
import { Command as
|
|
8189
|
-
import * as
|
|
8190
|
-
import
|
|
8461
|
+
import { Command as Command80 } from "commander";
|
|
8462
|
+
import * as p46 from "@clack/prompts";
|
|
8463
|
+
import pc21 from "picocolors";
|
|
8191
8464
|
var envUnset = addTargetOptions(
|
|
8192
|
-
new
|
|
8465
|
+
new Command80("unset").description("remove an environment variable").argument("<key>", "variable name").configureHelp(helpConfig),
|
|
8193
8466
|
"local"
|
|
8194
8467
|
).action(
|
|
8195
8468
|
(key, raw) => runCommand(
|
|
@@ -8198,22 +8471,22 @@ var envUnset = addTargetOptions(
|
|
|
8198
8471
|
{
|
|
8199
8472
|
local: async (ctx) => {
|
|
8200
8473
|
if (!(key in readLocalEnv(ctx.envFile))) {
|
|
8201
|
-
|
|
8474
|
+
p46.log.info(`${key} is not set \u2014 nothing to remove.`);
|
|
8202
8475
|
return;
|
|
8203
8476
|
}
|
|
8204
8477
|
unsetLocalEnv(ctx.envFile, key);
|
|
8205
|
-
|
|
8478
|
+
p46.log.success(`${key} removed ${pc21.dim("(local)")}`);
|
|
8206
8479
|
await applyLocalEnvChange(ctx, [key]);
|
|
8207
8480
|
},
|
|
8208
8481
|
remote: async (ctx) => {
|
|
8209
8482
|
const env2 = await readRemoteEnv(ctx.session, ctx.instance);
|
|
8210
8483
|
if (!(key in env2)) {
|
|
8211
|
-
|
|
8484
|
+
p46.log.info(`${key} is not set \u2014 nothing to remove.`);
|
|
8212
8485
|
return;
|
|
8213
8486
|
}
|
|
8214
8487
|
delete env2[key];
|
|
8215
8488
|
await writeRemoteEnv(ctx.session, ctx.instance, env2);
|
|
8216
|
-
|
|
8489
|
+
p46.log.success(`${key} removed ${pc21.dim(`(${ctx.targetName})`)}`);
|
|
8217
8490
|
await applyEnvRestart(ctx, [key]);
|
|
8218
8491
|
}
|
|
8219
8492
|
},
|
|
@@ -8226,12 +8499,12 @@ var envUnset = addTargetOptions(
|
|
|
8226
8499
|
// src/commands/env/import.ts
|
|
8227
8500
|
import fs35 from "node:fs";
|
|
8228
8501
|
import path38 from "node:path";
|
|
8229
|
-
import
|
|
8230
|
-
import { Command as
|
|
8231
|
-
import * as
|
|
8232
|
-
import
|
|
8502
|
+
import process30 from "node:process";
|
|
8503
|
+
import { Command as Command81 } from "commander";
|
|
8504
|
+
import * as p47 from "@clack/prompts";
|
|
8505
|
+
import pc22 from "picocolors";
|
|
8233
8506
|
var envImport = addTargetOptions(
|
|
8234
|
-
new
|
|
8507
|
+
new Command81("import").description("merge a dotenv file into the environment").argument("<file>", "dotenv file to read").configureHelp(helpConfig),
|
|
8235
8508
|
"local"
|
|
8236
8509
|
).action(
|
|
8237
8510
|
(file, raw) => runCommand(
|
|
@@ -8246,22 +8519,22 @@ var envImport = addTargetOptions(
|
|
|
8246
8519
|
const incoming = read(source, file);
|
|
8247
8520
|
const keys = Object.keys(incoming);
|
|
8248
8521
|
if (keys.length === 0) return;
|
|
8249
|
-
|
|
8522
|
+
p47.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
|
|
8250
8523
|
editLocalEnv(
|
|
8251
8524
|
ctx.envFile,
|
|
8252
8525
|
(content) => keys.reduce((acc, key) => upsertEnvVar(acc, key, incoming[key]), content)
|
|
8253
8526
|
);
|
|
8254
|
-
|
|
8527
|
+
p47.log.success(`${keys.length} variable(s) updated ${pc22.dim("(local)")}`);
|
|
8255
8528
|
await applyLocalEnvChange(ctx, keys);
|
|
8256
8529
|
},
|
|
8257
8530
|
remote: async (ctx) => {
|
|
8258
8531
|
const incoming = read(resolve(file), file);
|
|
8259
8532
|
const keys = Object.keys(incoming);
|
|
8260
8533
|
if (keys.length === 0) return;
|
|
8261
|
-
|
|
8534
|
+
p47.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
|
|
8262
8535
|
const existing = await readRemoteEnv(ctx.session, ctx.instance);
|
|
8263
8536
|
await writeRemoteEnv(ctx.session, ctx.instance, { ...existing, ...incoming });
|
|
8264
|
-
|
|
8537
|
+
p47.log.success(`${keys.length} variable(s) updated ${pc22.dim(`(${ctx.targetName})`)}`);
|
|
8265
8538
|
await applyEnvRestart(ctx, keys);
|
|
8266
8539
|
}
|
|
8267
8540
|
},
|
|
@@ -8271,24 +8544,24 @@ var envImport = addTargetOptions(
|
|
|
8271
8544
|
)
|
|
8272
8545
|
);
|
|
8273
8546
|
function resolve(file) {
|
|
8274
|
-
return path38.resolve(
|
|
8547
|
+
return path38.resolve(process30.cwd(), file);
|
|
8275
8548
|
}
|
|
8276
8549
|
function read(resolved, shown) {
|
|
8277
8550
|
if (!fs35.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
|
|
8278
8551
|
const incoming = readLocalEnvFile(resolved);
|
|
8279
|
-
if (Object.keys(incoming).length === 0)
|
|
8552
|
+
if (Object.keys(incoming).length === 0) p47.log.info(`${shown} has no variables to import.`);
|
|
8280
8553
|
return incoming;
|
|
8281
8554
|
}
|
|
8282
8555
|
|
|
8283
8556
|
// src/commands/env.ts
|
|
8284
|
-
var env = new
|
|
8557
|
+
var env = new Command82("env").description("manage environment variables, locally or on a target").configureHelp(helpConfig).addCommand(envList).addCommand(envSet).addCommand(envUnset).addCommand(envImport);
|
|
8285
8558
|
|
|
8286
8559
|
// src/commands/status.ts
|
|
8287
|
-
import { Command as
|
|
8288
|
-
import * as
|
|
8289
|
-
import
|
|
8560
|
+
import { Command as Command83 } from "commander";
|
|
8561
|
+
import * as p48 from "@clack/prompts";
|
|
8562
|
+
import pc23 from "picocolors";
|
|
8290
8563
|
var status = addTargetOptions(
|
|
8291
|
-
new
|
|
8564
|
+
new Command83("status").description("show what is deployed").configureHelp(helpConfig),
|
|
8292
8565
|
"production"
|
|
8293
8566
|
).option("--all", "show every app on the server, not just this project").option("--json", "print raw JSON").action(
|
|
8294
8567
|
(raw) => runCommand(async () => {
|
|
@@ -8319,21 +8592,22 @@ function report2(states, json) {
|
|
|
8319
8592
|
return;
|
|
8320
8593
|
}
|
|
8321
8594
|
if (states.length === 0) {
|
|
8322
|
-
|
|
8595
|
+
p48.log.info("Nothing is deployed here yet.");
|
|
8323
8596
|
return;
|
|
8324
8597
|
}
|
|
8325
8598
|
for (const state of states) {
|
|
8326
|
-
|
|
8599
|
+
p48.log.info(describe(state));
|
|
8327
8600
|
}
|
|
8328
8601
|
}
|
|
8329
8602
|
function describe(state) {
|
|
8330
|
-
const health = (value) => value === "active" ?
|
|
8603
|
+
const health = (value) => value === "active" ? pc23.green(value) : pc23.red(value || "inactive");
|
|
8331
8604
|
const rows = [
|
|
8332
8605
|
["Instance", state.instance],
|
|
8333
8606
|
["Environment", state.env],
|
|
8334
8607
|
["Release", state.activeRelease ?? "\u2014"],
|
|
8335
8608
|
["Previous", state.previousRelease || "\u2014"],
|
|
8336
8609
|
["Domain", state.domain || "\u2014"],
|
|
8610
|
+
...state.managed ? [["Managed", state.managed]] : [],
|
|
8337
8611
|
["Ports", `web ${state.webPort ?? "?"}${state.backend ? `, pb ${state.pbPort ?? "?"}` : ""}`],
|
|
8338
8612
|
["App", health(state.services?.web)],
|
|
8339
8613
|
...state.backend ? [["PocketBase", health(state.services?.pocketbase)]] : [],
|
|
@@ -8342,15 +8616,15 @@ function describe(state) {
|
|
|
8342
8616
|
...state.gitSha ? [["Commit", state.gitSha.slice(0, 12)]] : []
|
|
8343
8617
|
];
|
|
8344
8618
|
const width = Math.max(...rows.map(([label4]) => label4.length));
|
|
8345
|
-
return
|
|
8619
|
+
return pc23.cyan(state.name) + "\n\n" + rows.map(([label4, value]) => ` ${label4.padEnd(width)} ${value}`).join("\n");
|
|
8346
8620
|
}
|
|
8347
8621
|
|
|
8348
8622
|
// src/commands/rollback.ts
|
|
8349
|
-
import { Command as
|
|
8350
|
-
import * as
|
|
8351
|
-
import
|
|
8623
|
+
import { Command as Command84 } from "commander";
|
|
8624
|
+
import * as p49 from "@clack/prompts";
|
|
8625
|
+
import pc24 from "picocolors";
|
|
8352
8626
|
var rollback = addTargetOptions(
|
|
8353
|
-
new
|
|
8627
|
+
new Command84("rollback").description("put the previous release back").configureHelp(helpConfig),
|
|
8354
8628
|
"production"
|
|
8355
8629
|
).option("--to <release>", "roll back to a specific release instead of the previous one").action(
|
|
8356
8630
|
(raw) => runCommand(async () => {
|
|
@@ -8359,8 +8633,8 @@ var rollback = addTargetOptions(
|
|
|
8359
8633
|
raw,
|
|
8360
8634
|
{
|
|
8361
8635
|
remote: async (ctx) => {
|
|
8362
|
-
|
|
8363
|
-
`Rolling back ${
|
|
8636
|
+
p49.log.step(
|
|
8637
|
+
`Rolling back ${pc24.cyan(ctx.appName)} ${pc24.dim(`(${ctx.targetName})`)} on ${ctx.server}`
|
|
8364
8638
|
);
|
|
8365
8639
|
const result = await runServerScript(
|
|
8366
8640
|
ctx.session,
|
|
@@ -8370,8 +8644,8 @@ var rollback = addTargetOptions(
|
|
|
8370
8644
|
stream: true
|
|
8371
8645
|
}
|
|
8372
8646
|
);
|
|
8373
|
-
|
|
8374
|
-
`Rolled back to ${
|
|
8647
|
+
p49.log.success(
|
|
8648
|
+
`Rolled back to ${pc24.cyan(result?.release ?? "the previous release")}` + (result?.from ? ` ${pc24.dim(`(was ${result.from})`)}` : "")
|
|
8375
8649
|
);
|
|
8376
8650
|
}
|
|
8377
8651
|
},
|
|
@@ -8384,9 +8658,9 @@ var rollback = addTargetOptions(
|
|
|
8384
8658
|
);
|
|
8385
8659
|
|
|
8386
8660
|
// src/commands/logs.ts
|
|
8387
|
-
import { Command as
|
|
8661
|
+
import { Command as Command85 } from "commander";
|
|
8388
8662
|
var logs = addTargetOptions(
|
|
8389
|
-
new
|
|
8663
|
+
new Command85("logs").description("tail the logs of a deployed app").configureHelp(helpConfig),
|
|
8390
8664
|
"production"
|
|
8391
8665
|
).option("-f, --follow", "keep streaming new output").option("-n, --lines <count>", "how many lines of history to show", "100").option("--pocketbase", "show the PocketBase service instead of the app").action(
|
|
8392
8666
|
(raw) => runCommand(async () => {
|
|
@@ -8420,16 +8694,16 @@ var logs = addTargetOptions(
|
|
|
8420
8694
|
);
|
|
8421
8695
|
|
|
8422
8696
|
// src/commands/admin.ts
|
|
8423
|
-
import { Command as
|
|
8697
|
+
import { Command as Command87 } from "commander";
|
|
8424
8698
|
|
|
8425
8699
|
// src/commands/admin/create.ts
|
|
8426
|
-
import
|
|
8427
|
-
import { Command as
|
|
8428
|
-
import * as
|
|
8429
|
-
import
|
|
8700
|
+
import process31 from "node:process";
|
|
8701
|
+
import { Command as Command86 } from "commander";
|
|
8702
|
+
import * as p50 from "@clack/prompts";
|
|
8703
|
+
import pc25 from "picocolors";
|
|
8430
8704
|
var MIN_PASSWORD = 10;
|
|
8431
8705
|
var adminCreate = addTargetOptions(
|
|
8432
|
-
new
|
|
8706
|
+
new Command86("create").description("create a login for the admin panel").argument("[email]", "email to sign in with \u2014 prompted for when omitted").configureHelp(helpConfig),
|
|
8433
8707
|
"local"
|
|
8434
8708
|
).action(
|
|
8435
8709
|
(email3, raw) => runCommand(
|
|
@@ -8457,8 +8731,8 @@ var adminCreate = addTargetOptions(
|
|
|
8457
8731
|
const metadata = getPocketbaseMetadata(ctx.workspaceRootDir);
|
|
8458
8732
|
if (metadata) signIn = `http://${metadata.viteHost}:${metadata.vitePort}`;
|
|
8459
8733
|
}
|
|
8460
|
-
|
|
8461
|
-
signIn ? `Sign in at ${
|
|
8734
|
+
p50.log.info(
|
|
8735
|
+
signIn ? `Sign in at ${pc25.cyan(`${signIn}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once ${pc25.cyan("vela dev")} is running.`
|
|
8462
8736
|
);
|
|
8463
8737
|
},
|
|
8464
8738
|
remote: async (ctx) => {
|
|
@@ -8471,8 +8745,8 @@ var adminCreate = addTargetOptions(
|
|
|
8471
8745
|
(pb) => upsertSuperuser(pb, address, password11)
|
|
8472
8746
|
);
|
|
8473
8747
|
const base2 = state?.domain ? `https://${state.domain.split(",")[0].trim()}` : "";
|
|
8474
|
-
|
|
8475
|
-
base2 ? `Sign in at ${
|
|
8748
|
+
p50.log.info(
|
|
8749
|
+
base2 ? `Sign in at ${pc25.cyan(`${base2}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once a domain is configured for this target.`
|
|
8476
8750
|
);
|
|
8477
8751
|
}
|
|
8478
8752
|
},
|
|
@@ -8484,20 +8758,20 @@ var adminCreate = addTargetOptions(
|
|
|
8484
8758
|
async function upsertSuperuser(pb, email3, password11) {
|
|
8485
8759
|
const existing = await findSuperuser(pb, email3);
|
|
8486
8760
|
if (existing) {
|
|
8487
|
-
const confirmed = await
|
|
8761
|
+
const confirmed = await p50.confirm({
|
|
8488
8762
|
message: `${email3} already has an account, update its password?`,
|
|
8489
8763
|
initialValue: false
|
|
8490
8764
|
});
|
|
8491
|
-
if (
|
|
8492
|
-
|
|
8493
|
-
|
|
8765
|
+
if (p50.isCancel(confirmed) || !confirmed) {
|
|
8766
|
+
p50.cancel("Operation cancelled.");
|
|
8767
|
+
process31.exit(0);
|
|
8494
8768
|
}
|
|
8495
8769
|
await pb.collection("_superusers").update(existing, { password: password11, passwordConfirm: password11 });
|
|
8496
|
-
|
|
8770
|
+
p50.log.success(`Password updated for ${pc25.cyan(email3)}, you can sign in now`);
|
|
8497
8771
|
return;
|
|
8498
8772
|
}
|
|
8499
8773
|
await pb.collection("_superusers").create({ email: email3, password: password11, passwordConfirm: password11 });
|
|
8500
|
-
|
|
8774
|
+
p50.log.success(`${pc25.cyan(email3)} can now sign in`);
|
|
8501
8775
|
}
|
|
8502
8776
|
async function findSuperuser(pb, email3) {
|
|
8503
8777
|
try {
|
|
@@ -8508,48 +8782,48 @@ async function findSuperuser(pb, email3) {
|
|
|
8508
8782
|
}
|
|
8509
8783
|
}
|
|
8510
8784
|
async function promptEmail() {
|
|
8511
|
-
const value = await
|
|
8785
|
+
const value = await p50.text({
|
|
8512
8786
|
message: "Email to sign in with",
|
|
8513
8787
|
validate: (input) => input?.includes("@") ? void 0 : "An email address is required"
|
|
8514
8788
|
});
|
|
8515
|
-
if (
|
|
8516
|
-
|
|
8517
|
-
|
|
8789
|
+
if (p50.isCancel(value)) {
|
|
8790
|
+
p50.cancel("Operation cancelled.");
|
|
8791
|
+
process31.exit(0);
|
|
8518
8792
|
}
|
|
8519
8793
|
return value.trim();
|
|
8520
8794
|
}
|
|
8521
8795
|
async function promptPassword2() {
|
|
8522
|
-
const value = await
|
|
8796
|
+
const value = await p50.password({
|
|
8523
8797
|
message: "Password",
|
|
8524
8798
|
validate: (input) => (input?.length ?? 0) >= MIN_PASSWORD ? void 0 : `At least ${MIN_PASSWORD} characters is required`
|
|
8525
8799
|
});
|
|
8526
|
-
if (
|
|
8527
|
-
|
|
8528
|
-
|
|
8800
|
+
if (p50.isCancel(value)) {
|
|
8801
|
+
p50.cancel("Operation cancelled.");
|
|
8802
|
+
process31.exit(0);
|
|
8529
8803
|
}
|
|
8530
|
-
const again = await
|
|
8804
|
+
const again = await p50.password({
|
|
8531
8805
|
message: "Password again",
|
|
8532
8806
|
validate: (input) => input === value ? void 0 : "The two do not match"
|
|
8533
8807
|
});
|
|
8534
|
-
if (
|
|
8535
|
-
|
|
8536
|
-
|
|
8808
|
+
if (p50.isCancel(again)) {
|
|
8809
|
+
p50.cancel("Operation cancelled.");
|
|
8810
|
+
process31.exit(0);
|
|
8537
8811
|
}
|
|
8538
8812
|
return value;
|
|
8539
8813
|
}
|
|
8540
8814
|
|
|
8541
8815
|
// src/commands/admin.ts
|
|
8542
|
-
var admin = new
|
|
8816
|
+
var admin = new Command87("admin").description("manage admin panel logins").configureHelp(helpConfig).addCommand(adminCreate);
|
|
8543
8817
|
|
|
8544
8818
|
// src/commands/backup.ts
|
|
8545
|
-
import { Command as
|
|
8819
|
+
import { Command as Command93 } from "commander";
|
|
8546
8820
|
|
|
8547
8821
|
// src/commands/backup/create.ts
|
|
8548
8822
|
import fs36 from "node:fs";
|
|
8549
8823
|
import path39 from "node:path";
|
|
8550
|
-
import { Command as
|
|
8551
|
-
import * as
|
|
8552
|
-
import
|
|
8824
|
+
import { Command as Command88 } from "commander";
|
|
8825
|
+
import * as p51 from "@clack/prompts";
|
|
8826
|
+
import pc26 from "picocolors";
|
|
8553
8827
|
|
|
8554
8828
|
// src/lib/backups.ts
|
|
8555
8829
|
var BACKUP_KEY = /^[a-z0-9_-]+\.zip$/;
|
|
@@ -8636,7 +8910,7 @@ async function writeSchedule(pb, cron, maxKeep) {
|
|
|
8636
8910
|
// src/commands/backup/create.ts
|
|
8637
8911
|
var DEFAULT_BACKUP_DIR = "backups";
|
|
8638
8912
|
var backupCreate = addTargetOptions(
|
|
8639
|
-
new
|
|
8913
|
+
new Command88("create").description("take a backup of the database and uploads").argument("[name]", "name for the archive \u2014 generated when omitted").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).option("--no-download", "leave the archive on the server").configureHelp(helpConfig),
|
|
8640
8914
|
"production"
|
|
8641
8915
|
).action(
|
|
8642
8916
|
(name, raw) => runCommand(() => {
|
|
@@ -8645,22 +8919,22 @@ var backupCreate = addTargetOptions(
|
|
|
8645
8919
|
const key = name ?? backupName(ctx.instance);
|
|
8646
8920
|
if (!isBackupKey(key)) {
|
|
8647
8921
|
throw new Error(
|
|
8648
|
-
`${
|
|
8922
|
+
`${pc26.cyan(key)} is not a name PocketBase will accept.
|
|
8649
8923
|
|
|
8650
|
-
Backup names are lowercase letters, digits, ${
|
|
8924
|
+
Backup names are lowercase letters, digits, ${pc26.cyan("-")} and ${pc26.cyan("_")}, ending in ${pc26.cyan(".zip")}.`
|
|
8651
8925
|
);
|
|
8652
8926
|
}
|
|
8653
8927
|
const storage = await readStorageSettings(ctx.pb);
|
|
8654
8928
|
if (storage.s3Enabled) {
|
|
8655
|
-
|
|
8929
|
+
p51.log.warn(
|
|
8656
8930
|
`Uploads are stored in S3, so this archive holds the database only.
|
|
8657
8931
|
|
|
8658
|
-
PocketBase leaves ${
|
|
8932
|
+
PocketBase leaves ${pc26.cyan("storage/")} out of a backup whenever S3 is on.
|
|
8659
8933
|
Your bucket's own versioning is what protects the uploaded files.`
|
|
8660
8934
|
);
|
|
8661
8935
|
}
|
|
8662
8936
|
if (ctx.session) await checkpointAppDatabases(ctx.session, ctx.instance);
|
|
8663
|
-
const spinner7 =
|
|
8937
|
+
const spinner7 = p51.spinner();
|
|
8664
8938
|
spinner7.start(`Backing up ${ctx.targetName}`);
|
|
8665
8939
|
try {
|
|
8666
8940
|
await createBackup(ctx.pb, key);
|
|
@@ -8707,7 +8981,7 @@ async function download(ctx, key, outputDir) {
|
|
|
8707
8981
|
fs36.copyFileSync(path39.join(ctx.workspaceRootDir, "data", "backups", key), destination);
|
|
8708
8982
|
return path39.relative(ctx.workspaceRootDir, destination);
|
|
8709
8983
|
}
|
|
8710
|
-
const spinner7 =
|
|
8984
|
+
const spinner7 = p51.spinner();
|
|
8711
8985
|
spinner7.start(`Downloading ${key}`);
|
|
8712
8986
|
try {
|
|
8713
8987
|
await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
|
|
@@ -8720,28 +8994,28 @@ async function download(ctx, key, outputDir) {
|
|
|
8720
8994
|
}
|
|
8721
8995
|
|
|
8722
8996
|
// src/commands/backup/list.ts
|
|
8723
|
-
import { Command as
|
|
8724
|
-
import * as
|
|
8725
|
-
import
|
|
8997
|
+
import { Command as Command89 } from "commander";
|
|
8998
|
+
import * as p52 from "@clack/prompts";
|
|
8999
|
+
import pc27 from "picocolors";
|
|
8726
9000
|
var backupList = addTargetOptions(
|
|
8727
|
-
new
|
|
9001
|
+
new Command89("list").description("list the backups on a target").configureHelp(helpConfig),
|
|
8728
9002
|
"production"
|
|
8729
9003
|
).action(
|
|
8730
9004
|
(raw) => runCommand(
|
|
8731
9005
|
() => withBackupTarget(raw, "backup list", async (ctx) => {
|
|
8732
9006
|
const backups = await listBackups(ctx.pb);
|
|
8733
9007
|
if (backups.length === 0) {
|
|
8734
|
-
|
|
8735
|
-
`${
|
|
9008
|
+
p52.log.info(
|
|
9009
|
+
`${pc27.cyan(ctx.targetName)} has no backups yet.
|
|
8736
9010
|
|
|
8737
|
-
Take one with ${
|
|
9011
|
+
Take one with ${pc27.cyan("vela backup create")}.`
|
|
8738
9012
|
);
|
|
8739
9013
|
return;
|
|
8740
9014
|
}
|
|
8741
9015
|
const width = Math.max(...backups.map((b) => b.key.length));
|
|
8742
|
-
|
|
9016
|
+
p52.log.message(
|
|
8743
9017
|
backups.map(
|
|
8744
|
-
(b) => `${b.key.padEnd(width)} ${
|
|
9018
|
+
(b) => `${b.key.padEnd(width)} ${pc27.dim(formatBytes(b.size).padStart(8))} ${pc27.dim(b.modified)}`
|
|
8745
9019
|
).join("\n")
|
|
8746
9020
|
);
|
|
8747
9021
|
}),
|
|
@@ -8752,11 +9026,11 @@ Take one with ${pc25.cyan("vela backup create")}.`
|
|
|
8752
9026
|
// src/commands/backup/download.ts
|
|
8753
9027
|
import fs37 from "node:fs";
|
|
8754
9028
|
import path40 from "node:path";
|
|
8755
|
-
import { Command as
|
|
8756
|
-
import * as
|
|
8757
|
-
import
|
|
9029
|
+
import { Command as Command90 } from "commander";
|
|
9030
|
+
import * as p53 from "@clack/prompts";
|
|
9031
|
+
import pc28 from "picocolors";
|
|
8758
9032
|
var backupDownload = addTargetOptions(
|
|
8759
|
-
new
|
|
9033
|
+
new Command90("download").description("save a backup off the server").argument("<key>", "archive to download, as shown by `vela backup list`").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).configureHelp(helpConfig),
|
|
8760
9034
|
"production"
|
|
8761
9035
|
).action(
|
|
8762
9036
|
(key, raw) => runCommand(() => {
|
|
@@ -8765,9 +9039,9 @@ var backupDownload = addTargetOptions(
|
|
|
8765
9039
|
const found = (await listBackups(ctx.pb)).find((b) => b.key === key);
|
|
8766
9040
|
if (!found) {
|
|
8767
9041
|
throw new Error(
|
|
8768
|
-
`${ctx.targetName} has no backup called ${
|
|
9042
|
+
`${ctx.targetName} has no backup called ${pc28.cyan(key)}.
|
|
8769
9043
|
|
|
8770
|
-
Run ${
|
|
9044
|
+
Run ${pc28.cyan("vela backup list")} to see what it does have.`
|
|
8771
9045
|
);
|
|
8772
9046
|
}
|
|
8773
9047
|
const storage = await readStorageSettings(ctx.pb);
|
|
@@ -8784,7 +9058,7 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
|
8784
9058
|
if (!ctx.session) {
|
|
8785
9059
|
fs37.copyFileSync(path40.join(ctx.workspaceRootDir, "data", "backups", key), destination);
|
|
8786
9060
|
} else {
|
|
8787
|
-
const spinner7 =
|
|
9061
|
+
const spinner7 = p53.spinner();
|
|
8788
9062
|
spinner7.start(`Downloading ${key} (${formatBytes(found.size)})`);
|
|
8789
9063
|
try {
|
|
8790
9064
|
await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
|
|
@@ -8803,12 +9077,12 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
|
8803
9077
|
);
|
|
8804
9078
|
|
|
8805
9079
|
// src/commands/backup/delete.ts
|
|
8806
|
-
import
|
|
8807
|
-
import { Command as
|
|
8808
|
-
import * as
|
|
8809
|
-
import
|
|
9080
|
+
import process32 from "node:process";
|
|
9081
|
+
import { Command as Command91 } from "commander";
|
|
9082
|
+
import * as p54 from "@clack/prompts";
|
|
9083
|
+
import pc29 from "picocolors";
|
|
8810
9084
|
var backupDelete = addTargetOptions(
|
|
8811
|
-
new
|
|
9085
|
+
new Command91("delete").description("remove a backup from a target").argument("<key>", "archive to delete, as shown by `vela backup list`").option("-y, --yes", "skip the confirmation").configureHelp(helpConfig),
|
|
8812
9086
|
"production"
|
|
8813
9087
|
).action(
|
|
8814
9088
|
(key, raw) => runCommand(() => {
|
|
@@ -8817,19 +9091,19 @@ var backupDelete = addTargetOptions(
|
|
|
8817
9091
|
const found = (await listBackups(ctx.pb)).find((b) => b.key === key);
|
|
8818
9092
|
if (!found) {
|
|
8819
9093
|
throw new Error(
|
|
8820
|
-
`${ctx.targetName} has no backup called ${
|
|
9094
|
+
`${ctx.targetName} has no backup called ${pc29.cyan(key)}.
|
|
8821
9095
|
|
|
8822
|
-
Run ${
|
|
9096
|
+
Run ${pc29.cyan("vela backup list")} to see what it does have.`
|
|
8823
9097
|
);
|
|
8824
9098
|
}
|
|
8825
9099
|
if (!options.yes) {
|
|
8826
|
-
const confirmed = await
|
|
9100
|
+
const confirmed = await p54.confirm({
|
|
8827
9101
|
message: `Delete ${key} (${formatBytes(found.size)}) from ${ctx.targetName}?`,
|
|
8828
9102
|
initialValue: false
|
|
8829
9103
|
});
|
|
8830
|
-
if (
|
|
8831
|
-
|
|
8832
|
-
|
|
9104
|
+
if (p54.isCancel(confirmed) || !confirmed) {
|
|
9105
|
+
p54.cancel("Operation cancelled.");
|
|
9106
|
+
process32.exit(0);
|
|
8833
9107
|
}
|
|
8834
9108
|
}
|
|
8835
9109
|
await ctx.pb.backups.delete(key);
|
|
@@ -8839,12 +9113,12 @@ Run ${pc27.cyan("vela backup list")} to see what it does have.`
|
|
|
8839
9113
|
);
|
|
8840
9114
|
|
|
8841
9115
|
// src/commands/backup/schedule.ts
|
|
8842
|
-
import { Command as
|
|
8843
|
-
import * as
|
|
8844
|
-
import
|
|
9116
|
+
import { Command as Command92 } from "commander";
|
|
9117
|
+
import * as p55 from "@clack/prompts";
|
|
9118
|
+
import pc30 from "picocolors";
|
|
8845
9119
|
var DEFAULT_KEEP = 7;
|
|
8846
9120
|
var backupSchedule = addTargetOptions(
|
|
8847
|
-
new
|
|
9121
|
+
new Command92("schedule").description("back up automatically on a schedule").argument("[cron]", "when to run, as a cron expression \u2014 shows the current one when omitted").option("--keep <n>", "how many scheduled archives to keep", String(DEFAULT_KEEP)).option("--off", "stop backing up automatically").configureHelp(helpConfig),
|
|
8848
9122
|
"production"
|
|
8849
9123
|
).action(
|
|
8850
9124
|
(cron, raw) => runCommand(() => {
|
|
@@ -8857,17 +9131,17 @@ var backupSchedule = addTargetOptions(
|
|
|
8857
9131
|
}
|
|
8858
9132
|
if (!cron) {
|
|
8859
9133
|
const current = await readSchedule(ctx.pb);
|
|
8860
|
-
|
|
8861
|
-
current.cron ? `${ctx.targetName} backs up on ${
|
|
9134
|
+
p55.log.info(
|
|
9135
|
+
current.cron ? `${ctx.targetName} backs up on ${pc30.cyan(current.cron)}, keeping ${current.maxKeep}.` : `${ctx.targetName} has no backup schedule.
|
|
8862
9136
|
|
|
8863
|
-
Set one with ${
|
|
9137
|
+
Set one with ${pc30.cyan('vela backup schedule "0 3 * * *"')}.`
|
|
8864
9138
|
);
|
|
8865
9139
|
return;
|
|
8866
9140
|
}
|
|
8867
9141
|
const keep = Number.parseInt(options.keep, 10);
|
|
8868
9142
|
if (!Number.isInteger(keep) || keep < 1) {
|
|
8869
9143
|
throw new Error(
|
|
8870
|
-
`${
|
|
9144
|
+
`${pc30.cyan(options.keep)} is not a number of backups to keep \u2014 pass at least 1.`
|
|
8871
9145
|
);
|
|
8872
9146
|
}
|
|
8873
9147
|
await writeSchedule(ctx.pb, cron, keep);
|
|
@@ -8888,17 +9162,17 @@ Set one with ${pc28.cyan('vela backup schedule "0 3 * * *"')}.`
|
|
|
8888
9162
|
);
|
|
8889
9163
|
|
|
8890
9164
|
// src/commands/backup.ts
|
|
8891
|
-
var backup = new
|
|
9165
|
+
var backup = new Command93("backup").description("back up the database and uploads, locally or on a target").configureHelp(helpConfig).addCommand(backupCreate).addCommand(backupList).addCommand(backupDownload).addCommand(backupDelete).addCommand(backupSchedule);
|
|
8892
9166
|
|
|
8893
9167
|
// src/commands/restore.ts
|
|
8894
9168
|
import fs38 from "node:fs";
|
|
8895
9169
|
import path41 from "node:path";
|
|
8896
|
-
import
|
|
8897
|
-
import { Command as
|
|
8898
|
-
import * as
|
|
8899
|
-
import
|
|
9170
|
+
import process33 from "node:process";
|
|
9171
|
+
import { Command as Command94 } from "commander";
|
|
9172
|
+
import * as p56 from "@clack/prompts";
|
|
9173
|
+
import pc31 from "picocolors";
|
|
8900
9174
|
var restore = addTargetOptions(
|
|
8901
|
-
new
|
|
9175
|
+
new Command94("restore").description("replace a deployment\u2019s database and uploads from a backup").argument("[source]", "a backup key on the target, or a path to a local archive").configureHelp(helpConfig),
|
|
8902
9176
|
"production"
|
|
8903
9177
|
).option("-y, --yes", "skip the confirmation prompt").option("--no-migrate", "do not run migrations against the restored database").option("--keep-previous <n>", "how many replaced databases to keep", "1").action(
|
|
8904
9178
|
(source, raw) => runCommand(async () => {
|
|
@@ -8933,19 +9207,19 @@ var restore = addTargetOptions(
|
|
|
8933
9207
|
],
|
|
8934
9208
|
stream: true
|
|
8935
9209
|
});
|
|
8936
|
-
|
|
8937
|
-
`Restored ${
|
|
9210
|
+
p56.log.success(
|
|
9211
|
+
`Restored ${pc31.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc31.cyan(
|
|
8938
9212
|
local ? path41.basename(local) : key
|
|
8939
9213
|
)}.`
|
|
8940
9214
|
);
|
|
8941
9215
|
if (result?.storageCarriedOver) {
|
|
8942
|
-
|
|
9216
|
+
p56.log.info(
|
|
8943
9217
|
"The archive held no uploads, so the files already on the server were kept."
|
|
8944
9218
|
);
|
|
8945
9219
|
}
|
|
8946
9220
|
if (result?.previousDataDir) {
|
|
8947
|
-
|
|
8948
|
-
`The database this replaced is at ${
|
|
9221
|
+
p56.log.info(
|
|
9222
|
+
`The database this replaced is at ${pc31.cyan(result.previousDataDir)}.
|
|
8949
9223
|
|
|
8950
9224
|
It is the only way back. Remove it once you are satisfied with the restore.`
|
|
8951
9225
|
);
|
|
@@ -8962,18 +9236,18 @@ It is the only way back. Remove it once you are satisfied with the restore.`
|
|
|
8962
9236
|
async function resolveKey(ctx, source) {
|
|
8963
9237
|
if (source && !isBackupKey(source)) {
|
|
8964
9238
|
throw new Error(
|
|
8965
|
-
`${
|
|
9239
|
+
`${pc31.cyan(source)} is neither a file on this machine nor a backup key.
|
|
8966
9240
|
|
|
8967
|
-
Run ${
|
|
9241
|
+
Run ${pc31.cyan("vela backup list")} to see what ${ctx.targetName} has.`
|
|
8968
9242
|
);
|
|
8969
9243
|
}
|
|
8970
9244
|
const backups = await withRemotePocketbase(ctx.session, ctx.instance, listBackups);
|
|
8971
9245
|
if (source) {
|
|
8972
9246
|
if (!backups.some((b) => b.key === source)) {
|
|
8973
9247
|
throw new Error(
|
|
8974
|
-
`${ctx.targetName} has no backup called ${
|
|
9248
|
+
`${ctx.targetName} has no backup called ${pc31.cyan(source)}.
|
|
8975
9249
|
|
|
8976
|
-
Run ${
|
|
9250
|
+
Run ${pc31.cyan("vela backup list")} to see what it does have.`
|
|
8977
9251
|
);
|
|
8978
9252
|
}
|
|
8979
9253
|
return source;
|
|
@@ -8982,10 +9256,10 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
|
|
|
8982
9256
|
throw new Error(
|
|
8983
9257
|
`${ctx.targetName} has no backups to restore from.
|
|
8984
9258
|
|
|
8985
|
-
Take one with ${
|
|
9259
|
+
Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive on this machine.`
|
|
8986
9260
|
);
|
|
8987
9261
|
}
|
|
8988
|
-
const chosen = await
|
|
9262
|
+
const chosen = await p56.select({
|
|
8989
9263
|
message: `Which backup should ${ctx.targetName} be restored from?`,
|
|
8990
9264
|
options: backups.map((b) => ({
|
|
8991
9265
|
value: b.key,
|
|
@@ -8993,16 +9267,16 @@ Take one with ${pc29.cyan("vela backup create")}, or pass the path to an archive
|
|
|
8993
9267
|
hint: `${formatBytes(b.size)}, ${b.modified}`
|
|
8994
9268
|
}))
|
|
8995
9269
|
});
|
|
8996
|
-
if (
|
|
8997
|
-
|
|
8998
|
-
|
|
9270
|
+
if (p56.isCancel(chosen)) {
|
|
9271
|
+
p56.cancel("Operation cancelled.");
|
|
9272
|
+
process33.exit(0);
|
|
8999
9273
|
}
|
|
9000
9274
|
return chosen;
|
|
9001
9275
|
}
|
|
9002
9276
|
async function stage(ctx, file) {
|
|
9003
9277
|
const dir = remotePaths.restoreStage(ctx.instance);
|
|
9004
9278
|
const remote = `${dir}/${path41.basename(file)}`;
|
|
9005
|
-
const spinner7 =
|
|
9279
|
+
const spinner7 = p56.spinner();
|
|
9006
9280
|
spinner7.start(`Uploading ${path41.basename(file)}`);
|
|
9007
9281
|
try {
|
|
9008
9282
|
await ctx.session.script(`mkdir -p "$1"`, { args: [dir] });
|
|
@@ -9015,32 +9289,32 @@ async function stage(ctx, file) {
|
|
|
9015
9289
|
return remote;
|
|
9016
9290
|
}
|
|
9017
9291
|
async function confirm12(appName, targetName, envTag, from) {
|
|
9018
|
-
const what = `${
|
|
9292
|
+
const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(path41.basename(from))}`;
|
|
9019
9293
|
if (isProd(envTag)) {
|
|
9020
|
-
const answer = await
|
|
9294
|
+
const answer = await p56.text({
|
|
9021
9295
|
message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
|
|
9022
9296
|
validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
|
|
9023
9297
|
});
|
|
9024
|
-
if (
|
|
9025
|
-
|
|
9026
|
-
|
|
9298
|
+
if (p56.isCancel(answer)) {
|
|
9299
|
+
p56.cancel("Operation cancelled.");
|
|
9300
|
+
process33.exit(0);
|
|
9027
9301
|
}
|
|
9028
9302
|
return;
|
|
9029
9303
|
}
|
|
9030
|
-
const ok = await
|
|
9304
|
+
const ok = await p56.confirm({
|
|
9031
9305
|
message: `Replace the database and uploads of ${what}?`,
|
|
9032
9306
|
initialValue: false
|
|
9033
9307
|
});
|
|
9034
|
-
if (
|
|
9035
|
-
|
|
9036
|
-
|
|
9308
|
+
if (p56.isCancel(ok) || !ok) {
|
|
9309
|
+
p56.cancel("Operation cancelled.");
|
|
9310
|
+
process33.exit(0);
|
|
9037
9311
|
}
|
|
9038
9312
|
}
|
|
9039
9313
|
|
|
9040
9314
|
// src/commands/targets.ts
|
|
9041
|
-
import { Command as
|
|
9042
|
-
import * as
|
|
9043
|
-
import
|
|
9315
|
+
import { Command as Command95 } from "commander";
|
|
9316
|
+
import * as p57 from "@clack/prompts";
|
|
9317
|
+
import pc32 from "picocolors";
|
|
9044
9318
|
import * as v8 from "valibot";
|
|
9045
9319
|
var OptionsSchema4 = v8.object({
|
|
9046
9320
|
...SSH_OPTION_SCHEMA,
|
|
@@ -9048,7 +9322,7 @@ var OptionsSchema4 = v8.object({
|
|
|
9048
9322
|
offline: v8.optional(v8.boolean())
|
|
9049
9323
|
});
|
|
9050
9324
|
var targets = addSshOptions(
|
|
9051
|
-
new
|
|
9325
|
+
new Command95("targets").description("list the targets this project can deploy to").configureHelp(helpConfig)
|
|
9052
9326
|
).option("--json", "print raw JSON").option("--offline", "skip connecting to servers").action(
|
|
9053
9327
|
(raw) => runCommand(async () => {
|
|
9054
9328
|
const options = parseOptions(OptionsSchema4, raw);
|
|
@@ -9112,13 +9386,13 @@ function report3(rows, offline) {
|
|
|
9112
9386
|
const domain = width("DOMAIN", (row) => row.domain);
|
|
9113
9387
|
const header = `${"TARGET".padEnd(target)} ${"SERVER".padEnd(server)} ${"DOMAIN".padEnd(domain)} RELEASE`;
|
|
9114
9388
|
const lines = rows.map(
|
|
9115
|
-
(row) => `${row.kind === "local" ?
|
|
9389
|
+
(row) => `${row.kind === "local" ? pc32.dim(row.target.padEnd(target)) : pc32.cyan(row.target.padEnd(target))} ${row.server.padEnd(server)} ${row.domain.padEnd(domain)} ${row.release}`
|
|
9116
9390
|
);
|
|
9117
|
-
|
|
9391
|
+
p57.log.info(`${pc32.dim(header)}
|
|
9118
9392
|
${lines.join("\n")}`);
|
|
9119
9393
|
const unreachable = rows.filter((row) => row.kind === "remote" && !row.reachable);
|
|
9120
9394
|
if (!offline && unreachable.length > 0) {
|
|
9121
|
-
|
|
9395
|
+
p57.log.warn(
|
|
9122
9396
|
`Could not reach ${unreachable.map((row) => row.server).join(", ")}.
|
|
9123
9397
|
Release and domain are shown from what this project recorded.`
|
|
9124
9398
|
);
|
|
@@ -9127,16 +9401,16 @@ Release and domain are shown from what this project recorded.`
|
|
|
9127
9401
|
|
|
9128
9402
|
// src/commands/test.ts
|
|
9129
9403
|
import path42 from "node:path";
|
|
9130
|
-
import
|
|
9131
|
-
import { Command as
|
|
9404
|
+
import process34 from "node:process";
|
|
9405
|
+
import { Command as Command96 } from "commander";
|
|
9132
9406
|
import PocketBase6 from "pocketbase";
|
|
9133
|
-
import
|
|
9407
|
+
import pc33 from "picocolors";
|
|
9134
9408
|
import { x as x5 } from "tinyexec";
|
|
9135
9409
|
import { detect as detect7 } from "package-manager-detector";
|
|
9136
9410
|
import { resolveCommand as resolveCommand7 } from "package-manager-detector/commands";
|
|
9137
9411
|
import fs39 from "node:fs";
|
|
9138
|
-
var testServer = new
|
|
9139
|
-
const cwd =
|
|
9412
|
+
var testServer = new Command96("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
|
|
9413
|
+
const cwd = process34.cwd();
|
|
9140
9414
|
const email3 = `test-${Math.random().toString(36).slice(2)}@example.com`;
|
|
9141
9415
|
const password11 = "password";
|
|
9142
9416
|
const testDataDir = path42.join(cwd, "test-data");
|
|
@@ -9151,12 +9425,12 @@ var testServer = new Command95("test:server").description("run server tests").al
|
|
|
9151
9425
|
email: email3,
|
|
9152
9426
|
password: password11
|
|
9153
9427
|
});
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
console.log(`${
|
|
9428
|
+
process34.env.POCKETBASE_URL = url;
|
|
9429
|
+
process34.env.POCKETBASE_SUPERUSER_EMAIL = email3;
|
|
9430
|
+
process34.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
|
|
9431
|
+
process34.env.VELA_DATA_DIR = testDataDir;
|
|
9432
|
+
process34.env.TEST = "true";
|
|
9433
|
+
console.log(`${pc33.greenBright("\u2713")} Created test database`);
|
|
9160
9434
|
let vite;
|
|
9161
9435
|
let cleanedUp = false;
|
|
9162
9436
|
const cleanupSync = () => {
|
|
@@ -9172,14 +9446,14 @@ var testServer = new Command95("test:server").description("run server tests").al
|
|
|
9172
9446
|
cleanupSync();
|
|
9173
9447
|
};
|
|
9174
9448
|
const fail = async (message) => {
|
|
9175
|
-
console.error(`${
|
|
9449
|
+
console.error(`${pc33.redBright("\u2717")} ${message}`);
|
|
9176
9450
|
await cleanup();
|
|
9177
|
-
|
|
9451
|
+
process34.exit(1);
|
|
9178
9452
|
};
|
|
9179
|
-
|
|
9180
|
-
|
|
9453
|
+
process34.on("exit", cleanupSync);
|
|
9454
|
+
process34.on("SIGINT", () => {
|
|
9181
9455
|
cleanupSync();
|
|
9182
|
-
|
|
9456
|
+
process34.exit(130);
|
|
9183
9457
|
});
|
|
9184
9458
|
const pb = new PocketBase6(url);
|
|
9185
9459
|
try {
|
|
@@ -9190,11 +9464,11 @@ var testServer = new Command95("test:server").description("run server tests").al
|
|
|
9190
9464
|
try {
|
|
9191
9465
|
const seeds2 = await loadSeeds(pb, cwd);
|
|
9192
9466
|
if (seeds2.length > 0) {
|
|
9193
|
-
console.log(`${
|
|
9467
|
+
console.log(`${pc33.greenBright("\u2713")} Loaded ${seeds2.length} seed file(s)`);
|
|
9194
9468
|
}
|
|
9195
9469
|
const fixtures2 = await loadFixtures(pb, cwd);
|
|
9196
9470
|
if (fixtures2.length > 0) {
|
|
9197
|
-
console.log(`${
|
|
9471
|
+
console.log(`${pc33.greenBright("\u2713")} Loaded ${fixtures2.length} fixture file(s)`);
|
|
9198
9472
|
}
|
|
9199
9473
|
} catch (e) {
|
|
9200
9474
|
await fail(describeLoadFailure(e));
|
|
@@ -9207,9 +9481,9 @@ var testServer = new Command95("test:server").description("run server tests").al
|
|
|
9207
9481
|
});
|
|
9208
9482
|
const vitePort = await findFreePort();
|
|
9209
9483
|
await vite.listen(vitePort);
|
|
9210
|
-
|
|
9211
|
-
console.log(`${
|
|
9212
|
-
console.log(`${
|
|
9484
|
+
process34.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
|
|
9485
|
+
console.log(`${pc33.greenBright("\u2713")} Started Vite: http://localhost:${vitePort}`);
|
|
9486
|
+
console.log(`${pc33.greenBright("\u2713")} Started PocketBase: ${url}`);
|
|
9213
9487
|
const extraArgs = (cmd.parent?.args ?? []).slice(1);
|
|
9214
9488
|
let filter = extraArgs.find((arg) => !arg.startsWith("-"));
|
|
9215
9489
|
const passthrough = filter ? extraArgs.filter((a) => a !== filter) : extraArgs;
|
|
@@ -9226,12 +9500,12 @@ var testServer = new Command95("test:server").description("run server tests").al
|
|
|
9226
9500
|
const resolvedArgs = resolved.args.slice();
|
|
9227
9501
|
if (pm === "npm") resolvedArgs.unshift("--yes");
|
|
9228
9502
|
const result = await x5(resolved.command, resolvedArgs, {
|
|
9229
|
-
nodeOptions: { cwd, stdio: "inherit", env: { ...
|
|
9503
|
+
nodeOptions: { cwd, stdio: "inherit", env: { ...process34.env, CI: "1" } }
|
|
9230
9504
|
});
|
|
9231
|
-
|
|
9505
|
+
process34.exitCode = result.exitCode ?? 1;
|
|
9232
9506
|
} catch (e) {
|
|
9233
|
-
console.error(`${
|
|
9234
|
-
|
|
9507
|
+
console.error(`${pc33.redBright("\u2717")} ${e.message}`);
|
|
9508
|
+
process34.exitCode = 1;
|
|
9235
9509
|
} finally {
|
|
9236
9510
|
await cleanup();
|
|
9237
9511
|
}
|
|
@@ -9264,7 +9538,7 @@ function stubPagesPlugin() {
|
|
|
9264
9538
|
// src/commands/routes.ts
|
|
9265
9539
|
import fs40 from "node:fs";
|
|
9266
9540
|
import path43 from "node:path";
|
|
9267
|
-
import { Command as
|
|
9541
|
+
import { Command as Command97 } from "commander";
|
|
9268
9542
|
var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
9269
9543
|
"GET",
|
|
9270
9544
|
"POST",
|
|
@@ -9275,7 +9549,7 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
|
9275
9549
|
"HEAD",
|
|
9276
9550
|
"fallback"
|
|
9277
9551
|
]);
|
|
9278
|
-
var routes = new
|
|
9552
|
+
var routes = new Command97("routes").description("list routes").configureHelp(helpConfig).action(async () => {
|
|
9279
9553
|
const { workspaceRootDir, routesDir } = await getWorkspace();
|
|
9280
9554
|
const routesRoot = path43.join(workspaceRootDir, routesDir);
|
|
9281
9555
|
const found = walk(routesRoot, routesRoot).filter((r) => r.methods.length > 0);
|
|
@@ -9350,13 +9624,13 @@ function printTable(routes2) {
|
|
|
9350
9624
|
}
|
|
9351
9625
|
|
|
9352
9626
|
// src/commands/i18n.ts
|
|
9353
|
-
import
|
|
9354
|
-
import { Command as
|
|
9627
|
+
import process35 from "node:process";
|
|
9628
|
+
import { Command as Command98 } from "commander";
|
|
9355
9629
|
import { x as x6 } from "tinyexec";
|
|
9356
9630
|
import { detect as detect8 } from "package-manager-detector";
|
|
9357
9631
|
import { resolveCommand as resolveCommand8 } from "package-manager-detector/commands";
|
|
9358
9632
|
async function runWuchale(extraArgs) {
|
|
9359
|
-
const cwd =
|
|
9633
|
+
const cwd = process35.cwd();
|
|
9360
9634
|
const pm = (await detect8({ cwd }))?.name ?? "npm";
|
|
9361
9635
|
const resolved = resolveCommand8(pm, "execute", ["wuchale", ...extraArgs]);
|
|
9362
9636
|
const args = resolved.args.slice();
|
|
@@ -9366,11 +9640,11 @@ async function runWuchale(extraArgs) {
|
|
|
9366
9640
|
throwOnError: true
|
|
9367
9641
|
});
|
|
9368
9642
|
}
|
|
9369
|
-
var extract = new
|
|
9370
|
-
var watch = new
|
|
9371
|
-
var status2 = new
|
|
9372
|
-
var clean = new
|
|
9373
|
-
var i18n3 = new
|
|
9643
|
+
var extract = new Command98("extract").description("extract translatable strings").configureHelp(helpConfig).action(() => runWuchale([]));
|
|
9644
|
+
var watch = new Command98("watch").description("watch and extract translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--watch"]));
|
|
9645
|
+
var status2 = new Command98("status").description("show i18n status").configureHelp(helpConfig).action(() => runWuchale(["status"]));
|
|
9646
|
+
var clean = new Command98("clean").description("clean unused translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--clean"]));
|
|
9647
|
+
var i18n3 = new Command98("i18n").description("i18n utilities").configureHelp(helpConfig).addCommand(extract, { isDefault: true }).addCommand(watch).addCommand(status2).addCommand(clean);
|
|
9374
9648
|
|
|
9375
9649
|
// src/commands/oauth.ts
|
|
9376
9650
|
var oauth = stubCommand("oauth", "configure OAuth providers");
|
|
@@ -9379,23 +9653,23 @@ var oauth = stubCommand("oauth", "configure OAuth providers");
|
|
|
9379
9653
|
var schemas = stubCommand("schemas", "manage database schemas");
|
|
9380
9654
|
|
|
9381
9655
|
// src/commands/cms.ts
|
|
9382
|
-
import { Command as
|
|
9656
|
+
import { Command as Command103 } from "commander";
|
|
9383
9657
|
|
|
9384
9658
|
// src/commands/cms/editor.ts
|
|
9385
|
-
import { Command as
|
|
9659
|
+
import { Command as Command102 } from "commander";
|
|
9386
9660
|
|
|
9387
9661
|
// src/commands/cms/editor/add.ts
|
|
9388
9662
|
import { randomBytes } from "node:crypto";
|
|
9389
|
-
import { Command as
|
|
9390
|
-
import * as
|
|
9391
|
-
import
|
|
9663
|
+
import { Command as Command99 } from "commander";
|
|
9664
|
+
import * as p58 from "@clack/prompts";
|
|
9665
|
+
import pc35 from "picocolors";
|
|
9392
9666
|
|
|
9393
9667
|
// src/lib/cms-backend.ts
|
|
9394
9668
|
import { createRequire as createRequire3 } from "node:module";
|
|
9395
9669
|
import path44 from "node:path";
|
|
9396
|
-
import
|
|
9670
|
+
import process36 from "node:process";
|
|
9397
9671
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
9398
|
-
import
|
|
9672
|
+
import pc34 from "picocolors";
|
|
9399
9673
|
var DEFAULT_PROJECT = "default";
|
|
9400
9674
|
async function loadBackendModule(root) {
|
|
9401
9675
|
let entry;
|
|
@@ -9405,12 +9679,12 @@ async function loadBackendModule(root) {
|
|
|
9405
9679
|
throw new Error(
|
|
9406
9680
|
`@velastack/cms is not installed in this project.
|
|
9407
9681
|
|
|
9408
|
-
Run ${
|
|
9682
|
+
Run ${pc34.cyan("vela enable cms")} first.`
|
|
9409
9683
|
);
|
|
9410
9684
|
}
|
|
9411
9685
|
return await import(pathToFileURL3(entry).href);
|
|
9412
9686
|
}
|
|
9413
|
-
async function withCmsBackend(fn, cwd =
|
|
9687
|
+
async function withCmsBackend(fn, cwd = process36.cwd()) {
|
|
9414
9688
|
const root = findWorkspaceRoot(cwd);
|
|
9415
9689
|
if (!root) {
|
|
9416
9690
|
throw new Error("Could not find workspace root (no package.json found)");
|
|
@@ -9429,42 +9703,42 @@ async function withCmsBackend(fn, cwd = process34.cwd()) {
|
|
|
9429
9703
|
}
|
|
9430
9704
|
|
|
9431
9705
|
// src/commands/cms/editor/add.ts
|
|
9432
|
-
var editorAdd = new
|
|
9706
|
+
var editorAdd = new Command99("add").description("create an editor who can sign in to the admin bar").argument("<email>", "email the editor signs in with").option("--password <password>", "password to set \u2014 generated and shown once when omitted").option("--project <id>", "project the editor may edit", DEFAULT_PROJECT).configureHelp(helpConfig).action(
|
|
9433
9707
|
(email3, options) => runCommand(async () => {
|
|
9434
9708
|
const generated = options.password === void 0;
|
|
9435
9709
|
const password11 = options.password ?? randomBytes(12).toString("base64url");
|
|
9436
9710
|
const editor2 = await withCmsBackend(
|
|
9437
9711
|
(cms3) => cms3.editors.create({ email: email3, password: password11, projects: [options.project] })
|
|
9438
9712
|
);
|
|
9439
|
-
const lines = [`Added ${
|
|
9713
|
+
const lines = [`Added ${pc35.cyan(editor2.email)} as an editor of ${pc35.cyan(options.project)}.`];
|
|
9440
9714
|
if (generated) {
|
|
9441
|
-
lines.push("", `Password: ${
|
|
9715
|
+
lines.push("", `Password: ${pc35.bold(password11)}`, "", "It is shown once; copy it now.");
|
|
9442
9716
|
}
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
`Run ${
|
|
9717
|
+
p58.log.success(lines.join("\n"));
|
|
9718
|
+
p58.log.info(
|
|
9719
|
+
`Run ${pc35.cyan("vela dev")}, open any page with ${pc35.cyan("?edit")} on the URL (or press ${pc35.cyan("Ctrl+E")}), and sign in.`
|
|
9446
9720
|
);
|
|
9447
9721
|
}, "Failed to add the editor.")
|
|
9448
9722
|
);
|
|
9449
9723
|
|
|
9450
9724
|
// src/commands/cms/editor/password.ts
|
|
9451
|
-
import { Command as
|
|
9452
|
-
import * as
|
|
9453
|
-
import
|
|
9454
|
-
var editorPassword = new
|
|
9725
|
+
import { Command as Command100 } from "commander";
|
|
9726
|
+
import * as p59 from "@clack/prompts";
|
|
9727
|
+
import pc36 from "picocolors";
|
|
9728
|
+
var editorPassword = new Command100("password").description("set an editor's password").argument("<email>", "email of the editor").argument("<password>", "new password").configureHelp(helpConfig).action(
|
|
9455
9729
|
(email3, password11) => runCommand(async () => {
|
|
9456
9730
|
await withCmsBackend((cms3) => cms3.editors.setPassword(email3, password11));
|
|
9457
|
-
|
|
9458
|
-
`Updated the password for ${
|
|
9731
|
+
p59.log.success(
|
|
9732
|
+
`Updated the password for ${pc36.cyan(email3)}. Existing sessions were signed out.`
|
|
9459
9733
|
);
|
|
9460
9734
|
}, "Failed to set the password.")
|
|
9461
9735
|
);
|
|
9462
9736
|
|
|
9463
9737
|
// src/commands/cms/editor/list.ts
|
|
9464
|
-
import { Command as
|
|
9465
|
-
import * as
|
|
9466
|
-
import
|
|
9467
|
-
var editorList = new
|
|
9738
|
+
import { Command as Command101 } from "commander";
|
|
9739
|
+
import * as p60 from "@clack/prompts";
|
|
9740
|
+
import pc37 from "picocolors";
|
|
9741
|
+
var editorList = new Command101("list").description("list editors and the projects they may edit").configureHelp(helpConfig).action(
|
|
9468
9742
|
() => runCommand(async () => {
|
|
9469
9743
|
const rows = await withCmsBackend(
|
|
9470
9744
|
async (cms3) => cms3.editors.list().map((editor2) => ({
|
|
@@ -9473,25 +9747,25 @@ var editorList = new Command100("list").description("list editors and the projec
|
|
|
9473
9747
|
}))
|
|
9474
9748
|
);
|
|
9475
9749
|
if (rows.length === 0) {
|
|
9476
|
-
|
|
9750
|
+
p60.log.info(`No editors yet. Add one with ${pc37.cyan("vela cms editor add <email>")}.`);
|
|
9477
9751
|
return;
|
|
9478
9752
|
}
|
|
9479
9753
|
const width = Math.max(...rows.map((row) => row.email.length));
|
|
9480
|
-
|
|
9754
|
+
p60.log.info(
|
|
9481
9755
|
`Editors
|
|
9482
9756
|
|
|
9483
9757
|
` + rows.map(
|
|
9484
|
-
(row) => ` ${row.email.padEnd(width)} ${
|
|
9758
|
+
(row) => ` ${row.email.padEnd(width)} ${pc37.dim(row.projects.join(", ") || "no projects")}`
|
|
9485
9759
|
).join("\n")
|
|
9486
9760
|
);
|
|
9487
9761
|
}, "Failed to list editors.")
|
|
9488
9762
|
);
|
|
9489
9763
|
|
|
9490
9764
|
// src/commands/cms/editor.ts
|
|
9491
|
-
var editor = new
|
|
9765
|
+
var editor = new Command102("editor").description("manage who can sign in to the admin bar").configureHelp(helpConfig).addCommand(editorAdd).addCommand(editorPassword).addCommand(editorList);
|
|
9492
9766
|
|
|
9493
9767
|
// src/commands/cms.ts
|
|
9494
|
-
var cms2 = new
|
|
9768
|
+
var cms2 = new Command103("cms").description("manage the CMS").configureHelp(helpConfig).addCommand(editor);
|
|
9495
9769
|
|
|
9496
9770
|
// src/program.ts
|
|
9497
9771
|
var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
|
|
@@ -9526,10 +9800,10 @@ var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
|
|
|
9526
9800
|
]);
|
|
9527
9801
|
var BACKEND_OPTIONAL_COMMANDS = /* @__PURE__ */ new Set(["dev", "build", "preview", "deploy"]);
|
|
9528
9802
|
var SELF_CREDENTIALED_COMMANDS = /* @__PURE__ */ new Set(["test:server"]);
|
|
9529
|
-
var program = new
|
|
9803
|
+
var program = new Command104().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
|
|
9530
9804
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
9531
9805
|
if (isStub(actionCommand)) return;
|
|
9532
|
-
const envRoot = findWorkspaceRoot() ??
|
|
9806
|
+
const envRoot = findWorkspaceRoot() ?? process37.cwd();
|
|
9533
9807
|
dotenv2.config({ path: nodePath.join(envRoot, ".env"), quiet: true });
|
|
9534
9808
|
const path45 = getCommandPath(actionCommand);
|
|
9535
9809
|
if (NO_BACKEND_COMMMANDS.has(path45)) return;
|
|
@@ -9537,30 +9811,30 @@ program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
|
9537
9811
|
if (NO_BACKEND_COMMMANDS.has(top)) return;
|
|
9538
9812
|
if (!hasBackend()) {
|
|
9539
9813
|
if (BACKEND_OPTIONAL_COMMANDS.has(top)) return;
|
|
9540
|
-
|
|
9541
|
-
`${
|
|
9814
|
+
p61.log.error(
|
|
9815
|
+
`${pc38.cyan(`vela ${path45}`)} needs a backend, and this project does not have one.
|
|
9542
9816
|
|
|
9543
9817
|
Static projects have no database to talk to.
|
|
9544
9818
|
|
|
9545
|
-
To add a backend to this project, run ${
|
|
9819
|
+
To add a backend to this project, run ${pc38.cyan("vela bless")}.`
|
|
9546
9820
|
);
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9821
|
+
p61.log.message();
|
|
9822
|
+
p61.cancel("Operation failed.");
|
|
9823
|
+
process37.exit(1);
|
|
9550
9824
|
}
|
|
9551
9825
|
if (SELF_CREDENTIALED_COMMANDS.has(path45)) return;
|
|
9552
|
-
if (!
|
|
9553
|
-
|
|
9826
|
+
if (!process37.env.POCKETBASE_SUPERUSER_EMAIL || !process37.env.POCKETBASE_SUPERUSER_PASSWORD) {
|
|
9827
|
+
p61.log.error(
|
|
9554
9828
|
`PocketBase superuser credentials are required.
|
|
9555
9829
|
|
|
9556
|
-
Set ${
|
|
9830
|
+
Set ${pc38.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc38.cyan("POCKETBASE_SUPERUSER_PASSWORD")} in your .env file.
|
|
9557
9831
|
|
|
9558
|
-
To set up a new project, run ${
|
|
9559
|
-
To set up an existing project, run ${
|
|
9832
|
+
To set up a new project, run ${pc38.cyan("vela create")}.
|
|
9833
|
+
To set up an existing project, run ${pc38.cyan("vela bless")}.`
|
|
9560
9834
|
);
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
|
|
9835
|
+
p61.log.message();
|
|
9836
|
+
p61.cancel("Operation failed.");
|
|
9837
|
+
process37.exit(1);
|
|
9564
9838
|
}
|
|
9565
9839
|
});
|
|
9566
9840
|
function getCommandPath(cmd) {
|
|
@@ -9614,5 +9888,5 @@ for (const command of [
|
|
|
9614
9888
|
}
|
|
9615
9889
|
|
|
9616
9890
|
// src/bin.ts
|
|
9617
|
-
program.parse(normalizeArgv(
|
|
9891
|
+
program.parse(normalizeArgv(process38.argv.slice(2)), { from: "user" });
|
|
9618
9892
|
//# sourceMappingURL=bin.js.map
|