vela 0.25.1 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/bin.js +477 -351
- package/dist/bin.js.map +4 -4
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -20,7 +20,7 @@ import dotenv2 from "dotenv";
|
|
|
20
20
|
// package.json
|
|
21
21
|
var package_default = {
|
|
22
22
|
name: "vela",
|
|
23
|
-
version: "0.
|
|
23
|
+
version: "0.26.0",
|
|
24
24
|
type: "module",
|
|
25
25
|
description: "A CLI for creating and updating SvelteKit projects",
|
|
26
26
|
license: "MIT",
|
|
@@ -1476,7 +1476,7 @@ async function execPackageBin(cwd, args, stdio = "pipe") {
|
|
|
1476
1476
|
if (packageManager2 === "npm") resolvedArgs.unshift("--yes");
|
|
1477
1477
|
return x(command, resolvedArgs, { nodeOptions: { cwd, stdio }, throwOnError: true });
|
|
1478
1478
|
}
|
|
1479
|
-
async function withPocketbase(cwd, fn, creds) {
|
|
1479
|
+
async function withPocketbase(cwd, fn, creds, opts = {}) {
|
|
1480
1480
|
const dir = path8.join(cwd, DATA_DIR);
|
|
1481
1481
|
const migrationsDir = path8.join(cwd, MIGRATIONS_DIR);
|
|
1482
1482
|
const host = "localhost";
|
|
@@ -1492,9 +1492,11 @@ async function withPocketbase(cwd, fn, creds) {
|
|
|
1492
1492
|
await fn(pb);
|
|
1493
1493
|
return;
|
|
1494
1494
|
}
|
|
1495
|
+
const hooksDir = path8.join(dir, "hooks");
|
|
1495
1496
|
const { proc, url } = await startPocketbaseServe({
|
|
1496
1497
|
dataDir: dir,
|
|
1497
1498
|
migrationsDir,
|
|
1499
|
+
...opts.hooks && fs9.existsSync(hooksDir) ? { hooksDir } : {},
|
|
1498
1500
|
host,
|
|
1499
1501
|
stdio: "ignore"
|
|
1500
1502
|
});
|
|
@@ -2772,18 +2774,18 @@ async function ensureEnvDeclarations(root, specs) {
|
|
|
2772
2774
|
|
|
2773
2775
|
// src/lib/result-report.ts
|
|
2774
2776
|
import * as p5 from "@clack/prompts";
|
|
2775
|
-
function reportResult(
|
|
2777
|
+
function reportResult(report6) {
|
|
2776
2778
|
const sections = [
|
|
2777
|
-
["Files created",
|
|
2778
|
-
["Files modified",
|
|
2779
|
-
["Files deleted",
|
|
2780
|
-
["UI components added",
|
|
2781
|
-
["Packages installed",
|
|
2782
|
-
["Collections added",
|
|
2783
|
-
["Records loaded",
|
|
2784
|
-
["Records cleared",
|
|
2779
|
+
["Files created", report6.filesCreated],
|
|
2780
|
+
["Files modified", report6.filesModified],
|
|
2781
|
+
["Files deleted", report6.filesDeleted],
|
|
2782
|
+
["UI components added", report6.componentsAdded],
|
|
2783
|
+
["Packages installed", report6.packagesInstalled],
|
|
2784
|
+
["Collections added", report6.collectionsAdded],
|
|
2785
|
+
["Records loaded", report6.recordsLoaded],
|
|
2786
|
+
["Records cleared", report6.recordsCleared]
|
|
2785
2787
|
];
|
|
2786
|
-
for (const extra of
|
|
2788
|
+
for (const extra of report6.sections ?? []) {
|
|
2787
2789
|
sections.push([extra.label, extra.items]);
|
|
2788
2790
|
}
|
|
2789
2791
|
const body = [];
|
|
@@ -2793,13 +2795,13 @@ function reportResult(report5) {
|
|
|
2793
2795
|
body.push(`${label2}:`);
|
|
2794
2796
|
for (const item of items) body.push(`- ${item}`);
|
|
2795
2797
|
}
|
|
2796
|
-
const failures =
|
|
2798
|
+
const failures = report6.failures ?? [];
|
|
2797
2799
|
if (body.length > 0) {
|
|
2798
|
-
p5.log.success(`${
|
|
2800
|
+
p5.log.success(`${report6.summary}
|
|
2799
2801
|
|
|
2800
2802
|
${body.join("\n")}`);
|
|
2801
2803
|
} else if (failures.length === 0) {
|
|
2802
|
-
p5.log.success(
|
|
2804
|
+
p5.log.success(report6.summary);
|
|
2803
2805
|
}
|
|
2804
2806
|
for (const failure of failures) {
|
|
2805
2807
|
const headline = failure.status === "not-found" ? `Could not find ${failure.path}` : `Could not update ${failure.path}`;
|
|
@@ -2807,8 +2809,8 @@ ${body.join("\n")}`);
|
|
|
2807
2809
|
|
|
2808
2810
|
${failure.message}` : headline);
|
|
2809
2811
|
}
|
|
2810
|
-
if (
|
|
2811
|
-
p5.note(
|
|
2812
|
+
if (report6.nextSteps && report6.nextSteps.length > 0) {
|
|
2813
|
+
p5.note(report6.nextSteps.map((s) => `- ${s}`).join("\n"), "Next steps", {
|
|
2812
2814
|
format: (line) => line
|
|
2813
2815
|
});
|
|
2814
2816
|
}
|
|
@@ -6939,7 +6941,7 @@ function splitCreated(creates, modifies, root, migrationsBefore) {
|
|
|
6939
6941
|
modified: modified.filter((f) => !isNewMigration(f))
|
|
6940
6942
|
};
|
|
6941
6943
|
}
|
|
6942
|
-
async function runPattern(slug2, argv, input,
|
|
6944
|
+
async function runPattern(slug2, argv, input, report6, after) {
|
|
6943
6945
|
const pattern = bySlug3[slug2];
|
|
6944
6946
|
if (!pattern) {
|
|
6945
6947
|
throw new Error(`Unknown pattern: ${slug2}`);
|
|
@@ -6957,7 +6959,7 @@ async function runPattern(slug2, argv, input, report5, after) {
|
|
|
6957
6959
|
provider: typeof input.provider === "string" ? input.provider : void 0
|
|
6958
6960
|
});
|
|
6959
6961
|
const migrationsBefore = listMigrations2(workspaceRootDir);
|
|
6960
|
-
const log58 = p13.taskLog({ title:
|
|
6962
|
+
const log58 = p13.taskLog({ title: report6.task.title });
|
|
6961
6963
|
let result;
|
|
6962
6964
|
try {
|
|
6963
6965
|
result = await pattern.generate({
|
|
@@ -6981,9 +6983,9 @@ async function runPattern(slug2, argv, input, report5, after) {
|
|
|
6981
6983
|
},
|
|
6982
6984
|
logger: { info: (message) => log58.message(message) }
|
|
6983
6985
|
});
|
|
6984
|
-
log58.success(
|
|
6986
|
+
log58.success(report6.task.success);
|
|
6985
6987
|
} catch (e) {
|
|
6986
|
-
log58.error(
|
|
6988
|
+
log58.error(report6.task.error);
|
|
6987
6989
|
throw e;
|
|
6988
6990
|
}
|
|
6989
6991
|
let afterError;
|
|
@@ -7013,7 +7015,7 @@ async function runPattern(slug2, argv, input, report5, after) {
|
|
|
7013
7015
|
p13.log.info(`${pattern.title ?? slug2} produced no changes.`);
|
|
7014
7016
|
} else {
|
|
7015
7017
|
reportResult({
|
|
7016
|
-
summary:
|
|
7018
|
+
summary: report6.summary ?? `Applied ${pattern.title ?? slug2}.`,
|
|
7017
7019
|
filesCreated: created.map((f) => rel(f.path)),
|
|
7018
7020
|
filesModified: modified.map((f) => rel(f.path)),
|
|
7019
7021
|
filesDeleted: deleted.map((f) => rel(f.path)),
|
|
@@ -7023,7 +7025,7 @@ async function runPattern(slug2, argv, input, report5, after) {
|
|
|
7023
7025
|
failures,
|
|
7024
7026
|
// Next steps assume the pattern applied; when part of it didn't, the
|
|
7025
7027
|
// remediation snippets above are the actual next step.
|
|
7026
|
-
nextSteps: failures.length > 0 || afterError ? void 0 :
|
|
7028
|
+
nextSteps: failures.length > 0 || afterError ? void 0 : report6.nextSteps
|
|
7027
7029
|
});
|
|
7028
7030
|
}
|
|
7029
7031
|
if (afterError) throw afterError;
|
|
@@ -8971,7 +8973,7 @@ import { Command as Command49 } from "commander";
|
|
|
8971
8973
|
// src/commands/destroy/_shared.ts
|
|
8972
8974
|
import process23 from "node:process";
|
|
8973
8975
|
import * as p25 from "@clack/prompts";
|
|
8974
|
-
async function runDestroy(slug2, model, confirmMessage,
|
|
8976
|
+
async function runDestroy(slug2, model, confirmMessage, report6, flags) {
|
|
8975
8977
|
if (!flags.yes) {
|
|
8976
8978
|
const ok = await p25.confirm({ message: confirmMessage, initialValue: false });
|
|
8977
8979
|
if (p25.isCancel(ok) || !ok) {
|
|
@@ -8979,7 +8981,7 @@ async function runDestroy(slug2, model, confirmMessage, report5, flags) {
|
|
|
8979
8981
|
process23.exit(0);
|
|
8980
8982
|
}
|
|
8981
8983
|
}
|
|
8982
|
-
await runPattern(slug2, [model], { destructive: true, route: flags.route },
|
|
8984
|
+
await runPattern(slug2, [model], { destructive: true, route: flags.route }, report6);
|
|
8983
8985
|
}
|
|
8984
8986
|
|
|
8985
8987
|
// src/commands/destroy/form.ts
|
|
@@ -10459,19 +10461,19 @@ var NEXT_STEPS4 = [
|
|
|
10459
10461
|
];
|
|
10460
10462
|
function uiAddReport(requested, outcome) {
|
|
10461
10463
|
const { installed: installed2, skipped, packages } = outcome;
|
|
10462
|
-
const
|
|
10464
|
+
const report6 = {
|
|
10463
10465
|
summary: installed2.length > 0 ? `Added ${installed2.length} UI component(s).` : `All ${new Set(requested).size} requested component(s) are already present.`,
|
|
10464
10466
|
componentsAdded: installed2,
|
|
10465
10467
|
packagesInstalled: packages,
|
|
10466
10468
|
nextSteps: [...NEXT_STEPS4]
|
|
10467
10469
|
};
|
|
10468
10470
|
if (skipped.length > 0) {
|
|
10469
|
-
|
|
10470
|
-
|
|
10471
|
+
report6.sections = [{ label: "Already present (pass --overwrite to replace)", items: skipped }];
|
|
10472
|
+
report6.nextSteps.push(
|
|
10471
10473
|
`Re-add an existing component with: vela ui add --overwrite ${skipped[0]}`
|
|
10472
10474
|
);
|
|
10473
10475
|
}
|
|
10474
|
-
return
|
|
10476
|
+
return report6;
|
|
10475
10477
|
}
|
|
10476
10478
|
|
|
10477
10479
|
// src/commands/ui/add.ts
|
|
@@ -12163,40 +12165,29 @@ import { Command as Command70 } from "commander";
|
|
|
12163
12165
|
import { Command as Command65 } from "commander";
|
|
12164
12166
|
|
|
12165
12167
|
// src/lib/data.ts
|
|
12168
|
+
import crypto6 from "node:crypto";
|
|
12166
12169
|
import fs43 from "node:fs";
|
|
12167
12170
|
import path44 from "node:path";
|
|
12168
12171
|
import { ClientResponseError } from "pocketbase";
|
|
12169
12172
|
|
|
12170
12173
|
// src/lib/collections.ts
|
|
12171
|
-
function dependencyOrder(collections2
|
|
12172
|
-
const order = [];
|
|
12173
|
-
const visited = {};
|
|
12174
|
-
const queue = [];
|
|
12174
|
+
function dependencyOrder(collections2) {
|
|
12175
12175
|
const eligible = collections2.filter((c) => !c.name.startsWith("_"));
|
|
12176
|
-
|
|
12177
|
-
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
|
|
12187
|
-
|
|
12188
|
-
|
|
12189
|
-
|
|
12190
|
-
|
|
12191
|
-
for (const field of source?.fields ?? []) {
|
|
12192
|
-
if (field.type === "relation" && field.collectionId && !visited[field.collectionId]) {
|
|
12193
|
-
visited[field.collectionId] = true;
|
|
12194
|
-
queue.push(field.collectionId);
|
|
12195
|
-
}
|
|
12196
|
-
}
|
|
12197
|
-
}
|
|
12198
|
-
const nameById = Object.fromEntries(collections2.map((c) => [c.id, c.name]));
|
|
12199
|
-
return { ids: order, names: order.map((id) => nameById[id]) };
|
|
12176
|
+
const byId = new Map(eligible.map((c) => [c.id, c]));
|
|
12177
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12178
|
+
const order = [];
|
|
12179
|
+
const visit = (collection) => {
|
|
12180
|
+
if (seen.has(collection.id)) return;
|
|
12181
|
+
seen.add(collection.id);
|
|
12182
|
+
for (const field of collection.fields) {
|
|
12183
|
+
if (field.type !== "relation" || !field.collectionId) continue;
|
|
12184
|
+
const target = byId.get(field.collectionId);
|
|
12185
|
+
if (target) visit(target);
|
|
12186
|
+
}
|
|
12187
|
+
order.push(collection);
|
|
12188
|
+
};
|
|
12189
|
+
for (const collection of eligible) visit(collection);
|
|
12190
|
+
return { ids: order.map((c) => c.id), names: order.map((c) => c.name) };
|
|
12200
12191
|
}
|
|
12201
12192
|
|
|
12202
12193
|
// src/lib/data.ts
|
|
@@ -12237,11 +12228,14 @@ function fixtureFilter(collectionName) {
|
|
|
12237
12228
|
var DataLoadError = class extends Error {
|
|
12238
12229
|
kind;
|
|
12239
12230
|
file;
|
|
12240
|
-
|
|
12231
|
+
/** The file is at fault as written, whatever the schema says. */
|
|
12232
|
+
malformed;
|
|
12233
|
+
constructor(kind, file, index, cause, opts = {}) {
|
|
12241
12234
|
super(`${file}, record ${index + 1}: ${describeError(cause)}`);
|
|
12242
12235
|
this.name = "DataLoadError";
|
|
12243
12236
|
this.kind = kind;
|
|
12244
12237
|
this.file = file;
|
|
12238
|
+
this.malformed = opts.malformed ?? false;
|
|
12245
12239
|
}
|
|
12246
12240
|
};
|
|
12247
12241
|
function describeError(e) {
|
|
@@ -12268,13 +12262,80 @@ async function createRecords(pb, kind, cwd, { collectionName, filePath }) {
|
|
|
12268
12262
|
}
|
|
12269
12263
|
return records.length;
|
|
12270
12264
|
}
|
|
12265
|
+
var ID_LOOKUP_CHUNK = 50;
|
|
12266
|
+
async function existingIds(pb, collectionName, ids) {
|
|
12267
|
+
const found = /* @__PURE__ */ new Set();
|
|
12268
|
+
for (let start = 0; start < ids.length; start += ID_LOOKUP_CHUNK) {
|
|
12269
|
+
const filter = ids.slice(start, start + ID_LOOKUP_CHUNK).map((id) => `id = ${JSON.stringify(id)}`).join(" || ");
|
|
12270
|
+
const records = await pb.collection(collectionName).getFullList({ filter, fields: "id" });
|
|
12271
|
+
for (const record of records) found.add(record.id);
|
|
12272
|
+
}
|
|
12273
|
+
return found;
|
|
12274
|
+
}
|
|
12275
|
+
function withPassword(record) {
|
|
12276
|
+
if (typeof record.password === "string" && record.password) {
|
|
12277
|
+
return { passwordConfirm: record.password, ...record };
|
|
12278
|
+
}
|
|
12279
|
+
const password8 = crypto6.randomBytes(24).toString("base64url");
|
|
12280
|
+
return { ...record, password: password8, passwordConfirm: password8 };
|
|
12281
|
+
}
|
|
12271
12282
|
async function loadSeeds(pb, cwd, seedFiles = getSeedFiles(cwd)) {
|
|
12272
|
-
const
|
|
12273
|
-
|
|
12274
|
-
|
|
12275
|
-
|
|
12283
|
+
const files = seedFiles.map((file) => ({ file, records: readRecords(file.filePath) }));
|
|
12284
|
+
if (files.length === 0) return [];
|
|
12285
|
+
for (const { file, records } of files) {
|
|
12286
|
+
for (const [index, record] of records.entries()) {
|
|
12287
|
+
if (typeof record.id === "string" && record.id) continue;
|
|
12288
|
+
throw new DataLoadError(
|
|
12289
|
+
"seeds",
|
|
12290
|
+
path44.relative(cwd, file.filePath),
|
|
12291
|
+
index,
|
|
12292
|
+
new Error(
|
|
12293
|
+
"seed records need an `id`. It is how a record already loaded is told from a new one."
|
|
12294
|
+
),
|
|
12295
|
+
{ malformed: true }
|
|
12296
|
+
);
|
|
12297
|
+
}
|
|
12276
12298
|
}
|
|
12277
|
-
|
|
12299
|
+
const authCollections = new Set(
|
|
12300
|
+
(await pb.collections.getFullList()).filter((c) => c.type === "auth").map((c) => c.name)
|
|
12301
|
+
);
|
|
12302
|
+
const results = [];
|
|
12303
|
+
for (const { file, records } of files) {
|
|
12304
|
+
const { collectionName, filePath } = file;
|
|
12305
|
+
const relative = path44.relative(cwd, filePath);
|
|
12306
|
+
const present = await existingIds(
|
|
12307
|
+
pb,
|
|
12308
|
+
collectionName,
|
|
12309
|
+
records.map((record) => record.id)
|
|
12310
|
+
);
|
|
12311
|
+
const isAuth = authCollections.has(collectionName);
|
|
12312
|
+
let created = 0;
|
|
12313
|
+
for (const [index, record] of records.entries()) {
|
|
12314
|
+
if (present.has(record.id)) continue;
|
|
12315
|
+
try {
|
|
12316
|
+
await pb.collection(collectionName).create(isAuth ? withPassword(record) : record);
|
|
12317
|
+
} catch (e) {
|
|
12318
|
+
throw new DataLoadError("seeds", relative, index, e);
|
|
12319
|
+
}
|
|
12320
|
+
present.add(record.id);
|
|
12321
|
+
created++;
|
|
12322
|
+
}
|
|
12323
|
+
const skipped = records.length - created;
|
|
12324
|
+
results.push({
|
|
12325
|
+
label: `${relative} (${created} created` + (skipped > 0 ? `, ${skipped} already there)` : ")"),
|
|
12326
|
+
created,
|
|
12327
|
+
skipped
|
|
12328
|
+
});
|
|
12329
|
+
}
|
|
12330
|
+
return results;
|
|
12331
|
+
}
|
|
12332
|
+
function summarizeSeedLoad(results) {
|
|
12333
|
+
const created = results.reduce((sum, r) => sum + r.created, 0);
|
|
12334
|
+
const skipped = results.reduce((sum, r) => sum + r.skipped, 0);
|
|
12335
|
+
const plural = (count) => `${count} seed record${count === 1 ? "" : "s"}`;
|
|
12336
|
+
if (created === 0 && skipped === 0) return "No seed records to load.";
|
|
12337
|
+
if (created === 0) return `All ${plural(skipped)} already there, nothing to load.`;
|
|
12338
|
+
return `Loaded ${plural(created)}` + (skipped > 0 ? `, ${skipped} already there.` : ".");
|
|
12278
12339
|
}
|
|
12279
12340
|
async function clearSeeds(pb, cwd, seedFiles = getSeedFiles(cwd)) {
|
|
12280
12341
|
const cleared = [];
|
|
@@ -12655,46 +12716,130 @@ import { Command as Command74 } from "commander";
|
|
|
12655
12716
|
|
|
12656
12717
|
// src/commands/seeds/load.ts
|
|
12657
12718
|
import { Command as Command71 } from "commander";
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
|
|
12676
|
-
|
|
12677
|
-
|
|
12719
|
+
import pc13 from "picocolors";
|
|
12720
|
+
|
|
12721
|
+
// src/lib/remote-pocketbase.ts
|
|
12722
|
+
import PocketBase5 from "pocketbase";
|
|
12723
|
+
async function requireRemoteDatabase(session, instance) {
|
|
12724
|
+
const [state] = await readInstanceStates(session, instance);
|
|
12725
|
+
const pbPort = instanceHasBackend(state) ? state?.pbPort : void 0;
|
|
12726
|
+
if (!pbPort) {
|
|
12727
|
+
throw new Error(
|
|
12728
|
+
`${instance} has no deployed database.
|
|
12729
|
+
|
|
12730
|
+
The database is created by the first \`vela deploy\` of a project with a backend.
|
|
12731
|
+
If this project has none, \`vela enable backend\` adds one; then deploy again.`
|
|
12732
|
+
);
|
|
12733
|
+
}
|
|
12734
|
+
return pbPort;
|
|
12735
|
+
}
|
|
12736
|
+
async function openRemoteDatabase(session, instance) {
|
|
12737
|
+
const pbPort = await requireRemoteDatabase(session, instance);
|
|
12738
|
+
const env2 = await readRemoteEnv(session, instance);
|
|
12739
|
+
const email2 = env2.POCKETBASE_SUPERUSER_EMAIL;
|
|
12740
|
+
const password8 = env2.POCKETBASE_SUPERUSER_PASSWORD;
|
|
12741
|
+
if (!email2 || !password8) {
|
|
12742
|
+
throw new Error(
|
|
12743
|
+
`${instance} has no PocketBase superuser credentials in its environment.
|
|
12744
|
+
|
|
12745
|
+
A deploy creates them. Deploy again to repair this instance.`
|
|
12746
|
+
);
|
|
12747
|
+
}
|
|
12748
|
+
const localPort = await findFreePort("127.0.0.1");
|
|
12749
|
+
await session.forwardLocalPort(localPort, "127.0.0.1", pbPort);
|
|
12750
|
+
return {
|
|
12751
|
+
url: `http://127.0.0.1:${localPort}`,
|
|
12752
|
+
email: email2,
|
|
12753
|
+
password: password8,
|
|
12754
|
+
close: () => session.cancelForward(localPort, "127.0.0.1", pbPort)
|
|
12755
|
+
};
|
|
12756
|
+
}
|
|
12757
|
+
async function withRemotePocketbase(session, instance, fn) {
|
|
12758
|
+
const db = await openRemoteDatabase(session, instance);
|
|
12759
|
+
try {
|
|
12760
|
+
const pb = new PocketBase5(db.url);
|
|
12761
|
+
await authWithRetries(pb, db.email, db.password);
|
|
12762
|
+
return await fn(pb);
|
|
12763
|
+
} finally {
|
|
12764
|
+
await db.close();
|
|
12765
|
+
}
|
|
12766
|
+
}
|
|
12767
|
+
|
|
12768
|
+
// src/commands/seeds/load.ts
|
|
12769
|
+
var load2 = addTargetOptions(
|
|
12770
|
+
new Command71("load").description("load seeds into the database, creating the records not already there").configureHelp(helpConfig),
|
|
12771
|
+
"local"
|
|
12772
|
+
).action(
|
|
12773
|
+
(raw) => runCommand(
|
|
12774
|
+
() => withTarget(
|
|
12775
|
+
raw,
|
|
12776
|
+
{
|
|
12777
|
+
local: async (ctx) => {
|
|
12778
|
+
if (!hasBackend(ctx.workspaceRootDir)) {
|
|
12779
|
+
throw new Error(missingBackendMessage("vela seeds load"));
|
|
12678
12780
|
}
|
|
12781
|
+
const seedFiles = requireSeedFiles(ctx.workspaceRootDir);
|
|
12782
|
+
if (!seedFiles) return;
|
|
12783
|
+
if (!hasSuperuserCredentials()) throw new Error(missingCredentialsMessage());
|
|
12784
|
+
let loaded = [];
|
|
12785
|
+
await withPocketbase(
|
|
12786
|
+
ctx.workspaceRootDir,
|
|
12787
|
+
async (pb) => {
|
|
12788
|
+
loaded = await loadSeeds(pb, ctx.workspaceRootDir, seedFiles);
|
|
12789
|
+
},
|
|
12790
|
+
void 0,
|
|
12791
|
+
// The app's hooks apply to a seed as to any other write, as
|
|
12792
|
+
// they do on a deployed copy and under `vela dev`.
|
|
12793
|
+
{ hooks: true }
|
|
12794
|
+
);
|
|
12795
|
+
report(loaded, [
|
|
12796
|
+
"Run `vela dev` to see the seeded data in the app.",
|
|
12797
|
+
"Run `vela seeds clear` to remove the seeded records."
|
|
12798
|
+
]);
|
|
12799
|
+
},
|
|
12800
|
+
remote: async (ctx) => {
|
|
12801
|
+
const seedFiles = requireSeedFiles(ctx.workspaceRootDir);
|
|
12802
|
+
if (!seedFiles) return;
|
|
12803
|
+
await requireRemoteDatabase(ctx.session, ctx.instance);
|
|
12804
|
+
const loaded = await withRemotePocketbase(
|
|
12805
|
+
ctx.session,
|
|
12806
|
+
ctx.instance,
|
|
12807
|
+
(pb) => loadSeeds(pb, ctx.workspaceRootDir, seedFiles)
|
|
12808
|
+
);
|
|
12809
|
+
report(
|
|
12810
|
+
loaded,
|
|
12811
|
+
[],
|
|
12812
|
+
` ${pc13.dim("\u2192")} ${pc13.cyan(ctx.targetName)} ${pc13.dim(`(${ctx.server})`)}`
|
|
12813
|
+
);
|
|
12679
12814
|
}
|
|
12680
|
-
}
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
12684
|
-
|
|
12685
|
-
recordsLoaded: loaded,
|
|
12686
|
-
nextSteps: [
|
|
12687
|
-
"Run `vela dev` to see the seeded data in the app.",
|
|
12688
|
-
"Run `vela seeds clear` to remove the seeded records."
|
|
12689
|
-
]
|
|
12690
|
-
});
|
|
12691
|
-
}, "Failed to load seeds.")
|
|
12815
|
+
},
|
|
12816
|
+
{ label: "seeds load" }
|
|
12817
|
+
),
|
|
12818
|
+
"Failed to load seeds."
|
|
12819
|
+
)
|
|
12692
12820
|
);
|
|
12821
|
+
function requireSeedFiles(workspaceRootDir) {
|
|
12822
|
+
const seedFiles = getSeedFiles(workspaceRootDir);
|
|
12823
|
+
if (seedFiles.length > 0) return seedFiles;
|
|
12824
|
+
reportResult({
|
|
12825
|
+
summary: "No seed files found in data/seeds.",
|
|
12826
|
+
nextSteps: ["Run `vela seeds save` to snapshot the current database contents as seeds."]
|
|
12827
|
+
});
|
|
12828
|
+
return null;
|
|
12829
|
+
}
|
|
12830
|
+
function report(loaded, nextSteps, where = "") {
|
|
12831
|
+
reportResult({
|
|
12832
|
+
summary: summarizeSeedLoad(loaded) + where,
|
|
12833
|
+
recordsLoaded: loaded.map((result) => result.label),
|
|
12834
|
+
nextSteps
|
|
12835
|
+
});
|
|
12836
|
+
}
|
|
12693
12837
|
|
|
12694
12838
|
// src/commands/seeds/save.ts
|
|
12695
12839
|
import fs45 from "node:fs";
|
|
12696
12840
|
import path46 from "node:path";
|
|
12697
12841
|
import { Command as Command72 } from "commander";
|
|
12842
|
+
var AUTH_IDENTITY_FIELDS = /* @__PURE__ */ new Set(["email", "emailVisibility", "verified"]);
|
|
12698
12843
|
var padZeros2 = (num, length) => num.toString().padStart(length, "0");
|
|
12699
12844
|
function filterSystemFields(record, systemFieldNames) {
|
|
12700
12845
|
const out = {};
|
|
@@ -12725,6 +12870,7 @@ var save = new Command72("save").description("save the current data as seeds").o
|
|
|
12725
12870
|
const collections2 = fullList.map((c) => ({
|
|
12726
12871
|
id: c.id,
|
|
12727
12872
|
name: c.name,
|
|
12873
|
+
type: c.type,
|
|
12728
12874
|
fields: c.fields.map((f) => ({
|
|
12729
12875
|
name: f.name,
|
|
12730
12876
|
type: f.type,
|
|
@@ -12737,10 +12883,13 @@ var save = new Command72("save").description("save the current data as seeds").o
|
|
|
12737
12883
|
for (const collectionName of names) {
|
|
12738
12884
|
const collection = collections2.find((c) => c.name === collectionName);
|
|
12739
12885
|
if (!collection) continue;
|
|
12886
|
+
if (collection.type === "view") continue;
|
|
12740
12887
|
const systemFieldNames = new Set(
|
|
12741
|
-
collection.fields.filter((f) => f.system && f.name !== "id").map((f) => f.name)
|
|
12888
|
+
collection.fields.filter((f) => f.system && f.name !== "id").filter((f) => !(collection.type === "auth" && AUTH_IDENTITY_FIELDS.has(f.name))).map((f) => f.name)
|
|
12742
12889
|
);
|
|
12743
|
-
const records = await pb.collection(collectionName).getFullList(
|
|
12890
|
+
const records = await pb.collection(collectionName).getFullList({
|
|
12891
|
+
filter: `id !~ "${FIXTURE_PREFIX}${collectionName.slice(0, 6)}%"`
|
|
12892
|
+
});
|
|
12744
12893
|
if (records.length === 0) continue;
|
|
12745
12894
|
const filtered = records.map(
|
|
12746
12895
|
(r) => filterSystemFields(r, systemFieldNames)
|
|
@@ -12760,7 +12909,7 @@ var save = new Command72("save").description("save the current data as seeds").o
|
|
|
12760
12909
|
reportResult({
|
|
12761
12910
|
summary: "No records to save.",
|
|
12762
12911
|
nextSteps: [
|
|
12763
|
-
"Create
|
|
12912
|
+
"Create the records the app needs first (in the app or its admin panel), then rerun `vela seeds save`. Fixtures are left out."
|
|
12764
12913
|
]
|
|
12765
12914
|
});
|
|
12766
12915
|
return;
|
|
@@ -12769,8 +12918,8 @@ var save = new Command72("save").description("save the current data as seeds").o
|
|
|
12769
12918
|
summary: `Saved ${saved.length} collection(s) as seeds.`,
|
|
12770
12919
|
filesCreated: saved,
|
|
12771
12920
|
nextSteps: [
|
|
12772
|
-
"
|
|
12773
|
-
"Run `vela seeds load`
|
|
12921
|
+
"Read through data/seeds/ before committing: `vela deploy` loads these records into every copy of the app.",
|
|
12922
|
+
"Run `vela seeds load` to load them here, or `vela seeds load -t production` into a deployed copy."
|
|
12774
12923
|
]
|
|
12775
12924
|
});
|
|
12776
12925
|
}, "Failed to save seeds.")
|
|
@@ -13039,11 +13188,11 @@ import path50 from "node:path";
|
|
|
13039
13188
|
import process31 from "node:process";
|
|
13040
13189
|
import { Command as Command83 } from "commander";
|
|
13041
13190
|
import * as p44 from "@clack/prompts";
|
|
13042
|
-
import
|
|
13191
|
+
import pc14 from "picocolors";
|
|
13043
13192
|
var sveltekit3 = new Command83("sveltekit-3").description("upgrade a SvelteKit 2 project to SvelteKit 3 (sv migrate, then the vela steps)").option("--cwd <path>", "the project to migrate (default: the current project)").option("--no-install", "skip installing dependencies").option("--force", "run even when the git working tree has uncommitted changes").option("--skip-sv", "only run the vela steps (sv has already been run)").configureHelp(helpConfig).action(
|
|
13044
13193
|
(options) => runCommand(async () => {
|
|
13045
13194
|
const root = options.cwd ? path50.resolve(options.cwd) : findWorkspaceRoot() ?? process31.cwd();
|
|
13046
|
-
p44.intro(
|
|
13195
|
+
p44.intro(pc14.bgCyan(pc14.black(" vela migrate sveltekit-3 ")));
|
|
13047
13196
|
const result = await runKit3Migration(root, {
|
|
13048
13197
|
install: options.install,
|
|
13049
13198
|
force: options.force,
|
|
@@ -13122,8 +13271,8 @@ import path52 from "node:path";
|
|
|
13122
13271
|
import process33 from "node:process";
|
|
13123
13272
|
import { performance } from "node:perf_hooks";
|
|
13124
13273
|
import { Command as Command85, InvalidArgumentError as InvalidArgumentError4 } from "commander";
|
|
13125
|
-
import
|
|
13126
|
-
import
|
|
13274
|
+
import pc16 from "picocolors";
|
|
13275
|
+
import PocketBase6 from "pocketbase";
|
|
13127
13276
|
|
|
13128
13277
|
// src/lib/pocketbase-log-filter.ts
|
|
13129
13278
|
import { Transform } from "node:stream";
|
|
@@ -13154,7 +13303,7 @@ import path51 from "node:path";
|
|
|
13154
13303
|
import process32 from "node:process";
|
|
13155
13304
|
import { createRequire as createRequire4 } from "node:module";
|
|
13156
13305
|
import { pathToFileURL } from "node:url";
|
|
13157
|
-
import
|
|
13306
|
+
import pc15 from "picocolors";
|
|
13158
13307
|
var REQUIRED_VITE_MAJOR = 8;
|
|
13159
13308
|
function viteVersionError(version) {
|
|
13160
13309
|
const major = Number.parseInt(version, 10);
|
|
@@ -13180,7 +13329,7 @@ async function loadVite(cwd = process32.cwd()) {
|
|
|
13180
13329
|
const vite = entry ? await import(pathToFileURL(entry).href) : await import("vite");
|
|
13181
13330
|
const error = viteVersionError(vite.version);
|
|
13182
13331
|
if (error) {
|
|
13183
|
-
console.error(`${
|
|
13332
|
+
console.error(`${pc15.redBright("\u2717")} ${error}`);
|
|
13184
13333
|
process32.exit(1);
|
|
13185
13334
|
}
|
|
13186
13335
|
return vite;
|
|
@@ -13196,7 +13345,7 @@ function parsePort(value) {
|
|
|
13196
13345
|
}
|
|
13197
13346
|
var dev = new Command85("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").option("--all-sql", "also print the auth lookup PocketBase runs on every request").configureHelp(helpConfig).action(async (options) => {
|
|
13198
13347
|
const cwd = process33.cwd();
|
|
13199
|
-
warnIfKit2(findWorkspaceRoot(cwd) ?? cwd, (m) => console.warn(
|
|
13348
|
+
warnIfKit2(findWorkspaceRoot(cwd) ?? cwd, (m) => console.warn(pc16.yellow(`\u25B2 ${m}`)));
|
|
13200
13349
|
process33.env.VELA_DATA_DIR ??= localDataDir(cwd);
|
|
13201
13350
|
const startTime = performance.now();
|
|
13202
13351
|
const { createServer, resolveConfig, version } = await loadVite(cwd);
|
|
@@ -13230,7 +13379,7 @@ var dev = new Command85("dev").description("start the development server").optio
|
|
|
13230
13379
|
const site = await readSite(cwd);
|
|
13231
13380
|
if (!site?.name) {
|
|
13232
13381
|
console.log(
|
|
13233
|
-
|
|
13382
|
+
pc16.dim(
|
|
13234
13383
|
`No app name in ${SITE_FILE}, so PocketBase keeps the one it has. Add \`export const site = { name: '\u2026', url: '\u2026' }\` there to set it from code.`
|
|
13235
13384
|
)
|
|
13236
13385
|
);
|
|
@@ -13270,7 +13419,7 @@ var dev = new Command85("dev").description("start the development server").optio
|
|
|
13270
13419
|
viteHost
|
|
13271
13420
|
})
|
|
13272
13421
|
);
|
|
13273
|
-
const pb = new
|
|
13422
|
+
const pb = new PocketBase6(process33.env.POCKETBASE_URL);
|
|
13274
13423
|
await pb.collection("_superusers").authWithPassword(
|
|
13275
13424
|
process33.env.POCKETBASE_SUPERUSER_EMAIL,
|
|
13276
13425
|
process33.env.POCKETBASE_SUPERUSER_PASSWORD
|
|
@@ -13279,12 +13428,12 @@ var dev = new Command85("dev").description("start the development server").optio
|
|
|
13279
13428
|
});
|
|
13280
13429
|
await server.listen();
|
|
13281
13430
|
const hasExistingLogs = process33.stdout.bytesWritten > 0 || process33.stderr.bytesWritten > 0;
|
|
13282
|
-
const startupDurationString =
|
|
13283
|
-
`ready in ${
|
|
13431
|
+
const startupDurationString = pc16.dim(
|
|
13432
|
+
`ready in ${pc16.reset(pc16.bold(Math.ceil(performance.now() - startTime)))} ms`
|
|
13284
13433
|
);
|
|
13285
13434
|
server.config.logger.info(
|
|
13286
13435
|
`
|
|
13287
|
-
${
|
|
13436
|
+
${pc16.green(`${pc16.bold("VITE")} v${version}`)} ${startupDurationString}
|
|
13288
13437
|
`,
|
|
13289
13438
|
{ clear: !hasExistingLogs }
|
|
13290
13439
|
);
|
|
@@ -13321,7 +13470,7 @@ import path53 from "node:path";
|
|
|
13321
13470
|
import process35 from "node:process";
|
|
13322
13471
|
import { Command as Command86 } from "commander";
|
|
13323
13472
|
import * as p45 from "@clack/prompts";
|
|
13324
|
-
import
|
|
13473
|
+
import pc17 from "picocolors";
|
|
13325
13474
|
import { x as x5 } from "tinyexec";
|
|
13326
13475
|
import { detect as detect8 } from "package-manager-detector";
|
|
13327
13476
|
import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
|
|
@@ -13437,17 +13586,17 @@ several hosts (or on none yet), and baking one in would make the others render
|
|
|
13437
13586
|
as it and refuse their form posts. Each host takes its origin from the request
|
|
13438
13587
|
instead, and a page prerendered at build time has none, so anything it takes
|
|
13439
13588
|
from the request's origin points at SvelteKit's placeholder host. Build such links
|
|
13440
|
-
from ${
|
|
13589
|
+
from ${pc17.cyan("src/lib/site.ts")}, as the templates' canonical links are.`
|
|
13441
13590
|
);
|
|
13442
13591
|
return;
|
|
13443
13592
|
}
|
|
13444
13593
|
p45.log.warn(
|
|
13445
13594
|
`Prerendered pages were built with no domain configured, so anything they take
|
|
13446
13595
|
from the request's origin points at SvelteKit's placeholder host rather than at
|
|
13447
|
-
this site. Links built from ${
|
|
13596
|
+
this site. Links built from ${pc17.cyan("src/lib/site.ts")}, as the templates' canonical
|
|
13448
13597
|
links are, don't depend on it.
|
|
13449
13598
|
|
|
13450
|
-
Set one with ${
|
|
13599
|
+
Set one with ${pc17.cyan("vela deploy --domain example.com")}, or pass ${pc17.cyan("VELA_ORIGIN")}.`
|
|
13451
13600
|
);
|
|
13452
13601
|
}
|
|
13453
13602
|
|
|
@@ -13457,7 +13606,7 @@ import path54 from "node:path";
|
|
|
13457
13606
|
import process36 from "node:process";
|
|
13458
13607
|
import { Command as Command87 } from "commander";
|
|
13459
13608
|
import * as p46 from "@clack/prompts";
|
|
13460
|
-
import
|
|
13609
|
+
import pc18 from "picocolors";
|
|
13461
13610
|
import { x as x6 } from "tinyexec";
|
|
13462
13611
|
import { detect as detect9 } from "package-manager-detector";
|
|
13463
13612
|
import { resolveCommand as resolveCommand7 } from "package-manager-detector/commands";
|
|
@@ -13521,10 +13670,10 @@ function warnIfOriginBaked(cwd) {
|
|
|
13521
13670
|
const origin = bakedOrigin(source);
|
|
13522
13671
|
if (!origin || isLocalUrl(origin)) return;
|
|
13523
13672
|
p46.log.warn(
|
|
13524
|
-
`This build was made for ${
|
|
13673
|
+
`This build was made for ${pc18.cyan(origin)}, and SvelteKit treats that as the origin of
|
|
13525
13674
|
every request. Form posts from localhost will be refused as cross-site (403).
|
|
13526
13675
|
|
|
13527
|
-
Build for this machine first: ${
|
|
13676
|
+
Build for this machine first: ${pc18.cyan("vela build -t local")}, or with ${pc18.cyan("VELA_ORIGIN=")}
|
|
13528
13677
|
set empty so no domain is baked in.`
|
|
13529
13678
|
);
|
|
13530
13679
|
}
|
|
@@ -13547,7 +13696,7 @@ var sync = new Command88("sync").description("sync types from the database").con
|
|
|
13547
13696
|
// src/commands/provision.ts
|
|
13548
13697
|
import { Command as Command89 } from "commander";
|
|
13549
13698
|
import * as p47 from "@clack/prompts";
|
|
13550
|
-
import
|
|
13699
|
+
import pc19 from "picocolors";
|
|
13551
13700
|
import * as v9 from "valibot";
|
|
13552
13701
|
var NODE_MAJOR = "24";
|
|
13553
13702
|
var OptionsSchema2 = v9.object({
|
|
@@ -13569,8 +13718,8 @@ var provision = addSshOptions(
|
|
|
13569
13718
|
(target, raw) => runCommand(async () => {
|
|
13570
13719
|
const options = parseOptions(OptionsSchema2, raw);
|
|
13571
13720
|
const pbVersion = options.pbVersion ?? pocketbaseVersion();
|
|
13572
|
-
p47.intro(
|
|
13573
|
-
p47.log.info(`Target ${
|
|
13721
|
+
p47.intro(pc19.bgCyan(pc19.black(" vela provision ")));
|
|
13722
|
+
p47.log.info(`Target ${pc19.cyan(target)}`);
|
|
13574
13723
|
await withSsh(target, sshOptionsFrom(options), async (session) => {
|
|
13575
13724
|
await session.detectElevation();
|
|
13576
13725
|
const existing = await readServerInfo(session);
|
|
@@ -13601,7 +13750,7 @@ var provision = addSshOptions(
|
|
|
13601
13750
|
PocketBase ${result?.pocketbase ?? pbVersion}`
|
|
13602
13751
|
);
|
|
13603
13752
|
});
|
|
13604
|
-
p47.outro(`Deploy with ${
|
|
13753
|
+
p47.outro(`Deploy with ${pc19.cyan(`vela deploy --server ${target}`)}`);
|
|
13605
13754
|
}, "Failed to provision.")
|
|
13606
13755
|
);
|
|
13607
13756
|
|
|
@@ -13611,7 +13760,7 @@ import fs54 from "node:fs";
|
|
|
13611
13760
|
import process38 from "node:process";
|
|
13612
13761
|
import { Command as Command90, Option as Option2 } from "commander";
|
|
13613
13762
|
import * as p49 from "@clack/prompts";
|
|
13614
|
-
import
|
|
13763
|
+
import pc21 from "picocolors";
|
|
13615
13764
|
import * as v10 from "valibot";
|
|
13616
13765
|
|
|
13617
13766
|
// src/lib/env-scopes.ts
|
|
@@ -13883,7 +14032,7 @@ import fs53 from "node:fs";
|
|
|
13883
14032
|
import path58 from "node:path";
|
|
13884
14033
|
import process37 from "node:process";
|
|
13885
14034
|
import * as p48 from "@clack/prompts";
|
|
13886
|
-
import
|
|
14035
|
+
import pc20 from "picocolors";
|
|
13887
14036
|
var ENV_EXAMPLE = ".env.example";
|
|
13888
14037
|
var SUPPLIED = /^(NODE_ENV|HOST|PORT|ORIGIN|PROTOCOL_HEADER|HOST_HEADER|ADDRESS_HEADER|XFF_DEPTH|PB_PORT|POCKETBASE_URL|POCKETBASE_SUPERUSER_EMAIL|POCKETBASE_SUPERUSER_PASSWORD|APP_NAME|VELA_)/;
|
|
13889
14038
|
function missingFromExample(root, present) {
|
|
@@ -13895,14 +14044,14 @@ function missingFromExample(root, present) {
|
|
|
13895
14044
|
async function nudgeMissingEnv(root, target, present) {
|
|
13896
14045
|
const missing = missingFromExample(root, present);
|
|
13897
14046
|
if (missing.length === 0) return [];
|
|
13898
|
-
const where =
|
|
14047
|
+
const where = pc20.cyan(target.targetName);
|
|
13899
14048
|
if (!isInteractive()) {
|
|
13900
14049
|
p48.log.warn(
|
|
13901
14050
|
`${where} does not have ${missing.length} of the variables ${ENV_EXAMPLE} documents:
|
|
13902
14051
|
|
|
13903
14052
|
` + missing.map((key) => ` ${key}`).join("\n") + `
|
|
13904
14053
|
|
|
13905
|
-
Set any it needs with ${
|
|
14054
|
+
Set any it needs with ${pc20.cyan(`vela env set KEY -t ${target.targetName}`)}.`
|
|
13906
14055
|
);
|
|
13907
14056
|
return [];
|
|
13908
14057
|
}
|
|
@@ -13923,7 +14072,7 @@ Set any it needs with ${pc19.cyan(`vela env set KEY -t ${target.targetName}`)}.`
|
|
|
13923
14072
|
const files = layer === "instance" ? layerFiles(target.appId, "instance", target.instance) : layerFiles(target.appId, layer);
|
|
13924
14073
|
await setInLayer(target.session, files, key, value, asPublic);
|
|
13925
14074
|
p48.log.success(
|
|
13926
|
-
`${key} set${asPublic ? " (public)" : ""} ${
|
|
14075
|
+
`${key} set${asPublic ? " (public)" : ""} ${pc20.dim(`(${layer === "instance" ? target.targetName : layer})`)}`
|
|
13927
14076
|
);
|
|
13928
14077
|
set.push(key);
|
|
13929
14078
|
}
|
|
@@ -13936,20 +14085,20 @@ async function pickLayer(key, target) {
|
|
|
13936
14085
|
];
|
|
13937
14086
|
if (target.preview) options.push({ value: "preview", label: "preview", hint: "every preview" });
|
|
13938
14087
|
options.push({ value: "skip", label: "skip", hint: "leave it unset" });
|
|
13939
|
-
const choice = await p48.select({ message: `Where should ${
|
|
14088
|
+
const choice = await p48.select({ message: `Where should ${pc20.cyan(key)} be set?`, options });
|
|
13940
14089
|
if (p48.isCancel(choice)) cancel22();
|
|
13941
14090
|
return choice === "skip" ? null : choice;
|
|
13942
14091
|
}
|
|
13943
14092
|
async function askPublic(key) {
|
|
13944
14093
|
const choice = await p48.confirm({
|
|
13945
|
-
message: `Is ${
|
|
14094
|
+
message: `Is ${pc20.cyan(key)} public? (readable back with vela env list; no for a secret)`,
|
|
13946
14095
|
initialValue: false
|
|
13947
14096
|
});
|
|
13948
14097
|
if (p48.isCancel(choice)) cancel22();
|
|
13949
14098
|
return choice;
|
|
13950
14099
|
}
|
|
13951
14100
|
async function promptValue(key, asPublic) {
|
|
13952
|
-
const message = `Value for ${
|
|
14101
|
+
const message = `Value for ${pc20.cyan(key)}${asPublic ? pc20.dim(" (public)") : ""}`;
|
|
13953
14102
|
const validate = (input) => !input?.length ? "Required" : void 0;
|
|
13954
14103
|
const value = asPublic ? await p48.text({ message, validate }) : await p48.password({ message, validate });
|
|
13955
14104
|
if (p48.isCancel(value)) cancel22();
|
|
@@ -13991,16 +14140,16 @@ var deploy = addLockWaitOption(
|
|
|
13991
14140
|
(raw) => runCommand(async () => {
|
|
13992
14141
|
const options = parseOptions(OptionsSchema3, raw);
|
|
13993
14142
|
const backend3 = hasBackend();
|
|
13994
|
-
p49.intro(
|
|
14143
|
+
p49.intro(pc21.bgCyan(pc21.black(" vela deploy ")));
|
|
13995
14144
|
if (options.build !== false) {
|
|
13996
14145
|
const { workspaceRootDir } = await getWorkspace();
|
|
13997
14146
|
await prepareAdapter(workspaceRootDir);
|
|
13998
14147
|
const foreign = foreignLockfile(workspaceRootDir);
|
|
13999
14148
|
if (foreign) {
|
|
14000
14149
|
p49.log.warn(
|
|
14001
|
-
`Dependencies are pinned by ${
|
|
14150
|
+
`Dependencies are pinned by ${pc21.cyan(foreign)}, but the server installs with npm, which cannot replay it.
|
|
14002
14151
|
Versions there are resolved from package.json ranges and may differ from yours. Commit a
|
|
14003
|
-
${
|
|
14152
|
+
${pc21.cyan("package-lock.json")} (${pc21.dim("npm install --package-lock-only")}) for a reproducible deploy.`
|
|
14004
14153
|
);
|
|
14005
14154
|
}
|
|
14006
14155
|
}
|
|
@@ -14011,14 +14160,14 @@ ${pc20.cyan("package-lock.json")} (${pc20.dim("npm install --package-lock-only")
|
|
|
14011
14160
|
remote: async (ctx) => {
|
|
14012
14161
|
const { session, instance, workspaceRootDir } = ctx;
|
|
14013
14162
|
p49.log.info(
|
|
14014
|
-
`${
|
|
14163
|
+
`${pc21.cyan(ctx.appName)} ${pc21.dim("\u2192")} ${pc21.cyan(ctx.targetName)} ${pc21.dim(`(${ctx.server})`)}`
|
|
14015
14164
|
);
|
|
14016
14165
|
const serverNode = await requireServerNode(session, ctx.server);
|
|
14017
14166
|
const drift = nodeMajorDrift(serverNode, process38.version);
|
|
14018
14167
|
if (drift) {
|
|
14019
14168
|
p49.log.warn(
|
|
14020
14169
|
`${ctx.server} runs Node ${drift.server}, but this deploy runs Node ${drift.build}. The server's npm can reject a lockfile this one accepts.
|
|
14021
|
-
Run ${
|
|
14170
|
+
Run ${pc21.cyan(`vela provision ${ctx.server}`)} to bring it up to ${drift.build}.`
|
|
14022
14171
|
);
|
|
14023
14172
|
}
|
|
14024
14173
|
const [existing] = await readInstanceStates(session, instance);
|
|
@@ -14029,7 +14178,7 @@ Run ${pc20.cyan(`vela provision ${ctx.server}`)} to bring it up to ${drift.build
|
|
|
14029
14178
|
const remoteDb = askedForRemoteDb ?? instanceHasBackend(existing);
|
|
14030
14179
|
if (existing && instanceHasBackend(existing) !== backend3) {
|
|
14031
14180
|
p49.log.info(
|
|
14032
|
-
backend3 ? `${
|
|
14181
|
+
backend3 ? `${pc21.cyan(ctx.targetName)} was deployed without a backend before. This deploy adds PocketBase.` : `${pc21.cyan(ctx.targetName)} was deployed with a backend before. This deploy removes PocketBase; its database stays on the server.`
|
|
14033
14182
|
);
|
|
14034
14183
|
}
|
|
14035
14184
|
let stack = await resolveStack(session, ctx.appId, instance, isPreview2);
|
|
@@ -14075,8 +14224,8 @@ Run ${pc20.cyan(`vela provision ${ctx.server}`)} to bring it up to ${drift.build
|
|
|
14075
14224
|
throw new Error(
|
|
14076
14225
|
`Nothing routes to this preview.
|
|
14077
14226
|
|
|
14078
|
-
Previews get a free velastack.app hostname from velastack.dev: ${
|
|
14079
|
-
project and ${
|
|
14227
|
+
Previews get a free velastack.app hostname from velastack.dev: ${pc21.cyan("vela link")} the
|
|
14228
|
+
project and ${pc21.cyan("vela login")} (or set ${pc21.cyan("VELA_API_KEY")}). Or pass ${pc21.cyan("--domain <host>")}
|
|
14080
14229
|
with DNS of your own pointing at ${ctx.server}.`
|
|
14081
14230
|
);
|
|
14082
14231
|
}
|
|
@@ -14092,15 +14241,15 @@ with DNS of your own pointing at ${ctx.server}.`
|
|
|
14092
14241
|
} catch (err) {
|
|
14093
14242
|
if (askedForRemoteDb) throw err;
|
|
14094
14243
|
p49.log.warn(
|
|
14095
|
-
`Could not build against the ${
|
|
14096
|
-
${
|
|
14244
|
+
`Could not build against the ${pc21.cyan(ctx.targetName)} database, using a local one instead.
|
|
14245
|
+
${pc21.dim(String(err))}`
|
|
14097
14246
|
);
|
|
14098
14247
|
}
|
|
14099
14248
|
}
|
|
14100
14249
|
if (tunnel) {
|
|
14101
14250
|
derived = { ...derived, ...tunnel.env };
|
|
14102
14251
|
p49.log.info(
|
|
14103
|
-
`Building against the ${
|
|
14252
|
+
`Building against the ${pc21.cyan(ctx.targetName)} database on ${ctx.server} ${pc21.dim(`(port ${tunnel.pbPort})`)}`
|
|
14104
14253
|
);
|
|
14105
14254
|
} else if (backend3) {
|
|
14106
14255
|
await ensureSuperuser(workspaceRootDir);
|
|
@@ -14112,7 +14261,7 @@ ${pc20.dim(String(err))}`
|
|
|
14112
14261
|
});
|
|
14113
14262
|
if (blanked.length > 0) {
|
|
14114
14263
|
p49.log.info(
|
|
14115
|
-
`Building without ${blanked.join(", ")} \u2014 set in .env but not for ${
|
|
14264
|
+
`Building without ${blanked.join(", ")} \u2014 set in .env but not for ${pc21.cyan(ctx.targetName)}.`
|
|
14116
14265
|
);
|
|
14117
14266
|
}
|
|
14118
14267
|
p49.log.step("Building");
|
|
@@ -14123,7 +14272,7 @@ ${pc20.dim(String(err))}`
|
|
|
14123
14272
|
}
|
|
14124
14273
|
}
|
|
14125
14274
|
const entries = collectArtifact(workspaceRootDir);
|
|
14126
|
-
p49.log.step(`Uploading release ${
|
|
14275
|
+
p49.log.step(`Uploading release ${pc21.dim(release)}`);
|
|
14127
14276
|
await uploadRelease(session, instance, release, entries);
|
|
14128
14277
|
p49.log.step("Activating");
|
|
14129
14278
|
result = await runServerScript(session, "apply.sh", {
|
|
@@ -14191,44 +14340,69 @@ ${pc20.dim(String(err))}`
|
|
|
14191
14340
|
});
|
|
14192
14341
|
const redirects = started?.environment.redirects ?? [];
|
|
14193
14342
|
p49.log.success(
|
|
14194
|
-
`Deployed ${
|
|
14343
|
+
`Deployed ${pc21.cyan(ctx.appName)} ${pc21.dim(release)}
|
|
14195
14344
|
|
|
14196
14345
|
URL ${url}
|
|
14197
|
-
` + (redirects.length ? ` Also ${redirects.map((h) => `https://${h}`).join(", ")} ${
|
|
14346
|
+
` + (redirects.length ? ` Also ${redirects.map((h) => `https://${h}`).join(", ")} ${pc21.dim("(redirects here)")}
|
|
14198
14347
|
` : "") + ` Port ${result?.webPort ?? "?"}${backend3 ? ` (PocketBase ${result?.pbPort ?? "?"})` : ""}`
|
|
14199
14348
|
);
|
|
14200
14349
|
if (managed && managed !== existing?.managed) {
|
|
14201
|
-
p49.log.info(`${
|
|
14350
|
+
p49.log.info(`${pc21.cyan(managed)} goes live within a minute.`);
|
|
14202
14351
|
}
|
|
14203
14352
|
if (result?.superuserCreated) {
|
|
14204
14353
|
p49.log.info(
|
|
14205
14354
|
`Created the PocketBase superuser this app authenticates as.
|
|
14206
14355
|
|
|
14207
14356
|
Its credentials are stored in the environment on the server. To use
|
|
14208
|
-
your own instead, ${
|
|
14357
|
+
your own instead, ${pc21.cyan("vela env set POCKETBASE_SUPERUSER_PASSWORD")}
|
|
14209
14358
|
and deploy again.`
|
|
14210
14359
|
);
|
|
14211
14360
|
}
|
|
14212
14361
|
if (!primaryHost) {
|
|
14213
14362
|
p49.log.warn(
|
|
14214
14363
|
`No domain configured, so nothing is proxied to this app yet.
|
|
14215
|
-
Redeploy with ${
|
|
14216
|
-
or ${
|
|
14364
|
+
Redeploy with ${pc21.cyan("--domain example.com")} once DNS points at ${ctx.server}` + (reporter.enabled ? "" : `,
|
|
14365
|
+
or ${pc21.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
|
|
14217
14366
|
);
|
|
14218
14367
|
}
|
|
14368
|
+
if (backend3) await loadDeployedSeeds(ctx);
|
|
14219
14369
|
}
|
|
14220
14370
|
},
|
|
14221
14371
|
{ project: options.project, askDomain: true, label: "deploy" }
|
|
14222
14372
|
);
|
|
14223
|
-
p49.outro(`${
|
|
14373
|
+
p49.outro(`${pc21.cyan("vela status")} to see what is running`);
|
|
14224
14374
|
}, "Failed to deploy.")
|
|
14225
14375
|
);
|
|
14376
|
+
async function loadDeployedSeeds(ctx) {
|
|
14377
|
+
const seedFiles = getSeedFiles(ctx.workspaceRootDir);
|
|
14378
|
+
if (seedFiles.length === 0) return;
|
|
14379
|
+
try {
|
|
14380
|
+
const loaded = await withRemotePocketbase(
|
|
14381
|
+
ctx.session,
|
|
14382
|
+
ctx.instance,
|
|
14383
|
+
(pb) => loadSeeds(pb, ctx.workspaceRootDir, seedFiles)
|
|
14384
|
+
);
|
|
14385
|
+
if (loaded.some((result) => result.created > 0)) {
|
|
14386
|
+
p49.log.success(summarizeSeedLoad(loaded));
|
|
14387
|
+
}
|
|
14388
|
+
} catch (err) {
|
|
14389
|
+
const retry = `vela seeds load -t ${ctx.targetName}`;
|
|
14390
|
+
p49.log.error(
|
|
14391
|
+
`The release is deployed, but its seeds did not all load.
|
|
14392
|
+
|
|
14393
|
+
${err instanceof Error ? err.message : String(err)}
|
|
14394
|
+
|
|
14395
|
+
` + (err instanceof DataLoadError ? `Fix the file, then run ${pc21.cyan(retry)}. Records already loaded are left as they are.` : `Run ${pc21.cyan(retry)} to try again.`)
|
|
14396
|
+
);
|
|
14397
|
+
process38.exitCode = 1;
|
|
14398
|
+
}
|
|
14399
|
+
}
|
|
14226
14400
|
async function prepareAdapter(workspaceRootDir) {
|
|
14227
14401
|
const rethrow = (err) => {
|
|
14228
14402
|
if (err instanceof AdapterError) {
|
|
14229
14403
|
throw new Error(err.snippet ? `${err.message}
|
|
14230
14404
|
|
|
14231
|
-
${
|
|
14405
|
+
${pc21.cyan(err.snippet)}` : err.message);
|
|
14232
14406
|
}
|
|
14233
14407
|
throw err;
|
|
14234
14408
|
};
|
|
@@ -14256,7 +14430,7 @@ Switch it to ${ADAPTER_NODE}? This edits ${path59.basename(current.file)} and pa
|
|
|
14256
14430
|
outcome.packageJsonChanged ? "package.json" : void 0
|
|
14257
14431
|
].filter((f) => Boolean(f));
|
|
14258
14432
|
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`;
|
|
14259
|
-
p49.log.step(`Switching the adapter to ${
|
|
14433
|
+
p49.log.step(`Switching the adapter to ${pc21.cyan(ADAPTER_NODE)}`);
|
|
14260
14434
|
p49.log.info(
|
|
14261
14435
|
`${why}, and vela deploy runs the app as a Node server.
|
|
14262
14436
|
|
|
@@ -14316,13 +14490,13 @@ Set them with \`vela env set POCKETBASE_SUPERUSER_EMAIL\` and \`vela env set POC
|
|
|
14316
14490
|
|
|
14317
14491
|
They are what \`--remote-db\` renders the build as. The usual cause is a password
|
|
14318
14492
|
changed in the PocketBase admin panel, which leaves the database and
|
|
14319
|
-
${
|
|
14493
|
+
${pc21.cyan(`/etc/vela/apps/${instance}/env`)} disagreeing.
|
|
14320
14494
|
|
|
14321
14495
|
Point the environment at the password the database has:
|
|
14322
|
-
${
|
|
14496
|
+
${pc21.cyan("vela env set POCKETBASE_SUPERUSER_PASSWORD")}
|
|
14323
14497
|
|
|
14324
14498
|
or build against a throwaway local database instead:
|
|
14325
|
-
${
|
|
14499
|
+
${pc21.cyan("vela deploy --no-remote-db")}`
|
|
14326
14500
|
);
|
|
14327
14501
|
}
|
|
14328
14502
|
return {
|
|
@@ -14387,7 +14561,7 @@ async function requireServerNode(session, server) {
|
|
|
14387
14561
|
throw new Error(
|
|
14388
14562
|
`${server} ${version ? `runs Node ${version}` : "has no Node"}, and this app needs ${major}.${minor} or later.
|
|
14389
14563
|
|
|
14390
|
-
Run ${
|
|
14564
|
+
Run ${pc21.cyan(`vela provision ${server}`)} to upgrade it, then deploy again.`
|
|
14391
14565
|
);
|
|
14392
14566
|
}
|
|
14393
14567
|
function nodeMajorDrift(serverVersion, buildVersion) {
|
|
@@ -14485,12 +14659,12 @@ import { Command as Command97 } from "commander";
|
|
|
14485
14659
|
import { Command as Command92 } from "commander";
|
|
14486
14660
|
import * as v12 from "valibot";
|
|
14487
14661
|
import * as p53 from "@clack/prompts";
|
|
14488
|
-
import
|
|
14662
|
+
import pc24 from "picocolors";
|
|
14489
14663
|
|
|
14490
14664
|
// src/lib/local-env.ts
|
|
14491
14665
|
import fs55 from "node:fs";
|
|
14492
14666
|
import * as p51 from "@clack/prompts";
|
|
14493
|
-
import
|
|
14667
|
+
import pc22 from "picocolors";
|
|
14494
14668
|
function readLocalEnv(envFile) {
|
|
14495
14669
|
if (!fs55.existsSync(envFile)) return {};
|
|
14496
14670
|
return readLocalEnvFile(envFile);
|
|
@@ -14519,12 +14693,12 @@ async function applyLocalEnvChange(ctx, changed) {
|
|
|
14519
14693
|
} else {
|
|
14520
14694
|
p51.log.warn(
|
|
14521
14695
|
`The local database still has the old superuser.
|
|
14522
|
-
Set both ${
|
|
14696
|
+
Set both ${pc22.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc22.cyan("POCKETBASE_SUPERUSER_PASSWORD")} to reconcile it.`
|
|
14523
14697
|
);
|
|
14524
14698
|
}
|
|
14525
14699
|
}
|
|
14526
14700
|
if (getPocketbaseMetadata(ctx.workspaceRootDir)) {
|
|
14527
|
-
p51.log.info(`Restart ${
|
|
14701
|
+
p51.log.info(`Restart ${pc22.cyan("vela dev")} to pick this up.`);
|
|
14528
14702
|
}
|
|
14529
14703
|
}
|
|
14530
14704
|
|
|
@@ -14532,7 +14706,7 @@ Set both ${pc21.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc21.cyan("POCKETBASE_
|
|
|
14532
14706
|
import process40 from "node:process";
|
|
14533
14707
|
import * as v11 from "valibot";
|
|
14534
14708
|
import * as p52 from "@clack/prompts";
|
|
14535
|
-
import
|
|
14709
|
+
import pc23 from "picocolors";
|
|
14536
14710
|
var ALL_SCOPE = "all";
|
|
14537
14711
|
var PREVIEW_SCOPE = "preview";
|
|
14538
14712
|
function parseEnvScope(raw) {
|
|
@@ -14575,7 +14749,7 @@ async function withEnvScope(raw, handlers, run) {
|
|
|
14575
14749
|
let scope = parseEnvScope(options.target);
|
|
14576
14750
|
if (!scope) {
|
|
14577
14751
|
if (!run.ask)
|
|
14578
|
-
throw new TargetError(`${label2} needs ${
|
|
14752
|
+
throw new TargetError(`${label2} needs ${pc23.cyan("-t")} to say which environment.`);
|
|
14579
14753
|
scope = await promptScope(workspaceRootDir, label2);
|
|
14580
14754
|
}
|
|
14581
14755
|
if (scope.kind === "local" || scope.kind === "instance") {
|
|
@@ -14610,9 +14784,9 @@ async function withEnvScope(raw, handlers, run) {
|
|
|
14610
14784
|
throw new TargetError(
|
|
14611
14785
|
layer === "all" ? `No target is bound to a server yet, so there is nowhere to write.
|
|
14612
14786
|
|
|
14613
|
-
Deploy once (${
|
|
14787
|
+
Deploy once (${pc23.cyan("vela deploy --server user@host")}) and the app-wide layer goes to every server it is deployed to.` : `Previews are not bound to a server yet.
|
|
14614
14788
|
|
|
14615
|
-
Deploy one first: ${
|
|
14789
|
+
Deploy one first: ${pc23.cyan("vela deploy -t preview --server user@host")}.`
|
|
14616
14790
|
);
|
|
14617
14791
|
}
|
|
14618
14792
|
const app = resolveAppIdentity(workspaceRootDir);
|
|
@@ -14648,7 +14822,7 @@ async function promptScope(workspaceRootDir, label2) {
|
|
|
14648
14822
|
const scopes = knownScopes(workspaceRootDir);
|
|
14649
14823
|
if (!isInteractive()) {
|
|
14650
14824
|
throw new TargetError(
|
|
14651
|
-
`${label2} needs ${
|
|
14825
|
+
`${label2} needs ${pc23.cyan("-t")} to say which environment: ${scopes.join(", ")}.`
|
|
14652
14826
|
);
|
|
14653
14827
|
}
|
|
14654
14828
|
const hints = {
|
|
@@ -14676,7 +14850,7 @@ async function applyLayerRestart(ctx, changed) {
|
|
|
14676
14850
|
`PocketBase superuser credentials changed.
|
|
14677
14851
|
|
|
14678
14852
|
Each database still holds the old ones, so nothing was restarted.
|
|
14679
|
-
Run ${
|
|
14853
|
+
Run ${pc23.cyan("vela deploy")} for every target to push them in.`
|
|
14680
14854
|
);
|
|
14681
14855
|
return;
|
|
14682
14856
|
}
|
|
@@ -14689,18 +14863,18 @@ Run ${pc22.cyan("vela deploy")} for every target to push them in.`
|
|
|
14689
14863
|
const reach = changed.filter((key) => !(key in shadowed));
|
|
14690
14864
|
if (Object.keys(shadowed).length > 0) p52.log.warn(shadowWarning(state, ctx.layer, shadowed));
|
|
14691
14865
|
if (reach.length === 0) {
|
|
14692
|
-
p52.log.info(`${state.env} not restarted ${
|
|
14866
|
+
p52.log.info(`${state.env} not restarted ${pc23.dim(`(${ctx.server})`)}`);
|
|
14693
14867
|
continue;
|
|
14694
14868
|
}
|
|
14695
14869
|
const outcome = await restartInstance(ctx.session, state.instance);
|
|
14696
14870
|
if (!outcome.deployed) continue;
|
|
14697
|
-
if (outcome.restarted) p52.log.success(`${state.env} restarted ${
|
|
14871
|
+
if (outcome.restarted) p52.log.success(`${state.env} restarted ${pc23.dim(`(${ctx.server})`)}`);
|
|
14698
14872
|
else {
|
|
14699
14873
|
p52.log.error(
|
|
14700
14874
|
`${state.env} restart failed.
|
|
14701
14875
|
|
|
14702
14876
|
The new value is stored and will be used the next time it starts.
|
|
14703
|
-
${
|
|
14877
|
+
${pc23.dim(outcome.error ?? "")}`
|
|
14704
14878
|
);
|
|
14705
14879
|
}
|
|
14706
14880
|
}
|
|
@@ -14717,7 +14891,7 @@ function shadowWarning(state, layer, shadowed) {
|
|
|
14717
14891
|
if (above === "preview") {
|
|
14718
14892
|
lines.push(
|
|
14719
14893
|
`The preview layer sets ${list3} too, and wins over ${layer} for ${state.env}.`,
|
|
14720
|
-
`To use the ${layer} value${plural ? "s" : ""} there: ${
|
|
14894
|
+
`To use the ${layer} value${plural ? "s" : ""} there: ${pc23.cyan(`vela env unset ${plural ? "<key>" : list3} -t preview`)}`
|
|
14721
14895
|
);
|
|
14722
14896
|
} else if (state.preview) {
|
|
14723
14897
|
lines.push(`${state.env} sets ${list3} itself, which wins over ${layer}.`);
|
|
@@ -14725,7 +14899,7 @@ function shadowWarning(state, layer, shadowed) {
|
|
|
14725
14899
|
const target = state.env === PROD_ENV ? PRODUCTION_TARGET : state.env;
|
|
14726
14900
|
lines.push(
|
|
14727
14901
|
`${state.env} sets ${list3} itself, which wins over ${layer}.`,
|
|
14728
|
-
`To use the ${layer} value${plural ? "s" : ""} there: ${
|
|
14902
|
+
`To use the ${layer} value${plural ? "s" : ""} there: ${pc23.cyan(`vela env unset ${plural ? "<key>" : list3} -t ${target}`)}`
|
|
14729
14903
|
);
|
|
14730
14904
|
}
|
|
14731
14905
|
}
|
|
@@ -14735,7 +14909,7 @@ async function applyChange(workspaceRootDir, ctx, changed) {
|
|
|
14735
14909
|
const { baked, how } = readAtBuildTime(workspaceRootDir, changed);
|
|
14736
14910
|
if (baked.length > 0) {
|
|
14737
14911
|
p52.log.info(
|
|
14738
|
-
`${baked.join(", ")} ${baked.length === 1 ? "is" : "are"} read at build time (${
|
|
14912
|
+
`${baked.join(", ")} ${baked.length === 1 ? "is" : "are"} read at build time (${pc23.cyan(how)}); redeploy to apply.`
|
|
14739
14913
|
);
|
|
14740
14914
|
const rest = changed.filter((key) => !baked.includes(key));
|
|
14741
14915
|
if (rest.length === 0) return;
|
|
@@ -14770,11 +14944,11 @@ var envList = addEnvTargetOptions(
|
|
|
14770
14944
|
local: async (ctx) => {
|
|
14771
14945
|
const keys = Object.keys(readLocalEnv(ctx.envFile)).sort();
|
|
14772
14946
|
if (keys.length === 0) {
|
|
14773
|
-
p53.log.info(`No environment variables configured ${
|
|
14947
|
+
p53.log.info(`No environment variables configured ${pc24.dim("(local)")}.`);
|
|
14774
14948
|
return;
|
|
14775
14949
|
}
|
|
14776
14950
|
p53.log.info(
|
|
14777
|
-
`Environment ${
|
|
14951
|
+
`Environment ${pc24.dim("(local, .env)")}
|
|
14778
14952
|
|
|
14779
14953
|
${keys.map((k) => ` ${k}`).join("\n")}`
|
|
14780
14954
|
);
|
|
@@ -14783,16 +14957,16 @@ ${keys.map((k) => ` ${k}`).join("\n")}`
|
|
|
14783
14957
|
const stack = await resolveStack(ctx.session, ctx.appId, ctx.instance, ctx.preview);
|
|
14784
14958
|
const keys = Object.keys(stack.entries).sort();
|
|
14785
14959
|
if (keys.length === 0) {
|
|
14786
|
-
p53.log.info(`No environment variables configured ${
|
|
14960
|
+
p53.log.info(`No environment variables configured ${pc24.dim(`(${ctx.targetName})`)}.`);
|
|
14787
14961
|
return;
|
|
14788
14962
|
}
|
|
14789
14963
|
const width = Math.max(...keys.map((k) => k.length));
|
|
14790
14964
|
p53.log.info(
|
|
14791
|
-
`Environment ${
|
|
14965
|
+
`Environment ${pc24.dim(`(${ctx.targetName}, as the app sees it)`)}
|
|
14792
14966
|
|
|
14793
14967
|
` + keys.map((key) => {
|
|
14794
14968
|
const entry = stack.entries[key];
|
|
14795
|
-
const from = entry.layer === "instance" ? "" :
|
|
14969
|
+
const from = entry.layer === "instance" ? "" : pc24.dim(` from ${entry.layer}`);
|
|
14796
14970
|
return ` ${key.padEnd(width)} ${cell(entry.visibility, entry.value)}${from}`;
|
|
14797
14971
|
}).join("\n")
|
|
14798
14972
|
);
|
|
@@ -14802,12 +14976,12 @@ ${keys.map((k) => ` ${k}`).join("\n")}`
|
|
|
14802
14976
|
const keys = [...Object.keys(contents.secret), ...Object.keys(contents.public)].sort();
|
|
14803
14977
|
const where = `${ctx.layer}, ${ctx.server}`;
|
|
14804
14978
|
if (keys.length === 0) {
|
|
14805
|
-
p53.log.info(`No environment variables configured ${
|
|
14979
|
+
p53.log.info(`No environment variables configured ${pc24.dim(`(${where})`)}.`);
|
|
14806
14980
|
return;
|
|
14807
14981
|
}
|
|
14808
14982
|
const width = Math.max(...keys.map((k) => k.length));
|
|
14809
14983
|
p53.log.info(
|
|
14810
|
-
`Environment ${
|
|
14984
|
+
`Environment ${pc24.dim(`(${where})`)}
|
|
14811
14985
|
|
|
14812
14986
|
` + keys.map(
|
|
14813
14987
|
(key) => ` ${key.padEnd(width)} ${key in contents.public ? cell("public", contents.public[key]) : cell("secret")}`
|
|
@@ -14820,7 +14994,7 @@ ${keys.map((k) => ` ${k}`).join("\n")}`
|
|
|
14820
14994
|
}, "Failed to read the environment.")
|
|
14821
14995
|
);
|
|
14822
14996
|
function cell(visibility, value) {
|
|
14823
|
-
if (visibility === "secret") return
|
|
14997
|
+
if (visibility === "secret") return pc24.dim(HIDDEN);
|
|
14824
14998
|
const shown = value ?? "";
|
|
14825
14999
|
return shown.length > MAX_VALUE ? `${shown.slice(0, MAX_VALUE - 1)}\u2026` : shown;
|
|
14826
15000
|
}
|
|
@@ -14831,13 +15005,13 @@ async function listMatrix(raw) {
|
|
|
14831
15005
|
const bindings = readBindings(workspaceRootDir);
|
|
14832
15006
|
const local = Object.keys(readLocalEnv(`${workspaceRootDir}/.env`)).sort();
|
|
14833
15007
|
p53.log.info(
|
|
14834
|
-
local.length ? `Local ${
|
|
15008
|
+
local.length ? `Local ${pc24.dim("(.env, names only)")}
|
|
14835
15009
|
|
|
14836
|
-
${local.map((k) => ` ${k}`).join("\n")}` : `No local environment ${
|
|
15010
|
+
${local.map((k) => ` ${k}`).join("\n")}` : `No local environment ${pc24.dim("(.env)")}.`
|
|
14837
15011
|
);
|
|
14838
15012
|
const servers = [...new Set(Object.values(bindings).map((b) => b.server))];
|
|
14839
15013
|
if (!app || servers.length === 0) {
|
|
14840
|
-
p53.log.info(`No target is bound to a server yet; ${
|
|
15014
|
+
p53.log.info(`No target is bound to a server yet; ${pc24.cyan("vela deploy")} binds one.`);
|
|
14841
15015
|
return;
|
|
14842
15016
|
}
|
|
14843
15017
|
for (const server of servers) {
|
|
@@ -14876,7 +15050,7 @@ ${local.map((k) => ` ${k}`).join("\n")}` : `No local environment ${pc23.dim("(.
|
|
|
14876
15050
|
)
|
|
14877
15051
|
].sort();
|
|
14878
15052
|
if (keys.length === 0) {
|
|
14879
|
-
p53.log.info(`No environment variables configured ${
|
|
15053
|
+
p53.log.info(`No environment variables configured ${pc24.dim(`(${server})`)}.`);
|
|
14880
15054
|
return;
|
|
14881
15055
|
}
|
|
14882
15056
|
const rows = keys.map((key) => [
|
|
@@ -14889,9 +15063,9 @@ ${local.map((k) => ` ${k}`).join("\n")}` : `No local environment ${pc23.dim("(.
|
|
|
14889
15063
|
);
|
|
14890
15064
|
const line = (cells) => cells.map((c, i) => c + " ".repeat(widths[i] - plain(c).length)).join(" ");
|
|
14891
15065
|
p53.log.info(
|
|
14892
|
-
`Environment ${
|
|
15066
|
+
`Environment ${pc24.dim(`(${server})`)}
|
|
14893
15067
|
|
|
14894
|
-
${
|
|
15068
|
+
${pc24.dim(line(headings))}
|
|
14895
15069
|
` + rows.map((r) => ` ${line(r)}`).join("\n")
|
|
14896
15070
|
);
|
|
14897
15071
|
});
|
|
@@ -14901,17 +15075,17 @@ function matrixCell(key, columns, index, states) {
|
|
|
14901
15075
|
const column = columns[index];
|
|
14902
15076
|
if (key in column.contents.public) return cell("public", column.contents.public[key]);
|
|
14903
15077
|
if (key in column.contents.secret) return cell("secret");
|
|
14904
|
-
if (column.layer !== "instance") return
|
|
15078
|
+
if (column.layer !== "instance") return pc24.dim("\u2014");
|
|
14905
15079
|
const state = states[index - columns.findIndex((c) => c.layer === "instance")];
|
|
14906
15080
|
const inherits = columns.filter(
|
|
14907
15081
|
(c) => c.layer === "all" || c.layer === "preview" && state?.preview === true
|
|
14908
15082
|
);
|
|
14909
15083
|
for (const layer of inherits.reverse()) {
|
|
14910
15084
|
if (key in layer.contents.public || key in layer.contents.secret) {
|
|
14911
|
-
return
|
|
15085
|
+
return pc24.dim(`\u2191 ${layer.heading}`);
|
|
14912
15086
|
}
|
|
14913
15087
|
}
|
|
14914
|
-
return
|
|
15088
|
+
return pc24.dim("\u2014");
|
|
14915
15089
|
}
|
|
14916
15090
|
var ANSI3 = /\u001b\[[0-9;]*m/g;
|
|
14917
15091
|
function plain(text20) {
|
|
@@ -14922,7 +15096,7 @@ function plain(text20) {
|
|
|
14922
15096
|
import process41 from "node:process";
|
|
14923
15097
|
import { Command as Command93 } from "commander";
|
|
14924
15098
|
import * as p54 from "@clack/prompts";
|
|
14925
|
-
import
|
|
15099
|
+
import pc25 from "picocolors";
|
|
14926
15100
|
var envSet = addEnvTargetOptions(
|
|
14927
15101
|
new Command93("set").description("set an environment variable \u2014 the value is prompted for, never an argument").argument("<key>", "variable name").option(
|
|
14928
15102
|
"--public",
|
|
@@ -14938,19 +15112,19 @@ var envSet = addEnvTargetOptions(
|
|
|
14938
15112
|
local: async (ctx) => {
|
|
14939
15113
|
const value = await promptValue2(key, "public");
|
|
14940
15114
|
setLocalEnv(ctx.envFile, key, value);
|
|
14941
|
-
p54.log.success(`${key} updated ${
|
|
15115
|
+
p54.log.success(`${key} updated ${pc25.dim("(local)")}`);
|
|
14942
15116
|
await applyLocalEnvChange(ctx, [key]);
|
|
14943
15117
|
},
|
|
14944
15118
|
instance: async (ctx) => {
|
|
14945
15119
|
const value = await promptValue2(key, visibilityFor(key, asPublic));
|
|
14946
15120
|
const outcome = await setInLayer(ctx.session, ctx.files, key, value, asPublic);
|
|
14947
|
-
|
|
15121
|
+
report2(key, outcome.visibility, outcome.moved, ctx.targetName);
|
|
14948
15122
|
await applyChange(ctx.workspaceRootDir, ctx, [key]);
|
|
14949
15123
|
},
|
|
14950
15124
|
layer: async (ctx) => {
|
|
14951
15125
|
const value = await promptValue2(key, visibilityFor(key, asPublic));
|
|
14952
15126
|
const outcome = await setInLayer(ctx.session, ctx.files, key, value, asPublic);
|
|
14953
|
-
|
|
15127
|
+
report2(key, outcome.visibility, outcome.moved, `${ctx.layer}, ${ctx.server}`);
|
|
14954
15128
|
await applyChange(ctx.workspaceRootDir, ctx, [key]);
|
|
14955
15129
|
}
|
|
14956
15130
|
},
|
|
@@ -14958,9 +15132,9 @@ var envSet = addEnvTargetOptions(
|
|
|
14958
15132
|
);
|
|
14959
15133
|
}, "Failed to set the variable.")
|
|
14960
15134
|
);
|
|
14961
|
-
function
|
|
15135
|
+
function report2(key, visibility, moved, where) {
|
|
14962
15136
|
const tag = visibility === "public" ? " (public)" : "";
|
|
14963
|
-
p54.log.success(`${key} updated${tag} ${
|
|
15137
|
+
p54.log.success(`${key} updated${tag} ${pc25.dim(`(${where})`)}`);
|
|
14964
15138
|
if (moved) {
|
|
14965
15139
|
p54.log.info(
|
|
14966
15140
|
visibility === "public" ? `${key} was secret before; it is readable from now on.` : `${key} was public before; it is write-only from now on.`
|
|
@@ -14968,7 +15142,7 @@ function report(key, visibility, moved, where) {
|
|
|
14968
15142
|
}
|
|
14969
15143
|
}
|
|
14970
15144
|
async function promptValue2(key, visibility) {
|
|
14971
|
-
const message = `Value for ${
|
|
15145
|
+
const message = `Value for ${pc25.cyan(key)}${visibility === "public" ? pc25.dim(" (public)") : ""}`;
|
|
14972
15146
|
const validate = (input) => !input?.length ? "Required" : void 0;
|
|
14973
15147
|
const value = visibility === "public" ? await p54.text({ message, validate }) : await p54.password({ message, validate });
|
|
14974
15148
|
if (p54.isCancel(value)) {
|
|
@@ -14984,7 +15158,7 @@ async function promptValue2(key, visibility) {
|
|
|
14984
15158
|
// src/commands/env/unset.ts
|
|
14985
15159
|
import { Command as Command94 } from "commander";
|
|
14986
15160
|
import * as p55 from "@clack/prompts";
|
|
14987
|
-
import
|
|
15161
|
+
import pc26 from "picocolors";
|
|
14988
15162
|
var envUnset = addEnvTargetOptions(
|
|
14989
15163
|
new Command94("unset").description("remove an environment variable").argument("<key>", "variable name").configureHelp(helpConfig)
|
|
14990
15164
|
).action(
|
|
@@ -14998,7 +15172,7 @@ var envUnset = addEnvTargetOptions(
|
|
|
14998
15172
|
return;
|
|
14999
15173
|
}
|
|
15000
15174
|
unsetLocalEnv(ctx.envFile, key);
|
|
15001
|
-
p55.log.success(`${key} removed ${
|
|
15175
|
+
p55.log.success(`${key} removed ${pc26.dim("(local)")}`);
|
|
15002
15176
|
await applyLocalEnvChange(ctx, [key]);
|
|
15003
15177
|
},
|
|
15004
15178
|
// Removed from whichever side it was on; nobody should have to
|
|
@@ -15008,7 +15182,7 @@ var envUnset = addEnvTargetOptions(
|
|
|
15008
15182
|
p55.log.info(`${key} is not set on ${ctx.targetName} \u2014 nothing to remove.`);
|
|
15009
15183
|
return;
|
|
15010
15184
|
}
|
|
15011
|
-
p55.log.success(`${key} removed ${
|
|
15185
|
+
p55.log.success(`${key} removed ${pc26.dim(`(${ctx.targetName})`)}`);
|
|
15012
15186
|
await applyChange(ctx.workspaceRootDir, ctx, [key]);
|
|
15013
15187
|
},
|
|
15014
15188
|
layer: async (ctx) => {
|
|
@@ -15016,7 +15190,7 @@ var envUnset = addEnvTargetOptions(
|
|
|
15016
15190
|
p55.log.info(`${key} is not set (${ctx.layer}, ${ctx.server}) \u2014 nothing to remove.`);
|
|
15017
15191
|
return;
|
|
15018
15192
|
}
|
|
15019
|
-
p55.log.success(`${key} removed ${
|
|
15193
|
+
p55.log.success(`${key} removed ${pc26.dim(`(${ctx.layer}, ${ctx.server})`)}`);
|
|
15020
15194
|
await applyChange(ctx.workspaceRootDir, ctx, [key]);
|
|
15021
15195
|
}
|
|
15022
15196
|
},
|
|
@@ -15032,7 +15206,7 @@ import path61 from "node:path";
|
|
|
15032
15206
|
import process42 from "node:process";
|
|
15033
15207
|
import { Command as Command95 } from "commander";
|
|
15034
15208
|
import * as p56 from "@clack/prompts";
|
|
15035
|
-
import
|
|
15209
|
+
import pc27 from "picocolors";
|
|
15036
15210
|
var envImport = addEnvTargetOptions(
|
|
15037
15211
|
new Command95("import").description("merge a dotenv file into the environment").argument("<file>", "dotenv file to read").option("--public", "import as readable values; PUBLIC_* keys are public regardless").configureHelp(helpConfig)
|
|
15038
15212
|
).action(
|
|
@@ -15048,12 +15222,12 @@ var envImport = addEnvTargetOptions(
|
|
|
15048
15222
|
const incoming = read(source, file);
|
|
15049
15223
|
const keys = Object.keys(incoming);
|
|
15050
15224
|
if (keys.length === 0) return;
|
|
15051
|
-
p56.log.step(`Importing ${keys.length} variable(s) from ${
|
|
15225
|
+
p56.log.step(`Importing ${keys.length} variable(s) from ${pc27.cyan(file)}`);
|
|
15052
15226
|
editLocalEnv(
|
|
15053
15227
|
ctx.envFile,
|
|
15054
15228
|
(content) => keys.reduce((acc, key) => upsertEnvVar(acc, key, incoming[key]), content)
|
|
15055
15229
|
);
|
|
15056
|
-
p56.log.success(`${keys.length} variable(s) updated ${
|
|
15230
|
+
p56.log.success(`${keys.length} variable(s) updated ${pc27.dim("(local)")}`);
|
|
15057
15231
|
await applyLocalEnvChange(ctx, keys);
|
|
15058
15232
|
},
|
|
15059
15233
|
// Merge: values in the layer that the file does not mention stay put.
|
|
@@ -15061,28 +15235,28 @@ var envImport = addEnvTargetOptions(
|
|
|
15061
15235
|
const incoming = read(resolve(file), file);
|
|
15062
15236
|
const keys = Object.keys(incoming);
|
|
15063
15237
|
if (keys.length === 0) return;
|
|
15064
|
-
p56.log.step(`Importing ${keys.length} variable(s) from ${
|
|
15238
|
+
p56.log.step(`Importing ${keys.length} variable(s) from ${pc27.cyan(file)}`);
|
|
15065
15239
|
const outcome = await importIntoLayer(
|
|
15066
15240
|
ctx.session,
|
|
15067
15241
|
ctx.files,
|
|
15068
15242
|
incoming,
|
|
15069
15243
|
raw.public === true
|
|
15070
15244
|
);
|
|
15071
|
-
|
|
15245
|
+
report3(outcome, ctx.targetName);
|
|
15072
15246
|
await applyChange(ctx.workspaceRootDir, ctx, keys);
|
|
15073
15247
|
},
|
|
15074
15248
|
layer: async (ctx) => {
|
|
15075
15249
|
const incoming = read(resolve(file), file);
|
|
15076
15250
|
const keys = Object.keys(incoming);
|
|
15077
15251
|
if (keys.length === 0) return;
|
|
15078
|
-
p56.log.step(`Importing ${keys.length} variable(s) from ${
|
|
15252
|
+
p56.log.step(`Importing ${keys.length} variable(s) from ${pc27.cyan(file)}`);
|
|
15079
15253
|
const outcome = await importIntoLayer(
|
|
15080
15254
|
ctx.session,
|
|
15081
15255
|
ctx.files,
|
|
15082
15256
|
incoming,
|
|
15083
15257
|
raw.public === true
|
|
15084
15258
|
);
|
|
15085
|
-
|
|
15259
|
+
report3(outcome, `${ctx.layer}, ${ctx.server}`);
|
|
15086
15260
|
await applyChange(ctx.workspaceRootDir, ctx, keys);
|
|
15087
15261
|
}
|
|
15088
15262
|
},
|
|
@@ -15091,12 +15265,12 @@ var envImport = addEnvTargetOptions(
|
|
|
15091
15265
|
"Failed to import the environment."
|
|
15092
15266
|
)
|
|
15093
15267
|
);
|
|
15094
|
-
function
|
|
15268
|
+
function report3(outcome, where) {
|
|
15095
15269
|
const parts = [
|
|
15096
15270
|
outcome.secret.length ? `${outcome.secret.length} secret` : "",
|
|
15097
15271
|
outcome.public.length ? `${outcome.public.length} public` : ""
|
|
15098
15272
|
].filter(Boolean);
|
|
15099
|
-
p56.log.success(`${parts.join(", ")} variable(s) updated ${
|
|
15273
|
+
p56.log.success(`${parts.join(", ")} variable(s) updated ${pc27.dim(`(${where})`)}`);
|
|
15100
15274
|
}
|
|
15101
15275
|
function resolve(file) {
|
|
15102
15276
|
return path61.resolve(process42.cwd(), file);
|
|
@@ -15112,7 +15286,7 @@ function read(resolved, shown) {
|
|
|
15112
15286
|
import process43 from "node:process";
|
|
15113
15287
|
import { Command as Command96 } from "commander";
|
|
15114
15288
|
import * as p57 from "@clack/prompts";
|
|
15115
|
-
import
|
|
15289
|
+
import pc28 from "picocolors";
|
|
15116
15290
|
var envGet = addEnvTargetOptions(
|
|
15117
15291
|
new Command96("get").description("print a public environment variable").argument("<key>", "variable name").configureHelp(helpConfig)
|
|
15118
15292
|
).action(
|
|
@@ -15155,8 +15329,8 @@ var envGet = addEnvTargetOptions(
|
|
|
15155
15329
|
);
|
|
15156
15330
|
function secret(key, where, from) {
|
|
15157
15331
|
p57.log.info(
|
|
15158
|
-
`${key} is secret ${
|
|
15159
|
-
Set it again to change it: ${
|
|
15332
|
+
`${key} is secret ${pc28.dim(`(${where}${from ? `, from ${from}` : ""})`)}, so it is not read back.
|
|
15333
|
+
Set it again to change it: ${pc28.cyan(`vela env set ${key}`)}`
|
|
15160
15334
|
);
|
|
15161
15335
|
process43.exitCode = 1;
|
|
15162
15336
|
}
|
|
@@ -15167,7 +15341,7 @@ var env = new Command97("env").description("manage environment variables, locall
|
|
|
15167
15341
|
// src/commands/status.ts
|
|
15168
15342
|
import { Command as Command98 } from "commander";
|
|
15169
15343
|
import * as p58 from "@clack/prompts";
|
|
15170
|
-
import
|
|
15344
|
+
import pc29 from "picocolors";
|
|
15171
15345
|
var status = addTargetOptions(
|
|
15172
15346
|
new Command98("status").description("show what is deployed").configureHelp(helpConfig),
|
|
15173
15347
|
"production"
|
|
@@ -15176,7 +15350,7 @@ var status = addTargetOptions(
|
|
|
15176
15350
|
const options = raw;
|
|
15177
15351
|
if (options.all) {
|
|
15178
15352
|
await withServerSession(raw, async (session) => {
|
|
15179
|
-
|
|
15353
|
+
report4(await readInstanceStates(session), options.json);
|
|
15180
15354
|
});
|
|
15181
15355
|
return;
|
|
15182
15356
|
}
|
|
@@ -15184,7 +15358,7 @@ var status = addTargetOptions(
|
|
|
15184
15358
|
raw,
|
|
15185
15359
|
{
|
|
15186
15360
|
remote: async (ctx) => {
|
|
15187
|
-
|
|
15361
|
+
report4(await readInstanceStates(ctx.session, ctx.instance), options.json);
|
|
15188
15362
|
}
|
|
15189
15363
|
},
|
|
15190
15364
|
{
|
|
@@ -15194,7 +15368,7 @@ var status = addTargetOptions(
|
|
|
15194
15368
|
);
|
|
15195
15369
|
}, "Failed to read status.")
|
|
15196
15370
|
);
|
|
15197
|
-
function
|
|
15371
|
+
function report4(states, json2) {
|
|
15198
15372
|
if (json2) {
|
|
15199
15373
|
console.log(JSON.stringify(states, null, 2));
|
|
15200
15374
|
return;
|
|
@@ -15208,7 +15382,7 @@ function report3(states, json2) {
|
|
|
15208
15382
|
}
|
|
15209
15383
|
}
|
|
15210
15384
|
function describe2(state) {
|
|
15211
|
-
const health = (value) => value === "active" ?
|
|
15385
|
+
const health = (value) => value === "active" ? pc29.green(value) : pc29.red(value || "inactive");
|
|
15212
15386
|
const rows = [
|
|
15213
15387
|
["Instance", state.instance],
|
|
15214
15388
|
["Environment", state.env],
|
|
@@ -15224,13 +15398,13 @@ function describe2(state) {
|
|
|
15224
15398
|
...state.gitSha ? [["Commit", state.gitSha.slice(0, 12)]] : []
|
|
15225
15399
|
];
|
|
15226
15400
|
const width = Math.max(...rows.map(([label2]) => label2.length));
|
|
15227
|
-
return
|
|
15401
|
+
return pc29.cyan(state.name) + "\n\n" + rows.map(([label2, value]) => ` ${label2.padEnd(width)} ${value}`).join("\n");
|
|
15228
15402
|
}
|
|
15229
15403
|
|
|
15230
15404
|
// src/commands/rollback.ts
|
|
15231
15405
|
import { Command as Command99 } from "commander";
|
|
15232
15406
|
import * as p59 from "@clack/prompts";
|
|
15233
|
-
import
|
|
15407
|
+
import pc30 from "picocolors";
|
|
15234
15408
|
var rollback = addLockWaitOption(
|
|
15235
15409
|
addTargetOptions(
|
|
15236
15410
|
new Command99("rollback").description("put the previous release back").configureHelp(helpConfig),
|
|
@@ -15244,7 +15418,7 @@ var rollback = addLockWaitOption(
|
|
|
15244
15418
|
{
|
|
15245
15419
|
remote: async (ctx) => {
|
|
15246
15420
|
p59.log.step(
|
|
15247
|
-
`Rolling back ${
|
|
15421
|
+
`Rolling back ${pc30.cyan(ctx.appName)} ${pc30.dim(`(${ctx.targetName})`)} on ${ctx.server}`
|
|
15248
15422
|
);
|
|
15249
15423
|
const result = await runServerScript(
|
|
15250
15424
|
ctx.session,
|
|
@@ -15259,7 +15433,7 @@ var rollback = addLockWaitOption(
|
|
|
15259
15433
|
}
|
|
15260
15434
|
);
|
|
15261
15435
|
p59.log.success(
|
|
15262
|
-
`Rolled back to ${
|
|
15436
|
+
`Rolled back to ${pc30.cyan(result?.release ?? "the previous release")}` + (result?.from ? ` ${pc30.dim(`(was ${result.from})`)}` : "")
|
|
15263
15437
|
);
|
|
15264
15438
|
}
|
|
15265
15439
|
},
|
|
@@ -15273,55 +15447,6 @@ var rollback = addLockWaitOption(
|
|
|
15273
15447
|
|
|
15274
15448
|
// src/commands/logs.ts
|
|
15275
15449
|
import { Command as Command100 } from "commander";
|
|
15276
|
-
|
|
15277
|
-
// src/lib/remote-pocketbase.ts
|
|
15278
|
-
import PocketBase6 from "pocketbase";
|
|
15279
|
-
async function requireRemoteDatabase(session, instance) {
|
|
15280
|
-
const [state] = await readInstanceStates(session, instance);
|
|
15281
|
-
const pbPort = instanceHasBackend(state) ? state?.pbPort : void 0;
|
|
15282
|
-
if (!pbPort) {
|
|
15283
|
-
throw new Error(
|
|
15284
|
-
`${instance} has no deployed database.
|
|
15285
|
-
|
|
15286
|
-
The database is created by the first \`vela deploy\` of a project with a backend.
|
|
15287
|
-
If this project has none, \`vela enable backend\` adds one; then deploy again.`
|
|
15288
|
-
);
|
|
15289
|
-
}
|
|
15290
|
-
return pbPort;
|
|
15291
|
-
}
|
|
15292
|
-
async function openRemoteDatabase(session, instance) {
|
|
15293
|
-
const pbPort = await requireRemoteDatabase(session, instance);
|
|
15294
|
-
const env2 = await readRemoteEnv(session, instance);
|
|
15295
|
-
const email2 = env2.POCKETBASE_SUPERUSER_EMAIL;
|
|
15296
|
-
const password8 = env2.POCKETBASE_SUPERUSER_PASSWORD;
|
|
15297
|
-
if (!email2 || !password8) {
|
|
15298
|
-
throw new Error(
|
|
15299
|
-
`${instance} has no PocketBase superuser credentials in its environment.
|
|
15300
|
-
|
|
15301
|
-
A deploy creates them. Deploy again to repair this instance.`
|
|
15302
|
-
);
|
|
15303
|
-
}
|
|
15304
|
-
const localPort = await findFreePort("127.0.0.1");
|
|
15305
|
-
await session.forwardLocalPort(localPort, "127.0.0.1", pbPort);
|
|
15306
|
-
return {
|
|
15307
|
-
url: `http://127.0.0.1:${localPort}`,
|
|
15308
|
-
email: email2,
|
|
15309
|
-
password: password8,
|
|
15310
|
-
close: () => session.cancelForward(localPort, "127.0.0.1", pbPort)
|
|
15311
|
-
};
|
|
15312
|
-
}
|
|
15313
|
-
async function withRemotePocketbase(session, instance, fn) {
|
|
15314
|
-
const db = await openRemoteDatabase(session, instance);
|
|
15315
|
-
try {
|
|
15316
|
-
const pb = new PocketBase6(db.url);
|
|
15317
|
-
await authWithRetries(pb, db.email, db.password);
|
|
15318
|
-
return await fn(pb);
|
|
15319
|
-
} finally {
|
|
15320
|
-
await db.close();
|
|
15321
|
-
}
|
|
15322
|
-
}
|
|
15323
|
-
|
|
15324
|
-
// src/commands/logs.ts
|
|
15325
15450
|
var logs = addTargetOptions(
|
|
15326
15451
|
new Command100("logs").description("tail the logs of a deployed app").configureHelp(helpConfig),
|
|
15327
15452
|
"production"
|
|
@@ -15364,7 +15489,7 @@ import { Command as Command102 } from "commander";
|
|
|
15364
15489
|
import process44 from "node:process";
|
|
15365
15490
|
import { Command as Command101 } from "commander";
|
|
15366
15491
|
import * as p60 from "@clack/prompts";
|
|
15367
|
-
import
|
|
15492
|
+
import pc31 from "picocolors";
|
|
15368
15493
|
var MIN_PASSWORD = 10;
|
|
15369
15494
|
var adminCreate = addTargetOptions(
|
|
15370
15495
|
new Command101("create").description("create a login for the admin panel").argument("[email]", "email to sign in with \u2014 prompted for when omitted").configureHelp(helpConfig),
|
|
@@ -15379,7 +15504,7 @@ var adminCreate = addTargetOptions(
|
|
|
15379
15504
|
throw new Error(
|
|
15380
15505
|
`This project has no backend, so there is no admin panel to sign in to.
|
|
15381
15506
|
|
|
15382
|
-
Run ${
|
|
15507
|
+
Run ${pc31.cyan("vela enable backend")} to add one.`
|
|
15383
15508
|
);
|
|
15384
15509
|
}
|
|
15385
15510
|
const creds = readLocalEnv(ctx.envFile);
|
|
@@ -15403,7 +15528,7 @@ Run ${pc30.cyan("vela enable backend")} to add one.`
|
|
|
15403
15528
|
if (metadata) signIn = `http://${metadata.viteHost}:${metadata.vitePort}`;
|
|
15404
15529
|
}
|
|
15405
15530
|
p60.log.info(
|
|
15406
|
-
signIn ? `Sign in at ${
|
|
15531
|
+
signIn ? `Sign in at ${pc31.cyan(`${signIn}/admin`)}` : `Sign in at ${pc31.cyan("/admin")} once ${pc31.cyan("vela dev")} is running.`
|
|
15407
15532
|
);
|
|
15408
15533
|
},
|
|
15409
15534
|
remote: async (ctx) => {
|
|
@@ -15418,7 +15543,7 @@ Run ${pc30.cyan("vela enable backend")} to add one.`
|
|
|
15418
15543
|
);
|
|
15419
15544
|
const base2 = state?.domain ? `https://${state.domain.split(",")[0].trim()}` : "";
|
|
15420
15545
|
p60.log.info(
|
|
15421
|
-
base2 ? `Sign in at ${
|
|
15546
|
+
base2 ? `Sign in at ${pc31.cyan(`${base2}/admin`)}` : `Sign in at ${pc31.cyan("/admin")} once a domain is configured for this target.`
|
|
15422
15547
|
);
|
|
15423
15548
|
}
|
|
15424
15549
|
},
|
|
@@ -15439,11 +15564,11 @@ async function upsertSuperuser2(pb, email2, password8) {
|
|
|
15439
15564
|
process44.exit(0);
|
|
15440
15565
|
}
|
|
15441
15566
|
await pb.collection("_superusers").update(existing, { password: password8, passwordConfirm: password8 });
|
|
15442
|
-
p60.log.success(`Password updated for ${
|
|
15567
|
+
p60.log.success(`Password updated for ${pc31.cyan(email2)}, you can sign in now`);
|
|
15443
15568
|
return;
|
|
15444
15569
|
}
|
|
15445
15570
|
await pb.collection("_superusers").create({ email: email2, password: password8, passwordConfirm: password8 });
|
|
15446
|
-
p60.log.success(`${
|
|
15571
|
+
p60.log.success(`${pc31.cyan(email2)} can now sign in`);
|
|
15447
15572
|
}
|
|
15448
15573
|
async function findSuperuser(pb, email2) {
|
|
15449
15574
|
try {
|
|
@@ -15495,10 +15620,10 @@ import fs57 from "node:fs";
|
|
|
15495
15620
|
import path62 from "node:path";
|
|
15496
15621
|
import { Command as Command103 } from "commander";
|
|
15497
15622
|
import * as p61 from "@clack/prompts";
|
|
15498
|
-
import
|
|
15623
|
+
import pc33 from "picocolors";
|
|
15499
15624
|
|
|
15500
15625
|
// src/lib/backup-target.ts
|
|
15501
|
-
import
|
|
15626
|
+
import pc32 from "picocolors";
|
|
15502
15627
|
async function withBackupTarget(raw, label2, fn) {
|
|
15503
15628
|
await withTarget(
|
|
15504
15629
|
raw,
|
|
@@ -15508,7 +15633,7 @@ async function withBackupTarget(raw, label2, fn) {
|
|
|
15508
15633
|
throw new Error(
|
|
15509
15634
|
`This project has no database, so there is nothing to back up.
|
|
15510
15635
|
|
|
15511
|
-
Run ${
|
|
15636
|
+
Run ${pc32.cyan("vela bless")} to add a backend.`
|
|
15512
15637
|
);
|
|
15513
15638
|
}
|
|
15514
15639
|
const creds = readLocalEnv(ctx.envFile);
|
|
@@ -15518,7 +15643,7 @@ Run ${pc31.cyan("vela bless")} to add a backend.`
|
|
|
15518
15643
|
throw new Error(
|
|
15519
15644
|
`The local database has no superuser credentials to sign in with.
|
|
15520
15645
|
|
|
15521
|
-
Set ${
|
|
15646
|
+
Set ${pc32.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc32.cyan("POCKETBASE_SUPERUSER_PASSWORD")} in ${pc32.cyan(".env")}.`
|
|
15522
15647
|
);
|
|
15523
15648
|
}
|
|
15524
15649
|
await withPocketbase(
|
|
@@ -15651,9 +15776,9 @@ var backupCreate = addTargetOptions(
|
|
|
15651
15776
|
const key = name ?? backupName(ctx.instance);
|
|
15652
15777
|
if (!isBackupKey(key)) {
|
|
15653
15778
|
throw new Error(
|
|
15654
|
-
`${
|
|
15779
|
+
`${pc33.cyan(key)} is not a name PocketBase will accept.
|
|
15655
15780
|
|
|
15656
|
-
Backup names are lowercase letters, digits, ${
|
|
15781
|
+
Backup names are lowercase letters, digits, ${pc33.cyan("-")} and ${pc33.cyan("_")}, ending in ${pc33.cyan(".zip")}.`
|
|
15657
15782
|
);
|
|
15658
15783
|
}
|
|
15659
15784
|
const storage = await readStorageSettings(ctx.pb);
|
|
@@ -15661,7 +15786,7 @@ Backup names are lowercase letters, digits, ${pc32.cyan("-")} and ${pc32.cyan("_
|
|
|
15661
15786
|
p61.log.warn(
|
|
15662
15787
|
`Uploads are stored in S3, so this archive holds the database only.
|
|
15663
15788
|
|
|
15664
|
-
PocketBase leaves ${
|
|
15789
|
+
PocketBase leaves ${pc33.cyan("storage/")} out of a backup whenever S3 is on.
|
|
15665
15790
|
Your bucket's own versioning is what protects the uploaded files.`
|
|
15666
15791
|
);
|
|
15667
15792
|
}
|
|
@@ -15728,7 +15853,7 @@ async function download(ctx, key, outputDir) {
|
|
|
15728
15853
|
// src/commands/backup/list.ts
|
|
15729
15854
|
import { Command as Command104 } from "commander";
|
|
15730
15855
|
import * as p62 from "@clack/prompts";
|
|
15731
|
-
import
|
|
15856
|
+
import pc34 from "picocolors";
|
|
15732
15857
|
var backupList = addTargetOptions(
|
|
15733
15858
|
new Command104("list").description("list the backups on a target").configureHelp(helpConfig),
|
|
15734
15859
|
"production"
|
|
@@ -15738,16 +15863,16 @@ var backupList = addTargetOptions(
|
|
|
15738
15863
|
const backups = await listBackups(ctx.pb);
|
|
15739
15864
|
if (backups.length === 0) {
|
|
15740
15865
|
p62.log.info(
|
|
15741
|
-
`${
|
|
15866
|
+
`${pc34.cyan(ctx.targetName)} has no backups yet.
|
|
15742
15867
|
|
|
15743
|
-
Take one with ${
|
|
15868
|
+
Take one with ${pc34.cyan("vela backup create")}.`
|
|
15744
15869
|
);
|
|
15745
15870
|
return;
|
|
15746
15871
|
}
|
|
15747
15872
|
const width = Math.max(...backups.map((b) => b.key.length));
|
|
15748
15873
|
p62.log.message(
|
|
15749
15874
|
backups.map(
|
|
15750
|
-
(b) => `${b.key.padEnd(width)} ${
|
|
15875
|
+
(b) => `${b.key.padEnd(width)} ${pc34.dim(formatBytes(b.size).padStart(8))} ${pc34.dim(b.modified)}`
|
|
15751
15876
|
).join("\n")
|
|
15752
15877
|
);
|
|
15753
15878
|
}),
|
|
@@ -15760,7 +15885,7 @@ import fs58 from "node:fs";
|
|
|
15760
15885
|
import path63 from "node:path";
|
|
15761
15886
|
import { Command as Command105 } from "commander";
|
|
15762
15887
|
import * as p63 from "@clack/prompts";
|
|
15763
|
-
import
|
|
15888
|
+
import pc35 from "picocolors";
|
|
15764
15889
|
var backupDownload = addTargetOptions(
|
|
15765
15890
|
new Command105("download").description("save a backup off the server").argument("<key>", "archive to download, as shown by `vela backup list`").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).configureHelp(helpConfig),
|
|
15766
15891
|
"production"
|
|
@@ -15771,9 +15896,9 @@ var backupDownload = addTargetOptions(
|
|
|
15771
15896
|
const found = (await listBackups(ctx.pb)).find((b) => b.key === key);
|
|
15772
15897
|
if (!found) {
|
|
15773
15898
|
throw new Error(
|
|
15774
|
-
`${ctx.targetName} has no backup called ${
|
|
15899
|
+
`${ctx.targetName} has no backup called ${pc35.cyan(key)}.
|
|
15775
15900
|
|
|
15776
|
-
Run ${
|
|
15901
|
+
Run ${pc35.cyan("vela backup list")} to see what it does have.`
|
|
15777
15902
|
);
|
|
15778
15903
|
}
|
|
15779
15904
|
const storage = await readStorageSettings(ctx.pb);
|
|
@@ -15812,7 +15937,7 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
|
15812
15937
|
import process45 from "node:process";
|
|
15813
15938
|
import { Command as Command106 } from "commander";
|
|
15814
15939
|
import * as p64 from "@clack/prompts";
|
|
15815
|
-
import
|
|
15940
|
+
import pc36 from "picocolors";
|
|
15816
15941
|
var backupDelete = addTargetOptions(
|
|
15817
15942
|
new Command106("delete").description("remove a backup from a target").argument("<key>", "archive to delete, as shown by `vela backup list`").option("-y, --yes", "skip the confirmation").configureHelp(helpConfig),
|
|
15818
15943
|
"production"
|
|
@@ -15823,9 +15948,9 @@ var backupDelete = addTargetOptions(
|
|
|
15823
15948
|
const found = (await listBackups(ctx.pb)).find((b) => b.key === key);
|
|
15824
15949
|
if (!found) {
|
|
15825
15950
|
throw new Error(
|
|
15826
|
-
`${ctx.targetName} has no backup called ${
|
|
15951
|
+
`${ctx.targetName} has no backup called ${pc36.cyan(key)}.
|
|
15827
15952
|
|
|
15828
|
-
Run ${
|
|
15953
|
+
Run ${pc36.cyan("vela backup list")} to see what it does have.`
|
|
15829
15954
|
);
|
|
15830
15955
|
}
|
|
15831
15956
|
if (!options.yes) {
|
|
@@ -15847,7 +15972,7 @@ Run ${pc35.cyan("vela backup list")} to see what it does have.`
|
|
|
15847
15972
|
// src/commands/backup/schedule.ts
|
|
15848
15973
|
import { Command as Command107 } from "commander";
|
|
15849
15974
|
import * as p65 from "@clack/prompts";
|
|
15850
|
-
import
|
|
15975
|
+
import pc37 from "picocolors";
|
|
15851
15976
|
var DEFAULT_KEEP = 7;
|
|
15852
15977
|
var backupSchedule = addTargetOptions(
|
|
15853
15978
|
new Command107("schedule").description("back up automatically on a schedule").argument("[cron]", "when to run, as a cron expression \u2014 shows the current one when omitted").option("--keep <n>", "how many scheduled archives to keep", String(DEFAULT_KEEP)).option("--off", "stop backing up automatically").configureHelp(helpConfig),
|
|
@@ -15864,16 +15989,16 @@ var backupSchedule = addTargetOptions(
|
|
|
15864
15989
|
if (!cron) {
|
|
15865
15990
|
const current = await readSchedule(ctx.pb);
|
|
15866
15991
|
p65.log.info(
|
|
15867
|
-
current.cron ? `${ctx.targetName} backs up on ${
|
|
15992
|
+
current.cron ? `${ctx.targetName} backs up on ${pc37.cyan(current.cron)}, keeping ${current.maxKeep}.` : `${ctx.targetName} has no backup schedule.
|
|
15868
15993
|
|
|
15869
|
-
Set one with ${
|
|
15994
|
+
Set one with ${pc37.cyan('vela backup schedule "0 3 * * *"')}.`
|
|
15870
15995
|
);
|
|
15871
15996
|
return;
|
|
15872
15997
|
}
|
|
15873
15998
|
const keep = Number.parseInt(options.keep, 10);
|
|
15874
15999
|
if (!Number.isInteger(keep) || keep < 1) {
|
|
15875
16000
|
throw new Error(
|
|
15876
|
-
`${
|
|
16001
|
+
`${pc37.cyan(options.keep)} is not a number of backups to keep \u2014 pass at least 1.`
|
|
15877
16002
|
);
|
|
15878
16003
|
}
|
|
15879
16004
|
await writeSchedule(ctx.pb, cron, keep);
|
|
@@ -15902,7 +16027,7 @@ import path64 from "node:path";
|
|
|
15902
16027
|
import process46 from "node:process";
|
|
15903
16028
|
import { Command as Command109 } from "commander";
|
|
15904
16029
|
import * as p66 from "@clack/prompts";
|
|
15905
|
-
import
|
|
16030
|
+
import pc38 from "picocolors";
|
|
15906
16031
|
var restore = addLockWaitOption(
|
|
15907
16032
|
addTargetOptions(
|
|
15908
16033
|
new Command109("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),
|
|
@@ -15950,7 +16075,7 @@ Run \`vela deploy\` first, then restore.`
|
|
|
15950
16075
|
stream: true
|
|
15951
16076
|
});
|
|
15952
16077
|
p66.log.success(
|
|
15953
|
-
`Restored ${
|
|
16078
|
+
`Restored ${pc38.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc38.cyan(
|
|
15954
16079
|
local ? path64.basename(local) : key
|
|
15955
16080
|
)}.`
|
|
15956
16081
|
);
|
|
@@ -15961,7 +16086,7 @@ Run \`vela deploy\` first, then restore.`
|
|
|
15961
16086
|
}
|
|
15962
16087
|
if (result?.previousDataDir) {
|
|
15963
16088
|
p66.log.info(
|
|
15964
|
-
`The database this replaced is at ${
|
|
16089
|
+
`The database this replaced is at ${pc38.cyan(result.previousDataDir)}.
|
|
15965
16090
|
|
|
15966
16091
|
It is the only way back. Remove it once you are satisfied with the restore.`
|
|
15967
16092
|
);
|
|
@@ -15978,18 +16103,18 @@ It is the only way back. Remove it once you are satisfied with the restore.`
|
|
|
15978
16103
|
async function resolveKey(ctx, source) {
|
|
15979
16104
|
if (source && !isBackupKey(source)) {
|
|
15980
16105
|
throw new Error(
|
|
15981
|
-
`${
|
|
16106
|
+
`${pc38.cyan(source)} is neither a file on this machine nor a backup key.
|
|
15982
16107
|
|
|
15983
|
-
Run ${
|
|
16108
|
+
Run ${pc38.cyan("vela backup list")} to see what ${ctx.targetName} has.`
|
|
15984
16109
|
);
|
|
15985
16110
|
}
|
|
15986
16111
|
const backups = await withRemotePocketbase(ctx.session, ctx.instance, listBackups);
|
|
15987
16112
|
if (source) {
|
|
15988
16113
|
if (!backups.some((b) => b.key === source)) {
|
|
15989
16114
|
throw new Error(
|
|
15990
|
-
`${ctx.targetName} has no backup called ${
|
|
16115
|
+
`${ctx.targetName} has no backup called ${pc38.cyan(source)}.
|
|
15991
16116
|
|
|
15992
|
-
Run ${
|
|
16117
|
+
Run ${pc38.cyan("vela backup list")} to see what it does have.`
|
|
15993
16118
|
);
|
|
15994
16119
|
}
|
|
15995
16120
|
return source;
|
|
@@ -15998,7 +16123,7 @@ Run ${pc37.cyan("vela backup list")} to see what it does have.`
|
|
|
15998
16123
|
throw new Error(
|
|
15999
16124
|
`${ctx.targetName} has no backups to restore from.
|
|
16000
16125
|
|
|
16001
|
-
Take one with ${
|
|
16126
|
+
Take one with ${pc38.cyan("vela backup create")}, or pass the path to an archive on this machine.`
|
|
16002
16127
|
);
|
|
16003
16128
|
}
|
|
16004
16129
|
const chosen = await p66.select({
|
|
@@ -16031,7 +16156,7 @@ async function stage(ctx, file) {
|
|
|
16031
16156
|
return remote;
|
|
16032
16157
|
}
|
|
16033
16158
|
async function confirm14(appName, targetName, envTag, from) {
|
|
16034
|
-
const what = `${
|
|
16159
|
+
const what = `${pc38.cyan(`${appName} (${targetName})`)} from ${pc38.cyan(path64.basename(from))}`;
|
|
16035
16160
|
if (isProd(envTag)) {
|
|
16036
16161
|
const answer = await p66.text({
|
|
16037
16162
|
message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
|
|
@@ -16056,7 +16181,7 @@ async function confirm14(appName, targetName, envTag, from) {
|
|
|
16056
16181
|
// src/commands/targets.ts
|
|
16057
16182
|
import { Command as Command110 } from "commander";
|
|
16058
16183
|
import * as p67 from "@clack/prompts";
|
|
16059
|
-
import
|
|
16184
|
+
import pc39 from "picocolors";
|
|
16060
16185
|
import * as v13 from "valibot";
|
|
16061
16186
|
var OptionsSchema6 = v13.object({
|
|
16062
16187
|
...SSH_OPTION_SCHEMA,
|
|
@@ -16117,19 +16242,19 @@ var targets = addSshOptions(
|
|
|
16117
16242
|
console.log(JSON.stringify(rows, null, 2));
|
|
16118
16243
|
return;
|
|
16119
16244
|
}
|
|
16120
|
-
|
|
16245
|
+
report5(rows, options.offline === true);
|
|
16121
16246
|
}, "Failed to list targets.")
|
|
16122
16247
|
);
|
|
16123
|
-
function
|
|
16248
|
+
function report5(rows, offline) {
|
|
16124
16249
|
const width = (heading, pick) => Math.max(heading.length, ...rows.map((row) => pick(row).length));
|
|
16125
16250
|
const target = width("TARGET", (row) => row.target);
|
|
16126
16251
|
const server = width("SERVER", (row) => row.server);
|
|
16127
16252
|
const domain = width("DOMAIN", (row) => row.domain);
|
|
16128
16253
|
const header = `${"TARGET".padEnd(target)} ${"SERVER".padEnd(server)} ${"DOMAIN".padEnd(domain)} RELEASE`;
|
|
16129
16254
|
const lines = rows.map(
|
|
16130
|
-
(row) => `${row.kind === "local" ?
|
|
16255
|
+
(row) => `${row.kind === "local" ? pc39.dim(row.target.padEnd(target)) : pc39.cyan(row.target.padEnd(target))} ${row.server.padEnd(server)} ${row.domain.padEnd(domain)} ${row.release}`
|
|
16131
16256
|
);
|
|
16132
|
-
p67.log.info(`${
|
|
16257
|
+
p67.log.info(`${pc39.dim(header)}
|
|
16133
16258
|
${lines.join("\n")}`);
|
|
16134
16259
|
const unreachable = rows.filter((row) => row.kind === "remote" && !row.reachable);
|
|
16135
16260
|
if (!offline && unreachable.length > 0) {
|
|
@@ -16143,7 +16268,7 @@ Release and domain are shown from what this project recorded.`
|
|
|
16143
16268
|
// src/commands/test.ts
|
|
16144
16269
|
import process48 from "node:process";
|
|
16145
16270
|
import { Command as Command111 } from "commander";
|
|
16146
|
-
import
|
|
16271
|
+
import pc40 from "picocolors";
|
|
16147
16272
|
import { x as x7 } from "tinyexec";
|
|
16148
16273
|
import { detect as detect10 } from "package-manager-detector";
|
|
16149
16274
|
import { resolveCommand as resolveCommand8 } from "package-manager-detector/commands";
|
|
@@ -16271,7 +16396,7 @@ function isAlive(pid) {
|
|
|
16271
16396
|
}
|
|
16272
16397
|
function describeLoadFailure(e) {
|
|
16273
16398
|
if (e instanceof DataLoadError) {
|
|
16274
|
-
const hint = e.kind === "fixtures" ? "Run `vela fixtures regen` to regenerate fixtures from the current schema." : `Check ${e.file} against the current schema.`;
|
|
16399
|
+
const hint = e.malformed ? `Fix ${e.file}, or rewrite it from a database with \`vela seeds save --force\`.` : e.kind === "fixtures" ? "Run `vela fixtures regen` to regenerate fixtures from the current schema." : `Check ${e.file} against the current schema.`;
|
|
16275
16400
|
return `Failed to load ${e.message}
|
|
16276
16401
|
${hint}`;
|
|
16277
16402
|
}
|
|
@@ -16297,7 +16422,7 @@ function stubPagesPlugin() {
|
|
|
16297
16422
|
// src/commands/test.ts
|
|
16298
16423
|
var testServer = new Command111("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
|
|
16299
16424
|
const cwd = process48.cwd();
|
|
16300
|
-
warnIfKit2(cwd, (m) => console.warn(
|
|
16425
|
+
warnIfKit2(cwd, (m) => console.warn(pc40.yellow(`\u25B2 ${m}`)));
|
|
16301
16426
|
const extraArgs = (cmd.parent?.args ?? []).slice(1);
|
|
16302
16427
|
const filtered = extraArgs.some((arg) => !arg.startsWith("-"));
|
|
16303
16428
|
try {
|
|
@@ -16318,7 +16443,7 @@ var testServer = new Command111("test:server").description("run server tests").a
|
|
|
16318
16443
|
});
|
|
16319
16444
|
process48.exitCode = result.exitCode ?? 1;
|
|
16320
16445
|
} catch (e) {
|
|
16321
|
-
console.error(`${
|
|
16446
|
+
console.error(`${pc40.redBright("\u2717")} ${e.message}`);
|
|
16322
16447
|
process48.exitCode = 1;
|
|
16323
16448
|
}
|
|
16324
16449
|
});
|
|
@@ -16326,7 +16451,7 @@ var testHarness = new Command111("test:harness").description("start the servers
|
|
|
16326
16451
|
const cwd = process48.cwd();
|
|
16327
16452
|
if (!process48.send) {
|
|
16328
16453
|
console.error(
|
|
16329
|
-
`${
|
|
16454
|
+
`${pc40.redBright("\u2717")} vela test:harness is started by vitest through \`vela/testing\`. Run \`vela test:server\` instead.`
|
|
16330
16455
|
);
|
|
16331
16456
|
process48.exit(1);
|
|
16332
16457
|
}
|
|
@@ -16352,11 +16477,11 @@ var testHarness = new Command111("test:harness").description("start the servers
|
|
|
16352
16477
|
});
|
|
16353
16478
|
try {
|
|
16354
16479
|
harness = await startTestHarness(cwd, {
|
|
16355
|
-
log: (message) => console.log(`${
|
|
16480
|
+
log: (message) => console.log(`${pc40.greenBright("\u2713")} ${message}`)
|
|
16356
16481
|
});
|
|
16357
16482
|
} catch (e) {
|
|
16358
16483
|
const message = e instanceof HarnessError ? e.message : `Failed to start the test servers: ${e.message}`;
|
|
16359
|
-
console.error(`${
|
|
16484
|
+
console.error(`${pc40.redBright("\u2717")} ${message}`);
|
|
16360
16485
|
process48.send({ type: "error", message });
|
|
16361
16486
|
process48.exit(1);
|
|
16362
16487
|
}
|
|
@@ -16492,7 +16617,7 @@ import { Command as Command119 } from "commander";
|
|
|
16492
16617
|
import process50 from "node:process";
|
|
16493
16618
|
import { Command as Command114 } from "commander";
|
|
16494
16619
|
import * as p68 from "@clack/prompts";
|
|
16495
|
-
import
|
|
16620
|
+
import pc41 from "picocolors";
|
|
16496
16621
|
var POLL_INTERVAL2 = 5e3;
|
|
16497
16622
|
var POLL_TIMEOUT = 30 * 6e4;
|
|
16498
16623
|
var inFlight = (run) => run?.status === "pending" || run?.status === "building";
|
|
@@ -16508,18 +16633,18 @@ var deploy2 = new Command114("deploy").description("rebuild the hosted site with
|
|
|
16508
16633
|
throw new Error(
|
|
16509
16634
|
`This project has no hosted site to rebuild.
|
|
16510
16635
|
|
|
16511
|
-
A site deployed with ${
|
|
16636
|
+
A site deployed with ${pc41.cyan("vela deploy")} is updated by deploying again.`
|
|
16512
16637
|
);
|
|
16513
16638
|
}
|
|
16514
16639
|
const url = state.site?.url ?? "";
|
|
16515
16640
|
if (inFlight(state.latest)) {
|
|
16516
|
-
p68.log.info(`A deploy of ${
|
|
16641
|
+
p68.log.info(`A deploy of ${pc41.cyan(url)} is already in progress.`);
|
|
16517
16642
|
} else {
|
|
16518
16643
|
state = await startSiteDeploy(apiKey, projectId);
|
|
16519
16644
|
}
|
|
16520
16645
|
if (!options.wait) {
|
|
16521
16646
|
p68.log.success(
|
|
16522
|
-
`Build started for ${
|
|
16647
|
+
`Build started for ${pc41.cyan(url)} (deployment ${pc41.dim(state.latest?.id ?? "")}).
|
|
16523
16648
|
It goes live when the build finishes.`
|
|
16524
16649
|
);
|
|
16525
16650
|
return;
|
|
@@ -16545,7 +16670,7 @@ It goes live on its own if it does; the deployments page on velastack.dev shows
|
|
|
16545
16670
|
spinner9.stop(`Deploy of ${url} failed.`);
|
|
16546
16671
|
throw new Error(latest.error || "the build did not finish");
|
|
16547
16672
|
}
|
|
16548
|
-
spinner9.stop(`Deployed ${
|
|
16673
|
+
spinner9.stop(`Deployed ${pc41.cyan(url)}`);
|
|
16549
16674
|
}, "Failed to deploy the site.")
|
|
16550
16675
|
);
|
|
16551
16676
|
function resolveProjectId(explicit) {
|
|
@@ -16561,7 +16686,7 @@ function resolveProjectId(explicit) {
|
|
|
16561
16686
|
throw new Error(
|
|
16562
16687
|
`This project is not linked to velastack.dev.
|
|
16563
16688
|
|
|
16564
|
-
Run ${
|
|
16689
|
+
Run ${pc41.cyan("vela link")}, or pass ${pc41.cyan("--project <id>")}.`
|
|
16565
16690
|
);
|
|
16566
16691
|
}
|
|
16567
16692
|
return link2.projectId;
|
|
@@ -16591,14 +16716,14 @@ import { Command as Command118 } from "commander";
|
|
|
16591
16716
|
import { randomBytes } from "node:crypto";
|
|
16592
16717
|
import { Command as Command115 } from "commander";
|
|
16593
16718
|
import * as p69 from "@clack/prompts";
|
|
16594
|
-
import
|
|
16719
|
+
import pc43 from "picocolors";
|
|
16595
16720
|
|
|
16596
16721
|
// src/lib/cms-backend.ts
|
|
16597
16722
|
import { createRequire as createRequire5 } from "node:module";
|
|
16598
16723
|
import path68 from "node:path";
|
|
16599
16724
|
import process51 from "node:process";
|
|
16600
16725
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
16601
|
-
import
|
|
16726
|
+
import pc42 from "picocolors";
|
|
16602
16727
|
var DEFAULT_PROJECT = "default";
|
|
16603
16728
|
async function loadBackendModule(root) {
|
|
16604
16729
|
let entry;
|
|
@@ -16608,7 +16733,7 @@ async function loadBackendModule(root) {
|
|
|
16608
16733
|
throw new Error(
|
|
16609
16734
|
`@velastack/cms is not installed in this project.
|
|
16610
16735
|
|
|
16611
|
-
Run ${
|
|
16736
|
+
Run ${pc42.cyan("vela enable cms")} first.`
|
|
16612
16737
|
);
|
|
16613
16738
|
}
|
|
16614
16739
|
return await import(pathToFileURL2(entry).href);
|
|
@@ -16639,13 +16764,13 @@ var editorAdd = new Command115("add").description("create an editor who can sign
|
|
|
16639
16764
|
const editor2 = await withCmsBackend(
|
|
16640
16765
|
(cms3) => cms3.editors.create({ email: email2, password: password8, projects: [options.project] })
|
|
16641
16766
|
);
|
|
16642
|
-
const lines = [`Added ${
|
|
16767
|
+
const lines = [`Added ${pc43.cyan(editor2.email)} as an editor of ${pc43.cyan(options.project)}.`];
|
|
16643
16768
|
if (generated) {
|
|
16644
|
-
lines.push("", `Password: ${
|
|
16769
|
+
lines.push("", `Password: ${pc43.bold(password8)}`, "", "It is shown once; copy it now.");
|
|
16645
16770
|
}
|
|
16646
16771
|
p69.log.success(lines.join("\n"));
|
|
16647
16772
|
p69.log.info(
|
|
16648
|
-
`Run ${
|
|
16773
|
+
`Run ${pc43.cyan("vela dev")}, open any page with ${pc43.cyan("?edit")} on the URL (or press ${pc43.cyan("Ctrl+E")}), and sign in.`
|
|
16649
16774
|
);
|
|
16650
16775
|
}, "Failed to add the editor.")
|
|
16651
16776
|
);
|
|
@@ -16653,12 +16778,12 @@ var editorAdd = new Command115("add").description("create an editor who can sign
|
|
|
16653
16778
|
// src/commands/cms/editor/password.ts
|
|
16654
16779
|
import { Command as Command116 } from "commander";
|
|
16655
16780
|
import * as p70 from "@clack/prompts";
|
|
16656
|
-
import
|
|
16781
|
+
import pc44 from "picocolors";
|
|
16657
16782
|
var editorPassword = new Command116("password").description("set an editor's password").argument("<email>", "email of the editor").argument("<password>", "new password").configureHelp(helpConfig).action(
|
|
16658
16783
|
(email2, password8) => runCommand(async () => {
|
|
16659
16784
|
await withCmsBackend((cms3) => cms3.editors.setPassword(email2, password8));
|
|
16660
16785
|
p70.log.success(
|
|
16661
|
-
`Updated the password for ${
|
|
16786
|
+
`Updated the password for ${pc44.cyan(email2)}. Existing sessions were signed out.`
|
|
16662
16787
|
);
|
|
16663
16788
|
}, "Failed to set the password.")
|
|
16664
16789
|
);
|
|
@@ -16666,7 +16791,7 @@ var editorPassword = new Command116("password").description("set an editor's pas
|
|
|
16666
16791
|
// src/commands/cms/editor/list.ts
|
|
16667
16792
|
import { Command as Command117 } from "commander";
|
|
16668
16793
|
import * as p71 from "@clack/prompts";
|
|
16669
|
-
import
|
|
16794
|
+
import pc45 from "picocolors";
|
|
16670
16795
|
var editorList = new Command117("list").description("list editors and the projects they may edit").configureHelp(helpConfig).action(
|
|
16671
16796
|
() => runCommand(async () => {
|
|
16672
16797
|
const rows = await withCmsBackend(
|
|
@@ -16676,7 +16801,7 @@ var editorList = new Command117("list").description("list editors and the projec
|
|
|
16676
16801
|
}))
|
|
16677
16802
|
);
|
|
16678
16803
|
if (rows.length === 0) {
|
|
16679
|
-
p71.log.info(`No editors yet. Add one with ${
|
|
16804
|
+
p71.log.info(`No editors yet. Add one with ${pc45.cyan("vela cms editor add <email>")}.`);
|
|
16680
16805
|
return;
|
|
16681
16806
|
}
|
|
16682
16807
|
const width = Math.max(...rows.map((row) => row.email.length));
|
|
@@ -16684,7 +16809,7 @@ var editorList = new Command117("list").description("list editors and the projec
|
|
|
16684
16809
|
`Editors
|
|
16685
16810
|
|
|
16686
16811
|
` + rows.map(
|
|
16687
|
-
(row) => ` ${row.email.padEnd(width)} ${
|
|
16812
|
+
(row) => ` ${row.email.padEnd(width)} ${pc45.dim(row.projects.join(", ") || "no projects")}`
|
|
16688
16813
|
).join("\n")
|
|
16689
16814
|
);
|
|
16690
16815
|
}, "Failed to list editors.")
|
|
@@ -16703,7 +16828,7 @@ import { Command as Command123 } from "commander";
|
|
|
16703
16828
|
import process52 from "node:process";
|
|
16704
16829
|
import { Command as Command120, InvalidArgumentError as InvalidArgumentError5 } from "commander";
|
|
16705
16830
|
import * as p72 from "@clack/prompts";
|
|
16706
|
-
import
|
|
16831
|
+
import pc46 from "picocolors";
|
|
16707
16832
|
|
|
16708
16833
|
// src/lib/workflows-api.ts
|
|
16709
16834
|
var NAMESPACE = "default";
|
|
@@ -16763,17 +16888,17 @@ function parseLimit(value) {
|
|
|
16763
16888
|
return n;
|
|
16764
16889
|
}
|
|
16765
16890
|
var STATUS_COLOR = {
|
|
16766
|
-
pending:
|
|
16767
|
-
running:
|
|
16768
|
-
completed:
|
|
16769
|
-
failed:
|
|
16770
|
-
canceled:
|
|
16891
|
+
pending: pc46.yellow,
|
|
16892
|
+
running: pc46.cyan,
|
|
16893
|
+
completed: pc46.green,
|
|
16894
|
+
failed: pc46.red,
|
|
16895
|
+
canceled: pc46.dim
|
|
16771
16896
|
};
|
|
16772
16897
|
function formatRun(run, nameWidth) {
|
|
16773
16898
|
const status3 = STATUS_COLOR[run.status](run.status.padEnd(9));
|
|
16774
|
-
const when =
|
|
16775
|
-
const attempts = run.attempts > 1 ?
|
|
16776
|
-
const error = run.status === "failed" && run.error?.message ?
|
|
16899
|
+
const when = pc46.dim((run.finishedAt ?? run.updatedAt).replace("T", " ").slice(0, 19));
|
|
16900
|
+
const attempts = run.attempts > 1 ? pc46.dim(` \xD7${run.attempts}`) : "";
|
|
16901
|
+
const error = run.status === "failed" && run.error?.message ? pc46.red(` ${run.error.message}`) : "";
|
|
16777
16902
|
return `${run.id} ${run.workflowName.padEnd(nameWidth)} ${status3}${attempts} ${when}${error}`;
|
|
16778
16903
|
}
|
|
16779
16904
|
var workflowsList = new Command120("list").description("list recent workflow runs").option("--status <status>", `only runs in this state (${STATUSES.join(", ")})`, parseStatus).option("--name <workflow>", "only runs of this workflow").option("--limit <n>", "how many to show", parseLimit, 50).configureHelp(helpConfig).action(
|
|
@@ -16788,7 +16913,7 @@ var workflowsList = new Command120("list").description("list recent workflow run
|
|
|
16788
16913
|
p72.log.info(
|
|
16789
16914
|
`No workflow runs yet.
|
|
16790
16915
|
|
|
16791
|
-
Start one from server code with ${
|
|
16916
|
+
Start one from server code with ${pc46.cyan("<workflow>.run(input)")}, or with ${pc46.cyan("vela workflows run <name>")}.`
|
|
16792
16917
|
);
|
|
16793
16918
|
return;
|
|
16794
16919
|
}
|
|
@@ -16802,7 +16927,7 @@ Start one from server code with ${pc45.cyan("<workflow>.run(input)")}, or with $
|
|
|
16802
16927
|
import process53 from "node:process";
|
|
16803
16928
|
import { Command as Command121, InvalidArgumentError as InvalidArgumentError6 } from "commander";
|
|
16804
16929
|
import * as p73 from "@clack/prompts";
|
|
16805
|
-
import
|
|
16930
|
+
import pc47 from "picocolors";
|
|
16806
16931
|
function parseInput(value) {
|
|
16807
16932
|
try {
|
|
16808
16933
|
return JSON.parse(value);
|
|
@@ -16815,9 +16940,9 @@ var workflowsRun = new Command121("run").description("start a run of a workflow;
|
|
|
16815
16940
|
await withPocketbase(process53.cwd(), async (pb) => {
|
|
16816
16941
|
const run = await createRun(pb, name, input);
|
|
16817
16942
|
p73.log.success(
|
|
16818
|
-
`Queued ${
|
|
16943
|
+
`Queued ${pc47.cyan(name)} as run ${pc47.bold(run.id)}.
|
|
16819
16944
|
|
|
16820
|
-
It runs once the app is up (${
|
|
16945
|
+
It runs once the app is up (${pc47.cyan("vela dev")}); ${pc47.cyan("vela workflows list")} shows its state.`
|
|
16821
16946
|
);
|
|
16822
16947
|
});
|
|
16823
16948
|
}, "Failed to start the workflow run.")
|
|
@@ -16827,12 +16952,12 @@ It runs once the app is up (${pc46.cyan("vela dev")}); ${pc46.cyan("vela workflo
|
|
|
16827
16952
|
import process54 from "node:process";
|
|
16828
16953
|
import { Command as Command122 } from "commander";
|
|
16829
16954
|
import * as p74 from "@clack/prompts";
|
|
16830
|
-
import
|
|
16955
|
+
import pc48 from "picocolors";
|
|
16831
16956
|
var workflowsCancel = new Command122("cancel").description("cancel a pending or running workflow run").argument("<run-id>", "the run id from `vela workflows list`").configureHelp(helpConfig).action(
|
|
16832
16957
|
(id) => runCommand(async () => {
|
|
16833
16958
|
await withPocketbase(process54.cwd(), async (pb) => {
|
|
16834
16959
|
const run = await cancelRun(pb, id);
|
|
16835
|
-
p74.log.success(`Canceled run ${
|
|
16960
|
+
p74.log.success(`Canceled run ${pc48.bold(run.id)} of ${pc48.cyan(run.workflowName)}.`);
|
|
16836
16961
|
});
|
|
16837
16962
|
}, "Failed to cancel the workflow run.")
|
|
16838
16963
|
);
|
|
@@ -16901,6 +17026,7 @@ var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
|
|
|
16901
17026
|
// own credentials rather than requiring them in this process.
|
|
16902
17027
|
"backup",
|
|
16903
17028
|
"restore",
|
|
17029
|
+
"seeds load",
|
|
16904
17030
|
// Removes a copy from its server. `destroy resource` and `destroy scaffold`
|
|
16905
17031
|
// drop collections and stay gated.
|
|
16906
17032
|
"destroy deployment"
|