vela 0.11.3 → 0.11.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -2
- package/dist/bin.js +854 -313
- package/dist/bin.js.map +4 -4
- package/package.json +19 -4
- package/templates/minimal/package.template.json +1 -1
- package/templates/minimal/vite.config.ts +1 -1
- package/templates/minimal/vitest.config.ts +3 -0
- package/templates/server/apply.sh +126 -36
- package/templates/server/destroy.sh +49 -6
- package/templates/server/lib.sh +114 -9
- package/templates/server/origin.sh +2 -0
- package/templates/server/restore.sh +7 -4
- package/templates/server/rollback.sh +12 -16
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 process39 from "node:process";
|
|
5
5
|
|
|
6
6
|
// src/lib/argv.ts
|
|
7
7
|
function normalizeArgv(argv) {
|
|
@@ -11,7 +11,7 @@ function normalizeArgv(argv) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// src/program.ts
|
|
14
|
-
import
|
|
14
|
+
import process38 from "node:process";
|
|
15
15
|
import * as p61 from "@clack/prompts";
|
|
16
16
|
import { Command as Command104 } from "commander";
|
|
17
17
|
import nodePath from "node:path";
|
|
@@ -21,7 +21,7 @@ import pc38 from "picocolors";
|
|
|
21
21
|
// package.json
|
|
22
22
|
var package_default = {
|
|
23
23
|
name: "vela",
|
|
24
|
-
version: "0.11.
|
|
24
|
+
version: "0.11.5",
|
|
25
25
|
type: "module",
|
|
26
26
|
description: "A CLI for creating and updating SvelteKit projects",
|
|
27
27
|
license: "MIT",
|
|
@@ -45,17 +45,19 @@ var package_default = {
|
|
|
45
45
|
build: "node --experimental-strip-types scripts/build.ts",
|
|
46
46
|
dev: "node --experimental-strip-types scripts/build.ts --watch",
|
|
47
47
|
clean: "rm -rf dist",
|
|
48
|
-
lint: "npm run lint:ts && npm run lint:format",
|
|
48
|
+
lint: "npm run lint:ts && npm run lint:format && npm run lint:sh",
|
|
49
49
|
"lint:ts": "tsc --noEmit",
|
|
50
50
|
"lint:format": "prettier --check .",
|
|
51
51
|
format: "prettier --write .",
|
|
52
52
|
test: "vitest run",
|
|
53
|
-
prepare: "npm run build"
|
|
53
|
+
prepare: "npm run build",
|
|
54
|
+
"lint:sh": "shellcheck -x -P SCRIPTDIR -S warning templates/server/*.sh",
|
|
55
|
+
"test:scripts": "bash scripts/test-server-scripts.sh"
|
|
54
56
|
},
|
|
55
57
|
dependencies: {
|
|
56
58
|
"@clack/prompts": "^1.7.0",
|
|
57
59
|
"@faker-js/faker": "^10.6.0",
|
|
58
|
-
"@velastack/patterns": "^0.2.
|
|
60
|
+
"@velastack/patterns": "^0.2.4",
|
|
59
61
|
"@velastack/pocketbase-codegen": "^0.1.0",
|
|
60
62
|
"annotate-json-schema": "^0.1.0",
|
|
61
63
|
commander: "^13.1.0",
|
|
@@ -81,6 +83,7 @@ var package_default = {
|
|
|
81
83
|
"@types/node": "^22.0.0",
|
|
82
84
|
esbuild: "^0.28.2",
|
|
83
85
|
prettier: "^3.9.6",
|
|
86
|
+
shellcheck: "^4.1.0",
|
|
84
87
|
typescript: "^5.6.0",
|
|
85
88
|
vite: "^8.2.2",
|
|
86
89
|
vitest: "^4.1.11"
|
|
@@ -97,6 +100,18 @@ var package_default = {
|
|
|
97
100
|
optional: true
|
|
98
101
|
}
|
|
99
102
|
},
|
|
103
|
+
overrides: {
|
|
104
|
+
"global-agent": "^4.1.3",
|
|
105
|
+
"@xhmikosr/decompress-unzip": {
|
|
106
|
+
"file-type": "^21.3.1"
|
|
107
|
+
},
|
|
108
|
+
"@xhmikosr/decompress-tar": {
|
|
109
|
+
"file-type": "^21.3.1"
|
|
110
|
+
},
|
|
111
|
+
"@felipecrs/decompress-tarxz": {
|
|
112
|
+
"file-type": "^21.3.1"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
100
115
|
keywords: [
|
|
101
116
|
"svelte",
|
|
102
117
|
"sveltekit",
|
|
@@ -288,8 +303,20 @@ function mergePackageJson(user, template) {
|
|
|
288
303
|
}
|
|
289
304
|
return { merged, added, conflicts, replaced };
|
|
290
305
|
}
|
|
291
|
-
function
|
|
292
|
-
|
|
306
|
+
function dropTemplateAdapters(user, template) {
|
|
307
|
+
const isAdapter = (name) => name.startsWith("@sveltejs/adapter-");
|
|
308
|
+
const userHasOne = DEP_KINDS.some((kind) => Object.keys(user[kind] ?? {}).some(isAdapter));
|
|
309
|
+
if (!userHasOne) return template;
|
|
310
|
+
const copy = { ...template };
|
|
311
|
+
for (const kind of DEP_KINDS) {
|
|
312
|
+
const deps = template[kind];
|
|
313
|
+
if (!deps) continue;
|
|
314
|
+
copy[kind] = Object.fromEntries(Object.entries(deps).filter(([name]) => !isAdapter(name)));
|
|
315
|
+
}
|
|
316
|
+
return copy;
|
|
317
|
+
}
|
|
318
|
+
function readPackageJson(path47) {
|
|
319
|
+
return JSON.parse(fs.readFileSync(path47, "utf8"));
|
|
293
320
|
}
|
|
294
321
|
var PACKAGE_NAME_PLACEHOLDER = /~TODO~/g;
|
|
295
322
|
var APP_NAME_PLACEHOLDER = /~APP_NAME~/g;
|
|
@@ -302,12 +329,12 @@ function fillTemplatePlaceholders(raw, values) {
|
|
|
302
329
|
function escapeSingleQuoted(value) {
|
|
303
330
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
304
331
|
}
|
|
305
|
-
function readTemplatePackageJson(
|
|
306
|
-
const raw = fillTemplatePlaceholders(fs.readFileSync(
|
|
332
|
+
function readTemplatePackageJson(path47, values) {
|
|
333
|
+
const raw = fillTemplatePlaceholders(fs.readFileSync(path47, "utf8"), values);
|
|
307
334
|
return JSON.parse(raw);
|
|
308
335
|
}
|
|
309
|
-
function writePackageJson(
|
|
310
|
-
fs.writeFileSync(
|
|
336
|
+
function writePackageJson(path47, pkg) {
|
|
337
|
+
fs.writeFileSync(path47, JSON.stringify(pkg, null, " ") + "\n");
|
|
311
338
|
}
|
|
312
339
|
function toValidPackageName(name) {
|
|
313
340
|
return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9~.-]+/g, "-");
|
|
@@ -863,7 +890,7 @@ async function packageManagerPrompt(cwd) {
|
|
|
863
890
|
}
|
|
864
891
|
return pm;
|
|
865
892
|
}
|
|
866
|
-
async function installDependencies(agent, cwd) {
|
|
893
|
+
async function installDependencies(agent, cwd, { exitOnFailure = true } = {}) {
|
|
867
894
|
const task = p2.taskLog({
|
|
868
895
|
title: `Installing dependencies with ${agent}...`,
|
|
869
896
|
limit: Math.ceil(process5.stdout.rows / 2),
|
|
@@ -880,14 +907,16 @@ async function installDependencies(agent, cwd) {
|
|
|
880
907
|
proc.process?.stderr?.on("data", (data) => task.message(data.toString(), { raw: true }));
|
|
881
908
|
await proc;
|
|
882
909
|
task.success("Successfully installed dependencies");
|
|
910
|
+
return true;
|
|
883
911
|
} catch {
|
|
884
912
|
task.error("Failed to install dependencies");
|
|
913
|
+
if (!exitOnFailure) return false;
|
|
885
914
|
p2.cancel("Operation failed.");
|
|
886
915
|
process5.exit(2);
|
|
887
916
|
}
|
|
888
917
|
}
|
|
889
|
-
function addPnpmBuildDependencies(cwd,
|
|
890
|
-
if (!
|
|
918
|
+
function addPnpmBuildDependencies(cwd, packageManager2, allowedPackages) {
|
|
919
|
+
if (!packageManager2 || packageManager2 !== "pnpm") return;
|
|
891
920
|
const pkgPath = path6.join(cwd, "package.json");
|
|
892
921
|
if (!fs7.existsSync(pkgPath)) return;
|
|
893
922
|
const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
|
|
@@ -1024,11 +1053,11 @@ function getPocketbaseMetadata(cwd) {
|
|
|
1024
1053
|
return null;
|
|
1025
1054
|
}
|
|
1026
1055
|
async function execPackageBin(cwd, args, stdio = "pipe") {
|
|
1027
|
-
const
|
|
1028
|
-
const resolved = resolveCommand(
|
|
1029
|
-
if (!resolved) throw new Error(`Could not resolve command for ${
|
|
1056
|
+
const packageManager2 = (await detect2({ cwd }))?.name ?? "npm";
|
|
1057
|
+
const resolved = resolveCommand(packageManager2, "execute", args);
|
|
1058
|
+
if (!resolved) throw new Error(`Could not resolve command for ${packageManager2}`);
|
|
1030
1059
|
const { command, args: resolvedArgs } = resolved;
|
|
1031
|
-
if (
|
|
1060
|
+
if (packageManager2 === "npm") resolvedArgs.unshift("--yes");
|
|
1032
1061
|
return x(command, resolvedArgs, { nodeOptions: { cwd, stdio }, throwOnError: true });
|
|
1033
1062
|
}
|
|
1034
1063
|
async function withPocketbase(cwd, fn, creds) {
|
|
@@ -1476,7 +1505,14 @@ var GITIGNORE_ENTRIES = [
|
|
|
1476
1505
|
"!.env.example",
|
|
1477
1506
|
"!.env.test",
|
|
1478
1507
|
"vite.config.js.timestamp-*",
|
|
1479
|
-
"vite.config.ts.timestamp-*"
|
|
1508
|
+
"vite.config.ts.timestamp-*",
|
|
1509
|
+
// The local database, minus the parts that are source. Same block as the
|
|
1510
|
+
// template's _gitignore; without it a blessed project commits its SQLite.
|
|
1511
|
+
"/data/*",
|
|
1512
|
+
"!/data/fixtures",
|
|
1513
|
+
"!/data/seeds",
|
|
1514
|
+
"!/data/hooks",
|
|
1515
|
+
"/backups"
|
|
1480
1516
|
];
|
|
1481
1517
|
function mergeGitignore(filePath) {
|
|
1482
1518
|
const existing = fs13.existsSync(filePath) ? fs13.readFileSync(filePath, "utf8") : "";
|
|
@@ -1644,13 +1680,13 @@ async function blessProject(cwdArg, options) {
|
|
|
1644
1680
|
mergeAppDts(templateDir, projectPath);
|
|
1645
1681
|
maybeReplaceRoutes(projectPath, templateDir, options);
|
|
1646
1682
|
p4.log.success("Vela files in place");
|
|
1647
|
-
let
|
|
1683
|
+
let packageManager2;
|
|
1648
1684
|
if (options.install !== false) {
|
|
1649
1685
|
const pm = typeof options.install === "string" ? options.install : await packageManagerPrompt(projectPath);
|
|
1650
1686
|
if (pm) {
|
|
1651
1687
|
addPnpmBuildDependencies(projectPath, pm, ["esbuild", "pocketbase-server"]);
|
|
1652
1688
|
await installDependencies(pm, projectPath);
|
|
1653
|
-
|
|
1689
|
+
packageManager2 = pm;
|
|
1654
1690
|
}
|
|
1655
1691
|
}
|
|
1656
1692
|
p4.log.step("Initializing PocketBase...");
|
|
@@ -1664,7 +1700,7 @@ async function blessProject(cwdArg, options) {
|
|
|
1664
1700
|
["PocketBase superuser credentials \u2014 used by `vela` commands"]
|
|
1665
1701
|
);
|
|
1666
1702
|
p4.log.success("PocketBase initialized");
|
|
1667
|
-
printNextSteps(projectPath,
|
|
1703
|
+
printNextSteps(projectPath, packageManager2);
|
|
1668
1704
|
}
|
|
1669
1705
|
function ensureShadcnCss(projectPath) {
|
|
1670
1706
|
if (ensureShadcnImport(path13.join(projectPath, "src", "app.css"))) {
|
|
@@ -1710,7 +1746,10 @@ function mergeDependencies(projectPath, templateDir) {
|
|
|
1710
1746
|
appName,
|
|
1711
1747
|
cliVersion: package_default.version
|
|
1712
1748
|
});
|
|
1713
|
-
const { merged, added, conflicts, replaced } = mergePackageJson(
|
|
1749
|
+
const { merged, added, conflicts, replaced } = mergePackageJson(
|
|
1750
|
+
userPkg,
|
|
1751
|
+
dropTemplateAdapters(userPkg, templatePkg)
|
|
1752
|
+
);
|
|
1714
1753
|
writePackageJson(userPkgPath, merged);
|
|
1715
1754
|
if (added.length > 0) {
|
|
1716
1755
|
p4.log.info(
|
|
@@ -1848,9 +1887,9 @@ function summarize(names) {
|
|
|
1848
1887
|
if (names.length <= 4) return names.join(", ");
|
|
1849
1888
|
return `${names.slice(0, 3).join(", ")}, and ${names.length - 3} more`;
|
|
1850
1889
|
}
|
|
1851
|
-
function printNextSteps(projectPath,
|
|
1890
|
+
function printNextSteps(projectPath, packageManager2) {
|
|
1852
1891
|
const relative = path13.relative(process7.cwd(), projectPath);
|
|
1853
|
-
const pm =
|
|
1892
|
+
const pm = packageManager2 ?? getUserAgent() ?? "npm";
|
|
1854
1893
|
const nextSteps = [];
|
|
1855
1894
|
if (relative !== "") {
|
|
1856
1895
|
const hasSpaces = relative.includes(" ");
|
|
@@ -1898,19 +1937,19 @@ var create = new Command3("create").description("scaffold a new velastack projec
|
|
|
1898
1937
|
return runCommand(async () => {
|
|
1899
1938
|
const listing = await listAllTemplates();
|
|
1900
1939
|
const options = parseOptions(optionsSchema2(listing), rawOpts);
|
|
1901
|
-
const { directory, packageManager, name, template } = await createProject(
|
|
1940
|
+
const { directory, packageManager: packageManager2, name, template } = await createProject(
|
|
1902
1941
|
projectPath,
|
|
1903
1942
|
options,
|
|
1904
1943
|
listing
|
|
1905
1944
|
);
|
|
1906
1945
|
const relative = path14.relative(process8.cwd(), directory);
|
|
1907
|
-
const pm =
|
|
1946
|
+
const pm = packageManager2 ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
|
|
1908
1947
|
const nextSteps = [];
|
|
1909
1948
|
if (relative !== "") {
|
|
1910
1949
|
const hasSpaces = relative.includes(" ");
|
|
1911
1950
|
nextSteps.push(`\`cd ${hasSpaces ? `"${relative}"` : relative}\``);
|
|
1912
1951
|
}
|
|
1913
|
-
if (!
|
|
1952
|
+
if (!packageManager2) {
|
|
1914
1953
|
const resolved = resolveCommand3(pm, "install", []);
|
|
1915
1954
|
if (resolved) {
|
|
1916
1955
|
nextSteps.push(
|
|
@@ -1999,14 +2038,14 @@ async function createProject(cwdArg, options, listing) {
|
|
|
1999
2038
|
throw new Error(`Template ${template.name} is missing package.template.json`);
|
|
2000
2039
|
}
|
|
2001
2040
|
p5.log.success("Project created");
|
|
2002
|
-
let
|
|
2041
|
+
let packageManager2;
|
|
2003
2042
|
if (options.install !== false) {
|
|
2004
2043
|
const pm = typeof options.install === "string" ? options.install : await packageManagerPrompt(projectPath);
|
|
2005
2044
|
if (pm) {
|
|
2006
2045
|
const builds = template.backend ? ["esbuild", "pocketbase-server"] : ["esbuild"];
|
|
2007
2046
|
addPnpmBuildDependencies(projectPath, pm, builds);
|
|
2008
2047
|
await installDependencies(pm, projectPath);
|
|
2009
|
-
|
|
2048
|
+
packageManager2 = pm;
|
|
2010
2049
|
}
|
|
2011
2050
|
}
|
|
2012
2051
|
if (credentials) {
|
|
@@ -2032,7 +2071,7 @@ async function createProject(cwdArg, options, listing) {
|
|
|
2032
2071
|
);
|
|
2033
2072
|
p5.log.success("PocketBase initialized");
|
|
2034
2073
|
}
|
|
2035
|
-
return { directory: projectPath, packageManager, name, template };
|
|
2074
|
+
return { directory: projectPath, packageManager: packageManager2, name, template };
|
|
2036
2075
|
}
|
|
2037
2076
|
function promptCredentials(options, onCancel2) {
|
|
2038
2077
|
return p5.group(
|
|
@@ -2996,13 +3035,13 @@ var notifications = new Command18("notifications").description("enable in-app no
|
|
|
2996
3035
|
);
|
|
2997
3036
|
|
|
2998
3037
|
// src/commands/enable/s3.ts
|
|
2999
|
-
import
|
|
3038
|
+
import process13 from "node:process";
|
|
3000
3039
|
import { Command as Command19 } from "commander";
|
|
3001
3040
|
import * as p17 from "@clack/prompts";
|
|
3002
3041
|
import pc8 from "picocolors";
|
|
3003
3042
|
|
|
3004
3043
|
// src/lib/server-command.ts
|
|
3005
|
-
import
|
|
3044
|
+
import process12 from "node:process";
|
|
3006
3045
|
import * as v6 from "valibot";
|
|
3007
3046
|
import * as p15 from "@clack/prompts";
|
|
3008
3047
|
import pc5 from "picocolors";
|
|
@@ -3133,6 +3172,7 @@ function writeBinding(workspaceRootDir, envTag, binding) {
|
|
|
3133
3172
|
}
|
|
3134
3173
|
|
|
3135
3174
|
// src/lib/instance.ts
|
|
3175
|
+
import crypto2 from "node:crypto";
|
|
3136
3176
|
var PROD_ENV = "prod";
|
|
3137
3177
|
var MAX_SEGMENT = 48;
|
|
3138
3178
|
function normalizeEnvTag(tag) {
|
|
@@ -3145,9 +3185,14 @@ function normalizeEnvTag(tag) {
|
|
|
3145
3185
|
}
|
|
3146
3186
|
return normalized === "production" ? PROD_ENV : normalized;
|
|
3147
3187
|
}
|
|
3188
|
+
var SLUG_HASH = 6;
|
|
3148
3189
|
function branchToEnvTag(branch) {
|
|
3149
|
-
const
|
|
3150
|
-
|
|
3190
|
+
const lower = branch.toLowerCase();
|
|
3191
|
+
const slug2 = lower.replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
3192
|
+
if (slug2 === branch && slug2.length <= MAX_SEGMENT) return `preview--${slug2}`;
|
|
3193
|
+
const hash = crypto2.createHash("sha256").update(branch).digest("hex").slice(0, SLUG_HASH);
|
|
3194
|
+
const head = slug2.slice(0, MAX_SEGMENT - SLUG_HASH - 1).replace(/-+$/, "");
|
|
3195
|
+
return `preview--${head}-${hash}`;
|
|
3151
3196
|
}
|
|
3152
3197
|
function instanceId(appId, envTag = PROD_ENV) {
|
|
3153
3198
|
const env2 = normalizeEnvTag(envTag);
|
|
@@ -3156,8 +3201,12 @@ function instanceId(appId, envTag = PROD_ENV) {
|
|
|
3156
3201
|
function isProd(envTag) {
|
|
3157
3202
|
return normalizeEnvTag(envTag) === PROD_ENV;
|
|
3158
3203
|
}
|
|
3159
|
-
function releaseId(date = /* @__PURE__ */ new Date()) {
|
|
3160
|
-
|
|
3204
|
+
function releaseId(date = /* @__PURE__ */ new Date(), suffix = randomSuffix()) {
|
|
3205
|
+
const stamp = date.toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z");
|
|
3206
|
+
return `${stamp}-${suffix}`;
|
|
3207
|
+
}
|
|
3208
|
+
function randomSuffix() {
|
|
3209
|
+
return crypto2.randomBytes(2).toString("hex");
|
|
3161
3210
|
}
|
|
3162
3211
|
|
|
3163
3212
|
// src/lib/artifact.ts
|
|
@@ -3170,7 +3219,7 @@ import { resolveCommand as resolveCommand4 } from "package-manager-detector/comm
|
|
|
3170
3219
|
import fs20 from "node:fs";
|
|
3171
3220
|
import os3 from "node:os";
|
|
3172
3221
|
import path19 from "node:path";
|
|
3173
|
-
import
|
|
3222
|
+
import crypto3 from "node:crypto";
|
|
3174
3223
|
import process10 from "node:process";
|
|
3175
3224
|
import { spawn as spawn2 } from "node:child_process";
|
|
3176
3225
|
var RemoteCommandError = class extends Error {
|
|
@@ -3214,7 +3263,7 @@ var SshSession = class {
|
|
|
3214
3263
|
if (this.controlPath) return;
|
|
3215
3264
|
const dir = path19.join(os3.tmpdir(), "vela-ssh");
|
|
3216
3265
|
fs20.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
3217
|
-
const socket = path19.join(dir, `${
|
|
3266
|
+
const socket = path19.join(dir, `${crypto3.randomBytes(6).toString("hex")}.sock`);
|
|
3218
3267
|
this.controlPath = socket;
|
|
3219
3268
|
const args = [
|
|
3220
3269
|
...this.sshArgs(),
|
|
@@ -3510,10 +3559,11 @@ function collectArtifact(cwd, config = {}) {
|
|
|
3510
3559
|
const buildPath = path20.join(cwd, outputDir);
|
|
3511
3560
|
if (!fs21.existsSync(path20.join(buildPath, "index.js"))) {
|
|
3512
3561
|
throw new BuildError(
|
|
3513
|
-
`No ${outputDir}/index.js
|
|
3562
|
+
`No ${outputDir}/index.js to deploy.
|
|
3514
3563
|
|
|
3515
|
-
Deploying to a server needs @sveltejs/adapter-node.
|
|
3516
|
-
|
|
3564
|
+
Deploying to a server needs the output of @sveltejs/adapter-node. Check that the
|
|
3565
|
+
build ran with it as the adapter (and that \`outputDir\` in velastack.config
|
|
3566
|
+
matches where it writes), then deploy again.`
|
|
3517
3567
|
);
|
|
3518
3568
|
}
|
|
3519
3569
|
entries.push({ localPath: buildPath, remoteDir: "" });
|
|
@@ -3562,24 +3612,79 @@ function sshOptionsFrom(options) {
|
|
|
3562
3612
|
}
|
|
3563
3613
|
|
|
3564
3614
|
// src/lib/remote.ts
|
|
3615
|
+
import crypto4 from "node:crypto";
|
|
3616
|
+
import fs22 from "node:fs";
|
|
3565
3617
|
import path21 from "node:path";
|
|
3618
|
+
import process11 from "node:process";
|
|
3566
3619
|
var VELA_ROOT = "/var/lib/vela";
|
|
3567
3620
|
var VELA_ETC = "/etc/vela";
|
|
3568
3621
|
var VELA_USER = "vela";
|
|
3569
|
-
var
|
|
3622
|
+
var SCRIPT_VERSIONS_DIR = `${VELA_ROOT}/script-versions`;
|
|
3570
3623
|
var PROVISIONED_MARKER = `${VELA_ETC}/provisioned`;
|
|
3571
3624
|
var ORIGIN_FILE = `${VELA_ETC}/origin.json`;
|
|
3625
|
+
function instanceHasBackend(state) {
|
|
3626
|
+
if (!state) return false;
|
|
3627
|
+
return state.backend ?? Boolean(state.pbPort);
|
|
3628
|
+
}
|
|
3572
3629
|
function serverTemplatesDir() {
|
|
3573
3630
|
return path21.join(templatesDir(), "server");
|
|
3574
3631
|
}
|
|
3632
|
+
var DIGEST_LENGTH = 12;
|
|
3633
|
+
function serverScriptsDigest(dir = serverTemplatesDir()) {
|
|
3634
|
+
const hash = crypto4.createHash("sha256");
|
|
3635
|
+
for (const file of listFiles(dir).sort()) {
|
|
3636
|
+
hash.update(file).update("\0").update(fs22.readFileSync(path21.join(dir, file))).update("\0");
|
|
3637
|
+
}
|
|
3638
|
+
return hash.digest("hex").slice(0, DIGEST_LENGTH);
|
|
3639
|
+
}
|
|
3640
|
+
function listFiles(root, prefix = "") {
|
|
3641
|
+
const files = [];
|
|
3642
|
+
for (const entry of fs22.readdirSync(path21.join(root, prefix), { withFileTypes: true })) {
|
|
3643
|
+
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
3644
|
+
if (entry.isDirectory()) files.push(...listFiles(root, rel));
|
|
3645
|
+
else if (entry.isFile()) files.push(rel);
|
|
3646
|
+
}
|
|
3647
|
+
return files;
|
|
3648
|
+
}
|
|
3649
|
+
var scriptDirs = /* @__PURE__ */ new WeakMap();
|
|
3575
3650
|
async function syncServerScripts(session) {
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
await session.script(`
|
|
3651
|
+
const digest = serverScriptsDigest();
|
|
3652
|
+
const dir = `${SCRIPT_VERSIONS_DIR}/${digest}`;
|
|
3653
|
+
const present = await session.script(`[ -d "$1" ] && echo yes || echo no`, { args: [dir] });
|
|
3654
|
+
if (present.stdout.trim() !== "yes") {
|
|
3655
|
+
const incoming = `${SCRIPT_VERSIONS_DIR}/.incoming.${digest}.${process11.pid}.${Date.now()}`;
|
|
3656
|
+
await session.script(`mkdir -p "$1" && chmod 0755 "$(dirname "$1")" "$1"`, {
|
|
3657
|
+
args: [incoming]
|
|
3658
|
+
});
|
|
3659
|
+
await session.uploadDir(serverTemplatesDir(), incoming, ["--chmod=D755,F755"]);
|
|
3660
|
+
await session.script(
|
|
3661
|
+
`chown -R root:root "$1"
|
|
3662
|
+
if [ -d "$2" ]; then rm -rf "$1"; else mv -T "$1" "$2" || { rm -rf "$1"; [ -d "$2" ]; }; fi`,
|
|
3663
|
+
{ args: [incoming, dir] }
|
|
3664
|
+
);
|
|
3665
|
+
}
|
|
3666
|
+
await session.script(
|
|
3667
|
+
`touch "$1"
|
|
3668
|
+
ln -sfn "$1" "$2/.current.tmp" && mv -Tf "$2/.current.tmp" "$2/current"
|
|
3669
|
+
find "$2" -mindepth 1 -maxdepth 1 -type d -name '[0-9a-f]*' ! -name "$(basename "$1")" -mtime +30 -exec rm -rf {} + 2>/dev/null || true
|
|
3670
|
+
find "$2" -mindepth 1 -maxdepth 1 -type d -name '.incoming.*' -mmin +120 -exec rm -rf {} + 2>/dev/null || true`,
|
|
3671
|
+
{ args: [dir, SCRIPT_VERSIONS_DIR] }
|
|
3672
|
+
);
|
|
3673
|
+
scriptDirs.set(session, dir);
|
|
3674
|
+
return dir;
|
|
3675
|
+
}
|
|
3676
|
+
async function serverTime(session) {
|
|
3677
|
+
const result = await session.script(`date -u +%s`);
|
|
3678
|
+
const seconds = Number(result.stdout.trim());
|
|
3679
|
+
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
3680
|
+
throw new Error(`could not read the clock on ${session.target}`);
|
|
3681
|
+
}
|
|
3682
|
+
return new Date(seconds * 1e3);
|
|
3579
3683
|
}
|
|
3580
3684
|
async function runServerScript(session, name, opts = {}) {
|
|
3685
|
+
const dir = scriptDirs.get(session) ?? `${SCRIPT_VERSIONS_DIR}/current`;
|
|
3581
3686
|
const result = await session.script(`script="$1"; shift; exec "$script" "$@"`, {
|
|
3582
|
-
args: [`${
|
|
3687
|
+
args: [`${dir}/${name}`, ...opts.args ?? []],
|
|
3583
3688
|
stream: opts.stream
|
|
3584
3689
|
});
|
|
3585
3690
|
return parseResult(result);
|
|
@@ -3653,7 +3758,7 @@ var remotePaths = {
|
|
|
3653
3758
|
};
|
|
3654
3759
|
|
|
3655
3760
|
// src/lib/remote-env.ts
|
|
3656
|
-
import
|
|
3761
|
+
import fs23 from "node:fs";
|
|
3657
3762
|
import dotenv from "dotenv";
|
|
3658
3763
|
var KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
3659
3764
|
function isValidKey(key) {
|
|
@@ -3701,7 +3806,7 @@ function quote(value) {
|
|
|
3701
3806
|
return `"${escaped}"`;
|
|
3702
3807
|
}
|
|
3703
3808
|
function readLocalEnvFile(file) {
|
|
3704
|
-
const parsed = dotenv.parse(
|
|
3809
|
+
const parsed = dotenv.parse(fs23.readFileSync(file));
|
|
3705
3810
|
const result = {};
|
|
3706
3811
|
for (const [key, value] of Object.entries(parsed)) {
|
|
3707
3812
|
if (isValidKey(key)) result[key] = value;
|
|
@@ -3817,6 +3922,20 @@ var SERVER_OPTIONS_SCHEMA = {
|
|
|
3817
3922
|
server: v6.optional(v6.string())
|
|
3818
3923
|
};
|
|
3819
3924
|
var OptionsSchema = v6.object(SERVER_OPTIONS_SCHEMA);
|
|
3925
|
+
var DEFAULT_LOCK_WAIT = "300";
|
|
3926
|
+
var LOCK_WAIT_SCHEMA = {
|
|
3927
|
+
lockWait: v6.optional(v6.pipe(v6.string(), v6.regex(/^\d+$/, "must be a whole number of seconds")))
|
|
3928
|
+
};
|
|
3929
|
+
function addLockWaitOption(command) {
|
|
3930
|
+
return command.option(
|
|
3931
|
+
"--lock-wait <seconds>",
|
|
3932
|
+
"how long to wait for another operation on this target to finish before giving up",
|
|
3933
|
+
DEFAULT_LOCK_WAIT
|
|
3934
|
+
);
|
|
3935
|
+
}
|
|
3936
|
+
function lockWaitArgs(lockWait) {
|
|
3937
|
+
return ["--lock-wait", lockWait ?? DEFAULT_LOCK_WAIT];
|
|
3938
|
+
}
|
|
3820
3939
|
function addTargetOptions(command, fallback) {
|
|
3821
3940
|
return addSshOptions(command).option("-t, --target <target>", "which copy of the app to act on", fallback).option("--server <ssh>", "server this target runs on \u2014 recorded on first use");
|
|
3822
3941
|
}
|
|
@@ -3883,6 +4002,7 @@ async function ensureBinding(workspaceRootDir, target, request = {}) {
|
|
|
3883
4002
|
const key = bindingKey(target);
|
|
3884
4003
|
const existing = readBinding(workspaceRootDir, key);
|
|
3885
4004
|
const moving = Boolean(request.server && existing && existing.server !== request.server);
|
|
4005
|
+
if (moving) await confirmMove(target, existing.server, request.server);
|
|
3886
4006
|
let server = request.server ?? existing?.server;
|
|
3887
4007
|
if (!server) {
|
|
3888
4008
|
server = await promptServer(target);
|
|
@@ -3905,12 +4025,31 @@ longer reach it. Remove it there first if that was not intended.`
|
|
|
3905
4025
|
}
|
|
3906
4026
|
return binding;
|
|
3907
4027
|
}
|
|
4028
|
+
async function confirmMove(target, from, to) {
|
|
4029
|
+
const name = bindingName(target);
|
|
4030
|
+
if (!process12.stdout.isTTY || process12.env.CI) {
|
|
4031
|
+
throw new Error(
|
|
4032
|
+
`${pc5.cyan(`--server ${to}`)} does not match the server recorded for ${pc5.cyan(name)}, ${pc5.cyan(from)}.
|
|
4033
|
+
|
|
4034
|
+
Drop ${pc5.cyan("--server")} to use the recorded one, or move the binding on purpose by running
|
|
4035
|
+
this command once from a terminal (or editing .vela/project.json).`
|
|
4036
|
+
);
|
|
4037
|
+
}
|
|
4038
|
+
const ok = await p15.confirm({
|
|
4039
|
+
message: `${name} ${target.kind === "preview" ? "run" : "runs"} on ${from}. Point ${name} at ${to} instead?`,
|
|
4040
|
+
initialValue: false
|
|
4041
|
+
});
|
|
4042
|
+
if (p15.isCancel(ok) || !ok) {
|
|
4043
|
+
p15.cancel("Operation cancelled.");
|
|
4044
|
+
process12.exit(0);
|
|
4045
|
+
}
|
|
4046
|
+
}
|
|
3908
4047
|
function bindingName(target) {
|
|
3909
4048
|
return target.kind === "preview" ? "previews" : target.name;
|
|
3910
4049
|
}
|
|
3911
4050
|
async function promptServer(target) {
|
|
3912
4051
|
const name = bindingName(target);
|
|
3913
|
-
if (!
|
|
4052
|
+
if (!process12.stdout.isTTY || process12.env.CI) {
|
|
3914
4053
|
throw new Error(
|
|
3915
4054
|
`${name} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet, and there is no terminal to ask on.
|
|
3916
4055
|
|
|
@@ -3928,19 +4067,19 @@ and commit ${pc5.cyan(".vela/project.json")}.`
|
|
|
3928
4067
|
});
|
|
3929
4068
|
if (p15.isCancel(value)) {
|
|
3930
4069
|
p15.cancel("Operation cancelled.");
|
|
3931
|
-
|
|
4070
|
+
process12.exit(0);
|
|
3932
4071
|
}
|
|
3933
4072
|
return value.trim();
|
|
3934
4073
|
}
|
|
3935
4074
|
async function promptDomain(target) {
|
|
3936
|
-
if (!
|
|
4075
|
+
if (!process12.stdout.isTTY || process12.env.CI) return void 0;
|
|
3937
4076
|
const value = await p15.text({
|
|
3938
4077
|
message: `Which hostname should ${target.name} be served on?`,
|
|
3939
4078
|
placeholder: "example.com \u2014 leave blank to decide later"
|
|
3940
4079
|
});
|
|
3941
4080
|
if (p15.isCancel(value)) {
|
|
3942
4081
|
p15.cancel("Operation cancelled.");
|
|
3943
|
-
|
|
4082
|
+
process12.exit(0);
|
|
3944
4083
|
}
|
|
3945
4084
|
return value.trim() || void 0;
|
|
3946
4085
|
}
|
|
@@ -3996,17 +4135,17 @@ function envFilePath(workspaceRootDir) {
|
|
|
3996
4135
|
import pc7 from "picocolors";
|
|
3997
4136
|
|
|
3998
4137
|
// src/lib/local-env.ts
|
|
3999
|
-
import
|
|
4138
|
+
import fs24 from "node:fs";
|
|
4000
4139
|
import * as p16 from "@clack/prompts";
|
|
4001
4140
|
import pc6 from "picocolors";
|
|
4002
4141
|
function readLocalEnv(envFile) {
|
|
4003
|
-
if (!
|
|
4142
|
+
if (!fs24.existsSync(envFile)) return {};
|
|
4004
4143
|
return readLocalEnvFile(envFile);
|
|
4005
4144
|
}
|
|
4006
4145
|
function editLocalEnv(envFile, edit) {
|
|
4007
|
-
const before =
|
|
4146
|
+
const before = fs24.existsSync(envFile) ? fs24.readFileSync(envFile, "utf8") : "";
|
|
4008
4147
|
const after = edit(before);
|
|
4009
|
-
if (after !== before)
|
|
4148
|
+
if (after !== before) fs24.writeFileSync(envFile, after);
|
|
4010
4149
|
}
|
|
4011
4150
|
function setLocalEnv(envFile, key, value) {
|
|
4012
4151
|
editLocalEnv(envFile, (content) => upsertEnvVar(content, key, value));
|
|
@@ -4040,12 +4179,13 @@ Set both ${pc6.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc6.cyan("POCKETBASE_SU
|
|
|
4040
4179
|
import PocketBase2 from "pocketbase";
|
|
4041
4180
|
async function openRemoteDatabase(session, instance) {
|
|
4042
4181
|
const [state] = await readInstanceStates(session, instance);
|
|
4043
|
-
const pbPort = state?.pbPort;
|
|
4182
|
+
const pbPort = instanceHasBackend(state) ? state?.pbPort : void 0;
|
|
4044
4183
|
if (!pbPort) {
|
|
4045
4184
|
throw new Error(
|
|
4046
4185
|
`${instance} has no deployed database yet.
|
|
4047
4186
|
|
|
4048
|
-
Run \`vela deploy\` first \u2014 the database is created by the first deploy
|
|
4187
|
+
Run \`vela deploy\` first \u2014 the database is created by the first deploy of a
|
|
4188
|
+
project with a backend (\`vela bless\` adds one).`
|
|
4049
4189
|
);
|
|
4050
4190
|
}
|
|
4051
4191
|
const env2 = await readRemoteEnv(session, instance);
|
|
@@ -4138,7 +4278,7 @@ Set ${pc7.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc7.cyan("POCKETBASE_SUPERUS
|
|
|
4138
4278
|
}
|
|
4139
4279
|
|
|
4140
4280
|
// src/lib/s3-settings.ts
|
|
4141
|
-
import
|
|
4281
|
+
import fs25 from "node:fs";
|
|
4142
4282
|
import path22 from "node:path";
|
|
4143
4283
|
var VIRTUAL_HOSTED = [/\.amazonaws\.com$/i, /\.r2\.cloudflarestorage\.com$/i];
|
|
4144
4284
|
function defaultForcePathStyle(endpoint) {
|
|
@@ -4182,7 +4322,7 @@ async function hasLocalUploads(session, instance, workspaceRootDir) {
|
|
|
4182
4322
|
function hasFile(dir) {
|
|
4183
4323
|
let entries;
|
|
4184
4324
|
try {
|
|
4185
|
-
entries =
|
|
4325
|
+
entries = fs25.readdirSync(dir, { withFileTypes: true });
|
|
4186
4326
|
} catch {
|
|
4187
4327
|
return false;
|
|
4188
4328
|
}
|
|
@@ -4261,8 +4401,8 @@ async function promptConfig(options, existing) {
|
|
|
4261
4401
|
const bucket = options.bucket ?? await text7("S3 bucket name", existing.bucket);
|
|
4262
4402
|
const region = options.region ?? await text7("S3 region", existing.region || "us-east-1");
|
|
4263
4403
|
const accessKey = options.accessKey ?? await text7("S3 access key", existing.accessKey);
|
|
4264
|
-
const secret = options.secret ??
|
|
4265
|
-
const forcePathStyle = options.forcePathStyle ?? await
|
|
4404
|
+
const secret = options.secret ?? process13.env.VELA_S3_SECRET ?? await password5("S3 secret key");
|
|
4405
|
+
const forcePathStyle = options.forcePathStyle ?? await confirm4(
|
|
4266
4406
|
"Address the bucket in the path? (MinIO, Ceph and most self-hosted gateways need this)",
|
|
4267
4407
|
defaultForcePathStyle(endpoint)
|
|
4268
4408
|
);
|
|
@@ -4276,7 +4416,7 @@ async function text7(message, initialValue = "") {
|
|
|
4276
4416
|
});
|
|
4277
4417
|
if (p17.isCancel(value)) {
|
|
4278
4418
|
p17.cancel("Operation cancelled.");
|
|
4279
|
-
|
|
4419
|
+
process13.exit(0);
|
|
4280
4420
|
}
|
|
4281
4421
|
return value.trim();
|
|
4282
4422
|
}
|
|
@@ -4287,21 +4427,21 @@ async function password5(message) {
|
|
|
4287
4427
|
});
|
|
4288
4428
|
if (p17.isCancel(value)) {
|
|
4289
4429
|
p17.cancel("Operation cancelled.");
|
|
4290
|
-
|
|
4430
|
+
process13.exit(0);
|
|
4291
4431
|
}
|
|
4292
4432
|
return value;
|
|
4293
4433
|
}
|
|
4294
|
-
async function
|
|
4434
|
+
async function confirm4(message, initialValue) {
|
|
4295
4435
|
const value = await p17.confirm({ message, initialValue });
|
|
4296
4436
|
if (p17.isCancel(value)) {
|
|
4297
4437
|
p17.cancel("Operation cancelled.");
|
|
4298
|
-
|
|
4438
|
+
process13.exit(0);
|
|
4299
4439
|
}
|
|
4300
4440
|
return value;
|
|
4301
4441
|
}
|
|
4302
4442
|
|
|
4303
4443
|
// src/commands/enable/smtp.ts
|
|
4304
|
-
import
|
|
4444
|
+
import process14 from "node:process";
|
|
4305
4445
|
import { Command as Command20 } from "commander";
|
|
4306
4446
|
import * as p18 from "@clack/prompts";
|
|
4307
4447
|
var smtp = new Command20("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
|
|
@@ -4330,7 +4470,7 @@ var smtp = new Command20("smtp").description("configure SMTP for transactional e
|
|
|
4330
4470
|
{
|
|
4331
4471
|
onCancel: () => {
|
|
4332
4472
|
p18.cancel("Operation cancelled.");
|
|
4333
|
-
|
|
4473
|
+
process14.exit(0);
|
|
4334
4474
|
}
|
|
4335
4475
|
}
|
|
4336
4476
|
);
|
|
@@ -4357,7 +4497,7 @@ var smtp = new Command20("smtp").description("configure SMTP for transactional e
|
|
|
4357
4497
|
);
|
|
4358
4498
|
|
|
4359
4499
|
// src/commands/enable/cms.ts
|
|
4360
|
-
import
|
|
4500
|
+
import process15 from "node:process";
|
|
4361
4501
|
import { Command as Command21 } from "commander";
|
|
4362
4502
|
import * as p19 from "@clack/prompts";
|
|
4363
4503
|
import pc9 from "picocolors";
|
|
@@ -4374,7 +4514,7 @@ Run ${pc9.cyan("vela bless")} to add a backend, or point at a hosted CMS with ${
|
|
|
4374
4514
|
);
|
|
4375
4515
|
p19.log.message();
|
|
4376
4516
|
p19.cancel("Operation failed.");
|
|
4377
|
-
|
|
4517
|
+
process15.exitCode = 1;
|
|
4378
4518
|
return;
|
|
4379
4519
|
}
|
|
4380
4520
|
await runPattern("enable-cms", cmd.args, opts.endpoint ? { endpoint: opts.endpoint } : {}, {
|
|
@@ -4454,7 +4594,7 @@ import { Command as Command35 } from "commander";
|
|
|
4454
4594
|
import { Command as Command25 } from "commander";
|
|
4455
4595
|
|
|
4456
4596
|
// src/commands/disable/_shared.ts
|
|
4457
|
-
import
|
|
4597
|
+
import process16 from "node:process";
|
|
4458
4598
|
import * as p20 from "@clack/prompts";
|
|
4459
4599
|
async function runDisable(opts, flags, cmdArgs) {
|
|
4460
4600
|
if (!flags.yes) {
|
|
@@ -4464,7 +4604,7 @@ async function runDisable(opts, flags, cmdArgs) {
|
|
|
4464
4604
|
});
|
|
4465
4605
|
if (p20.isCancel(ok) || !ok) {
|
|
4466
4606
|
p20.cancel("Operation cancelled.");
|
|
4467
|
-
|
|
4607
|
+
process16.exit(0);
|
|
4468
4608
|
}
|
|
4469
4609
|
}
|
|
4470
4610
|
await runPattern(opts.slug, cmdArgs, { destructive: true }, opts.report);
|
|
@@ -4735,14 +4875,14 @@ import { Command as Command41 } from "commander";
|
|
|
4735
4875
|
import { Command as Command36 } from "commander";
|
|
4736
4876
|
|
|
4737
4877
|
// src/commands/destroy/_shared.ts
|
|
4738
|
-
import
|
|
4878
|
+
import process17 from "node:process";
|
|
4739
4879
|
import * as p22 from "@clack/prompts";
|
|
4740
4880
|
async function runDestroy(slug2, model, confirmMessage, report4, flags) {
|
|
4741
4881
|
if (!flags.yes) {
|
|
4742
4882
|
const ok = await p22.confirm({ message: confirmMessage, initialValue: false });
|
|
4743
4883
|
if (p22.isCancel(ok) || !ok) {
|
|
4744
4884
|
p22.cancel("Operation cancelled.");
|
|
4745
|
-
|
|
4885
|
+
process17.exit(0);
|
|
4746
4886
|
}
|
|
4747
4887
|
}
|
|
4748
4888
|
await runPattern(slug2, [model], { destructive: true, route: flags.route }, report4);
|
|
@@ -4845,11 +4985,55 @@ var scaffold2 = new Command39("scaffold").description("destroy a scaffold genera
|
|
|
4845
4985
|
);
|
|
4846
4986
|
|
|
4847
4987
|
// src/commands/destroy/deployment.ts
|
|
4848
|
-
import
|
|
4988
|
+
import process18 from "node:process";
|
|
4849
4989
|
import { Command as Command40 } from "commander";
|
|
4850
4990
|
import * as p25 from "@clack/prompts";
|
|
4851
4991
|
import pc13 from "picocolors";
|
|
4852
4992
|
|
|
4993
|
+
// src/lib/destroy-guard.ts
|
|
4994
|
+
function isPreview(envTag) {
|
|
4995
|
+
return envTag.startsWith("preview--");
|
|
4996
|
+
}
|
|
4997
|
+
function destroyDecision(request) {
|
|
4998
|
+
const { appName, purge, yes, confirm: confirm14, interactive } = request;
|
|
4999
|
+
const dangerous = isProd(request.envTag) || purge && !isPreview(request.envTag);
|
|
5000
|
+
const what = describe(request);
|
|
5001
|
+
if (confirm14 !== void 0) {
|
|
5002
|
+
if (confirm14 === appName) return { kind: "proceed" };
|
|
5003
|
+
return {
|
|
5004
|
+
kind: "refuse",
|
|
5005
|
+
message: `\`--confirm ${confirm14}\` does not name this app. Removing ${what} takes \`--confirm ${appName}\`.`
|
|
5006
|
+
};
|
|
5007
|
+
}
|
|
5008
|
+
if (dangerous) {
|
|
5009
|
+
if (yes) {
|
|
5010
|
+
return {
|
|
5011
|
+
kind: "refuse",
|
|
5012
|
+
message: `\`--yes\` is not enough to remove ${what}.
|
|
5013
|
+
|
|
5014
|
+
Pass \`--confirm ${appName}\` as well \u2014 the app name, the same thing a terminal would ask you to type.`
|
|
5015
|
+
};
|
|
5016
|
+
}
|
|
5017
|
+
if (interactive) return { kind: "prompt", byName: true };
|
|
5018
|
+
return {
|
|
5019
|
+
kind: "refuse",
|
|
5020
|
+
message: `Removing ${what} needs a confirmation, and there is no terminal to ask on.
|
|
5021
|
+
|
|
5022
|
+
Pass \`--confirm ${appName}\` \u2014 the app name, the same thing a terminal would ask you to type.`
|
|
5023
|
+
};
|
|
5024
|
+
}
|
|
5025
|
+
if (yes) return { kind: "proceed" };
|
|
5026
|
+
if (interactive) return { kind: "prompt", byName: false };
|
|
5027
|
+
return {
|
|
5028
|
+
kind: "refuse",
|
|
5029
|
+
message: `Removing ${what} needs a confirmation, and there is no terminal to ask on. Pass \`--yes\`.`
|
|
5030
|
+
};
|
|
5031
|
+
}
|
|
5032
|
+
function describe({ appName, envTag, purge }) {
|
|
5033
|
+
const target = isProd(envTag) ? "production" : `the ${envTag} environment`;
|
|
5034
|
+
return purge ? `${target} of ${appName} and its database` : `${target} of ${appName}`;
|
|
5035
|
+
}
|
|
5036
|
+
|
|
4853
5037
|
// src/lib/deploy-report.ts
|
|
4854
5038
|
import * as p24 from "@clack/prompts";
|
|
4855
5039
|
import pc12 from "picocolors";
|
|
@@ -5042,26 +5226,52 @@ ${pc12.dim(err instanceof Error ? err.message : String(err))}`
|
|
|
5042
5226
|
}
|
|
5043
5227
|
|
|
5044
5228
|
// src/commands/destroy/deployment.ts
|
|
5045
|
-
var deployment =
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5229
|
+
var deployment = addLockWaitOption(
|
|
5230
|
+
addTargetOptions(
|
|
5231
|
+
new Command40("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
|
|
5232
|
+
"production"
|
|
5233
|
+
)
|
|
5234
|
+
).option("--purge", "also delete the database and uploaded files").option("-y, --yes", "skip the confirmation prompt").option(
|
|
5235
|
+
"--confirm <app-name>",
|
|
5236
|
+
"confirm removing production, or a purge, by typing the app name \u2014 what a terminal would ask for"
|
|
5237
|
+
).action(
|
|
5049
5238
|
(raw) => runCommand(async () => {
|
|
5050
5239
|
const options = raw;
|
|
5051
5240
|
await withTarget(
|
|
5052
5241
|
raw,
|
|
5053
5242
|
{
|
|
5054
5243
|
remote: async (ctx) => {
|
|
5055
|
-
|
|
5056
|
-
|
|
5244
|
+
const decision = destroyDecision({
|
|
5245
|
+
appName: ctx.appName,
|
|
5246
|
+
envTag: ctx.envTag,
|
|
5247
|
+
purge: options.purge === true,
|
|
5248
|
+
yes: options.yes === true,
|
|
5249
|
+
confirm: options.confirm,
|
|
5250
|
+
interactive: Boolean(process18.stdin.isTTY && process18.stdout.isTTY)
|
|
5251
|
+
});
|
|
5252
|
+
if (decision.kind === "refuse") throw new Error(decision.message);
|
|
5253
|
+
if (decision.kind === "prompt") {
|
|
5254
|
+
await confirm8(ctx.appName, ctx.targetName, decision.byName);
|
|
5057
5255
|
}
|
|
5058
5256
|
const result = await runServerScript(ctx.session, "destroy.sh", {
|
|
5059
|
-
args: [
|
|
5257
|
+
args: [
|
|
5258
|
+
ctx.instance,
|
|
5259
|
+
...options.purge ? ["--purge"] : [],
|
|
5260
|
+
...lockWaitArgs(options.lockWait)
|
|
5261
|
+
],
|
|
5060
5262
|
stream: true
|
|
5061
5263
|
});
|
|
5264
|
+
if (result?.existed === false) {
|
|
5265
|
+
p25.log.info(
|
|
5266
|
+
`Nothing named ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} on ${ctx.server}; nothing to remove.`
|
|
5267
|
+
);
|
|
5268
|
+
return;
|
|
5269
|
+
}
|
|
5062
5270
|
await reportEnvironmentDestroyed(ctx.workspaceRootDir, ctx.envTag);
|
|
5063
5271
|
p25.log.success(
|
|
5064
|
-
`Removed ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${ctx.server}.` + (result?.purged ?
|
|
5272
|
+
`Removed ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${ctx.server}.` + (result?.purged ? result.trash ? `
|
|
5273
|
+
|
|
5274
|
+
A snapshot of its data is at ${pc13.cyan(result.trash)} on the server for two weeks.` : "" : `
|
|
5065
5275
|
|
|
5066
5276
|
The database and uploads are still in the instance's shared directory. Pass ${pc13.cyan("--purge")} to delete them.`)
|
|
5067
5277
|
);
|
|
@@ -5074,15 +5284,15 @@ The database and uploads are still in the instance's shared directory. Pass ${pc
|
|
|
5074
5284
|
);
|
|
5075
5285
|
}, "Failed to remove the deployment.")
|
|
5076
5286
|
);
|
|
5077
|
-
async function
|
|
5078
|
-
if (
|
|
5287
|
+
async function confirm8(appName, targetName, byName) {
|
|
5288
|
+
if (byName) {
|
|
5079
5289
|
const answer = await p25.text({
|
|
5080
|
-
message: `This removes ${pc13.cyan(`${appName} (${targetName})`)}
|
|
5290
|
+
message: `This removes ${pc13.cyan(`${appName} (${targetName})`)}. Type the app name to confirm`,
|
|
5081
5291
|
validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
|
|
5082
5292
|
});
|
|
5083
5293
|
if (p25.isCancel(answer)) {
|
|
5084
5294
|
p25.cancel("Operation cancelled.");
|
|
5085
|
-
|
|
5295
|
+
process18.exit(0);
|
|
5086
5296
|
}
|
|
5087
5297
|
return;
|
|
5088
5298
|
}
|
|
@@ -5092,7 +5302,7 @@ async function confirm7(appName, targetName, envTag, purge) {
|
|
|
5092
5302
|
});
|
|
5093
5303
|
if (p25.isCancel(ok) || !ok) {
|
|
5094
5304
|
p25.cancel("Operation cancelled.");
|
|
5095
|
-
|
|
5305
|
+
process18.exit(0);
|
|
5096
5306
|
}
|
|
5097
5307
|
}
|
|
5098
5308
|
|
|
@@ -5376,13 +5586,13 @@ var ui = new Command47("ui").description("generate ui components").configureHelp
|
|
|
5376
5586
|
import { Command as Command50 } from "commander";
|
|
5377
5587
|
|
|
5378
5588
|
// src/commands/legal/terms.ts
|
|
5379
|
-
import
|
|
5589
|
+
import fs26 from "node:fs";
|
|
5380
5590
|
import path23 from "node:path";
|
|
5381
5591
|
import { Command as Command48 } from "commander";
|
|
5382
5592
|
import * as p32 from "@clack/prompts";
|
|
5383
5593
|
|
|
5384
5594
|
// src/commands/legal/shared.ts
|
|
5385
|
-
import
|
|
5595
|
+
import process19 from "node:process";
|
|
5386
5596
|
import * as p31 from "@clack/prompts";
|
|
5387
5597
|
var sharedFields = {
|
|
5388
5598
|
websiteUrl: () => p31.text({
|
|
@@ -5451,7 +5661,7 @@ var sharedFields = {
|
|
|
5451
5661
|
};
|
|
5452
5662
|
var onCancel = () => {
|
|
5453
5663
|
p31.cancel("Operation cancelled.");
|
|
5454
|
-
|
|
5664
|
+
process19.exit(0);
|
|
5455
5665
|
};
|
|
5456
5666
|
async function contactMethods(type) {
|
|
5457
5667
|
const selection = await p31.multiselect({
|
|
@@ -6044,9 +6254,9 @@ async function termsAction() {
|
|
|
6044
6254
|
"+page.svelte"
|
|
6045
6255
|
);
|
|
6046
6256
|
const termsPageTs = path23.join(workspaceRootDir, publicRoutesDir, LEGAL_DIR, "terms", "+page.ts");
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6257
|
+
fs26.mkdirSync(path23.dirname(termsPage), { recursive: true });
|
|
6258
|
+
fs26.writeFileSync(termsPage, html);
|
|
6259
|
+
fs26.writeFileSync(
|
|
6050
6260
|
termsPageTs,
|
|
6051
6261
|
pageMetaTagsLoader("Terms of Service", `Terms of Service for ${core.websiteName}`)
|
|
6052
6262
|
);
|
|
@@ -6065,7 +6275,7 @@ async function termsAction() {
|
|
|
6065
6275
|
var terms = new Command48("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
|
|
6066
6276
|
|
|
6067
6277
|
// src/commands/legal/privacy.ts
|
|
6068
|
-
import
|
|
6278
|
+
import fs27 from "node:fs";
|
|
6069
6279
|
import path24 from "node:path";
|
|
6070
6280
|
import { Command as Command49 } from "commander";
|
|
6071
6281
|
import * as p33 from "@clack/prompts";
|
|
@@ -6793,9 +7003,9 @@ async function privacyAction() {
|
|
|
6793
7003
|
"privacy",
|
|
6794
7004
|
"+page.ts"
|
|
6795
7005
|
);
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
7006
|
+
fs27.mkdirSync(path24.dirname(privacyPage), { recursive: true });
|
|
7007
|
+
fs27.writeFileSync(privacyPage, html);
|
|
7008
|
+
fs27.writeFileSync(
|
|
6799
7009
|
privacyPageTs,
|
|
6800
7010
|
pageMetaTagsLoader("Privacy Policy", `Privacy Policy for ${core.websiteName}`)
|
|
6801
7011
|
);
|
|
@@ -6823,7 +7033,7 @@ import { Command as Command56 } from "commander";
|
|
|
6823
7033
|
import { Command as Command51 } from "commander";
|
|
6824
7034
|
|
|
6825
7035
|
// src/lib/data.ts
|
|
6826
|
-
import
|
|
7036
|
+
import fs28 from "node:fs";
|
|
6827
7037
|
import path25 from "node:path";
|
|
6828
7038
|
import { ClientResponseError } from "pocketbase";
|
|
6829
7039
|
|
|
@@ -6865,8 +7075,8 @@ function dataDir(cwd, kind) {
|
|
|
6865
7075
|
}
|
|
6866
7076
|
function getDataFiles(cwd, kind) {
|
|
6867
7077
|
const dir = dataDir(cwd, kind);
|
|
6868
|
-
if (!
|
|
6869
|
-
return
|
|
7078
|
+
if (!fs28.existsSync(dir)) return [];
|
|
7079
|
+
return fs28.readdirSync(dir).filter((file) => file.endsWith(".json")).sort((a, b) => a.localeCompare(b)).map((file) => ({
|
|
6870
7080
|
collectionName: file.replace(/\.json$/i, "").replace(/^\d+[-_]?/, ""),
|
|
6871
7081
|
filePath: path25.join(dir, file)
|
|
6872
7082
|
}));
|
|
@@ -6878,7 +7088,7 @@ function getFixtureFiles(cwd) {
|
|
|
6878
7088
|
return getDataFiles(cwd, "fixtures");
|
|
6879
7089
|
}
|
|
6880
7090
|
function readRecords(filePath) {
|
|
6881
|
-
return JSON.parse(
|
|
7091
|
+
return JSON.parse(fs28.readFileSync(filePath, "utf8"));
|
|
6882
7092
|
}
|
|
6883
7093
|
function readSeedIds(cwd) {
|
|
6884
7094
|
const ids = /* @__PURE__ */ new Map();
|
|
@@ -7097,7 +7307,7 @@ var reset = new Command53("reset").description("clear and reload fixtures").conf
|
|
|
7097
7307
|
);
|
|
7098
7308
|
|
|
7099
7309
|
// src/commands/fixtures/generate.ts
|
|
7100
|
-
import
|
|
7310
|
+
import fs29 from "node:fs";
|
|
7101
7311
|
import path26 from "node:path";
|
|
7102
7312
|
import { Command as Command54, InvalidArgumentError } from "commander";
|
|
7103
7313
|
import * as p34 from "@clack/prompts";
|
|
@@ -7135,9 +7345,9 @@ async function loadCollections(pb) {
|
|
|
7135
7345
|
}
|
|
7136
7346
|
async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
7137
7347
|
const fixturesDir = dataDir(workspaceRootDir, "fixtures");
|
|
7138
|
-
|
|
7139
|
-
for (const file of
|
|
7140
|
-
if (file.endsWith(".json"))
|
|
7348
|
+
fs29.mkdirSync(fixturesDir, { recursive: true });
|
|
7349
|
+
for (const file of fs29.readdirSync(fixturesDir)) {
|
|
7350
|
+
if (file.endsWith(".json")) fs29.unlinkSync(path26.join(fixturesDir, file));
|
|
7141
7351
|
}
|
|
7142
7352
|
if (opts.seed !== void 0) faker.seed(opts.seed);
|
|
7143
7353
|
const generator = createGenerator({
|
|
@@ -7204,7 +7414,7 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
|
7204
7414
|
items.push(record);
|
|
7205
7415
|
}
|
|
7206
7416
|
const filename = `${padZeros(fileIndex, 2)}-${collection.name}.json`;
|
|
7207
|
-
|
|
7417
|
+
fs29.writeFileSync(path26.join(fixturesDir, filename), JSON.stringify(items, null, 2));
|
|
7208
7418
|
writtenFiles.push(`${path26.join(DATA_DIR, "fixtures", filename)} (${items.length} records)`);
|
|
7209
7419
|
fileIndex++;
|
|
7210
7420
|
}
|
|
@@ -7352,7 +7562,7 @@ var load2 = new Command57("load").description("load seeds into the database").op
|
|
|
7352
7562
|
);
|
|
7353
7563
|
|
|
7354
7564
|
// src/commands/seeds/save.ts
|
|
7355
|
-
import
|
|
7565
|
+
import fs30 from "node:fs";
|
|
7356
7566
|
import path27 from "node:path";
|
|
7357
7567
|
import { Command as Command58 } from "commander";
|
|
7358
7568
|
var padZeros2 = (num, length) => num.toString().padStart(length, "0");
|
|
@@ -7373,10 +7583,10 @@ var save = new Command58("save").description("save the current data as seeds").o
|
|
|
7373
7583
|
if (existing.length > 0 && !opts.force) {
|
|
7374
7584
|
throw new Error("Existing seed files found in data/seeds. Pass --force to overwrite.");
|
|
7375
7585
|
}
|
|
7376
|
-
|
|
7586
|
+
fs30.mkdirSync(seedsPath, { recursive: true });
|
|
7377
7587
|
if (opts.force) {
|
|
7378
|
-
for (const file of
|
|
7379
|
-
if (file.endsWith(".json"))
|
|
7588
|
+
for (const file of fs30.readdirSync(seedsPath)) {
|
|
7589
|
+
if (file.endsWith(".json")) fs30.unlinkSync(path27.join(seedsPath, file));
|
|
7380
7590
|
}
|
|
7381
7591
|
}
|
|
7382
7592
|
const saved = [];
|
|
@@ -7411,7 +7621,7 @@ var save = new Command58("save").description("save the current data as seeds").o
|
|
|
7411
7621
|
`${padZeros2(count, 2)}-${collectionName}.json`
|
|
7412
7622
|
);
|
|
7413
7623
|
const seedPath = path27.join(workspaceRootDir, relativeSeedPath);
|
|
7414
|
-
|
|
7624
|
+
fs30.writeFileSync(seedPath, JSON.stringify(filtered, null, 2));
|
|
7415
7625
|
saved.push(`${relativeSeedPath} (${filtered.length} records)`);
|
|
7416
7626
|
count++;
|
|
7417
7627
|
}
|
|
@@ -7623,10 +7833,10 @@ import { Command as Command65 } from "commander";
|
|
|
7623
7833
|
|
|
7624
7834
|
// src/lib/migrate.ts
|
|
7625
7835
|
import path28 from "node:path";
|
|
7626
|
-
import
|
|
7836
|
+
import process20 from "node:process";
|
|
7627
7837
|
import { x as x2 } from "tinyexec";
|
|
7628
7838
|
async function runPocketbaseMigrate(args) {
|
|
7629
|
-
const cwd =
|
|
7839
|
+
const cwd = process20.cwd();
|
|
7630
7840
|
const { getBinaryPath } = await import("pocketbase-server");
|
|
7631
7841
|
const binaryPath = getBinaryPath();
|
|
7632
7842
|
await x2(
|
|
@@ -7683,13 +7893,13 @@ var down = new Command66("down").alias("rollback").description("revert the last
|
|
|
7683
7893
|
);
|
|
7684
7894
|
|
|
7685
7895
|
// src/commands/migrate/create.ts
|
|
7686
|
-
import
|
|
7896
|
+
import fs31 from "node:fs";
|
|
7687
7897
|
import path29 from "node:path";
|
|
7688
|
-
import
|
|
7898
|
+
import process21 from "node:process";
|
|
7689
7899
|
import { Command as Command67 } from "commander";
|
|
7690
7900
|
var create2 = new Command67("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
|
|
7691
7901
|
(name) => runCommand(async () => {
|
|
7692
|
-
const cwd =
|
|
7902
|
+
const cwd = process21.cwd();
|
|
7693
7903
|
const before = listMigrationFiles(cwd);
|
|
7694
7904
|
await runPocketbaseMigrate(["create", name]);
|
|
7695
7905
|
const after = listMigrationFiles(cwd);
|
|
@@ -7706,18 +7916,18 @@ var create2 = new Command67("create").alias("new").description("create a new bla
|
|
|
7706
7916
|
);
|
|
7707
7917
|
function listMigrationFiles(cwd) {
|
|
7708
7918
|
const dir = path29.join(cwd, MIGRATIONS_DIR);
|
|
7709
|
-
if (!
|
|
7710
|
-
return new Set(
|
|
7919
|
+
if (!fs31.existsSync(dir)) return /* @__PURE__ */ new Set();
|
|
7920
|
+
return new Set(fs31.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
|
|
7711
7921
|
}
|
|
7712
7922
|
|
|
7713
7923
|
// src/commands/migrate/collections.ts
|
|
7714
|
-
import
|
|
7924
|
+
import fs32 from "node:fs";
|
|
7715
7925
|
import path30 from "node:path";
|
|
7716
|
-
import
|
|
7926
|
+
import process22 from "node:process";
|
|
7717
7927
|
import { Command as Command68 } from "commander";
|
|
7718
7928
|
var collections = new Command68("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
|
|
7719
7929
|
() => runCommand(async () => {
|
|
7720
|
-
const cwd =
|
|
7930
|
+
const cwd = process22.cwd();
|
|
7721
7931
|
const before = listMigrationFiles2(cwd);
|
|
7722
7932
|
await runPocketbaseMigrate(["collections"]);
|
|
7723
7933
|
const after = listMigrationFiles2(cwd);
|
|
@@ -7741,8 +7951,8 @@ var collections = new Command68("collections").alias("snapshot").description("sn
|
|
|
7741
7951
|
);
|
|
7742
7952
|
function listMigrationFiles2(cwd) {
|
|
7743
7953
|
const dir = path30.join(cwd, MIGRATIONS_DIR);
|
|
7744
|
-
if (!
|
|
7745
|
-
return new Set(
|
|
7954
|
+
if (!fs32.existsSync(dir)) return /* @__PURE__ */ new Set();
|
|
7955
|
+
return new Set(fs32.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
|
|
7746
7956
|
}
|
|
7747
7957
|
|
|
7748
7958
|
// src/commands/migrate/history-sync.ts
|
|
@@ -7761,9 +7971,9 @@ var historySync = new Command69("history-sync").description("drop _migrations ro
|
|
|
7761
7971
|
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);
|
|
7762
7972
|
|
|
7763
7973
|
// src/commands/dev.ts
|
|
7764
|
-
import
|
|
7974
|
+
import fs33 from "node:fs";
|
|
7765
7975
|
import path32 from "node:path";
|
|
7766
|
-
import
|
|
7976
|
+
import process24 from "node:process";
|
|
7767
7977
|
import { performance } from "node:perf_hooks";
|
|
7768
7978
|
import { Command as Command71, InvalidArgumentError as InvalidArgumentError4 } from "commander";
|
|
7769
7979
|
import pc15 from "picocolors";
|
|
@@ -7771,7 +7981,7 @@ import PocketBase4 from "pocketbase";
|
|
|
7771
7981
|
|
|
7772
7982
|
// src/lib/vite.ts
|
|
7773
7983
|
import path31 from "node:path";
|
|
7774
|
-
import
|
|
7984
|
+
import process23 from "node:process";
|
|
7775
7985
|
import { createRequire as createRequire2 } from "node:module";
|
|
7776
7986
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
7777
7987
|
import pc14 from "picocolors";
|
|
@@ -7795,13 +8005,13 @@ function resolveProjectVite(cwd) {
|
|
|
7795
8005
|
return null;
|
|
7796
8006
|
}
|
|
7797
8007
|
}
|
|
7798
|
-
async function loadVite(cwd =
|
|
8008
|
+
async function loadVite(cwd = process23.cwd()) {
|
|
7799
8009
|
const entry = resolveProjectVite(cwd);
|
|
7800
8010
|
const vite = entry ? await import(pathToFileURL2(entry).href) : await import("vite");
|
|
7801
8011
|
const error = viteVersionError(vite.version);
|
|
7802
8012
|
if (error) {
|
|
7803
8013
|
console.error(`${pc14.redBright("\u2717")} ${error}`);
|
|
7804
|
-
|
|
8014
|
+
process23.exit(1);
|
|
7805
8015
|
}
|
|
7806
8016
|
return vite;
|
|
7807
8017
|
}
|
|
@@ -7815,18 +8025,18 @@ function parsePort(value) {
|
|
|
7815
8025
|
return port;
|
|
7816
8026
|
}
|
|
7817
8027
|
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) => {
|
|
7818
|
-
const cwd =
|
|
7819
|
-
|
|
8028
|
+
const cwd = process24.cwd();
|
|
8029
|
+
process24.env.VELA_DATA_DIR ??= localDataDir(cwd);
|
|
7820
8030
|
const startTime = performance.now();
|
|
7821
8031
|
const { createServer, version } = await loadVite(cwd);
|
|
7822
8032
|
const viteMetadataDir = path32.join(cwd, "node_modules", ".vite");
|
|
7823
8033
|
const viteMetadataFile = path32.join(viteMetadataDir, "_pocketbase_metadata.json");
|
|
7824
8034
|
let pbProc;
|
|
7825
8035
|
const backend3 = hasBackend(cwd);
|
|
7826
|
-
const needsStart = backend3 && !
|
|
8036
|
+
const needsStart = backend3 && !process24.env.POCKETBASE_URL;
|
|
7827
8037
|
const cleanup = () => {
|
|
7828
8038
|
if (pbProc?.pid) pbProc.kill();
|
|
7829
|
-
if (
|
|
8039
|
+
if (fs33.existsSync(viteMetadataFile)) fs33.rmSync(viteMetadataFile);
|
|
7830
8040
|
};
|
|
7831
8041
|
if (needsStart) {
|
|
7832
8042
|
const dataDir2 = path32.join(cwd, DATA_DIR);
|
|
@@ -7838,15 +8048,15 @@ var dev = new Command71("dev").description("start the development server").optio
|
|
|
7838
8048
|
stdio: "pipe"
|
|
7839
8049
|
});
|
|
7840
8050
|
pbProc = started.proc;
|
|
7841
|
-
|
|
7842
|
-
pbProc.stdout?.pipe(
|
|
7843
|
-
pbProc.stderr?.pipe(
|
|
8051
|
+
process24.env.POCKETBASE_URL = started.url;
|
|
8052
|
+
pbProc.stdout?.pipe(process24.stdout);
|
|
8053
|
+
pbProc.stderr?.pipe(process24.stderr);
|
|
7844
8054
|
pbProc.on("error", (err) => console.error("PocketBase error:", err));
|
|
7845
8055
|
pbProc.on("exit", (code) => console.log(`PocketBase exited with code ${code}`));
|
|
7846
|
-
|
|
7847
|
-
|
|
8056
|
+
process24.on("exit", cleanup);
|
|
8057
|
+
process24.on("SIGINT", () => {
|
|
7848
8058
|
cleanup();
|
|
7849
|
-
|
|
8059
|
+
process24.exit(0);
|
|
7850
8060
|
});
|
|
7851
8061
|
}
|
|
7852
8062
|
const serverOptions = {};
|
|
@@ -7864,25 +8074,25 @@ var dev = new Command71("dev").description("start the development server").optio
|
|
|
7864
8074
|
if (!backend3) return;
|
|
7865
8075
|
const { address, port: vitePort } = server.httpServer.address();
|
|
7866
8076
|
const viteHost = address === "::1" ? "localhost" : address;
|
|
7867
|
-
await
|
|
7868
|
-
await
|
|
8077
|
+
await fs33.promises.mkdir(viteMetadataDir, { recursive: true });
|
|
8078
|
+
await fs33.promises.writeFile(
|
|
7869
8079
|
viteMetadataFile,
|
|
7870
8080
|
JSON.stringify({
|
|
7871
|
-
pocketbaseUrl:
|
|
8081
|
+
pocketbaseUrl: process24.env.POCKETBASE_URL,
|
|
7872
8082
|
vitePort,
|
|
7873
8083
|
viteHost
|
|
7874
8084
|
})
|
|
7875
8085
|
);
|
|
7876
|
-
const pb = new PocketBase4(
|
|
8086
|
+
const pb = new PocketBase4(process24.env.POCKETBASE_URL);
|
|
7877
8087
|
await pb.collection("_superusers").authWithPassword(
|
|
7878
|
-
|
|
7879
|
-
|
|
8088
|
+
process24.env.POCKETBASE_SUPERUSER_EMAIL,
|
|
8089
|
+
process24.env.POCKETBASE_SUPERUSER_PASSWORD
|
|
7880
8090
|
);
|
|
7881
8091
|
await pb.settings.update({ meta: { appURL: `http://${viteHost}:${vitePort}` } });
|
|
7882
8092
|
await startWatchingTypes(cwd, pb);
|
|
7883
8093
|
});
|
|
7884
8094
|
await server.listen();
|
|
7885
|
-
const hasExistingLogs =
|
|
8095
|
+
const hasExistingLogs = process24.stdout.bytesWritten > 0 || process24.stderr.bytesWritten > 0;
|
|
7886
8096
|
const startupDurationString = pc15.dim(
|
|
7887
8097
|
`ready in ${pc15.reset(pc15.bold(Math.ceil(performance.now() - startTime)))} ms`
|
|
7888
8098
|
);
|
|
@@ -7906,9 +8116,9 @@ async function startWatchingTypes(cwd, pb) {
|
|
|
7906
8116
|
void (async () => {
|
|
7907
8117
|
for (; ; ) {
|
|
7908
8118
|
try {
|
|
7909
|
-
await
|
|
7910
|
-
for await (const event of
|
|
7911
|
-
if (event.eventType === "rename" && event.filename === "$types.d.ts" && !
|
|
8119
|
+
await fs33.promises.mkdir(pocketbaseDir, { recursive: true });
|
|
8120
|
+
for await (const event of fs33.promises.watch(pocketbaseDir)) {
|
|
8121
|
+
if (event.eventType === "rename" && event.filename === "$types.d.ts" && !fs33.existsSync(pocketbaseTypes)) {
|
|
7912
8122
|
setTimeout(regenerate, 100);
|
|
7913
8123
|
}
|
|
7914
8124
|
}
|
|
@@ -7920,9 +8130,9 @@ async function startWatchingTypes(cwd, pb) {
|
|
|
7920
8130
|
}
|
|
7921
8131
|
|
|
7922
8132
|
// src/commands/build.ts
|
|
7923
|
-
import
|
|
8133
|
+
import fs34 from "node:fs";
|
|
7924
8134
|
import path33 from "node:path";
|
|
7925
|
-
import
|
|
8135
|
+
import process26 from "node:process";
|
|
7926
8136
|
import { Command as Command72 } from "commander";
|
|
7927
8137
|
import * as p40 from "@clack/prompts";
|
|
7928
8138
|
import pc16 from "picocolors";
|
|
@@ -7937,10 +8147,10 @@ function applyBuildEnv(cwd, env2 = process.env) {
|
|
|
7937
8147
|
}
|
|
7938
8148
|
|
|
7939
8149
|
// src/lib/origin.ts
|
|
7940
|
-
import
|
|
8150
|
+
import process25 from "node:process";
|
|
7941
8151
|
function resolveOrigin(workspaceRootDir, envTag, config = {}) {
|
|
7942
8152
|
return normalizeOrigin(
|
|
7943
|
-
|
|
8153
|
+
process25.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
|
|
7944
8154
|
);
|
|
7945
8155
|
}
|
|
7946
8156
|
function normalizeOrigin(value) {
|
|
@@ -7961,12 +8171,12 @@ function splitHosts(value) {
|
|
|
7961
8171
|
// src/commands/build.ts
|
|
7962
8172
|
var PRERENDERED_DIR = path33.join(".svelte-kit", "output", "prerendered");
|
|
7963
8173
|
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) => {
|
|
7964
|
-
const cwd =
|
|
8174
|
+
const cwd = process26.cwd();
|
|
7965
8175
|
applyBuildEnv(cwd);
|
|
7966
8176
|
const origin = await originForBuild(cwd, options.target);
|
|
7967
|
-
if (origin)
|
|
8177
|
+
if (origin) process26.env.VELA_ORIGIN = origin;
|
|
7968
8178
|
let pbProc;
|
|
7969
|
-
const needsStart = hasBackend(cwd) && !
|
|
8179
|
+
const needsStart = hasBackend(cwd) && !process26.env.POCKETBASE_URL;
|
|
7970
8180
|
const cleanup = () => {
|
|
7971
8181
|
if (pbProc?.pid) pbProc.kill();
|
|
7972
8182
|
};
|
|
@@ -7980,11 +8190,11 @@ var build = new Command72("build").description("build the app").configureHelp(he
|
|
|
7980
8190
|
dev: true
|
|
7981
8191
|
});
|
|
7982
8192
|
pbProc = started.proc;
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
8193
|
+
process26.env.POCKETBASE_URL = started.url;
|
|
8194
|
+
process26.on("exit", cleanup);
|
|
8195
|
+
process26.on("SIGINT", () => {
|
|
7986
8196
|
cleanup();
|
|
7987
|
-
|
|
8197
|
+
process26.exit(0);
|
|
7988
8198
|
});
|
|
7989
8199
|
}
|
|
7990
8200
|
try {
|
|
@@ -8016,7 +8226,7 @@ async function originForBuild(cwd, target) {
|
|
|
8016
8226
|
}
|
|
8017
8227
|
function warnIfPrerendered(cwd) {
|
|
8018
8228
|
const dir = path33.join(cwd, PRERENDERED_DIR);
|
|
8019
|
-
if (!
|
|
8229
|
+
if (!fs34.existsSync(dir) || fs34.readdirSync(dir).length === 0) return;
|
|
8020
8230
|
p40.log.warn(
|
|
8021
8231
|
`Prerendered pages were built with no domain configured, so their canonical
|
|
8022
8232
|
links point at SvelteKit's placeholder host rather than at this site.
|
|
@@ -8027,16 +8237,16 @@ Set one with ${pc16.cyan("vela deploy --domain example.com")}, or pass ${pc16.cy
|
|
|
8027
8237
|
|
|
8028
8238
|
// src/commands/preview.ts
|
|
8029
8239
|
import path34 from "node:path";
|
|
8030
|
-
import
|
|
8240
|
+
import process27 from "node:process";
|
|
8031
8241
|
import { Command as Command73 } from "commander";
|
|
8032
8242
|
import { x as x4 } from "tinyexec";
|
|
8033
8243
|
import { detect as detect6 } from "package-manager-detector";
|
|
8034
8244
|
import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
|
|
8035
8245
|
var preview = new Command73("preview").description("preview the built app").configureHelp(helpConfig).action(async () => {
|
|
8036
|
-
const cwd =
|
|
8037
|
-
|
|
8246
|
+
const cwd = process27.cwd();
|
|
8247
|
+
process27.env.VELA_DATA_DIR ??= localDataDir(cwd);
|
|
8038
8248
|
let pbProc;
|
|
8039
|
-
const needsStart = hasBackend(cwd) && !
|
|
8249
|
+
const needsStart = hasBackend(cwd) && !process27.env.POCKETBASE_URL;
|
|
8040
8250
|
const cleanup = () => {
|
|
8041
8251
|
if (pbProc?.pid) pbProc.kill();
|
|
8042
8252
|
};
|
|
@@ -8049,11 +8259,11 @@ var preview = new Command73("preview").description("preview the built app").conf
|
|
|
8049
8259
|
dev: true
|
|
8050
8260
|
});
|
|
8051
8261
|
pbProc = started.proc;
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
|
|
8262
|
+
process27.env.POCKETBASE_URL = started.url;
|
|
8263
|
+
process27.on("exit", cleanup);
|
|
8264
|
+
process27.on("SIGINT", () => {
|
|
8055
8265
|
cleanup();
|
|
8056
|
-
|
|
8266
|
+
process27.exit(0);
|
|
8057
8267
|
});
|
|
8058
8268
|
}
|
|
8059
8269
|
try {
|
|
@@ -8138,24 +8348,24 @@ var provision = addSshOptions(
|
|
|
8138
8348
|
);
|
|
8139
8349
|
|
|
8140
8350
|
// src/commands/deploy.ts
|
|
8141
|
-
import
|
|
8142
|
-
import
|
|
8351
|
+
import path38 from "node:path";
|
|
8352
|
+
import fs37 from "node:fs";
|
|
8143
8353
|
import { Command as Command76, Option as Option2 } from "commander";
|
|
8144
8354
|
import * as p42 from "@clack/prompts";
|
|
8145
8355
|
import pc18 from "picocolors";
|
|
8146
8356
|
import * as v8 from "valibot";
|
|
8147
8357
|
|
|
8148
8358
|
// src/lib/pocketbase-settings.ts
|
|
8149
|
-
import
|
|
8359
|
+
import fs35 from "node:fs";
|
|
8150
8360
|
import path36 from "node:path";
|
|
8151
|
-
import
|
|
8361
|
+
import process28 from "node:process";
|
|
8152
8362
|
import PocketBase5 from "pocketbase";
|
|
8153
8363
|
var COPIED_KEYS = ["appName", "senderName", "senderAddress"];
|
|
8154
8364
|
async function readLocalMeta(cwd) {
|
|
8155
8365
|
const dataDir2 = path36.join(cwd, DATA_DIR);
|
|
8156
|
-
if (!
|
|
8157
|
-
const email3 =
|
|
8158
|
-
const password11 =
|
|
8366
|
+
if (!fs35.existsSync(dataDir2)) return null;
|
|
8367
|
+
const email3 = process28.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
8368
|
+
const password11 = process28.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
8159
8369
|
if (!email3 || !password11) return null;
|
|
8160
8370
|
let proc;
|
|
8161
8371
|
try {
|
|
@@ -8203,11 +8413,278 @@ async function seedRemoteMeta(session, instance, local, appURL) {
|
|
|
8203
8413
|
return Object.keys(patch);
|
|
8204
8414
|
}
|
|
8205
8415
|
|
|
8416
|
+
// src/lib/adapter.ts
|
|
8417
|
+
import fs36 from "node:fs";
|
|
8418
|
+
import path37 from "node:path";
|
|
8419
|
+
import {
|
|
8420
|
+
Project as Project2,
|
|
8421
|
+
QuoteKind as QuoteKind2,
|
|
8422
|
+
SyntaxKind as SyntaxKind2
|
|
8423
|
+
} from "ts-morph";
|
|
8424
|
+
import { detect as detect7 } from "package-manager-detector";
|
|
8425
|
+
var ADAPTER_NODE = "@sveltejs/adapter-node";
|
|
8426
|
+
var ADAPTER_AUTO = "@sveltejs/adapter-auto";
|
|
8427
|
+
var ADAPTER_STATIC = "@sveltejs/adapter-static";
|
|
8428
|
+
var ADAPTER_NODE_RANGE = "^5.5.7";
|
|
8429
|
+
var ADAPTER_SNIPPET = `import adapter from '${ADAPTER_NODE}';
|
|
8430
|
+
|
|
8431
|
+
// ...
|
|
8432
|
+
adapter: adapter()`;
|
|
8433
|
+
var AdapterError = class extends Error {
|
|
8434
|
+
constructor(message, snippet = ADAPTER_SNIPPET) {
|
|
8435
|
+
super(message);
|
|
8436
|
+
this.snippet = snippet;
|
|
8437
|
+
this.name = "AdapterError";
|
|
8438
|
+
}
|
|
8439
|
+
snippet;
|
|
8440
|
+
};
|
|
8441
|
+
function newProject() {
|
|
8442
|
+
return new Project2({
|
|
8443
|
+
compilerOptions: { allowJs: true },
|
|
8444
|
+
manipulationSettings: { quoteKind: QuoteKind2.Single }
|
|
8445
|
+
});
|
|
8446
|
+
}
|
|
8447
|
+
function getDefaultExportObject(sourceFile) {
|
|
8448
|
+
const exported = sourceFile.getExportAssignment((ea) => !ea.isExportEquals())?.getExpression();
|
|
8449
|
+
if (exported?.getKind() === SyntaxKind2.ObjectLiteralExpression) {
|
|
8450
|
+
return exported;
|
|
8451
|
+
}
|
|
8452
|
+
if (exported?.getKind() === SyntaxKind2.Identifier) {
|
|
8453
|
+
const init = sourceFile.getVariableDeclaration(exported.getText())?.getInitializer();
|
|
8454
|
+
if (init?.getKind() === SyntaxKind2.ObjectLiteralExpression) {
|
|
8455
|
+
return init;
|
|
8456
|
+
}
|
|
8457
|
+
}
|
|
8458
|
+
return null;
|
|
8459
|
+
}
|
|
8460
|
+
function resolveKitTarget(root) {
|
|
8461
|
+
const vite = inspectViteSveltekit(root);
|
|
8462
|
+
if (vite?.inlineArg) {
|
|
8463
|
+
return {
|
|
8464
|
+
sourceFile: vite.sourceFile,
|
|
8465
|
+
filePath: vite.filePath,
|
|
8466
|
+
container: "vite-inline",
|
|
8467
|
+
kit: vite.inlineArg,
|
|
8468
|
+
created: false,
|
|
8469
|
+
originalText: vite.sourceFile.getFullText()
|
|
8470
|
+
};
|
|
8471
|
+
}
|
|
8472
|
+
const sveltePath = probeFirstExisting(root, SVELTE_CONFIG_CANDIDATES);
|
|
8473
|
+
if (sveltePath) {
|
|
8474
|
+
const name = path37.basename(sveltePath);
|
|
8475
|
+
if (sveltePath.endsWith(".cjs")) {
|
|
8476
|
+
throw new AdapterError(`${name} is CommonJS, which vela does not edit.`);
|
|
8477
|
+
}
|
|
8478
|
+
const sourceFile = newProject().addSourceFileAtPath(sveltePath);
|
|
8479
|
+
const config = getDefaultExportObject(sourceFile);
|
|
8480
|
+
const kit = config && getOrCreateObjectLiteralProperty(config, "kit", "{}");
|
|
8481
|
+
if (!kit) {
|
|
8482
|
+
throw new AdapterError(`${name} has a shape vela does not understand.`);
|
|
8483
|
+
}
|
|
8484
|
+
return {
|
|
8485
|
+
sourceFile,
|
|
8486
|
+
filePath: sveltePath,
|
|
8487
|
+
container: "svelte-config",
|
|
8488
|
+
kit,
|
|
8489
|
+
created: false,
|
|
8490
|
+
originalText: sourceFile.getFullText()
|
|
8491
|
+
};
|
|
8492
|
+
}
|
|
8493
|
+
if (vite?.sveltekitCall) {
|
|
8494
|
+
const name = path37.basename(vite.filePath);
|
|
8495
|
+
if (vite.nonObjectArg) {
|
|
8496
|
+
throw new AdapterError(`${name} passes sveltekit() something other than an object literal.`);
|
|
8497
|
+
}
|
|
8498
|
+
const originalText = vite.sourceFile.getFullText();
|
|
8499
|
+
const kit = createSveltekitArg(vite);
|
|
8500
|
+
if (!kit)
|
|
8501
|
+
throw new AdapterError(`${name} has a sveltekit() call vela cannot add an argument to.`);
|
|
8502
|
+
return {
|
|
8503
|
+
sourceFile: vite.sourceFile,
|
|
8504
|
+
filePath: vite.filePath,
|
|
8505
|
+
container: "vite-inline",
|
|
8506
|
+
kit,
|
|
8507
|
+
created: true,
|
|
8508
|
+
originalText
|
|
8509
|
+
};
|
|
8510
|
+
}
|
|
8511
|
+
throw new AdapterError(
|
|
8512
|
+
`No svelte.config or vite.config with a sveltekit() plugin found in ${root}.`
|
|
8513
|
+
);
|
|
8514
|
+
}
|
|
8515
|
+
function classify(specifier) {
|
|
8516
|
+
if (specifier === ADAPTER_NODE) return "node";
|
|
8517
|
+
if (specifier === ADAPTER_AUTO) return "auto";
|
|
8518
|
+
if (specifier === ADAPTER_STATIC) return "static";
|
|
8519
|
+
return "other";
|
|
8520
|
+
}
|
|
8521
|
+
function importOf(sourceFile, identifier) {
|
|
8522
|
+
return sourceFile.getImportDeclarations().find((decl) => decl.getDefaultImport()?.getText() === identifier);
|
|
8523
|
+
}
|
|
8524
|
+
function inspectAdapter(target) {
|
|
8525
|
+
const base2 = { file: target.filePath, container: target.container };
|
|
8526
|
+
const prop = target.kit.getProperty("adapter");
|
|
8527
|
+
if (!prop) return { info: { ...base2, kind: "none" } };
|
|
8528
|
+
if (prop.getKind() !== SyntaxKind2.PropertyAssignment) {
|
|
8529
|
+
return { info: { ...base2, kind: "other" } };
|
|
8530
|
+
}
|
|
8531
|
+
const init = prop.asKindOrThrow(SyntaxKind2.PropertyAssignment).getInitializer();
|
|
8532
|
+
if (!init || init.getKind() !== SyntaxKind2.CallExpression) {
|
|
8533
|
+
return { info: { ...base2, kind: "other" } };
|
|
8534
|
+
}
|
|
8535
|
+
const callee = init.asKindOrThrow(SyntaxKind2.CallExpression).getExpression();
|
|
8536
|
+
if (callee.getKind() !== SyntaxKind2.Identifier) {
|
|
8537
|
+
return { info: { ...base2, kind: "other" } };
|
|
8538
|
+
}
|
|
8539
|
+
const importDecl = importOf(target.sourceFile, callee.getText());
|
|
8540
|
+
if (!importDecl) return { info: { ...base2, kind: "other" } };
|
|
8541
|
+
const specifier = importDecl.getModuleSpecifierValue();
|
|
8542
|
+
return { info: { ...base2, kind: classify(specifier), specifier }, importDecl };
|
|
8543
|
+
}
|
|
8544
|
+
async function ensureNodeAdapter(root, { install = true } = {}) {
|
|
8545
|
+
const target = resolveKitTarget(root);
|
|
8546
|
+
const { info, importDecl } = inspectAdapter(target);
|
|
8547
|
+
const name = path37.basename(target.filePath);
|
|
8548
|
+
const outcome = {
|
|
8549
|
+
previous: info.kind,
|
|
8550
|
+
removedDeps: [],
|
|
8551
|
+
packageJsonChanged: false
|
|
8552
|
+
};
|
|
8553
|
+
switch (info.kind) {
|
|
8554
|
+
case "node":
|
|
8555
|
+
break;
|
|
8556
|
+
case "static":
|
|
8557
|
+
throw new AdapterError(
|
|
8558
|
+
`This project builds a static site with ${ADAPTER_STATIC} (${name}).
|
|
8559
|
+
|
|
8560
|
+
vela deploy runs the app as a Node server, which needs ${ADAPTER_NODE}. Switch
|
|
8561
|
+
the adapter to deploy it here, or host the static output elsewhere.`
|
|
8562
|
+
);
|
|
8563
|
+
case "other":
|
|
8564
|
+
throw new AdapterError(
|
|
8565
|
+
`This project's adapter${info.specifier ? ` (${info.specifier})` : ""} in ${name} is not one
|
|
8566
|
+
vela will change for you.
|
|
8567
|
+
|
|
8568
|
+
vela deploy runs the app as a Node server, which needs ${ADAPTER_NODE}:`
|
|
8569
|
+
);
|
|
8570
|
+
case "auto":
|
|
8571
|
+
switchImport(target, importDecl);
|
|
8572
|
+
outcome.configFile = name;
|
|
8573
|
+
break;
|
|
8574
|
+
case "none":
|
|
8575
|
+
addAdapter(target);
|
|
8576
|
+
outcome.configFile = name;
|
|
8577
|
+
break;
|
|
8578
|
+
}
|
|
8579
|
+
if (outcome.configFile) saveTarget(target);
|
|
8580
|
+
const pkgPath = path37.join(root, "package.json");
|
|
8581
|
+
if (fs36.existsSync(pkgPath)) {
|
|
8582
|
+
const pkg = readPackageJson(pkgPath);
|
|
8583
|
+
const { changed, removed } = adoptNodeAdapter(pkg);
|
|
8584
|
+
if (changed) {
|
|
8585
|
+
writePackageJson(pkgPath, pkg);
|
|
8586
|
+
outcome.packageJsonChanged = true;
|
|
8587
|
+
outcome.removedDeps = removed;
|
|
8588
|
+
}
|
|
8589
|
+
}
|
|
8590
|
+
if (outcome.packageJsonChanged && install) {
|
|
8591
|
+
outcome.installedWith = await installAdapterDependencies(root);
|
|
8592
|
+
}
|
|
8593
|
+
return outcome;
|
|
8594
|
+
}
|
|
8595
|
+
async function installAdapterDependencies(root) {
|
|
8596
|
+
const agent = await packageManager(root);
|
|
8597
|
+
const ok = await installDependencies(agent, root, { exitOnFailure: false });
|
|
8598
|
+
if (!ok) {
|
|
8599
|
+
throw new AdapterError(
|
|
8600
|
+
`Installing ${ADAPTER_NODE} with ${agent} failed.
|
|
8601
|
+
|
|
8602
|
+
The config and package.json are already updated: run \`${agent} install\`, then deploy again.`,
|
|
8603
|
+
""
|
|
8604
|
+
);
|
|
8605
|
+
}
|
|
8606
|
+
return agent;
|
|
8607
|
+
}
|
|
8608
|
+
function switchImport(target, importDecl) {
|
|
8609
|
+
importDecl.setModuleSpecifier(ADAPTER_NODE);
|
|
8610
|
+
const prop = target.kit.getPropertyOrThrow("adapter").asKindOrThrow(SyntaxKind2.PropertyAssignment);
|
|
8611
|
+
const call = prop.getInitializerIfKindOrThrow(SyntaxKind2.CallExpression);
|
|
8612
|
+
for (let i = call.getArguments().length - 1; i >= 0; i--) call.removeArgument(i);
|
|
8613
|
+
dropAdapterAutoComments(target);
|
|
8614
|
+
}
|
|
8615
|
+
var ADAPTER_AUTO_COMMENT = /adapter-auto|svelte\.dev\/docs\/kit\/adapters|switch out the adapter/;
|
|
8616
|
+
function dropAdapterAutoComments(target) {
|
|
8617
|
+
const prop = target.kit.getPropertyOrThrow("adapter");
|
|
8618
|
+
const ranges = prop.getLeadingCommentRanges();
|
|
8619
|
+
if (ranges.length === 0 || !ranges.every((r) => ADAPTER_AUTO_COMMENT.test(r.getText()))) return;
|
|
8620
|
+
const fullStart = prop.getFullStart();
|
|
8621
|
+
const start = prop.getStart();
|
|
8622
|
+
const trivia = target.sourceFile.getFullText().slice(fullStart, start);
|
|
8623
|
+
const lastNewline = trivia.lastIndexOf("\n");
|
|
8624
|
+
if (lastNewline === -1) return;
|
|
8625
|
+
const indent = trivia.slice(lastNewline + 1);
|
|
8626
|
+
target.sourceFile.replaceText([fullStart, start], `
|
|
8627
|
+
${indent}`);
|
|
8628
|
+
}
|
|
8629
|
+
function addAdapter(target) {
|
|
8630
|
+
const taken = importOf(target.sourceFile, "adapter") ?? target.sourceFile.getVariableDeclaration("adapter");
|
|
8631
|
+
if (taken) {
|
|
8632
|
+
throw new AdapterError(
|
|
8633
|
+
`${path37.basename(target.filePath)} already binds the name \`adapter\` to something that is not the SvelteKit adapter.`
|
|
8634
|
+
);
|
|
8635
|
+
}
|
|
8636
|
+
target.sourceFile.addImportDeclaration({
|
|
8637
|
+
defaultImport: "adapter",
|
|
8638
|
+
moduleSpecifier: ADAPTER_NODE
|
|
8639
|
+
});
|
|
8640
|
+
target.kit.addPropertyAssignment({ name: "adapter", initializer: "adapter()" });
|
|
8641
|
+
}
|
|
8642
|
+
function saveTarget(target) {
|
|
8643
|
+
if (target.created) target.sourceFile.formatText();
|
|
8644
|
+
if (target.sourceFile.getFullText() === target.originalText) return;
|
|
8645
|
+
target.sourceFile.saveSync();
|
|
8646
|
+
}
|
|
8647
|
+
function adoptNodeAdapter(pkg) {
|
|
8648
|
+
const removed = [];
|
|
8649
|
+
let changed = false;
|
|
8650
|
+
for (const kind of ["dependencies", "devDependencies"]) {
|
|
8651
|
+
const deps = pkg[kind];
|
|
8652
|
+
if (deps && ADAPTER_AUTO in deps) {
|
|
8653
|
+
delete deps[ADAPTER_AUTO];
|
|
8654
|
+
removed.push(ADAPTER_AUTO);
|
|
8655
|
+
changed = true;
|
|
8656
|
+
}
|
|
8657
|
+
}
|
|
8658
|
+
if (!pkg.dependencies?.[ADAPTER_NODE] && !pkg.devDependencies?.[ADAPTER_NODE]) {
|
|
8659
|
+
pkg.devDependencies = sortKeys({ ...pkg.devDependencies, [ADAPTER_NODE]: ADAPTER_NODE_RANGE });
|
|
8660
|
+
changed = true;
|
|
8661
|
+
}
|
|
8662
|
+
return { changed, removed: [...new Set(removed)] };
|
|
8663
|
+
}
|
|
8664
|
+
function lockfileFor(agent) {
|
|
8665
|
+
switch (agent) {
|
|
8666
|
+
case "pnpm":
|
|
8667
|
+
return "pnpm-lock.yaml";
|
|
8668
|
+
case "yarn":
|
|
8669
|
+
return "yarn.lock";
|
|
8670
|
+
case "bun":
|
|
8671
|
+
return "bun.lock";
|
|
8672
|
+
case "deno":
|
|
8673
|
+
return "deno.lock";
|
|
8674
|
+
default:
|
|
8675
|
+
return "package-lock.json";
|
|
8676
|
+
}
|
|
8677
|
+
}
|
|
8678
|
+
async function packageManager(root) {
|
|
8679
|
+
return (await detect7({ cwd: root }))?.name ?? getUserAgent() ?? "npm";
|
|
8680
|
+
}
|
|
8681
|
+
|
|
8206
8682
|
// src/commands/deploy.ts
|
|
8207
8683
|
var OptionsSchema3 = v8.object({
|
|
8208
8684
|
...SSH_OPTION_SCHEMA,
|
|
8209
8685
|
env: v8.optional(v8.string()),
|
|
8210
8686
|
project: v8.optional(v8.string()),
|
|
8687
|
+
...LOCK_WAIT_SCHEMA,
|
|
8211
8688
|
remoteDb: v8.optional(v8.boolean()),
|
|
8212
8689
|
domain: v8.optional(v8.string()),
|
|
8213
8690
|
healthPath: v8.optional(v8.string()),
|
|
@@ -8215,9 +8692,11 @@ var OptionsSchema3 = v8.object({
|
|
|
8215
8692
|
pbVersion: v8.optional(v8.string()),
|
|
8216
8693
|
build: v8.optional(v8.boolean())
|
|
8217
8694
|
});
|
|
8218
|
-
var deploy =
|
|
8219
|
-
|
|
8220
|
-
|
|
8695
|
+
var deploy = addLockWaitOption(
|
|
8696
|
+
addTargetOptions(
|
|
8697
|
+
new Command76("deploy").description("deploy the app").configureHelp(helpConfig),
|
|
8698
|
+
"production"
|
|
8699
|
+
)
|
|
8221
8700
|
).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(
|
|
8222
8701
|
new Option2(
|
|
8223
8702
|
"--remote-db",
|
|
@@ -8231,8 +8710,11 @@ var deploy = addTargetOptions(
|
|
|
8231
8710
|
(raw) => runCommand(async () => {
|
|
8232
8711
|
const options = parseOptions(OptionsSchema3, raw);
|
|
8233
8712
|
const backend3 = hasBackend();
|
|
8234
|
-
const release = releaseId();
|
|
8235
8713
|
p42.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
|
|
8714
|
+
if (options.build !== false) {
|
|
8715
|
+
const { workspaceRootDir } = await getWorkspace();
|
|
8716
|
+
await prepareAdapter(workspaceRootDir);
|
|
8717
|
+
}
|
|
8236
8718
|
await withTarget(
|
|
8237
8719
|
raw,
|
|
8238
8720
|
{
|
|
@@ -8242,10 +8724,16 @@ var deploy = addTargetOptions(
|
|
|
8242
8724
|
`${pc18.cyan(ctx.appName)} ${pc18.dim("\u2192")} ${pc18.cyan(ctx.targetName)} ${pc18.dim(`(${ctx.server})`)}`
|
|
8243
8725
|
);
|
|
8244
8726
|
const [existing] = await readInstanceStates(session, instance);
|
|
8245
|
-
const
|
|
8246
|
-
const
|
|
8727
|
+
const release = releaseId(await serverTimeOrLocal(session));
|
|
8728
|
+
const isPreview2 = ctx.target.kind === "preview";
|
|
8729
|
+
const configured = options.domain ?? (isPreview2 ? existing?.domain : ctx.binding.domain ?? config.deploy?.domain ?? existing?.domain) ?? "";
|
|
8247
8730
|
const askedForRemoteDb = options.remoteDb ?? config.deploy?.buildAgainstRemote;
|
|
8248
|
-
const remoteDb = askedForRemoteDb ??
|
|
8731
|
+
const remoteDb = askedForRemoteDb ?? instanceHasBackend(existing);
|
|
8732
|
+
if (existing && instanceHasBackend(existing) !== backend3) {
|
|
8733
|
+
p42.log.info(
|
|
8734
|
+
backend3 ? `${pc18.cyan(ctx.targetName)} was deployed without a backend before. This deploy adds PocketBase.` : `${pc18.cyan(ctx.targetName)} was deployed with a backend before. This deploy removes PocketBase; its database stays on the server.`
|
|
8735
|
+
);
|
|
8736
|
+
}
|
|
8249
8737
|
const sha = await gitSha(workspaceRootDir);
|
|
8250
8738
|
const reporter = createDeployReporter(workspaceRootDir);
|
|
8251
8739
|
const server = await reporter.identifyServer(session);
|
|
@@ -8265,17 +8753,17 @@ var deploy = addTargetOptions(
|
|
|
8265
8753
|
const managed = managedHosts.join(",");
|
|
8266
8754
|
const primaryHost = directHosts[0] ?? managedHosts[0] ?? "";
|
|
8267
8755
|
const primaryUrl = started?.environment.primaryUrl || normalizeOrigin(primaryHost) || "";
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8756
|
+
let result = null;
|
|
8757
|
+
try {
|
|
8758
|
+
if (isPreview2 && !primaryHost) {
|
|
8759
|
+
throw new Error(
|
|
8760
|
+
`Nothing routes to this preview.
|
|
8271
8761
|
|
|
8272
8762
|
Previews get a free velastack.app hostname from velastack.dev: ${pc18.cyan("vela link")} the
|
|
8273
8763
|
project and ${pc18.cyan("vela login")} (or set ${pc18.cyan("VELA_API_KEY")}). Or pass ${pc18.cyan("--domain <host>")}
|
|
8274
8764
|
with DNS of your own pointing at ${ctx.server}.`
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
let result = null;
|
|
8278
|
-
try {
|
|
8765
|
+
);
|
|
8766
|
+
}
|
|
8279
8767
|
if (options.build !== false) {
|
|
8280
8768
|
const origin = normalizeOrigin(process.env.VELA_ORIGIN ?? primaryUrl);
|
|
8281
8769
|
let buildEnv = origin ? { VELA_ORIGIN: origin } : {};
|
|
@@ -8333,7 +8821,8 @@ ${pc18.dim(String(err))}`
|
|
|
8333
8821
|
"--pb-version",
|
|
8334
8822
|
options.pbVersion ?? config.deploy?.pocketbaseVersion ?? pocketbaseVersion(),
|
|
8335
8823
|
"--git-sha",
|
|
8336
|
-
sha
|
|
8824
|
+
sha,
|
|
8825
|
+
...lockWaitArgs(options.lockWait)
|
|
8337
8826
|
],
|
|
8338
8827
|
stream: true
|
|
8339
8828
|
});
|
|
@@ -8347,7 +8836,7 @@ ${pc18.dim(String(err))}`
|
|
|
8347
8836
|
writeBinding(
|
|
8348
8837
|
workspaceRootDir,
|
|
8349
8838
|
bindingKey(ctx.target),
|
|
8350
|
-
|
|
8839
|
+
isPreview2 ? { server: ctx.server } : { server: ctx.server, domain: domain || void 0 }
|
|
8351
8840
|
);
|
|
8352
8841
|
if (!existing) await reportEmptyEnvironment(session, instance, workspaceRootDir);
|
|
8353
8842
|
const url = result?.url ?? "";
|
|
@@ -8400,6 +8889,38 @@ or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
|
|
|
8400
8889
|
p42.outro(`${pc18.cyan("vela status")} to see what is running`);
|
|
8401
8890
|
}, "Failed to deploy.")
|
|
8402
8891
|
);
|
|
8892
|
+
async function prepareAdapter(workspaceRootDir) {
|
|
8893
|
+
const rethrow = (err) => {
|
|
8894
|
+
if (err instanceof AdapterError) {
|
|
8895
|
+
throw new Error(err.snippet ? `${err.message}
|
|
8896
|
+
|
|
8897
|
+
${pc18.cyan(err.snippet)}` : err.message);
|
|
8898
|
+
}
|
|
8899
|
+
throw err;
|
|
8900
|
+
};
|
|
8901
|
+
const outcome = await ensureNodeAdapter(workspaceRootDir, { install: false }).catch(rethrow);
|
|
8902
|
+
if (!outcome.configFile && !outcome.packageJsonChanged) return;
|
|
8903
|
+
const changed = [
|
|
8904
|
+
outcome.configFile,
|
|
8905
|
+
outcome.packageJsonChanged ? "package.json" : void 0
|
|
8906
|
+
].filter((f) => Boolean(f));
|
|
8907
|
+
const why = outcome.previous === "auto" ? `${ADAPTER_AUTO} builds nothing for a server of your own` : outcome.previous === "none" ? "No adapter was configured" : `${ADAPTER_NODE} was configured but not in package.json`;
|
|
8908
|
+
p42.log.step(`Switching the adapter to ${pc18.cyan(ADAPTER_NODE)}`);
|
|
8909
|
+
p42.log.info(
|
|
8910
|
+
`${why}, and vela deploy runs the app as a Node server.
|
|
8911
|
+
|
|
8912
|
+
Changed ${changed.join(", ")}` + (outcome.removedDeps.length ? `
|
|
8913
|
+
Removed ${outcome.removedDeps.join(", ")}` : "")
|
|
8914
|
+
);
|
|
8915
|
+
if (outcome.packageJsonChanged) {
|
|
8916
|
+
try {
|
|
8917
|
+
changed.push(lockfileFor(await installAdapterDependencies(workspaceRootDir)));
|
|
8918
|
+
} catch (err) {
|
|
8919
|
+
rethrow(err);
|
|
8920
|
+
}
|
|
8921
|
+
}
|
|
8922
|
+
p42.log.warn(`Commit ${changed.join(", ")} so every deploy builds the same way.`);
|
|
8923
|
+
}
|
|
8403
8924
|
async function reportAppURLDrift(session, instance, domain) {
|
|
8404
8925
|
const expected = normalizeOrigin(domain);
|
|
8405
8926
|
if (!expected) return;
|
|
@@ -8435,10 +8956,10 @@ Set them in the admin panel instead. ${pc18.dim(String(err))}`
|
|
|
8435
8956
|
}
|
|
8436
8957
|
}
|
|
8437
8958
|
async function openDatabaseTunnel(session, instance, state) {
|
|
8438
|
-
const pbPort = state?.pbPort;
|
|
8959
|
+
const pbPort = instanceHasBackend(state) ? state?.pbPort : void 0;
|
|
8439
8960
|
if (!pbPort) {
|
|
8440
8961
|
throw new Error(
|
|
8441
|
-
`--remote-db needs
|
|
8962
|
+
`--remote-db needs a deployed database to build against, and ${instance} ${state ? "has no backend" : "has not been deployed yet"}.
|
|
8442
8963
|
|
|
8443
8964
|
Deploy once without it, then turn it on.`
|
|
8444
8965
|
);
|
|
@@ -8498,7 +9019,7 @@ async function superuserAuthenticates(port, identity, password11) {
|
|
|
8498
9019
|
}
|
|
8499
9020
|
async function uploadRelease(session, instance, release, entries) {
|
|
8500
9021
|
const dir = remotePaths.release(instance, release);
|
|
8501
|
-
await session.script(`mkdir -p "$1"`, { args: [dir] });
|
|
9022
|
+
await session.script(`mkdir -p "$(dirname "$1")" && mkdir "$1"`, { args: [dir] });
|
|
8502
9023
|
const byTarget = /* @__PURE__ */ new Map();
|
|
8503
9024
|
for (const entry of entries) {
|
|
8504
9025
|
const target = entry.remoteDir ? `${dir}/${entry.remoteDir}` : dir;
|
|
@@ -8512,7 +9033,7 @@ async function uploadRelease(session, instance, release, entries) {
|
|
|
8512
9033
|
}
|
|
8513
9034
|
function isDirectory(target) {
|
|
8514
9035
|
try {
|
|
8515
|
-
return
|
|
9036
|
+
return fs37.statSync(target).isDirectory();
|
|
8516
9037
|
} catch {
|
|
8517
9038
|
return false;
|
|
8518
9039
|
}
|
|
@@ -8520,7 +9041,7 @@ function isDirectory(target) {
|
|
|
8520
9041
|
async function reportEmptyEnvironment(session, instance, workspaceRootDir) {
|
|
8521
9042
|
const remote = await readRemoteEnv(session, instance);
|
|
8522
9043
|
if (Object.keys(remote).length > 0) return;
|
|
8523
|
-
if (!
|
|
9044
|
+
if (!fs37.existsSync(path38.join(workspaceRootDir, ".env"))) return;
|
|
8524
9045
|
p42.log.warn(
|
|
8525
9046
|
`This app has no production environment variables yet.
|
|
8526
9047
|
|
|
@@ -8528,10 +9049,18 @@ Local ${pc18.cyan(".env")} values are not uploaded by a deploy. Set them with
|
|
|
8528
9049
|
${pc18.cyan("vela env set KEY")}, or copy a file across with ${pc18.cyan("vela env import .env.production")}.`
|
|
8529
9050
|
);
|
|
8530
9051
|
}
|
|
9052
|
+
async function serverTimeOrLocal(session) {
|
|
9053
|
+
try {
|
|
9054
|
+
return await serverTime(session);
|
|
9055
|
+
} catch {
|
|
9056
|
+
p42.log.warn("Could not read the clock on the server; stamping this release from this machine.");
|
|
9057
|
+
return /* @__PURE__ */ new Date();
|
|
9058
|
+
}
|
|
9059
|
+
}
|
|
8531
9060
|
|
|
8532
9061
|
// src/commands/link.ts
|
|
8533
|
-
import
|
|
8534
|
-
import
|
|
9062
|
+
import path39 from "node:path";
|
|
9063
|
+
import process29 from "node:process";
|
|
8535
9064
|
import { Command as Command77 } from "commander";
|
|
8536
9065
|
import * as p43 from "@clack/prompts";
|
|
8537
9066
|
var CREATE_NEW = "__new__";
|
|
@@ -8582,7 +9111,7 @@ async function pickExistingProject(projects) {
|
|
|
8582
9111
|
});
|
|
8583
9112
|
if (p43.isCancel(choice)) {
|
|
8584
9113
|
p43.cancel("Operation cancelled.");
|
|
8585
|
-
|
|
9114
|
+
process29.exit(0);
|
|
8586
9115
|
}
|
|
8587
9116
|
return choice;
|
|
8588
9117
|
}
|
|
@@ -8597,7 +9126,7 @@ async function pickTeam(teams3) {
|
|
|
8597
9126
|
});
|
|
8598
9127
|
if (p43.isCancel(choice)) {
|
|
8599
9128
|
p43.cancel("Operation cancelled.");
|
|
8600
|
-
|
|
9129
|
+
process29.exit(0);
|
|
8601
9130
|
}
|
|
8602
9131
|
return teams3.find((team) => team.id === choice);
|
|
8603
9132
|
}
|
|
@@ -8612,18 +9141,18 @@ async function promptProjectName(workspaceRootDir) {
|
|
|
8612
9141
|
});
|
|
8613
9142
|
if (p43.isCancel(value)) {
|
|
8614
9143
|
p43.cancel("Operation cancelled.");
|
|
8615
|
-
|
|
9144
|
+
process29.exit(0);
|
|
8616
9145
|
}
|
|
8617
9146
|
return value.trim();
|
|
8618
9147
|
}
|
|
8619
9148
|
function defaultProjectName2(workspaceRootDir) {
|
|
8620
9149
|
try {
|
|
8621
|
-
const pkg = readPackageJson(
|
|
9150
|
+
const pkg = readPackageJson(path39.join(workspaceRootDir, "package.json"));
|
|
8622
9151
|
const name = pkg.name;
|
|
8623
9152
|
if (typeof name === "string" && name.trim()) return name.trim();
|
|
8624
9153
|
} catch {
|
|
8625
9154
|
}
|
|
8626
|
-
return
|
|
9155
|
+
return path39.basename(workspaceRootDir);
|
|
8627
9156
|
}
|
|
8628
9157
|
|
|
8629
9158
|
// src/commands/env.ts
|
|
@@ -8667,7 +9196,7 @@ function report(keys, where) {
|
|
|
8667
9196
|
}
|
|
8668
9197
|
|
|
8669
9198
|
// src/commands/env/set.ts
|
|
8670
|
-
import
|
|
9199
|
+
import process30 from "node:process";
|
|
8671
9200
|
import { Command as Command79 } from "commander";
|
|
8672
9201
|
import * as p45 from "@clack/prompts";
|
|
8673
9202
|
import pc20 from "picocolors";
|
|
@@ -8709,7 +9238,7 @@ async function promptValue(key) {
|
|
|
8709
9238
|
});
|
|
8710
9239
|
if (p45.isCancel(value)) {
|
|
8711
9240
|
p45.cancel("Operation cancelled.");
|
|
8712
|
-
|
|
9241
|
+
process30.exit(0);
|
|
8713
9242
|
}
|
|
8714
9243
|
return value;
|
|
8715
9244
|
}
|
|
@@ -8754,9 +9283,9 @@ var envUnset = addTargetOptions(
|
|
|
8754
9283
|
);
|
|
8755
9284
|
|
|
8756
9285
|
// src/commands/env/import.ts
|
|
8757
|
-
import
|
|
8758
|
-
import
|
|
8759
|
-
import
|
|
9286
|
+
import fs38 from "node:fs";
|
|
9287
|
+
import path40 from "node:path";
|
|
9288
|
+
import process31 from "node:process";
|
|
8760
9289
|
import { Command as Command81 } from "commander";
|
|
8761
9290
|
import * as p47 from "@clack/prompts";
|
|
8762
9291
|
import pc22 from "picocolors";
|
|
@@ -8801,10 +9330,10 @@ var envImport = addTargetOptions(
|
|
|
8801
9330
|
)
|
|
8802
9331
|
);
|
|
8803
9332
|
function resolve(file) {
|
|
8804
|
-
return
|
|
9333
|
+
return path40.resolve(process31.cwd(), file);
|
|
8805
9334
|
}
|
|
8806
9335
|
function read(resolved, shown) {
|
|
8807
|
-
if (!
|
|
9336
|
+
if (!fs38.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
|
|
8808
9337
|
const incoming = readLocalEnvFile(resolved);
|
|
8809
9338
|
if (Object.keys(incoming).length === 0) p47.log.info(`${shown} has no variables to import.`);
|
|
8810
9339
|
return incoming;
|
|
@@ -8853,10 +9382,10 @@ function report2(states, json) {
|
|
|
8853
9382
|
return;
|
|
8854
9383
|
}
|
|
8855
9384
|
for (const state of states) {
|
|
8856
|
-
p48.log.info(
|
|
9385
|
+
p48.log.info(describe2(state));
|
|
8857
9386
|
}
|
|
8858
9387
|
}
|
|
8859
|
-
function
|
|
9388
|
+
function describe2(state) {
|
|
8860
9389
|
const health = (value) => value === "active" ? pc23.green(value) : pc23.red(value || "inactive");
|
|
8861
9390
|
const rows = [
|
|
8862
9391
|
["Instance", state.instance],
|
|
@@ -8880,9 +9409,11 @@ function describe(state) {
|
|
|
8880
9409
|
import { Command as Command84 } from "commander";
|
|
8881
9410
|
import * as p49 from "@clack/prompts";
|
|
8882
9411
|
import pc24 from "picocolors";
|
|
8883
|
-
var rollback =
|
|
8884
|
-
|
|
8885
|
-
|
|
9412
|
+
var rollback = addLockWaitOption(
|
|
9413
|
+
addTargetOptions(
|
|
9414
|
+
new Command84("rollback").description("put the previous release back").configureHelp(helpConfig),
|
|
9415
|
+
"production"
|
|
9416
|
+
)
|
|
8886
9417
|
).option("--to <release>", "roll back to a specific release instead of the previous one").action(
|
|
8887
9418
|
(raw) => runCommand(async () => {
|
|
8888
9419
|
const options = raw;
|
|
@@ -8897,7 +9428,11 @@ var rollback = addTargetOptions(
|
|
|
8897
9428
|
ctx.session,
|
|
8898
9429
|
"rollback.sh",
|
|
8899
9430
|
{
|
|
8900
|
-
args: [
|
|
9431
|
+
args: [
|
|
9432
|
+
ctx.instance,
|
|
9433
|
+
...options.to ? ["--to", options.to] : [],
|
|
9434
|
+
...lockWaitArgs(options.lockWait)
|
|
9435
|
+
],
|
|
8901
9436
|
stream: true
|
|
8902
9437
|
}
|
|
8903
9438
|
);
|
|
@@ -8954,7 +9489,7 @@ var logs = addTargetOptions(
|
|
|
8954
9489
|
import { Command as Command87 } from "commander";
|
|
8955
9490
|
|
|
8956
9491
|
// src/commands/admin/create.ts
|
|
8957
|
-
import
|
|
9492
|
+
import process32 from "node:process";
|
|
8958
9493
|
import { Command as Command86 } from "commander";
|
|
8959
9494
|
import * as p50 from "@clack/prompts";
|
|
8960
9495
|
import pc25 from "picocolors";
|
|
@@ -9021,7 +9556,7 @@ async function upsertSuperuser(pb, email3, password11) {
|
|
|
9021
9556
|
});
|
|
9022
9557
|
if (p50.isCancel(confirmed) || !confirmed) {
|
|
9023
9558
|
p50.cancel("Operation cancelled.");
|
|
9024
|
-
|
|
9559
|
+
process32.exit(0);
|
|
9025
9560
|
}
|
|
9026
9561
|
await pb.collection("_superusers").update(existing, { password: password11, passwordConfirm: password11 });
|
|
9027
9562
|
p50.log.success(`Password updated for ${pc25.cyan(email3)}, you can sign in now`);
|
|
@@ -9045,7 +9580,7 @@ async function promptEmail() {
|
|
|
9045
9580
|
});
|
|
9046
9581
|
if (p50.isCancel(value)) {
|
|
9047
9582
|
p50.cancel("Operation cancelled.");
|
|
9048
|
-
|
|
9583
|
+
process32.exit(0);
|
|
9049
9584
|
}
|
|
9050
9585
|
return value.trim();
|
|
9051
9586
|
}
|
|
@@ -9056,7 +9591,7 @@ async function promptPassword2() {
|
|
|
9056
9591
|
});
|
|
9057
9592
|
if (p50.isCancel(value)) {
|
|
9058
9593
|
p50.cancel("Operation cancelled.");
|
|
9059
|
-
|
|
9594
|
+
process32.exit(0);
|
|
9060
9595
|
}
|
|
9061
9596
|
const again = await p50.password({
|
|
9062
9597
|
message: "Password again",
|
|
@@ -9064,7 +9599,7 @@ async function promptPassword2() {
|
|
|
9064
9599
|
});
|
|
9065
9600
|
if (p50.isCancel(again)) {
|
|
9066
9601
|
p50.cancel("Operation cancelled.");
|
|
9067
|
-
|
|
9602
|
+
process32.exit(0);
|
|
9068
9603
|
}
|
|
9069
9604
|
return value;
|
|
9070
9605
|
}
|
|
@@ -9076,8 +9611,8 @@ var admin = new Command87("admin").description("manage admin panel logins").conf
|
|
|
9076
9611
|
import { Command as Command93 } from "commander";
|
|
9077
9612
|
|
|
9078
9613
|
// src/commands/backup/create.ts
|
|
9079
|
-
import
|
|
9080
|
-
import
|
|
9614
|
+
import fs39 from "node:fs";
|
|
9615
|
+
import path41 from "node:path";
|
|
9081
9616
|
import { Command as Command88 } from "commander";
|
|
9082
9617
|
import * as p51 from "@clack/prompts";
|
|
9083
9618
|
import pc26 from "picocolors";
|
|
@@ -9231,12 +9766,12 @@ Your bucket's own versioning is what protects the uploaded files.`
|
|
|
9231
9766
|
}, "Failed to create the backup.")
|
|
9232
9767
|
);
|
|
9233
9768
|
async function download(ctx, key, outputDir) {
|
|
9234
|
-
const dir =
|
|
9235
|
-
|
|
9236
|
-
const destination =
|
|
9769
|
+
const dir = path41.resolve(ctx.workspaceRootDir, outputDir);
|
|
9770
|
+
fs39.mkdirSync(dir, { recursive: true });
|
|
9771
|
+
const destination = path41.join(dir, key);
|
|
9237
9772
|
if (!ctx.session) {
|
|
9238
|
-
|
|
9239
|
-
return
|
|
9773
|
+
fs39.copyFileSync(path41.join(ctx.workspaceRootDir, "data", "backups", key), destination);
|
|
9774
|
+
return path41.relative(ctx.workspaceRootDir, destination);
|
|
9240
9775
|
}
|
|
9241
9776
|
const spinner7 = p51.spinner();
|
|
9242
9777
|
spinner7.start(`Downloading ${key}`);
|
|
@@ -9247,7 +9782,7 @@ async function download(ctx, key, outputDir) {
|
|
|
9247
9782
|
throw error;
|
|
9248
9783
|
}
|
|
9249
9784
|
spinner7.stop(`Downloaded ${key}`);
|
|
9250
|
-
return
|
|
9785
|
+
return path41.relative(ctx.workspaceRootDir, destination);
|
|
9251
9786
|
}
|
|
9252
9787
|
|
|
9253
9788
|
// src/commands/backup/list.ts
|
|
@@ -9281,8 +9816,8 @@ Take one with ${pc27.cyan("vela backup create")}.`
|
|
|
9281
9816
|
);
|
|
9282
9817
|
|
|
9283
9818
|
// src/commands/backup/download.ts
|
|
9284
|
-
import
|
|
9285
|
-
import
|
|
9819
|
+
import fs40 from "node:fs";
|
|
9820
|
+
import path42 from "node:path";
|
|
9286
9821
|
import { Command as Command90 } from "commander";
|
|
9287
9822
|
import * as p53 from "@clack/prompts";
|
|
9288
9823
|
import pc28 from "picocolors";
|
|
@@ -9309,11 +9844,11 @@ Run ${pc28.cyan("vela backup list")} to see what it does have.`
|
|
|
9309
9844
|
Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
9310
9845
|
);
|
|
9311
9846
|
}
|
|
9312
|
-
const dir =
|
|
9313
|
-
|
|
9314
|
-
const destination =
|
|
9847
|
+
const dir = path42.resolve(ctx.workspaceRootDir, options.output);
|
|
9848
|
+
fs40.mkdirSync(dir, { recursive: true });
|
|
9849
|
+
const destination = path42.join(dir, key);
|
|
9315
9850
|
if (!ctx.session) {
|
|
9316
|
-
|
|
9851
|
+
fs40.copyFileSync(path42.join(ctx.workspaceRootDir, "data", "backups", key), destination);
|
|
9317
9852
|
} else {
|
|
9318
9853
|
const spinner7 = p53.spinner();
|
|
9319
9854
|
spinner7.start(`Downloading ${key} (${formatBytes(found.size)})`);
|
|
@@ -9327,14 +9862,14 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
|
9327
9862
|
}
|
|
9328
9863
|
reportResult({
|
|
9329
9864
|
summary: `Saved ${key} from ${ctx.targetName}.`,
|
|
9330
|
-
filesCreated: [
|
|
9865
|
+
filesCreated: [path42.relative(ctx.workspaceRootDir, destination)]
|
|
9331
9866
|
});
|
|
9332
9867
|
});
|
|
9333
9868
|
}, "Failed to download the backup.")
|
|
9334
9869
|
);
|
|
9335
9870
|
|
|
9336
9871
|
// src/commands/backup/delete.ts
|
|
9337
|
-
import
|
|
9872
|
+
import process33 from "node:process";
|
|
9338
9873
|
import { Command as Command91 } from "commander";
|
|
9339
9874
|
import * as p54 from "@clack/prompts";
|
|
9340
9875
|
import pc29 from "picocolors";
|
|
@@ -9360,7 +9895,7 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
|
|
|
9360
9895
|
});
|
|
9361
9896
|
if (p54.isCancel(confirmed) || !confirmed) {
|
|
9362
9897
|
p54.cancel("Operation cancelled.");
|
|
9363
|
-
|
|
9898
|
+
process33.exit(0);
|
|
9364
9899
|
}
|
|
9365
9900
|
}
|
|
9366
9901
|
await ctx.pb.backups.delete(key);
|
|
@@ -9422,15 +9957,17 @@ Set one with ${pc30.cyan('vela backup schedule "0 3 * * *"')}.`
|
|
|
9422
9957
|
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);
|
|
9423
9958
|
|
|
9424
9959
|
// src/commands/restore.ts
|
|
9425
|
-
import
|
|
9426
|
-
import
|
|
9427
|
-
import
|
|
9960
|
+
import fs41 from "node:fs";
|
|
9961
|
+
import path43 from "node:path";
|
|
9962
|
+
import process34 from "node:process";
|
|
9428
9963
|
import { Command as Command94 } from "commander";
|
|
9429
9964
|
import * as p56 from "@clack/prompts";
|
|
9430
9965
|
import pc31 from "picocolors";
|
|
9431
|
-
var restore =
|
|
9432
|
-
|
|
9433
|
-
|
|
9966
|
+
var restore = addLockWaitOption(
|
|
9967
|
+
addTargetOptions(
|
|
9968
|
+
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),
|
|
9969
|
+
"production"
|
|
9970
|
+
)
|
|
9434
9971
|
).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(
|
|
9435
9972
|
(source, raw) => runCommand(async () => {
|
|
9436
9973
|
const options = raw;
|
|
@@ -9444,10 +9981,10 @@ var restore = addTargetOptions(
|
|
|
9444
9981
|
`${ctx.targetName} was deployed without a database, so there is nothing to restore.`
|
|
9445
9982
|
);
|
|
9446
9983
|
}
|
|
9447
|
-
const local = source &&
|
|
9984
|
+
const local = source && fs41.existsSync(source) ? source : void 0;
|
|
9448
9985
|
const key = local ? void 0 : await resolveKey(ctx, source);
|
|
9449
9986
|
if (!options.yes) {
|
|
9450
|
-
await
|
|
9987
|
+
await confirm13(ctx.appName, ctx.targetName, ctx.envTag, local ?? key);
|
|
9451
9988
|
}
|
|
9452
9989
|
const archive = local ? await stage(ctx, local) : remotePaths.backup(ctx.instance, key);
|
|
9453
9990
|
const result = await runServerScript(ctx.session, "restore.sh", {
|
|
@@ -9460,13 +9997,14 @@ var restore = addTargetOptions(
|
|
|
9460
9997
|
...options.migrate ? [] : ["--no-migrate"],
|
|
9461
9998
|
// A copy this machine pushed up is scratch; one already in the
|
|
9462
9999
|
// instance's own backups directory is not ours to delete.
|
|
9463
|
-
...local ? ["--cleanup-archive"] : []
|
|
10000
|
+
...local ? ["--cleanup-archive"] : [],
|
|
10001
|
+
...lockWaitArgs(options.lockWait)
|
|
9464
10002
|
],
|
|
9465
10003
|
stream: true
|
|
9466
10004
|
});
|
|
9467
10005
|
p56.log.success(
|
|
9468
10006
|
`Restored ${pc31.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc31.cyan(
|
|
9469
|
-
local ?
|
|
10007
|
+
local ? path43.basename(local) : key
|
|
9470
10008
|
)}.`
|
|
9471
10009
|
);
|
|
9472
10010
|
if (result?.storageCarriedOver) {
|
|
@@ -9526,27 +10064,27 @@ Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive
|
|
|
9526
10064
|
});
|
|
9527
10065
|
if (p56.isCancel(chosen)) {
|
|
9528
10066
|
p56.cancel("Operation cancelled.");
|
|
9529
|
-
|
|
10067
|
+
process34.exit(0);
|
|
9530
10068
|
}
|
|
9531
10069
|
return chosen;
|
|
9532
10070
|
}
|
|
9533
10071
|
async function stage(ctx, file) {
|
|
9534
10072
|
const dir = remotePaths.restoreStage(ctx.instance);
|
|
9535
|
-
const remote = `${dir}/${
|
|
10073
|
+
const remote = `${dir}/${path43.basename(file)}`;
|
|
9536
10074
|
const spinner7 = p56.spinner();
|
|
9537
|
-
spinner7.start(`Uploading ${
|
|
10075
|
+
spinner7.start(`Uploading ${path43.basename(file)}`);
|
|
9538
10076
|
try {
|
|
9539
10077
|
await ctx.session.script(`mkdir -p "$1"`, { args: [dir] });
|
|
9540
10078
|
await ctx.session.upload([file], dir);
|
|
9541
10079
|
} catch (error) {
|
|
9542
|
-
spinner7.stop(`Could not upload ${
|
|
10080
|
+
spinner7.stop(`Could not upload ${path43.basename(file)}.`);
|
|
9543
10081
|
throw error;
|
|
9544
10082
|
}
|
|
9545
|
-
spinner7.stop(`Uploaded ${
|
|
10083
|
+
spinner7.stop(`Uploaded ${path43.basename(file)}`);
|
|
9546
10084
|
return remote;
|
|
9547
10085
|
}
|
|
9548
|
-
async function
|
|
9549
|
-
const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(
|
|
10086
|
+
async function confirm13(appName, targetName, envTag, from) {
|
|
10087
|
+
const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(path43.basename(from))}`;
|
|
9550
10088
|
if (isProd(envTag)) {
|
|
9551
10089
|
const answer = await p56.text({
|
|
9552
10090
|
message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
|
|
@@ -9554,7 +10092,7 @@ async function confirm12(appName, targetName, envTag, from) {
|
|
|
9554
10092
|
});
|
|
9555
10093
|
if (p56.isCancel(answer)) {
|
|
9556
10094
|
p56.cancel("Operation cancelled.");
|
|
9557
|
-
|
|
10095
|
+
process34.exit(0);
|
|
9558
10096
|
}
|
|
9559
10097
|
return;
|
|
9560
10098
|
}
|
|
@@ -9564,7 +10102,7 @@ async function confirm12(appName, targetName, envTag, from) {
|
|
|
9564
10102
|
});
|
|
9565
10103
|
if (p56.isCancel(ok) || !ok) {
|
|
9566
10104
|
p56.cancel("Operation cancelled.");
|
|
9567
|
-
|
|
10105
|
+
process34.exit(0);
|
|
9568
10106
|
}
|
|
9569
10107
|
}
|
|
9570
10108
|
|
|
@@ -9657,36 +10195,36 @@ Release and domain are shown from what this project recorded.`
|
|
|
9657
10195
|
}
|
|
9658
10196
|
|
|
9659
10197
|
// src/commands/test.ts
|
|
9660
|
-
import
|
|
9661
|
-
import
|
|
10198
|
+
import path44 from "node:path";
|
|
10199
|
+
import process35 from "node:process";
|
|
9662
10200
|
import { Command as Command96 } from "commander";
|
|
9663
10201
|
import PocketBase6 from "pocketbase";
|
|
9664
10202
|
import pc33 from "picocolors";
|
|
9665
10203
|
import { x as x5 } from "tinyexec";
|
|
9666
|
-
import { detect as
|
|
10204
|
+
import { detect as detect8 } from "package-manager-detector";
|
|
9667
10205
|
import { resolveCommand as resolveCommand7 } from "package-manager-detector/commands";
|
|
9668
|
-
import
|
|
10206
|
+
import fs42 from "node:fs";
|
|
9669
10207
|
var testServer = new Command96("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
|
|
9670
|
-
const cwd =
|
|
10208
|
+
const cwd = process35.cwd();
|
|
9671
10209
|
const email3 = `test-${Math.random().toString(36).slice(2)}@example.com`;
|
|
9672
10210
|
const password11 = "password";
|
|
9673
|
-
const testDataDir =
|
|
9674
|
-
|
|
10211
|
+
const testDataDir = path44.join(cwd, "test-data");
|
|
10212
|
+
fs42.rmSync(testDataDir, { recursive: true, force: true });
|
|
9675
10213
|
const { stop, url } = await launchPocketbase(cwd, {
|
|
9676
10214
|
dir: testDataDir,
|
|
9677
|
-
migrationsDir:
|
|
10215
|
+
migrationsDir: path44.join(cwd, MIGRATIONS_DIR),
|
|
9678
10216
|
// The app's PocketBase hooks (slug generation, personal teams, …) are part
|
|
9679
10217
|
// of its behaviour; the suite runs against the same server dev and build
|
|
9680
10218
|
// start, so it loads them from the same place.
|
|
9681
|
-
hooksDir:
|
|
10219
|
+
hooksDir: path44.join(cwd, DATA_DIR, "hooks"),
|
|
9682
10220
|
email: email3,
|
|
9683
10221
|
password: password11
|
|
9684
10222
|
});
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
10223
|
+
process35.env.POCKETBASE_URL = url;
|
|
10224
|
+
process35.env.POCKETBASE_SUPERUSER_EMAIL = email3;
|
|
10225
|
+
process35.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
|
|
10226
|
+
process35.env.VELA_DATA_DIR = testDataDir;
|
|
10227
|
+
process35.env.TEST = "true";
|
|
9690
10228
|
console.log(`${pc33.greenBright("\u2713")} Created test database`);
|
|
9691
10229
|
let vite;
|
|
9692
10230
|
let cleanedUp = false;
|
|
@@ -9694,7 +10232,7 @@ var testServer = new Command96("test:server").description("run server tests").al
|
|
|
9694
10232
|
if (cleanedUp) return;
|
|
9695
10233
|
cleanedUp = true;
|
|
9696
10234
|
stop();
|
|
9697
|
-
|
|
10235
|
+
fs42.rmSync(testDataDir, { recursive: true, force: true });
|
|
9698
10236
|
};
|
|
9699
10237
|
const cleanup = async () => {
|
|
9700
10238
|
if (cleanedUp) return;
|
|
@@ -9705,12 +10243,12 @@ var testServer = new Command96("test:server").description("run server tests").al
|
|
|
9705
10243
|
const fail = async (message) => {
|
|
9706
10244
|
console.error(`${pc33.redBright("\u2717")} ${message}`);
|
|
9707
10245
|
await cleanup();
|
|
9708
|
-
|
|
10246
|
+
process35.exit(1);
|
|
9709
10247
|
};
|
|
9710
|
-
|
|
9711
|
-
|
|
10248
|
+
process35.on("exit", cleanupSync);
|
|
10249
|
+
process35.on("SIGINT", () => {
|
|
9712
10250
|
cleanupSync();
|
|
9713
|
-
|
|
10251
|
+
process35.exit(130);
|
|
9714
10252
|
});
|
|
9715
10253
|
const pb = new PocketBase6(url);
|
|
9716
10254
|
try {
|
|
@@ -9738,7 +10276,7 @@ var testServer = new Command96("test:server").description("run server tests").al
|
|
|
9738
10276
|
});
|
|
9739
10277
|
const vitePort = await findFreePort();
|
|
9740
10278
|
await vite.listen(vitePort);
|
|
9741
|
-
|
|
10279
|
+
process35.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
|
|
9742
10280
|
console.log(`${pc33.greenBright("\u2713")} Started Vite: http://localhost:${vitePort}`);
|
|
9743
10281
|
console.log(`${pc33.greenBright("\u2713")} Started PocketBase: ${url}`);
|
|
9744
10282
|
const extraArgs = (cmd.parent?.args ?? []).slice(1);
|
|
@@ -9746,7 +10284,7 @@ var testServer = new Command96("test:server").description("run server tests").al
|
|
|
9746
10284
|
const passthrough = filter ? extraArgs.filter((a) => a !== filter) : extraArgs;
|
|
9747
10285
|
if (!filter) filter = "server";
|
|
9748
10286
|
try {
|
|
9749
|
-
const pm = (await
|
|
10287
|
+
const pm = (await detect8({ cwd }))?.name ?? "npm";
|
|
9750
10288
|
const resolved = resolveCommand7(pm, "execute", [
|
|
9751
10289
|
"vitest",
|
|
9752
10290
|
"run",
|
|
@@ -9757,12 +10295,12 @@ var testServer = new Command96("test:server").description("run server tests").al
|
|
|
9757
10295
|
const resolvedArgs = resolved.args.slice();
|
|
9758
10296
|
if (pm === "npm") resolvedArgs.unshift("--yes");
|
|
9759
10297
|
const result = await x5(resolved.command, resolvedArgs, {
|
|
9760
|
-
nodeOptions: { cwd, stdio: "inherit", env: { ...
|
|
10298
|
+
nodeOptions: { cwd, stdio: "inherit", env: { ...process35.env, CI: "1" } }
|
|
9761
10299
|
});
|
|
9762
|
-
|
|
10300
|
+
process35.exitCode = result.exitCode ?? 1;
|
|
9763
10301
|
} catch (e) {
|
|
9764
10302
|
console.error(`${pc33.redBright("\u2717")} ${e.message}`);
|
|
9765
|
-
|
|
10303
|
+
process35.exitCode = 1;
|
|
9766
10304
|
} finally {
|
|
9767
10305
|
await cleanup();
|
|
9768
10306
|
}
|
|
@@ -9793,8 +10331,8 @@ function stubPagesPlugin() {
|
|
|
9793
10331
|
}
|
|
9794
10332
|
|
|
9795
10333
|
// src/commands/routes.ts
|
|
9796
|
-
import
|
|
9797
|
-
import
|
|
10334
|
+
import fs43 from "node:fs";
|
|
10335
|
+
import path45 from "node:path";
|
|
9798
10336
|
import { Command as Command97 } from "commander";
|
|
9799
10337
|
var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
9800
10338
|
"GET",
|
|
@@ -9808,30 +10346,30 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
|
9808
10346
|
]);
|
|
9809
10347
|
var routes = new Command97("routes").description("list routes").configureHelp(helpConfig).action(async () => {
|
|
9810
10348
|
const { workspaceRootDir, routesDir } = await getWorkspace();
|
|
9811
|
-
const routesRoot =
|
|
10349
|
+
const routesRoot = path45.join(workspaceRootDir, routesDir);
|
|
9812
10350
|
const found = walk(routesRoot, routesRoot).filter((r) => r.methods.length > 0);
|
|
9813
10351
|
found.sort((a, b) => a.urlPattern.localeCompare(b.urlPattern));
|
|
9814
10352
|
printTable(found);
|
|
9815
10353
|
});
|
|
9816
10354
|
function walk(root, dir) {
|
|
9817
|
-
const entries =
|
|
10355
|
+
const entries = fs43.readdirSync(dir, { withFileTypes: true });
|
|
9818
10356
|
const routes2 = [];
|
|
9819
10357
|
const hasLeaf = entries.some((e) => e.isFile() && isRouteFile(e.name));
|
|
9820
10358
|
if (hasLeaf) {
|
|
9821
|
-
const id = "/" +
|
|
10359
|
+
const id = "/" + path45.relative(root, dir).split(path45.sep).filter(Boolean).join("/");
|
|
9822
10360
|
const urlPattern = id.replace(/\([^)]+\)\/?/g, "").replace(/\/$/, "") || "/";
|
|
9823
10361
|
const methods = /* @__PURE__ */ new Set();
|
|
9824
10362
|
for (const entry of entries) {
|
|
9825
10363
|
if (!entry.isFile()) continue;
|
|
9826
10364
|
if (entry.name.endsWith("+page.svelte")) methods.add("GET");
|
|
9827
10365
|
if (entry.name.endsWith("+server.ts") || entry.name.endsWith("+server.js") || entry.name.endsWith("+page.server.ts") || entry.name.endsWith("+page.server.js")) {
|
|
9828
|
-
extractMethods(
|
|
10366
|
+
extractMethods(path45.join(dir, entry.name)).forEach((m) => methods.add(m));
|
|
9829
10367
|
}
|
|
9830
10368
|
}
|
|
9831
10369
|
routes2.push({ id: id || "/", urlPattern, methods: [...methods] });
|
|
9832
10370
|
}
|
|
9833
10371
|
for (const entry of entries) {
|
|
9834
|
-
if (entry.isDirectory()) routes2.push(...walk(root,
|
|
10372
|
+
if (entry.isDirectory()) routes2.push(...walk(root, path45.join(dir, entry.name)));
|
|
9835
10373
|
}
|
|
9836
10374
|
return routes2;
|
|
9837
10375
|
}
|
|
@@ -9840,7 +10378,7 @@ function isRouteFile(name) {
|
|
|
9840
10378
|
}
|
|
9841
10379
|
function extractMethods(file) {
|
|
9842
10380
|
try {
|
|
9843
|
-
const content =
|
|
10381
|
+
const content = fs43.readFileSync(file, "utf8");
|
|
9844
10382
|
const methods = [];
|
|
9845
10383
|
const exportRegex = /export\s+(?:const|async\s+function|function)\s+(\w+)/g;
|
|
9846
10384
|
let match;
|
|
@@ -9881,14 +10419,14 @@ function printTable(routes2) {
|
|
|
9881
10419
|
}
|
|
9882
10420
|
|
|
9883
10421
|
// src/commands/i18n.ts
|
|
9884
|
-
import
|
|
10422
|
+
import process36 from "node:process";
|
|
9885
10423
|
import { Command as Command98 } from "commander";
|
|
9886
10424
|
import { x as x6 } from "tinyexec";
|
|
9887
|
-
import { detect as
|
|
10425
|
+
import { detect as detect9 } from "package-manager-detector";
|
|
9888
10426
|
import { resolveCommand as resolveCommand8 } from "package-manager-detector/commands";
|
|
9889
10427
|
async function runWuchale(extraArgs) {
|
|
9890
|
-
const cwd =
|
|
9891
|
-
const pm = (await
|
|
10428
|
+
const cwd = process36.cwd();
|
|
10429
|
+
const pm = (await detect9({ cwd }))?.name ?? "npm";
|
|
9892
10430
|
const resolved = resolveCommand8(pm, "execute", ["wuchale", ...extraArgs]);
|
|
9893
10431
|
const args = resolved.args.slice();
|
|
9894
10432
|
if (pm === "npm") args.unshift("--yes");
|
|
@@ -9923,15 +10461,15 @@ import pc35 from "picocolors";
|
|
|
9923
10461
|
|
|
9924
10462
|
// src/lib/cms-backend.ts
|
|
9925
10463
|
import { createRequire as createRequire3 } from "node:module";
|
|
9926
|
-
import
|
|
9927
|
-
import
|
|
10464
|
+
import path46 from "node:path";
|
|
10465
|
+
import process37 from "node:process";
|
|
9928
10466
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
9929
10467
|
import pc34 from "picocolors";
|
|
9930
10468
|
var DEFAULT_PROJECT = "default";
|
|
9931
10469
|
async function loadBackendModule(root) {
|
|
9932
10470
|
let entry;
|
|
9933
10471
|
try {
|
|
9934
|
-
entry = createRequire3(
|
|
10472
|
+
entry = createRequire3(path46.join(root, "package.json")).resolve("@velastack/cms/backend");
|
|
9935
10473
|
} catch {
|
|
9936
10474
|
throw new Error(
|
|
9937
10475
|
`@velastack/cms is not installed in this project.
|
|
@@ -9941,7 +10479,7 @@ Run ${pc34.cyan("vela enable cms")} first.`
|
|
|
9941
10479
|
}
|
|
9942
10480
|
return await import(pathToFileURL3(entry).href);
|
|
9943
10481
|
}
|
|
9944
|
-
async function withCmsBackend(fn, cwd =
|
|
10482
|
+
async function withCmsBackend(fn, cwd = process37.cwd()) {
|
|
9945
10483
|
const root = findWorkspaceRoot(cwd);
|
|
9946
10484
|
if (!root) {
|
|
9947
10485
|
throw new Error("Could not find workspace root (no package.json found)");
|
|
@@ -9949,8 +10487,8 @@ async function withCmsBackend(fn, cwd = process36.cwd()) {
|
|
|
9949
10487
|
const { createCmsBackend } = await loadBackendModule(root);
|
|
9950
10488
|
const dataDir2 = localDataDir(root);
|
|
9951
10489
|
const backend3 = createCmsBackend({
|
|
9952
|
-
dbPath:
|
|
9953
|
-
uploadDir:
|
|
10490
|
+
dbPath: path46.join(dataDir2, "cms.sqlite"),
|
|
10491
|
+
uploadDir: path46.join(dataDir2, "uploads")
|
|
9954
10492
|
});
|
|
9955
10493
|
try {
|
|
9956
10494
|
return await fn(backend3);
|
|
@@ -10053,23 +10591,26 @@ var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
|
|
|
10053
10591
|
// Acts on whichever target `-t` names; the local path reads the project's
|
|
10054
10592
|
// own credentials rather than requiring them in this process.
|
|
10055
10593
|
"backup",
|
|
10056
|
-
"restore"
|
|
10594
|
+
"restore",
|
|
10595
|
+
// Removes a copy from its server; the other `destroy` subcommands edit the
|
|
10596
|
+
// local schema and stay gated.
|
|
10597
|
+
"destroy deployment"
|
|
10057
10598
|
]);
|
|
10058
10599
|
var BACKEND_OPTIONAL_COMMANDS = /* @__PURE__ */ new Set(["dev", "build", "preview", "deploy"]);
|
|
10059
10600
|
var SELF_CREDENTIALED_COMMANDS = /* @__PURE__ */ new Set(["test:server"]);
|
|
10060
10601
|
var program = new Command104().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
|
|
10061
10602
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
10062
10603
|
if (isStub(actionCommand)) return;
|
|
10063
|
-
const envRoot = findWorkspaceRoot() ??
|
|
10604
|
+
const envRoot = findWorkspaceRoot() ?? process38.cwd();
|
|
10064
10605
|
dotenv2.config({ path: nodePath.join(envRoot, ".env"), quiet: true });
|
|
10065
|
-
const
|
|
10066
|
-
if (NO_BACKEND_COMMMANDS.has(
|
|
10067
|
-
const top =
|
|
10606
|
+
const path47 = getCommandPath(actionCommand);
|
|
10607
|
+
if (NO_BACKEND_COMMMANDS.has(path47)) return;
|
|
10608
|
+
const top = path47.split(" ", 1)[0];
|
|
10068
10609
|
if (NO_BACKEND_COMMMANDS.has(top)) return;
|
|
10069
10610
|
if (!hasBackend()) {
|
|
10070
10611
|
if (BACKEND_OPTIONAL_COMMANDS.has(top)) return;
|
|
10071
10612
|
p61.log.error(
|
|
10072
|
-
`${pc38.cyan(`vela ${
|
|
10613
|
+
`${pc38.cyan(`vela ${path47}`)} needs a backend, and this project does not have one.
|
|
10073
10614
|
|
|
10074
10615
|
Static projects have no database to talk to.
|
|
10075
10616
|
|
|
@@ -10077,10 +10618,10 @@ To add a backend to this project, run ${pc38.cyan("vela bless")}.`
|
|
|
10077
10618
|
);
|
|
10078
10619
|
p61.log.message();
|
|
10079
10620
|
p61.cancel("Operation failed.");
|
|
10080
|
-
|
|
10621
|
+
process38.exit(1);
|
|
10081
10622
|
}
|
|
10082
|
-
if (SELF_CREDENTIALED_COMMANDS.has(
|
|
10083
|
-
if (!
|
|
10623
|
+
if (SELF_CREDENTIALED_COMMANDS.has(path47)) return;
|
|
10624
|
+
if (!process38.env.POCKETBASE_SUPERUSER_EMAIL || !process38.env.POCKETBASE_SUPERUSER_PASSWORD) {
|
|
10084
10625
|
p61.log.error(
|
|
10085
10626
|
`PocketBase superuser credentials are required.
|
|
10086
10627
|
|
|
@@ -10091,7 +10632,7 @@ To set up an existing project, run ${pc38.cyan("vela bless")}.`
|
|
|
10091
10632
|
);
|
|
10092
10633
|
p61.log.message();
|
|
10093
10634
|
p61.cancel("Operation failed.");
|
|
10094
|
-
|
|
10635
|
+
process38.exit(1);
|
|
10095
10636
|
}
|
|
10096
10637
|
});
|
|
10097
10638
|
function getCommandPath(cmd) {
|
|
@@ -10145,5 +10686,5 @@ for (const command of [
|
|
|
10145
10686
|
}
|
|
10146
10687
|
|
|
10147
10688
|
// src/bin.ts
|
|
10148
|
-
program.parse(normalizeArgv(
|
|
10689
|
+
program.parse(normalizeArgv(process39.argv.slice(2)), { from: "user" });
|
|
10149
10690
|
//# sourceMappingURL=bin.js.map
|