vela 0.10.12 → 0.10.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +792 -782
- package/dist/bin.js.map +4 -4
- package/package.json +1 -1
- package/templates/minimal/vite.config.ts +0 -4
- package/templates/static/vite.config.ts +0 -4
package/dist/bin.js
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/bin.ts
|
|
4
|
-
import
|
|
5
|
-
|
|
4
|
+
import process36 from "node:process";
|
|
5
|
+
|
|
6
|
+
// src/lib/argv.ts
|
|
7
|
+
function normalizeArgv(argv) {
|
|
8
|
+
const separator = argv.indexOf("--");
|
|
9
|
+
if (separator === -1) return argv;
|
|
10
|
+
return [...argv.slice(0, separator), ...argv.slice(separator + 1)];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/program.ts
|
|
14
|
+
import process35 from "node:process";
|
|
15
|
+
import * as p54 from "@clack/prompts";
|
|
16
|
+
import { Command as Command100 } from "commander";
|
|
17
|
+
import nodePath from "node:path";
|
|
18
|
+
import dotenv2 from "dotenv";
|
|
19
|
+
import pc36 from "picocolors";
|
|
6
20
|
|
|
7
21
|
// package.json
|
|
8
22
|
var package_default = {
|
|
9
23
|
name: "vela",
|
|
10
|
-
version: "0.10.
|
|
24
|
+
version: "0.10.13",
|
|
11
25
|
type: "module",
|
|
12
26
|
description: "A CLI for creating and updating SvelteKit projects",
|
|
13
27
|
license: "MIT",
|
|
@@ -93,88 +107,6 @@ var package_default = {
|
|
|
93
107
|
]
|
|
94
108
|
};
|
|
95
109
|
|
|
96
|
-
// src/lib/argv.ts
|
|
97
|
-
function normalizeArgv(argv2) {
|
|
98
|
-
const separator = argv2.indexOf("--");
|
|
99
|
-
if (separator === -1) return argv2;
|
|
100
|
-
return [...argv2.slice(0, separator), ...argv2.slice(separator + 1)];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// src/lib/delegate.ts
|
|
104
|
-
import fs from "node:fs";
|
|
105
|
-
import path from "node:path";
|
|
106
|
-
import process2 from "node:process";
|
|
107
|
-
import { spawnSync } from "node:child_process";
|
|
108
|
-
var NO_DELEGATE_COMMANDS = /* @__PURE__ */ new Set(["create", "bless"]);
|
|
109
|
-
var NO_DELEGATE_ENV = "VELA_NO_DELEGATE";
|
|
110
|
-
function realpath(target) {
|
|
111
|
-
try {
|
|
112
|
-
return fs.realpathSync(target);
|
|
113
|
-
} catch {
|
|
114
|
-
return path.resolve(target);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function findLocalCli(cwd, selfPath) {
|
|
118
|
-
const self = realpath(selfPath);
|
|
119
|
-
let dir = path.resolve(cwd);
|
|
120
|
-
for (; ; ) {
|
|
121
|
-
const pkgPath = path.join(dir, "node_modules", "vela", "package.json");
|
|
122
|
-
if (fs.existsSync(pkgPath)) {
|
|
123
|
-
const local = readLocalCli(pkgPath);
|
|
124
|
-
if (local && realpath(local.binPath) !== self) return local;
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
const parent = path.dirname(dir);
|
|
128
|
-
if (parent === dir) return null;
|
|
129
|
-
dir = parent;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
function readLocalCli(pkgPath) {
|
|
133
|
-
let pkg;
|
|
134
|
-
try {
|
|
135
|
-
pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
136
|
-
} catch {
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
const version = typeof pkg.version === "string" ? pkg.version : null;
|
|
140
|
-
const bin = pkg.bin;
|
|
141
|
-
const rel = typeof bin === "string" ? bin : isRecord(bin) ? bin.vela : void 0;
|
|
142
|
-
if (!version || typeof rel !== "string") return null;
|
|
143
|
-
const binPath = path.resolve(path.dirname(pkgPath), rel);
|
|
144
|
-
if (!fs.existsSync(binPath)) return null;
|
|
145
|
-
return { binPath, version };
|
|
146
|
-
}
|
|
147
|
-
function isRecord(value) {
|
|
148
|
-
return typeof value === "object" && value !== null;
|
|
149
|
-
}
|
|
150
|
-
function isDelegatable(argv2) {
|
|
151
|
-
const first = argv2.find((arg) => !arg.startsWith("-"));
|
|
152
|
-
return first === void 0 || !NO_DELEGATE_COMMANDS.has(first);
|
|
153
|
-
}
|
|
154
|
-
function delegateToLocalCli(opts) {
|
|
155
|
-
const env2 = opts.env ?? process2.env;
|
|
156
|
-
if (env2[NO_DELEGATE_ENV]) return null;
|
|
157
|
-
const argv2 = opts.argv ?? process2.argv.slice(2);
|
|
158
|
-
if (!isDelegatable(argv2)) return null;
|
|
159
|
-
const local = findLocalCli(opts.cwd ?? process2.cwd(), opts.selfPath);
|
|
160
|
-
if (!local || local.version === opts.selfVersion) return null;
|
|
161
|
-
const result = spawnSync(process2.execPath, [local.binPath, ...argv2], {
|
|
162
|
-
stdio: "inherit",
|
|
163
|
-
env: { ...env2, [NO_DELEGATE_ENV]: "1" }
|
|
164
|
-
});
|
|
165
|
-
if (result.error) return null;
|
|
166
|
-
if (result.signal) return 1;
|
|
167
|
-
return result.status ?? 0;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// src/program.ts
|
|
171
|
-
import process36 from "node:process";
|
|
172
|
-
import * as p54 from "@clack/prompts";
|
|
173
|
-
import { Command as Command100 } from "commander";
|
|
174
|
-
import nodePath from "node:path";
|
|
175
|
-
import dotenv2 from "dotenv";
|
|
176
|
-
import pc36 from "picocolors";
|
|
177
|
-
|
|
178
110
|
// src/lib/help.ts
|
|
179
111
|
import pc from "picocolors";
|
|
180
112
|
var NO_PREFIX = "--no-";
|
|
@@ -288,9 +220,9 @@ function stubCommand(name, description, fullName) {
|
|
|
288
220
|
}
|
|
289
221
|
|
|
290
222
|
// src/lib/workspace.ts
|
|
291
|
-
import
|
|
292
|
-
import
|
|
293
|
-
import
|
|
223
|
+
import fs2 from "node:fs";
|
|
224
|
+
import path from "node:path";
|
|
225
|
+
import process2 from "node:process";
|
|
294
226
|
|
|
295
227
|
// src/lib/constants.ts
|
|
296
228
|
var DATA_DIR = "data";
|
|
@@ -302,7 +234,7 @@ var API_URL = "https://velastack.dev";
|
|
|
302
234
|
var FIXTURE_PREFIX = "vela";
|
|
303
235
|
|
|
304
236
|
// src/lib/package-json.ts
|
|
305
|
-
import
|
|
237
|
+
import fs from "node:fs";
|
|
306
238
|
var DEP_KINDS = ["dependencies", "devDependencies"];
|
|
307
239
|
function mergePackageJson(user, template) {
|
|
308
240
|
const merged = structuredClone(user);
|
|
@@ -350,8 +282,8 @@ function mergePackageJson(user, template) {
|
|
|
350
282
|
}
|
|
351
283
|
return { merged, added, conflicts, replaced };
|
|
352
284
|
}
|
|
353
|
-
function readPackageJson(
|
|
354
|
-
return JSON.parse(
|
|
285
|
+
function readPackageJson(path45) {
|
|
286
|
+
return JSON.parse(fs.readFileSync(path45, "utf8"));
|
|
355
287
|
}
|
|
356
288
|
var PACKAGE_NAME_PLACEHOLDER = /~TODO~/g;
|
|
357
289
|
var APP_NAME_PLACEHOLDER = /~APP_NAME~/g;
|
|
@@ -364,12 +296,12 @@ function fillTemplatePlaceholders(raw, values) {
|
|
|
364
296
|
function escapeSingleQuoted(value) {
|
|
365
297
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
366
298
|
}
|
|
367
|
-
function readTemplatePackageJson(
|
|
368
|
-
const raw = fillTemplatePlaceholders(
|
|
299
|
+
function readTemplatePackageJson(path45, values) {
|
|
300
|
+
const raw = fillTemplatePlaceholders(fs.readFileSync(path45, "utf8"), values);
|
|
369
301
|
return JSON.parse(raw);
|
|
370
302
|
}
|
|
371
|
-
function writePackageJson(
|
|
372
|
-
|
|
303
|
+
function writePackageJson(path45, pkg) {
|
|
304
|
+
fs.writeFileSync(path45, JSON.stringify(pkg, null, " ") + "\n");
|
|
373
305
|
}
|
|
374
306
|
function toValidPackageName(name) {
|
|
375
307
|
return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9~.-]+/g, "-");
|
|
@@ -381,41 +313,41 @@ function sortKeys(obj) {
|
|
|
381
313
|
}
|
|
382
314
|
|
|
383
315
|
// src/lib/workspace.ts
|
|
384
|
-
function findWorkspaceRoot(from =
|
|
316
|
+
function findWorkspaceRoot(from = process2.cwd()) {
|
|
385
317
|
let currentDir = from;
|
|
386
|
-
while (currentDir !==
|
|
387
|
-
if (
|
|
388
|
-
currentDir =
|
|
318
|
+
while (currentDir !== path.parse(currentDir).root) {
|
|
319
|
+
if (fs2.existsSync(path.join(currentDir, "package.json"))) return currentDir;
|
|
320
|
+
currentDir = path.dirname(currentDir);
|
|
389
321
|
}
|
|
390
322
|
return null;
|
|
391
323
|
}
|
|
392
|
-
function hasBackend(from =
|
|
324
|
+
function hasBackend(from = process2.cwd()) {
|
|
393
325
|
const root = findWorkspaceRoot(from);
|
|
394
|
-
return root !== null &&
|
|
326
|
+
return root !== null && fs2.existsSync(path.join(root, DATA_DIR));
|
|
395
327
|
}
|
|
396
|
-
function localDataDir(from =
|
|
397
|
-
return
|
|
328
|
+
function localDataDir(from = process2.cwd()) {
|
|
329
|
+
return path.join(findWorkspaceRoot(from) ?? from, DATA_DIR);
|
|
398
330
|
}
|
|
399
331
|
async function getWorkspace() {
|
|
400
332
|
const workspaceRootDir = findWorkspaceRoot();
|
|
401
333
|
if (!workspaceRootDir) {
|
|
402
334
|
throw new Error("Could not find workspace root (no package.json found)");
|
|
403
335
|
}
|
|
404
|
-
const routesDir =
|
|
405
|
-
const fullRoutesPath =
|
|
406
|
-
if (!
|
|
336
|
+
const routesDir = path.join("src", "routes");
|
|
337
|
+
const fullRoutesPath = path.join(workspaceRootDir, routesDir);
|
|
338
|
+
if (!fs2.existsSync(fullRoutesPath)) {
|
|
407
339
|
throw new Error("Could not find src/routes directory");
|
|
408
340
|
}
|
|
409
|
-
let publicRoutesDir =
|
|
410
|
-
if (!
|
|
341
|
+
let publicRoutesDir = path.join(routesDir, PUBLIC_DIR);
|
|
342
|
+
if (!fs2.existsSync(path.join(workspaceRootDir, publicRoutesDir))) {
|
|
411
343
|
publicRoutesDir = routesDir;
|
|
412
344
|
}
|
|
413
345
|
let appRoutesDir;
|
|
414
|
-
const appRoutesPath =
|
|
415
|
-
const isAppMode =
|
|
416
|
-
if (isAppMode) appRoutesDir =
|
|
417
|
-
const isPaymentsMode =
|
|
418
|
-
|
|
346
|
+
const appRoutesPath = path.join(fullRoutesPath, APP_DIR);
|
|
347
|
+
const isAppMode = fs2.existsSync(appRoutesPath);
|
|
348
|
+
if (isAppMode) appRoutesDir = path.join(routesDir, APP_DIR);
|
|
349
|
+
const isPaymentsMode = fs2.existsSync(
|
|
350
|
+
path.join(workspaceRootDir, routesDir, "webhooks", "stripe")
|
|
419
351
|
);
|
|
420
352
|
const features = detectFeatures(workspaceRootDir, { isAppMode, isPaymentsMode });
|
|
421
353
|
return {
|
|
@@ -429,8 +361,8 @@ async function getWorkspace() {
|
|
|
429
361
|
};
|
|
430
362
|
}
|
|
431
363
|
function detectFeatures(root, { isAppMode, isPaymentsMode }) {
|
|
432
|
-
const has = (rel) =>
|
|
433
|
-
const pkg = readPackageJson(
|
|
364
|
+
const has = (rel) => fs2.existsSync(path.join(root, rel));
|
|
365
|
+
const pkg = readPackageJson(path.join(root, "package.json"));
|
|
434
366
|
const hasDep = (name) => Boolean(pkg.dependencies?.[name] || pkg.devDependencies?.[name]);
|
|
435
367
|
return {
|
|
436
368
|
auth: isAppMode,
|
|
@@ -447,9 +379,9 @@ function detectFeatures(root, { isAppMode, isPaymentsMode }) {
|
|
|
447
379
|
}
|
|
448
380
|
|
|
449
381
|
// src/commands/bless.ts
|
|
450
|
-
import
|
|
451
|
-
import
|
|
452
|
-
import
|
|
382
|
+
import fs11 from "node:fs";
|
|
383
|
+
import path10 from "node:path";
|
|
384
|
+
import process5 from "node:process";
|
|
453
385
|
import * as v2 from "valibot";
|
|
454
386
|
import { Command as Command2 } from "commander";
|
|
455
387
|
import * as p4 from "@clack/prompts";
|
|
@@ -484,32 +416,32 @@ function toFlag(key) {
|
|
|
484
416
|
}
|
|
485
417
|
|
|
486
418
|
// src/lib/templates.ts
|
|
487
|
-
import
|
|
488
|
-
import
|
|
419
|
+
import fs3 from "node:fs";
|
|
420
|
+
import path2 from "node:path";
|
|
489
421
|
import { fileURLToPath } from "node:url";
|
|
490
422
|
var TEMPLATE_MANIFEST = "template.json";
|
|
491
423
|
var DEFAULT_TEMPLATE = "minimal";
|
|
492
424
|
var cached;
|
|
493
425
|
function templatesDir() {
|
|
494
|
-
let dir =
|
|
495
|
-
const { root } =
|
|
426
|
+
let dir = path2.dirname(fileURLToPath(import.meta.url));
|
|
427
|
+
const { root } = path2.parse(dir);
|
|
496
428
|
while (dir !== root) {
|
|
497
|
-
const candidate =
|
|
429
|
+
const candidate = path2.join(dir, "templates");
|
|
498
430
|
if (holdsManifest(candidate)) return candidate;
|
|
499
|
-
dir =
|
|
431
|
+
dir = path2.dirname(dir);
|
|
500
432
|
}
|
|
501
433
|
throw new Error("Could not locate the templates directory");
|
|
502
434
|
}
|
|
503
435
|
function holdsManifest(dir) {
|
|
504
|
-
if (!
|
|
505
|
-
return
|
|
506
|
-
(entry) => entry.isDirectory() &&
|
|
436
|
+
if (!fs3.existsSync(dir)) return false;
|
|
437
|
+
return fs3.readdirSync(dir, { withFileTypes: true }).some(
|
|
438
|
+
(entry) => entry.isDirectory() && fs3.existsSync(path2.join(dir, entry.name, TEMPLATE_MANIFEST))
|
|
507
439
|
);
|
|
508
440
|
}
|
|
509
441
|
function listProjectTemplates() {
|
|
510
442
|
if (cached) return cached;
|
|
511
443
|
const root = templatesDir();
|
|
512
|
-
cached =
|
|
444
|
+
cached = fs3.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => readManifest(root, entry.name)).filter((template) => template !== void 0).sort((a, b) => a.name.localeCompare(b.name));
|
|
513
445
|
return cached;
|
|
514
446
|
}
|
|
515
447
|
function projectTemplateNames(options = {}) {
|
|
@@ -523,11 +455,11 @@ function findProjectTemplate(name) {
|
|
|
523
455
|
return template;
|
|
524
456
|
}
|
|
525
457
|
function readManifest(root, name) {
|
|
526
|
-
const manifestPath =
|
|
527
|
-
if (!
|
|
458
|
+
const manifestPath = path2.join(root, name, TEMPLATE_MANIFEST);
|
|
459
|
+
if (!fs3.existsSync(manifestPath)) return void 0;
|
|
528
460
|
let parsed;
|
|
529
461
|
try {
|
|
530
|
-
parsed = JSON.parse(
|
|
462
|
+
parsed = JSON.parse(fs3.readFileSync(manifestPath, "utf8"));
|
|
531
463
|
} catch (e) {
|
|
532
464
|
throw new Error(
|
|
533
465
|
`Template ${name} has an unreadable ${TEMPLATE_MANIFEST}: ${e.message}`
|
|
@@ -543,14 +475,14 @@ function readManifest(root, name) {
|
|
|
543
475
|
name,
|
|
544
476
|
description: manifest.description,
|
|
545
477
|
backend: manifest.backend,
|
|
546
|
-
dir:
|
|
478
|
+
dir: path2.join(root, name)
|
|
547
479
|
};
|
|
548
480
|
}
|
|
549
481
|
|
|
550
482
|
// src/lib/package-manager.ts
|
|
551
|
-
import
|
|
552
|
-
import
|
|
553
|
-
import
|
|
483
|
+
import fs4 from "node:fs";
|
|
484
|
+
import path3 from "node:path";
|
|
485
|
+
import process3 from "node:process";
|
|
554
486
|
import { exec } from "tinyexec";
|
|
555
487
|
import { Option } from "commander";
|
|
556
488
|
import * as p2 from "@clack/prompts";
|
|
@@ -566,7 +498,7 @@ var installOption = new Option(
|
|
|
566
498
|
"installs dependencies with a specified package manager"
|
|
567
499
|
).choices(AGENT_NAMES);
|
|
568
500
|
function getUserAgent() {
|
|
569
|
-
const userAgent =
|
|
501
|
+
const userAgent = process3.env.npm_config_user_agent;
|
|
570
502
|
if (!userAgent) return void 0;
|
|
571
503
|
const pmSpec = userAgent.split(" ")[0];
|
|
572
504
|
const separatorPos = pmSpec.lastIndexOf("/");
|
|
@@ -576,7 +508,7 @@ function getUserAgent() {
|
|
|
576
508
|
async function packageManagerPrompt(cwd) {
|
|
577
509
|
const detected = await detect({ cwd });
|
|
578
510
|
const agent = detected?.name ?? getUserAgent();
|
|
579
|
-
if (!
|
|
511
|
+
if (!process3.stdout.isTTY) return agent;
|
|
580
512
|
const options = [
|
|
581
513
|
{ label: "None", value: void 0 },
|
|
582
514
|
...AGENT_NAMES.map((pm2) => ({ value: pm2, label: pm2 }))
|
|
@@ -588,14 +520,14 @@ async function packageManagerPrompt(cwd) {
|
|
|
588
520
|
});
|
|
589
521
|
if (p2.isCancel(pm)) {
|
|
590
522
|
p2.cancel("Operation cancelled.");
|
|
591
|
-
|
|
523
|
+
process3.exit(1);
|
|
592
524
|
}
|
|
593
525
|
return pm;
|
|
594
526
|
}
|
|
595
527
|
async function installDependencies(agent, cwd) {
|
|
596
528
|
const task = p2.taskLog({
|
|
597
529
|
title: `Installing dependencies with ${agent}...`,
|
|
598
|
-
limit: Math.ceil(
|
|
530
|
+
limit: Math.ceil(process3.stdout.rows / 2),
|
|
599
531
|
spacing: 0,
|
|
600
532
|
retainLog: true
|
|
601
533
|
});
|
|
@@ -612,14 +544,14 @@ async function installDependencies(agent, cwd) {
|
|
|
612
544
|
} catch {
|
|
613
545
|
task.error("Failed to install dependencies");
|
|
614
546
|
p2.cancel("Operation failed.");
|
|
615
|
-
|
|
547
|
+
process3.exit(2);
|
|
616
548
|
}
|
|
617
549
|
}
|
|
618
550
|
function addPnpmBuildDependencies(cwd, packageManager, allowedPackages) {
|
|
619
551
|
if (!packageManager || packageManager !== "pnpm") return;
|
|
620
|
-
const pkgPath =
|
|
621
|
-
if (!
|
|
622
|
-
const pkg = JSON.parse(
|
|
552
|
+
const pkgPath = path3.join(cwd, "package.json");
|
|
553
|
+
if (!fs4.existsSync(pkgPath)) return;
|
|
554
|
+
const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
|
|
623
555
|
pkg.pnpm ??= {};
|
|
624
556
|
pkg.pnpm.onlyBuiltDependencies ??= [];
|
|
625
557
|
for (const name of allowedPackages) {
|
|
@@ -627,14 +559,14 @@ function addPnpmBuildDependencies(cwd, packageManager, allowedPackages) {
|
|
|
627
559
|
pkg.pnpm.onlyBuiltDependencies.push(name);
|
|
628
560
|
}
|
|
629
561
|
}
|
|
630
|
-
|
|
562
|
+
fs4.writeFileSync(pkgPath, JSON.stringify(pkg, null, " ") + "\n");
|
|
631
563
|
}
|
|
632
564
|
|
|
633
565
|
// src/lib/pocketbase.ts
|
|
634
|
-
import
|
|
566
|
+
import fs5 from "node:fs";
|
|
635
567
|
import net from "node:net";
|
|
636
|
-
import
|
|
637
|
-
import
|
|
568
|
+
import path4 from "node:path";
|
|
569
|
+
import process4 from "node:process";
|
|
638
570
|
import { createRequire } from "node:module";
|
|
639
571
|
import { spawn } from "node:child_process";
|
|
640
572
|
import PocketBase from "pocketbase";
|
|
@@ -746,9 +678,9 @@ async function authWithRetries(pb, email3, password11, attempts = 3) {
|
|
|
746
678
|
}
|
|
747
679
|
}
|
|
748
680
|
function getPocketbaseMetadata(cwd) {
|
|
749
|
-
const metadataPath =
|
|
750
|
-
if (
|
|
751
|
-
return JSON.parse(
|
|
681
|
+
const metadataPath = path4.join(cwd, "node_modules", ".vite", "_pocketbase_metadata.json");
|
|
682
|
+
if (fs5.existsSync(metadataPath)) {
|
|
683
|
+
return JSON.parse(fs5.readFileSync(metadataPath, "utf8"));
|
|
752
684
|
}
|
|
753
685
|
return null;
|
|
754
686
|
}
|
|
@@ -761,12 +693,12 @@ async function execPackageBin(cwd, args, stdio = "pipe") {
|
|
|
761
693
|
return x(command, resolvedArgs, { nodeOptions: { cwd, stdio }, throwOnError: true });
|
|
762
694
|
}
|
|
763
695
|
async function withPocketbase(cwd, fn, creds) {
|
|
764
|
-
const dir =
|
|
765
|
-
const migrationsDir =
|
|
696
|
+
const dir = path4.join(cwd, DATA_DIR);
|
|
697
|
+
const migrationsDir = path4.join(cwd, MIGRATIONS_DIR);
|
|
766
698
|
const host = "localhost";
|
|
767
|
-
const email3 = creds?.email ??
|
|
768
|
-
const password11 = creds?.password ??
|
|
769
|
-
if (!
|
|
699
|
+
const email3 = creds?.email ?? process4.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
700
|
+
const password11 = creds?.password ?? process4.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
701
|
+
if (!fs5.existsSync(dir)) {
|
|
770
702
|
throw new Error("PocketBase data directory does not exist");
|
|
771
703
|
}
|
|
772
704
|
const metadata = getPocketbaseMetadata(cwd);
|
|
@@ -791,10 +723,10 @@ async function withPocketbase(cwd, fn, creds) {
|
|
|
791
723
|
}
|
|
792
724
|
}
|
|
793
725
|
async function createSuperuser(cwd, email3, password11) {
|
|
794
|
-
const dir =
|
|
795
|
-
const migrationsDir =
|
|
796
|
-
|
|
797
|
-
|
|
726
|
+
const dir = path4.join(cwd, DATA_DIR);
|
|
727
|
+
const migrationsDir = path4.join(cwd, MIGRATIONS_DIR);
|
|
728
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
729
|
+
fs5.mkdirSync(migrationsDir, { recursive: true });
|
|
798
730
|
await execPackageBin(
|
|
799
731
|
cwd,
|
|
800
732
|
[
|
|
@@ -819,8 +751,8 @@ async function launchPocketbase(cwd, {
|
|
|
819
751
|
password: password11
|
|
820
752
|
}) {
|
|
821
753
|
const host = "localhost";
|
|
822
|
-
|
|
823
|
-
|
|
754
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
755
|
+
fs5.mkdirSync(migrationsDir, { recursive: true });
|
|
824
756
|
await execPackageBin(
|
|
825
757
|
cwd,
|
|
826
758
|
[
|
|
@@ -859,11 +791,11 @@ function pocketbaseVersion() {
|
|
|
859
791
|
return pkg.version;
|
|
860
792
|
}
|
|
861
793
|
async function ensureSuperuser(cwd) {
|
|
862
|
-
const email3 =
|
|
863
|
-
const password11 =
|
|
794
|
+
const email3 = process4.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
795
|
+
const password11 = process4.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
864
796
|
if (!email3 || !password11) return;
|
|
865
|
-
const dir =
|
|
866
|
-
if (!
|
|
797
|
+
const dir = path4.join(cwd, DATA_DIR);
|
|
798
|
+
if (!fs5.existsSync(dir)) return;
|
|
867
799
|
const { getBinaryPath } = await import("pocketbase-server");
|
|
868
800
|
await x(
|
|
869
801
|
getBinaryPath(),
|
|
@@ -871,7 +803,7 @@ async function ensureSuperuser(cwd) {
|
|
|
871
803
|
"--dir",
|
|
872
804
|
dir,
|
|
873
805
|
"--migrationsDir",
|
|
874
|
-
|
|
806
|
+
path4.join(cwd, MIGRATIONS_DIR),
|
|
875
807
|
"superuser",
|
|
876
808
|
"upsert",
|
|
877
809
|
email3,
|
|
@@ -882,8 +814,8 @@ async function ensureSuperuser(cwd) {
|
|
|
882
814
|
}
|
|
883
815
|
|
|
884
816
|
// src/lib/env.ts
|
|
885
|
-
import
|
|
886
|
-
import
|
|
817
|
+
import fs6 from "node:fs";
|
|
818
|
+
import path5 from "node:path";
|
|
887
819
|
function addEnvVar(content, key, value) {
|
|
888
820
|
if (content.includes(`${key}=`)) return content;
|
|
889
821
|
return appendLine(content, `${key}=${value}`);
|
|
@@ -898,11 +830,11 @@ function appendLine(existing, line) {
|
|
|
898
830
|
return withNewline + line + "\n";
|
|
899
831
|
}
|
|
900
832
|
function writeEnvFile(cwd, vars, comments = []) {
|
|
901
|
-
const envPath =
|
|
902
|
-
let content =
|
|
833
|
+
const envPath = path5.join(cwd, ".env");
|
|
834
|
+
let content = fs6.existsSync(envPath) ? fs6.readFileSync(envPath, "utf8") : "";
|
|
903
835
|
for (const comment of comments) content = addEnvComment(content, comment);
|
|
904
836
|
for (const [key, value] of Object.entries(vars)) content = addEnvVar(content, key, value);
|
|
905
|
-
|
|
837
|
+
fs6.writeFileSync(envPath, content);
|
|
906
838
|
}
|
|
907
839
|
function upsertEnvVar(content, key, value) {
|
|
908
840
|
const line = `${key}=${quoteEnvValue(value)}`;
|
|
@@ -935,12 +867,12 @@ function quoteEnvValue(value) {
|
|
|
935
867
|
}
|
|
936
868
|
|
|
937
869
|
// src/lib/config-merge.ts
|
|
938
|
-
import fs9 from "node:fs";
|
|
939
|
-
import path8 from "node:path";
|
|
940
|
-
|
|
941
|
-
// src/lib/config-target.ts
|
|
942
870
|
import fs8 from "node:fs";
|
|
943
871
|
import path7 from "node:path";
|
|
872
|
+
|
|
873
|
+
// src/lib/config-target.ts
|
|
874
|
+
import fs7 from "node:fs";
|
|
875
|
+
import path6 from "node:path";
|
|
944
876
|
import {
|
|
945
877
|
Project,
|
|
946
878
|
QuoteKind,
|
|
@@ -960,8 +892,8 @@ var SVELTE_CONFIG_CANDIDATES = [
|
|
|
960
892
|
];
|
|
961
893
|
function probeFirstExisting(root, candidates) {
|
|
962
894
|
for (const rel of candidates) {
|
|
963
|
-
const abs =
|
|
964
|
-
if (
|
|
895
|
+
const abs = path6.join(root, rel);
|
|
896
|
+
if (fs7.existsSync(abs)) return abs;
|
|
965
897
|
}
|
|
966
898
|
return null;
|
|
967
899
|
}
|
|
@@ -1037,7 +969,7 @@ function mergeSvelteConfig(projectRoot) {
|
|
|
1037
969
|
};
|
|
1038
970
|
}
|
|
1039
971
|
function mergeRunesIntoViteArg(vite, arg) {
|
|
1040
|
-
const file =
|
|
972
|
+
const file = path7.basename(vite.filePath);
|
|
1041
973
|
const compilerOptions = getOrCreateObjectLiteralProperty(arg, "compilerOptions", "{}");
|
|
1042
974
|
if (!compilerOptions) {
|
|
1043
975
|
return {
|
|
@@ -1056,8 +988,8 @@ function mergeRunesIntoViteArg(vite, arg) {
|
|
|
1056
988
|
return { applied: true, reason: "added runes compilerOption", file };
|
|
1057
989
|
}
|
|
1058
990
|
function mergeRunesIntoSvelteConfig(filePath) {
|
|
1059
|
-
const file =
|
|
1060
|
-
const original =
|
|
991
|
+
const file = path7.basename(filePath);
|
|
992
|
+
const original = fs8.readFileSync(filePath, "utf8");
|
|
1061
993
|
if (/runes\s*:/m.test(original)) {
|
|
1062
994
|
return { applied: false, reason: "runes already configured", file };
|
|
1063
995
|
}
|
|
@@ -1080,11 +1012,11 @@ function mergeRunesIntoSvelteConfig(filePath) {
|
|
|
1080
1012
|
}
|
|
1081
1013
|
const insertAt = anchor.index + anchor[0].length;
|
|
1082
1014
|
const updated = original.slice(0, insertAt) + RUNES_SNIPPET + original.slice(insertAt);
|
|
1083
|
-
|
|
1015
|
+
fs8.writeFileSync(filePath, updated);
|
|
1084
1016
|
return { applied: true, reason: "added runes compilerOption", file };
|
|
1085
1017
|
}
|
|
1086
1018
|
function mergeViteConfig(filePath) {
|
|
1087
|
-
if (!
|
|
1019
|
+
if (!fs8.existsSync(filePath)) {
|
|
1088
1020
|
return {
|
|
1089
1021
|
applied: false,
|
|
1090
1022
|
reason: "vite.config.ts not found",
|
|
@@ -1092,7 +1024,7 @@ function mergeViteConfig(filePath) {
|
|
|
1092
1024
|
// then add tailwindcss() to the plugins array`
|
|
1093
1025
|
};
|
|
1094
1026
|
}
|
|
1095
|
-
const original =
|
|
1027
|
+
const original = fs8.readFileSync(filePath, "utf8");
|
|
1096
1028
|
if (original.includes("@tailwindcss/vite")) {
|
|
1097
1029
|
return { applied: false, reason: "tailwindcss plugin already present" };
|
|
1098
1030
|
}
|
|
@@ -1111,14 +1043,14 @@ function mergeViteConfig(filePath) {
|
|
|
1111
1043
|
const trailing = withImport.slice(insertAt);
|
|
1112
1044
|
const prefix = /^\s*\]/.test(trailing) ? "tailwindcss()" : "tailwindcss(), ";
|
|
1113
1045
|
const updated = withImport.slice(0, insertAt) + prefix + withImport.slice(insertAt);
|
|
1114
|
-
|
|
1046
|
+
fs8.writeFileSync(filePath, updated);
|
|
1115
1047
|
return { applied: true, reason: "added @tailwindcss/vite plugin" };
|
|
1116
1048
|
}
|
|
1117
1049
|
function mergeTsconfig(filePath) {
|
|
1118
|
-
if (!
|
|
1050
|
+
if (!fs8.existsSync(filePath)) {
|
|
1119
1051
|
return { applied: false, reason: "tsconfig.json not found" };
|
|
1120
1052
|
}
|
|
1121
|
-
const original =
|
|
1053
|
+
const original = fs8.readFileSync(filePath, "utf8");
|
|
1122
1054
|
if (/rewriteRelativeImportExtensions/.test(original)) {
|
|
1123
1055
|
return { applied: false, reason: "rewriteRelativeImportExtensions already set" };
|
|
1124
1056
|
}
|
|
@@ -1134,7 +1066,7 @@ function mergeTsconfig(filePath) {
|
|
|
1134
1066
|
const indent = detectIndent(original, insertAt);
|
|
1135
1067
|
const updated = original.slice(0, insertAt) + `
|
|
1136
1068
|
${indent}"rewriteRelativeImportExtensions": true,` + original.slice(insertAt);
|
|
1137
|
-
|
|
1069
|
+
fs8.writeFileSync(filePath, updated);
|
|
1138
1070
|
return { applied: true, reason: "added rewriteRelativeImportExtensions" };
|
|
1139
1071
|
}
|
|
1140
1072
|
var GITIGNORE_ENTRIES = [
|
|
@@ -1146,7 +1078,7 @@ var GITIGNORE_ENTRIES = [
|
|
|
1146
1078
|
"vite.config.ts.timestamp-*"
|
|
1147
1079
|
];
|
|
1148
1080
|
function mergeGitignore(filePath) {
|
|
1149
|
-
const existing =
|
|
1081
|
+
const existing = fs8.existsSync(filePath) ? fs8.readFileSync(filePath, "utf8") : "";
|
|
1150
1082
|
const lines = existing.split("\n").map((l) => l.trim());
|
|
1151
1083
|
const missing = GITIGNORE_ENTRIES.filter((entry) => !lines.includes(entry));
|
|
1152
1084
|
if (missing.length === 0) {
|
|
@@ -1155,7 +1087,7 @@ function mergeGitignore(filePath) {
|
|
|
1155
1087
|
const needsNewline = existing.length > 0 && !existing.endsWith("\n");
|
|
1156
1088
|
const appended = `${existing}${needsNewline ? "\n" : ""}${missing.join("\n")}
|
|
1157
1089
|
`;
|
|
1158
|
-
|
|
1090
|
+
fs8.writeFileSync(filePath, appended);
|
|
1159
1091
|
return { applied: true, reason: `added ${missing.length} gitignore entries` };
|
|
1160
1092
|
}
|
|
1161
1093
|
function addImport(source, importLine) {
|
|
@@ -1180,14 +1112,14 @@ function detectIndent(source, atOffset) {
|
|
|
1180
1112
|
}
|
|
1181
1113
|
|
|
1182
1114
|
// src/lib/scaffold-detect.ts
|
|
1183
|
-
import
|
|
1184
|
-
import
|
|
1115
|
+
import fs9 from "node:fs";
|
|
1116
|
+
import path8 from "node:path";
|
|
1185
1117
|
var VANILLA_MARKER = "Welcome to SvelteKit";
|
|
1186
|
-
var PAGE_REL =
|
|
1118
|
+
var PAGE_REL = path8.join("src", "routes", "+page.svelte");
|
|
1187
1119
|
function isVanillaRoutes(cwd) {
|
|
1188
|
-
const pagePath =
|
|
1189
|
-
if (!
|
|
1190
|
-
return
|
|
1120
|
+
const pagePath = path8.join(cwd, PAGE_REL);
|
|
1121
|
+
if (!fs9.existsSync(pagePath)) return false;
|
|
1122
|
+
return fs9.readFileSync(pagePath, "utf8").includes(VANILLA_MARKER);
|
|
1191
1123
|
}
|
|
1192
1124
|
|
|
1193
1125
|
// src/lib/result-report.ts
|
|
@@ -1207,10 +1139,10 @@ function reportResult(report4) {
|
|
|
1207
1139
|
sections.push([extra.label, extra.items]);
|
|
1208
1140
|
}
|
|
1209
1141
|
const body = [];
|
|
1210
|
-
for (const [
|
|
1142
|
+
for (const [label4, items] of sections) {
|
|
1211
1143
|
if (!items || items.length === 0) continue;
|
|
1212
1144
|
if (body.length > 0) body.push("");
|
|
1213
|
-
body.push(`${
|
|
1145
|
+
body.push(`${label4}:`);
|
|
1214
1146
|
for (const item of items) body.push(`- ${item}`);
|
|
1215
1147
|
}
|
|
1216
1148
|
const failures = report4.failures ?? [];
|
|
@@ -1235,41 +1167,41 @@ ${failure.message}` : headline);
|
|
|
1235
1167
|
}
|
|
1236
1168
|
|
|
1237
1169
|
// src/lib/template-files.ts
|
|
1238
|
-
import
|
|
1239
|
-
import
|
|
1170
|
+
import fs10 from "node:fs";
|
|
1171
|
+
import path9 from "node:path";
|
|
1240
1172
|
var PUBLISH_SAFE_NAMES = {
|
|
1241
1173
|
".gitignore": "_gitignore",
|
|
1242
1174
|
".npmrc": "_npmrc"
|
|
1243
1175
|
};
|
|
1244
1176
|
function templateName(projectRelPath) {
|
|
1245
|
-
const safe = PUBLISH_SAFE_NAMES[
|
|
1177
|
+
const safe = PUBLISH_SAFE_NAMES[path9.basename(projectRelPath)];
|
|
1246
1178
|
if (!safe) return projectRelPath;
|
|
1247
|
-
const dir =
|
|
1248
|
-
return dir === "." ? safe :
|
|
1179
|
+
const dir = path9.dirname(projectRelPath);
|
|
1180
|
+
return dir === "." ? safe : path9.join(dir, safe);
|
|
1249
1181
|
}
|
|
1250
1182
|
function restoreTemplateNames(target) {
|
|
1251
1183
|
for (const [real, safe] of Object.entries(PUBLISH_SAFE_NAMES)) {
|
|
1252
|
-
const from =
|
|
1253
|
-
if (!
|
|
1254
|
-
|
|
1184
|
+
const from = path9.join(target, safe);
|
|
1185
|
+
if (!fs10.existsSync(from)) continue;
|
|
1186
|
+
fs10.renameSync(from, path9.join(target, real));
|
|
1255
1187
|
}
|
|
1256
1188
|
}
|
|
1257
1189
|
var TEMPLATE_SOURCE = /\.template\.([^.]+)$/;
|
|
1258
1190
|
function applyTemplateFiles(target, values) {
|
|
1259
1191
|
const written = [];
|
|
1260
1192
|
for (const source of findTemplateSources(target)) {
|
|
1261
|
-
const raw =
|
|
1193
|
+
const raw = fs10.readFileSync(source, "utf8");
|
|
1262
1194
|
const dest = source.replace(TEMPLATE_SOURCE, ".$1");
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
written.push(
|
|
1195
|
+
fs10.writeFileSync(dest, fillTemplatePlaceholders(raw, values));
|
|
1196
|
+
fs10.unlinkSync(source);
|
|
1197
|
+
written.push(path9.relative(target, dest));
|
|
1266
1198
|
}
|
|
1267
1199
|
return written.sort();
|
|
1268
1200
|
}
|
|
1269
1201
|
function findTemplateSources(dir) {
|
|
1270
1202
|
const found = [];
|
|
1271
|
-
for (const entry of
|
|
1272
|
-
const full =
|
|
1203
|
+
for (const entry of fs10.readdirSync(dir, { withFileTypes: true })) {
|
|
1204
|
+
const full = path9.join(dir, entry.name);
|
|
1273
1205
|
if (entry.isDirectory()) {
|
|
1274
1206
|
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
1275
1207
|
found.push(...findTemplateSources(full));
|
|
@@ -1339,7 +1271,7 @@ async function blessProject(cwdArg, options) {
|
|
|
1339
1271
|
{
|
|
1340
1272
|
onCancel: () => {
|
|
1341
1273
|
p4.cancel("Operation cancelled.");
|
|
1342
|
-
|
|
1274
|
+
process5.exit(0);
|
|
1343
1275
|
}
|
|
1344
1276
|
}
|
|
1345
1277
|
);
|
|
@@ -1372,22 +1304,22 @@ async function blessProject(cwdArg, options) {
|
|
|
1372
1304
|
printNextSteps(projectPath, packageManager);
|
|
1373
1305
|
}
|
|
1374
1306
|
function resolveProjectPath(cwdArg) {
|
|
1375
|
-
const projectPath =
|
|
1376
|
-
if (!
|
|
1307
|
+
const projectPath = path10.resolve(cwdArg);
|
|
1308
|
+
if (!fs11.existsSync(projectPath)) {
|
|
1377
1309
|
throw new Error(`Path does not exist: ${projectPath}`);
|
|
1378
1310
|
}
|
|
1379
|
-
if (!
|
|
1311
|
+
if (!fs11.existsSync(path10.join(projectPath, "package.json"))) {
|
|
1380
1312
|
throw new Error(`No package.json found at ${projectPath}`);
|
|
1381
1313
|
}
|
|
1382
|
-
if (!
|
|
1314
|
+
if (!fs11.existsSync(path10.join(projectPath, "src", "routes"))) {
|
|
1383
1315
|
throw new Error(`No src/routes directory found at ${projectPath}`);
|
|
1384
1316
|
}
|
|
1385
1317
|
return projectPath;
|
|
1386
1318
|
}
|
|
1387
1319
|
function assertNotAlreadyBlessed(projectPath) {
|
|
1388
|
-
const hooksPath =
|
|
1389
|
-
if (!
|
|
1390
|
-
const content =
|
|
1320
|
+
const hooksPath = path10.join(projectPath, "src", "hooks.server.ts");
|
|
1321
|
+
if (!fs11.existsSync(hooksPath)) return;
|
|
1322
|
+
const content = fs11.readFileSync(hooksPath, "utf8");
|
|
1391
1323
|
if (content.includes("@velastack/pocketbase")) {
|
|
1392
1324
|
throw new Error(
|
|
1393
1325
|
"This project already looks blessed (src/hooks.server.ts imports @velastack/pocketbase). Run `vela sync` instead."
|
|
@@ -1395,8 +1327,8 @@ function assertNotAlreadyBlessed(projectPath) {
|
|
|
1395
1327
|
}
|
|
1396
1328
|
}
|
|
1397
1329
|
function mergeDependencies(projectPath, templateDir) {
|
|
1398
|
-
const userPkgPath =
|
|
1399
|
-
const templatePkgPath =
|
|
1330
|
+
const userPkgPath = path10.join(projectPath, "package.json");
|
|
1331
|
+
const templatePkgPath = path10.join(templateDir, "package.template.json");
|
|
1400
1332
|
const userPkg = readPackageJson(userPkgPath);
|
|
1401
1333
|
const appName = typeof userPkg.name === "string" ? userPkg.name : "sveltekit";
|
|
1402
1334
|
const templatePkg = readTemplatePackageJson(templatePkgPath, {
|
|
@@ -1428,21 +1360,21 @@ ${lines.join("\n")}`);
|
|
|
1428
1360
|
function copyVelaOnlyFiles(templateDir, projectPath) {
|
|
1429
1361
|
const kept = [];
|
|
1430
1362
|
for (const file of VELA_ONLY_FILES) {
|
|
1431
|
-
const src =
|
|
1432
|
-
const dest =
|
|
1433
|
-
if (!
|
|
1434
|
-
if (
|
|
1363
|
+
const src = path10.join(templateDir, templateName(file.path));
|
|
1364
|
+
const dest = path10.join(projectPath, file.path);
|
|
1365
|
+
if (!fs11.existsSync(src)) continue;
|
|
1366
|
+
if (fs11.existsSync(dest)) {
|
|
1435
1367
|
kept.push(file);
|
|
1436
1368
|
continue;
|
|
1437
1369
|
}
|
|
1438
|
-
|
|
1439
|
-
|
|
1370
|
+
fs11.mkdirSync(path10.dirname(dest), { recursive: true });
|
|
1371
|
+
fs11.copyFileSync(src, dest);
|
|
1440
1372
|
}
|
|
1441
1373
|
reportKeptFiles(kept);
|
|
1442
1374
|
for (const rel of VELA_ONLY_DIRS) {
|
|
1443
|
-
const src =
|
|
1444
|
-
const dest =
|
|
1445
|
-
if (!
|
|
1375
|
+
const src = path10.join(templateDir, rel);
|
|
1376
|
+
const dest = path10.join(projectPath, rel);
|
|
1377
|
+
if (!fs11.existsSync(src)) continue;
|
|
1446
1378
|
copyDirShallow(src, dest);
|
|
1447
1379
|
}
|
|
1448
1380
|
}
|
|
@@ -1456,15 +1388,15 @@ ${lines.join("\n")}`
|
|
|
1456
1388
|
);
|
|
1457
1389
|
}
|
|
1458
1390
|
function copyDirShallow(src, dest) {
|
|
1459
|
-
|
|
1460
|
-
for (const entry of
|
|
1391
|
+
fs11.mkdirSync(dest, { recursive: true });
|
|
1392
|
+
for (const entry of fs11.readdirSync(src, { withFileTypes: true })) {
|
|
1461
1393
|
if (entry.name === ".DS_Store") continue;
|
|
1462
|
-
const srcChild =
|
|
1463
|
-
const destChild =
|
|
1394
|
+
const srcChild = path10.join(src, entry.name);
|
|
1395
|
+
const destChild = path10.join(dest, entry.name);
|
|
1464
1396
|
if (entry.isDirectory()) {
|
|
1465
1397
|
copyDirShallow(srcChild, destChild);
|
|
1466
|
-
} else if (entry.isFile() && !
|
|
1467
|
-
|
|
1398
|
+
} else if (entry.isFile() && !fs11.existsSync(destChild)) {
|
|
1399
|
+
fs11.copyFileSync(srcChild, destChild);
|
|
1468
1400
|
}
|
|
1469
1401
|
}
|
|
1470
1402
|
}
|
|
@@ -1472,9 +1404,9 @@ function mergeConfigFiles(projectPath) {
|
|
|
1472
1404
|
const runes = mergeSvelteConfig(projectPath);
|
|
1473
1405
|
const outcomes = [
|
|
1474
1406
|
[runes.file ?? "svelte.config", runes],
|
|
1475
|
-
["vite.config.ts", mergeViteConfig(
|
|
1476
|
-
["tsconfig.json", mergeTsconfig(
|
|
1477
|
-
[".gitignore", mergeGitignore(
|
|
1407
|
+
["vite.config.ts", mergeViteConfig(path10.join(projectPath, "vite.config.ts"))],
|
|
1408
|
+
["tsconfig.json", mergeTsconfig(path10.join(projectPath, "tsconfig.json"))],
|
|
1409
|
+
[".gitignore", mergeGitignore(path10.join(projectPath, ".gitignore"))]
|
|
1478
1410
|
];
|
|
1479
1411
|
for (const [name, outcome] of outcomes) {
|
|
1480
1412
|
if (outcome.applied) {
|
|
@@ -1491,14 +1423,14 @@ ${pc3.cyan(outcome.snippet)}`
|
|
|
1491
1423
|
}
|
|
1492
1424
|
}
|
|
1493
1425
|
function mergeAppDts(templateDir, projectPath) {
|
|
1494
|
-
const dest =
|
|
1495
|
-
const templateFile =
|
|
1496
|
-
if (!
|
|
1497
|
-
if (!
|
|
1498
|
-
|
|
1426
|
+
const dest = path10.join(projectPath, "src", "app.d.ts");
|
|
1427
|
+
const templateFile = path10.join(templateDir, "src", "app.d.ts");
|
|
1428
|
+
if (!fs11.existsSync(dest)) {
|
|
1429
|
+
if (!fs11.existsSync(templateFile)) return;
|
|
1430
|
+
fs11.copyFileSync(templateFile, dest);
|
|
1499
1431
|
return;
|
|
1500
1432
|
}
|
|
1501
|
-
const current =
|
|
1433
|
+
const current = fs11.readFileSync(dest, "utf8");
|
|
1502
1434
|
if (current.includes("namespace Superforms")) return;
|
|
1503
1435
|
const block = ` namespace Superforms {
|
|
1504
1436
|
type Message = {
|
|
@@ -1517,7 +1449,7 @@ ${pc3.cyan(block)}`
|
|
|
1517
1449
|
}
|
|
1518
1450
|
const insertAt = match.index + match[0].length;
|
|
1519
1451
|
const updated = current.slice(0, insertAt) + block + current.slice(insertAt);
|
|
1520
|
-
|
|
1452
|
+
fs11.writeFileSync(dest, updated);
|
|
1521
1453
|
}
|
|
1522
1454
|
function maybeReplaceRoutes(projectPath, templateDir, options) {
|
|
1523
1455
|
if (options.skipRoutes) {
|
|
@@ -1528,12 +1460,12 @@ function maybeReplaceRoutes(projectPath, templateDir, options) {
|
|
|
1528
1460
|
p4.log.info("Leaving src/routes alone (looks customized).");
|
|
1529
1461
|
return;
|
|
1530
1462
|
}
|
|
1531
|
-
const target =
|
|
1532
|
-
|
|
1533
|
-
const src =
|
|
1534
|
-
|
|
1463
|
+
const target = path10.join(projectPath, "src", "routes");
|
|
1464
|
+
fs11.rmSync(target, { recursive: true, force: true });
|
|
1465
|
+
const src = path10.join(templateDir, "src", "routes");
|
|
1466
|
+
fs11.cpSync(src, target, {
|
|
1535
1467
|
recursive: true,
|
|
1536
|
-
filter: (s) =>
|
|
1468
|
+
filter: (s) => path10.basename(s) !== ".DS_Store"
|
|
1537
1469
|
});
|
|
1538
1470
|
p4.log.success("Replaced src/routes with the vela template.");
|
|
1539
1471
|
}
|
|
@@ -1542,7 +1474,7 @@ function summarize(names) {
|
|
|
1542
1474
|
return `${names.slice(0, 3).join(", ")}, and ${names.length - 3} more`;
|
|
1543
1475
|
}
|
|
1544
1476
|
function printNextSteps(projectPath, packageManager) {
|
|
1545
|
-
const relative =
|
|
1477
|
+
const relative = path10.relative(process5.cwd(), projectPath);
|
|
1546
1478
|
const pm = packageManager ?? getUserAgent() ?? "npm";
|
|
1547
1479
|
const nextSteps = [];
|
|
1548
1480
|
if (relative !== "") {
|
|
@@ -1566,9 +1498,9 @@ function printNextSteps(projectPath, packageManager) {
|
|
|
1566
1498
|
}
|
|
1567
1499
|
|
|
1568
1500
|
// src/commands/create.ts
|
|
1569
|
-
import
|
|
1570
|
-
import
|
|
1571
|
-
import
|
|
1501
|
+
import fs12 from "node:fs";
|
|
1502
|
+
import path11 from "node:path";
|
|
1503
|
+
import process6 from "node:process";
|
|
1572
1504
|
import * as v3 from "valibot";
|
|
1573
1505
|
import { Command as Command3 } from "commander";
|
|
1574
1506
|
import * as p5 from "@clack/prompts";
|
|
@@ -1590,7 +1522,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
|
|
|
1590
1522
|
projectPath,
|
|
1591
1523
|
options
|
|
1592
1524
|
);
|
|
1593
|
-
const relative =
|
|
1525
|
+
const relative = path11.relative(process6.cwd(), directory);
|
|
1594
1526
|
const pm = packageManager ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
|
|
1595
1527
|
const nextSteps = [];
|
|
1596
1528
|
if (relative !== "") {
|
|
@@ -1629,7 +1561,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
|
|
|
1629
1561
|
async function createProject(cwdArg, options) {
|
|
1630
1562
|
const onCancel2 = () => {
|
|
1631
1563
|
p5.cancel("Operation cancelled.");
|
|
1632
|
-
|
|
1564
|
+
process6.exit(0);
|
|
1633
1565
|
};
|
|
1634
1566
|
const template = findProjectTemplate(options.template ?? DEFAULT_TEMPLATE);
|
|
1635
1567
|
if (!template.backend && (options.email || options.password)) {
|
|
@@ -1639,7 +1571,7 @@ async function createProject(cwdArg, options) {
|
|
|
1639
1571
|
}
|
|
1640
1572
|
let directory;
|
|
1641
1573
|
if (cwdArg) {
|
|
1642
|
-
directory =
|
|
1574
|
+
directory = path11.resolve(cwdArg);
|
|
1643
1575
|
} else {
|
|
1644
1576
|
const answer = await p5.text({
|
|
1645
1577
|
message: "Where would you like your project to be created?",
|
|
@@ -1647,16 +1579,16 @@ async function createProject(cwdArg, options) {
|
|
|
1647
1579
|
defaultValue: "./"
|
|
1648
1580
|
});
|
|
1649
1581
|
if (p5.isCancel(answer)) onCancel2();
|
|
1650
|
-
directory =
|
|
1582
|
+
directory = path11.resolve(answer);
|
|
1651
1583
|
}
|
|
1652
|
-
if (
|
|
1584
|
+
if (fs12.existsSync(directory) && fs12.readdirSync(directory).filter((f) => !f.startsWith(".git")).length > 0) {
|
|
1653
1585
|
const force = await p5.confirm({
|
|
1654
1586
|
message: "Directory not empty. Continue?",
|
|
1655
1587
|
initialValue: false
|
|
1656
1588
|
});
|
|
1657
1589
|
if (p5.isCancel(force) || !force) onCancel2();
|
|
1658
1590
|
}
|
|
1659
|
-
const dirName =
|
|
1591
|
+
const dirName = path11.basename(directory);
|
|
1660
1592
|
const { name } = await p5.group(
|
|
1661
1593
|
{
|
|
1662
1594
|
name: () => {
|
|
@@ -1674,7 +1606,7 @@ async function createProject(cwdArg, options) {
|
|
|
1674
1606
|
const projectPath = directory;
|
|
1675
1607
|
copyTemplate(template, projectPath);
|
|
1676
1608
|
applyTemplateFiles(projectPath, { appName: name, cliVersion: package_default.version });
|
|
1677
|
-
if (!
|
|
1609
|
+
if (!fs12.existsSync(path11.join(projectPath, "package.json"))) {
|
|
1678
1610
|
throw new Error(`Template ${template.name} is missing package.template.json`);
|
|
1679
1611
|
}
|
|
1680
1612
|
p5.log.success("Project created");
|
|
@@ -1736,11 +1668,11 @@ function promptCredentials(options, onCancel2) {
|
|
|
1736
1668
|
);
|
|
1737
1669
|
}
|
|
1738
1670
|
function copyTemplate(template, target) {
|
|
1739
|
-
|
|
1740
|
-
|
|
1671
|
+
fs12.mkdirSync(target, { recursive: true });
|
|
1672
|
+
fs12.cpSync(template.dir, target, {
|
|
1741
1673
|
recursive: true,
|
|
1742
1674
|
// The manifest describes the template to the CLI; it isn't part of the project.
|
|
1743
|
-
filter: (src) =>
|
|
1675
|
+
filter: (src) => path11.basename(src) !== ".DS_Store" && path11.relative(template.dir, src) !== TEMPLATE_MANIFEST
|
|
1744
1676
|
});
|
|
1745
1677
|
restoreTemplateNames(target);
|
|
1746
1678
|
}
|
|
@@ -1753,14 +1685,14 @@ import { Command as Command4 } from "commander";
|
|
|
1753
1685
|
import * as p11 from "@clack/prompts";
|
|
1754
1686
|
|
|
1755
1687
|
// src/lib/pattern-runner.ts
|
|
1756
|
-
import
|
|
1688
|
+
import path12 from "node:path";
|
|
1757
1689
|
import * as p6 from "@clack/prompts";
|
|
1758
1690
|
import { bySlug } from "@velastack/patterns";
|
|
1759
1691
|
function toRelative(root, filePath) {
|
|
1760
|
-
return
|
|
1692
|
+
return path12.isAbsolute(filePath) ? path12.relative(root, filePath) : filePath;
|
|
1761
1693
|
}
|
|
1762
1694
|
var isSuccess = (f) => (f.status ?? "success") === "success";
|
|
1763
|
-
async function runPattern(slug2,
|
|
1695
|
+
async function runPattern(slug2, argv, input, report4) {
|
|
1764
1696
|
const pattern = bySlug[slug2];
|
|
1765
1697
|
if (!pattern) {
|
|
1766
1698
|
throw new Error(`Unknown pattern: ${slug2}`);
|
|
@@ -1770,7 +1702,7 @@ async function runPattern(slug2, argv2, input, report4) {
|
|
|
1770
1702
|
let result;
|
|
1771
1703
|
try {
|
|
1772
1704
|
result = await pattern.generate({
|
|
1773
|
-
argv
|
|
1705
|
+
argv,
|
|
1774
1706
|
env: "runtime",
|
|
1775
1707
|
root: workspaceRootDir,
|
|
1776
1708
|
features,
|
|
@@ -1824,31 +1756,31 @@ async function runPattern(slug2, argv2, input, report4) {
|
|
|
1824
1756
|
}
|
|
1825
1757
|
|
|
1826
1758
|
// src/lib/ai-flow.ts
|
|
1827
|
-
import
|
|
1828
|
-
import
|
|
1759
|
+
import fs15 from "node:fs";
|
|
1760
|
+
import path15 from "node:path";
|
|
1829
1761
|
import * as p10 from "@clack/prompts";
|
|
1830
1762
|
import pc4 from "picocolors";
|
|
1831
1763
|
|
|
1832
1764
|
// src/lib/config.ts
|
|
1833
|
-
import
|
|
1765
|
+
import fs13 from "node:fs";
|
|
1834
1766
|
import os from "node:os";
|
|
1835
|
-
import
|
|
1836
|
-
var CONFIG_DIR =
|
|
1837
|
-
var CONFIG_PATH =
|
|
1767
|
+
import path13 from "node:path";
|
|
1768
|
+
var CONFIG_DIR = path13.join(os.homedir(), ".vela");
|
|
1769
|
+
var CONFIG_PATH = path13.join(CONFIG_DIR, "config.json");
|
|
1838
1770
|
function readConfig() {
|
|
1839
|
-
if (!
|
|
1771
|
+
if (!fs13.existsSync(CONFIG_PATH)) return null;
|
|
1840
1772
|
try {
|
|
1841
|
-
return JSON.parse(
|
|
1773
|
+
return JSON.parse(fs13.readFileSync(CONFIG_PATH, "utf8"));
|
|
1842
1774
|
} catch {
|
|
1843
1775
|
return null;
|
|
1844
1776
|
}
|
|
1845
1777
|
}
|
|
1846
1778
|
function writeConfig(config) {
|
|
1847
|
-
|
|
1848
|
-
|
|
1779
|
+
fs13.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
1780
|
+
fs13.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
1849
1781
|
}
|
|
1850
1782
|
function clearConfig() {
|
|
1851
|
-
if (
|
|
1783
|
+
if (fs13.existsSync(CONFIG_PATH)) fs13.unlinkSync(CONFIG_PATH);
|
|
1852
1784
|
}
|
|
1853
1785
|
function requireApiKey() {
|
|
1854
1786
|
const config = readConfig();
|
|
@@ -1859,16 +1791,16 @@ function requireApiKey() {
|
|
|
1859
1791
|
}
|
|
1860
1792
|
|
|
1861
1793
|
// src/lib/project-config.ts
|
|
1862
|
-
import
|
|
1863
|
-
import
|
|
1794
|
+
import fs14 from "node:fs";
|
|
1795
|
+
import path14 from "node:path";
|
|
1864
1796
|
function projectConfigPath(workspaceRootDir) {
|
|
1865
|
-
return
|
|
1797
|
+
return path14.join(workspaceRootDir, ".vela", "project.json");
|
|
1866
1798
|
}
|
|
1867
1799
|
function readProjectConfig(workspaceRootDir) {
|
|
1868
1800
|
const file = projectConfigPath(workspaceRootDir);
|
|
1869
|
-
if (!
|
|
1801
|
+
if (!fs14.existsSync(file)) return null;
|
|
1870
1802
|
try {
|
|
1871
|
-
const parsed = JSON.parse(
|
|
1803
|
+
const parsed = JSON.parse(fs14.readFileSync(file, "utf8"));
|
|
1872
1804
|
if (typeof parsed.projectId !== "string" || typeof parsed.teamId !== "string" || typeof parsed.projectName !== "string") {
|
|
1873
1805
|
return null;
|
|
1874
1806
|
}
|
|
@@ -1883,15 +1815,15 @@ function readProjectConfig(workspaceRootDir) {
|
|
|
1883
1815
|
}
|
|
1884
1816
|
function writeProjectConfig(workspaceRootDir, config) {
|
|
1885
1817
|
const file = projectConfigPath(workspaceRootDir);
|
|
1886
|
-
|
|
1818
|
+
fs14.mkdirSync(path14.dirname(file), { recursive: true });
|
|
1887
1819
|
let existing = {};
|
|
1888
|
-
if (
|
|
1820
|
+
if (fs14.existsSync(file)) {
|
|
1889
1821
|
try {
|
|
1890
|
-
existing = JSON.parse(
|
|
1822
|
+
existing = JSON.parse(fs14.readFileSync(file, "utf8"));
|
|
1891
1823
|
} catch {
|
|
1892
1824
|
}
|
|
1893
1825
|
}
|
|
1894
|
-
|
|
1826
|
+
fs14.writeFileSync(file, JSON.stringify({ ...existing, ...config }, null, 2) + "\n");
|
|
1895
1827
|
}
|
|
1896
1828
|
|
|
1897
1829
|
// src/lib/ai-client.ts
|
|
@@ -2016,7 +1948,7 @@ function typeArg(field) {
|
|
|
2016
1948
|
return null;
|
|
2017
1949
|
}
|
|
2018
1950
|
function collectionSpecToArgv(spec) {
|
|
2019
|
-
const
|
|
1951
|
+
const argv = [spec.name];
|
|
2020
1952
|
for (const field of spec.fields) {
|
|
2021
1953
|
const type = typeArg(field);
|
|
2022
1954
|
if (type === null) {
|
|
@@ -2026,9 +1958,9 @@ function collectionSpecToArgv(spec) {
|
|
|
2026
1958
|
continue;
|
|
2027
1959
|
}
|
|
2028
1960
|
const required = field.required ? "!" : "";
|
|
2029
|
-
|
|
1961
|
+
argv.push(`${field.name}:${type}${required}`);
|
|
2030
1962
|
}
|
|
2031
|
-
return
|
|
1963
|
+
return argv;
|
|
2032
1964
|
}
|
|
2033
1965
|
|
|
2034
1966
|
// src/lib/ai-grid.ts
|
|
@@ -2165,11 +2097,11 @@ function specToArgv(spec) {
|
|
|
2165
2097
|
return collectionSpecToArgv(spec);
|
|
2166
2098
|
}
|
|
2167
2099
|
function writeLayoutSidecar(workspaceRootDir, modelName, layout) {
|
|
2168
|
-
const dir =
|
|
2169
|
-
|
|
2170
|
-
const file =
|
|
2171
|
-
|
|
2172
|
-
return
|
|
2100
|
+
const dir = path15.join(workspaceRootDir, "data", "ai-form-layouts");
|
|
2101
|
+
fs15.mkdirSync(dir, { recursive: true });
|
|
2102
|
+
const file = path15.join(dir, `${modelName}.json`);
|
|
2103
|
+
fs15.writeFileSync(file, JSON.stringify(layout, null, 2) + "\n");
|
|
2104
|
+
return path15.relative(workspaceRootDir, file);
|
|
2173
2105
|
}
|
|
2174
2106
|
|
|
2175
2107
|
// src/commands/generate/form.ts
|
|
@@ -2181,7 +2113,7 @@ var form = new Command4("form").description("generate a form from a model").argu
|
|
|
2181
2113
|
"design the form with AI from a natural-language description (two stages: schema \u2192 layout)"
|
|
2182
2114
|
).allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
2183
2115
|
(model, fields, options) => runCommand(async () => {
|
|
2184
|
-
let
|
|
2116
|
+
let argv;
|
|
2185
2117
|
let modelName;
|
|
2186
2118
|
let sidecarPath = null;
|
|
2187
2119
|
if (options.ai) {
|
|
@@ -2198,14 +2130,14 @@ var form = new Command4("form").description("generate a form from a model").argu
|
|
|
2198
2130
|
p11.cancel("Aborted before any files were written.");
|
|
2199
2131
|
return;
|
|
2200
2132
|
}
|
|
2201
|
-
|
|
2133
|
+
argv = specToArgv(stage2.model);
|
|
2202
2134
|
modelName = stage2.model.name;
|
|
2203
2135
|
sidecarPath = writeLayoutSidecar(stage2.workspaceRootDir, modelName, layout);
|
|
2204
2136
|
} else {
|
|
2205
2137
|
if (!model) {
|
|
2206
2138
|
throw new Error("Missing required argument: model. Pass a model name or use --ai.");
|
|
2207
2139
|
}
|
|
2208
|
-
|
|
2140
|
+
argv = [model, ...fields];
|
|
2209
2141
|
modelName = model;
|
|
2210
2142
|
}
|
|
2211
2143
|
const slug2 = options.remote ? "generate-form-remote" : "generate-form";
|
|
@@ -2220,7 +2152,7 @@ var form = new Command4("form").description("generate a form from a model").argu
|
|
|
2220
2152
|
}
|
|
2221
2153
|
await runPattern(
|
|
2222
2154
|
slug2,
|
|
2223
|
-
|
|
2155
|
+
argv,
|
|
2224
2156
|
{ route: options.route },
|
|
2225
2157
|
{
|
|
2226
2158
|
summary: `Created ${modelName} form.`,
|
|
@@ -2240,7 +2172,7 @@ import { Command as Command5 } from "commander";
|
|
|
2240
2172
|
import * as p12 from "@clack/prompts";
|
|
2241
2173
|
var schema = new Command5("schema").description("generate a schema from a model").argument("[model]", "model name").argument("[fields...]", "field definitions").option("--ai <description>", "design the schema with AI from a natural-language description").allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
2242
2174
|
(model, fields, options) => runCommand(async () => {
|
|
2243
|
-
let
|
|
2175
|
+
let argv;
|
|
2244
2176
|
let modelName;
|
|
2245
2177
|
if (options.ai) {
|
|
2246
2178
|
if (model) {
|
|
@@ -2251,18 +2183,18 @@ var schema = new Command5("schema").description("generate a schema from a model"
|
|
|
2251
2183
|
p12.cancel("Aborted before any files were written.");
|
|
2252
2184
|
return;
|
|
2253
2185
|
}
|
|
2254
|
-
|
|
2186
|
+
argv = specToArgv(stage2.model);
|
|
2255
2187
|
modelName = stage2.model.name;
|
|
2256
2188
|
} else {
|
|
2257
2189
|
if (!model) {
|
|
2258
2190
|
throw new Error("Missing required argument: model. Pass a model name or use --ai.");
|
|
2259
2191
|
}
|
|
2260
|
-
|
|
2192
|
+
argv = [model, ...fields];
|
|
2261
2193
|
modelName = model;
|
|
2262
2194
|
}
|
|
2263
2195
|
await runPattern(
|
|
2264
2196
|
"generate-schema",
|
|
2265
|
-
|
|
2197
|
+
argv,
|
|
2266
2198
|
{},
|
|
2267
2199
|
{
|
|
2268
2200
|
summary: `Created ${modelName} schema.`,
|
|
@@ -2317,7 +2249,7 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
|
|
|
2317
2249
|
"design the scaffold with AI from a natural-language description (two stages: schema \u2192 layout)"
|
|
2318
2250
|
).allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
2319
2251
|
(model, fields, options) => runCommand(async () => {
|
|
2320
|
-
let
|
|
2252
|
+
let argv;
|
|
2321
2253
|
let modelName;
|
|
2322
2254
|
let sidecarPath = null;
|
|
2323
2255
|
if (options.ai) {
|
|
@@ -2334,14 +2266,14 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
|
|
|
2334
2266
|
p13.cancel("Aborted before any files were written.");
|
|
2335
2267
|
return;
|
|
2336
2268
|
}
|
|
2337
|
-
|
|
2269
|
+
argv = specToArgv(stage2.model);
|
|
2338
2270
|
modelName = stage2.model.name;
|
|
2339
2271
|
sidecarPath = writeLayoutSidecar(stage2.workspaceRootDir, modelName, layout);
|
|
2340
2272
|
} else {
|
|
2341
2273
|
if (!model) {
|
|
2342
2274
|
throw new Error("Missing required argument: model. Pass a model name or use --ai.");
|
|
2343
2275
|
}
|
|
2344
|
-
|
|
2276
|
+
argv = [model, ...fields];
|
|
2345
2277
|
modelName = model;
|
|
2346
2278
|
}
|
|
2347
2279
|
const slug2 = options.remote ? "generate-scaffold-remote" : "generate-scaffold";
|
|
@@ -2357,7 +2289,7 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
|
|
|
2357
2289
|
}
|
|
2358
2290
|
await runPattern(
|
|
2359
2291
|
slug2,
|
|
2360
|
-
|
|
2292
|
+
argv,
|
|
2361
2293
|
{ route: options.route },
|
|
2362
2294
|
{
|
|
2363
2295
|
summary: `Created ${modelName} scaffold.`,
|
|
@@ -2560,7 +2492,7 @@ var teams = new Command15("teams").description("enable team / multi-tenant suppo
|
|
|
2560
2492
|
);
|
|
2561
2493
|
|
|
2562
2494
|
// src/commands/enable/payments.ts
|
|
2563
|
-
import
|
|
2495
|
+
import process7 from "node:process";
|
|
2564
2496
|
import { Command as Command16 } from "commander";
|
|
2565
2497
|
import * as p14 from "@clack/prompts";
|
|
2566
2498
|
var PROVIDERS = [{ value: "stripe", label: "Stripe" }];
|
|
@@ -2606,12 +2538,12 @@ async function resolveProvider(value, source) {
|
|
|
2606
2538
|
});
|
|
2607
2539
|
if (p14.isCancel(selected)) {
|
|
2608
2540
|
p14.cancel("Operation cancelled.");
|
|
2609
|
-
|
|
2541
|
+
process7.exit(0);
|
|
2610
2542
|
}
|
|
2611
2543
|
return selected;
|
|
2612
2544
|
}
|
|
2613
2545
|
async function ensureWebhookSecret() {
|
|
2614
|
-
const existing =
|
|
2546
|
+
const existing = process7.env.STRIPE_WEBHOOK_SECRET;
|
|
2615
2547
|
if (existing) return existing;
|
|
2616
2548
|
p14.note(
|
|
2617
2549
|
[
|
|
@@ -2639,12 +2571,12 @@ async function ensurePriceId() {
|
|
|
2639
2571
|
});
|
|
2640
2572
|
if (p14.isCancel(value)) {
|
|
2641
2573
|
p14.cancel("Operation cancelled.");
|
|
2642
|
-
|
|
2574
|
+
process7.exit(0);
|
|
2643
2575
|
}
|
|
2644
2576
|
return (value ?? "").trim();
|
|
2645
2577
|
}
|
|
2646
2578
|
async function ensureKey(envVar, message) {
|
|
2647
|
-
const existing =
|
|
2579
|
+
const existing = process7.env[envVar];
|
|
2648
2580
|
if (existing) return existing;
|
|
2649
2581
|
return promptPassword(message);
|
|
2650
2582
|
}
|
|
@@ -2655,7 +2587,7 @@ async function promptPassword(message) {
|
|
|
2655
2587
|
});
|
|
2656
2588
|
if (p14.isCancel(value)) {
|
|
2657
2589
|
p14.cancel("Operation cancelled.");
|
|
2658
|
-
|
|
2590
|
+
process7.exit(0);
|
|
2659
2591
|
}
|
|
2660
2592
|
return value;
|
|
2661
2593
|
}
|
|
@@ -2687,20 +2619,20 @@ var subscriptions = new Command17("subscriptions").description("enable Stripe su
|
|
|
2687
2619
|
);
|
|
2688
2620
|
|
|
2689
2621
|
// src/commands/enable/s3.ts
|
|
2690
|
-
import
|
|
2622
|
+
import process10 from "node:process";
|
|
2691
2623
|
import { Command as Command18 } from "commander";
|
|
2692
2624
|
import * as p17 from "@clack/prompts";
|
|
2693
2625
|
import pc8 from "picocolors";
|
|
2694
2626
|
|
|
2695
2627
|
// src/lib/server-command.ts
|
|
2696
|
-
import
|
|
2628
|
+
import process9 from "node:process";
|
|
2697
2629
|
import * as v5 from "valibot";
|
|
2698
2630
|
import * as p15 from "@clack/prompts";
|
|
2699
2631
|
import pc5 from "picocolors";
|
|
2700
2632
|
|
|
2701
2633
|
// src/lib/deploy-config.ts
|
|
2702
|
-
import
|
|
2703
|
-
import
|
|
2634
|
+
import fs16 from "node:fs";
|
|
2635
|
+
import path16 from "node:path";
|
|
2704
2636
|
import crypto from "node:crypto";
|
|
2705
2637
|
import { pathToFileURL } from "node:url";
|
|
2706
2638
|
var CONFIG_BASENAMES = [
|
|
@@ -2711,8 +2643,8 @@ var CONFIG_BASENAMES = [
|
|
|
2711
2643
|
];
|
|
2712
2644
|
function findConfigFile(workspaceRootDir) {
|
|
2713
2645
|
for (const name of CONFIG_BASENAMES) {
|
|
2714
|
-
const file =
|
|
2715
|
-
if (
|
|
2646
|
+
const file = path16.join(workspaceRootDir, name);
|
|
2647
|
+
if (fs16.existsSync(file)) return file;
|
|
2716
2648
|
}
|
|
2717
2649
|
return null;
|
|
2718
2650
|
}
|
|
@@ -2720,49 +2652,49 @@ async function loadDeployConfig(workspaceRootDir) {
|
|
|
2720
2652
|
const file = findConfigFile(workspaceRootDir);
|
|
2721
2653
|
if (!file) return {};
|
|
2722
2654
|
if (file.endsWith(".json")) {
|
|
2723
|
-
return JSON.parse(
|
|
2655
|
+
return JSON.parse(fs16.readFileSync(file, "utf8"));
|
|
2724
2656
|
}
|
|
2725
2657
|
const url = file.endsWith(".ts") ? await transpileToTemp(file) : pathToFileURL(file).href;
|
|
2726
2658
|
try {
|
|
2727
2659
|
const mod = await import(url);
|
|
2728
2660
|
const config = mod.default;
|
|
2729
2661
|
if (!config || typeof config !== "object") {
|
|
2730
|
-
throw new Error(`${
|
|
2662
|
+
throw new Error(`${path16.basename(file)} must export a config object as its default export.`);
|
|
2731
2663
|
}
|
|
2732
2664
|
return config;
|
|
2733
2665
|
} finally {
|
|
2734
|
-
if (url !== pathToFileURL(file).href)
|
|
2666
|
+
if (url !== pathToFileURL(file).href) fs16.rmSync(new URL(url), { force: true });
|
|
2735
2667
|
}
|
|
2736
2668
|
}
|
|
2737
2669
|
async function transpileToTemp(file) {
|
|
2738
2670
|
const { ts } = await import("ts-morph");
|
|
2739
|
-
const source =
|
|
2671
|
+
const source = fs16.readFileSync(file, "utf8");
|
|
2740
2672
|
const { outputText } = ts.transpileModule(source, {
|
|
2741
2673
|
compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 }
|
|
2742
2674
|
});
|
|
2743
|
-
const temp =
|
|
2744
|
-
|
|
2675
|
+
const temp = path16.join(
|
|
2676
|
+
path16.dirname(file),
|
|
2745
2677
|
`.velastack.config.${crypto.randomBytes(4).toString("hex")}.mjs`
|
|
2746
2678
|
);
|
|
2747
|
-
|
|
2679
|
+
fs16.writeFileSync(temp, outputText);
|
|
2748
2680
|
return pathToFileURL(temp).href;
|
|
2749
2681
|
}
|
|
2750
2682
|
function projectFilePath(workspaceRootDir) {
|
|
2751
|
-
return
|
|
2683
|
+
return path16.join(workspaceRootDir, ".vela", "project.json");
|
|
2752
2684
|
}
|
|
2753
2685
|
function readProjectFile(workspaceRootDir) {
|
|
2754
2686
|
const file = projectFilePath(workspaceRootDir);
|
|
2755
|
-
if (!
|
|
2687
|
+
if (!fs16.existsSync(file)) return {};
|
|
2756
2688
|
try {
|
|
2757
|
-
return JSON.parse(
|
|
2689
|
+
return JSON.parse(fs16.readFileSync(file, "utf8"));
|
|
2758
2690
|
} catch {
|
|
2759
2691
|
return {};
|
|
2760
2692
|
}
|
|
2761
2693
|
}
|
|
2762
2694
|
function writeProjectFile(workspaceRootDir, data) {
|
|
2763
2695
|
const file = projectFilePath(workspaceRootDir);
|
|
2764
|
-
|
|
2765
|
-
|
|
2696
|
+
fs16.mkdirSync(path16.dirname(file), { recursive: true });
|
|
2697
|
+
fs16.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
|
|
2766
2698
|
}
|
|
2767
2699
|
function resolveAppIdentity(workspaceRootDir, config = {}) {
|
|
2768
2700
|
const project = readProjectFile(workspaceRootDir);
|
|
@@ -2787,11 +2719,11 @@ function readAppIdentity(workspaceRootDir, config = {}) {
|
|
|
2787
2719
|
}
|
|
2788
2720
|
function defaultProjectName(workspaceRootDir) {
|
|
2789
2721
|
try {
|
|
2790
|
-
const pkg = readPackageJson(
|
|
2722
|
+
const pkg = readPackageJson(path16.join(workspaceRootDir, "package.json"));
|
|
2791
2723
|
if (typeof pkg.name === "string" && pkg.name.trim()) return pkg.name.trim();
|
|
2792
2724
|
} catch {
|
|
2793
2725
|
}
|
|
2794
|
-
return
|
|
2726
|
+
return path16.basename(workspaceRootDir);
|
|
2795
2727
|
}
|
|
2796
2728
|
function slug(value) {
|
|
2797
2729
|
return value.toLowerCase().replace(/^@/, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 32) || "app";
|
|
@@ -2870,11 +2802,11 @@ function sshOptionsFrom(options) {
|
|
|
2870
2802
|
}
|
|
2871
2803
|
|
|
2872
2804
|
// src/lib/ssh.ts
|
|
2873
|
-
import
|
|
2805
|
+
import fs17 from "node:fs";
|
|
2874
2806
|
import os2 from "node:os";
|
|
2875
|
-
import
|
|
2807
|
+
import path17 from "node:path";
|
|
2876
2808
|
import crypto2 from "node:crypto";
|
|
2877
|
-
import
|
|
2809
|
+
import process8 from "node:process";
|
|
2878
2810
|
import { spawn as spawn2 } from "node:child_process";
|
|
2879
2811
|
var RemoteCommandError = class extends Error {
|
|
2880
2812
|
exitCode;
|
|
@@ -2915,9 +2847,9 @@ var SshSession = class {
|
|
|
2915
2847
|
}
|
|
2916
2848
|
async open() {
|
|
2917
2849
|
if (this.controlPath) return;
|
|
2918
|
-
const dir =
|
|
2919
|
-
|
|
2920
|
-
const socket =
|
|
2850
|
+
const dir = path17.join(os2.tmpdir(), "vela-ssh");
|
|
2851
|
+
fs17.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
2852
|
+
const socket = path17.join(dir, `${crypto2.randomBytes(6).toString("hex")}.sock`);
|
|
2921
2853
|
this.controlPath = socket;
|
|
2922
2854
|
const args = [
|
|
2923
2855
|
...this.sshArgs(),
|
|
@@ -3152,17 +3084,17 @@ function spawnCapture(command, args, opts = {}) {
|
|
|
3152
3084
|
const child = spawn2(command, args, {
|
|
3153
3085
|
stdio,
|
|
3154
3086
|
cwd: opts.cwd,
|
|
3155
|
-
env: opts.env ? { ...
|
|
3087
|
+
env: opts.env ? { ...process8.env, ...opts.env } : void 0
|
|
3156
3088
|
});
|
|
3157
3089
|
let stdout = "";
|
|
3158
3090
|
let stderr = "";
|
|
3159
3091
|
child.stdout?.on("data", (chunk) => {
|
|
3160
3092
|
stdout += chunk;
|
|
3161
|
-
if (opts.streamStdout)
|
|
3093
|
+
if (opts.streamStdout) process8.stdout.write(chunk);
|
|
3162
3094
|
});
|
|
3163
3095
|
child.stderr?.on("data", (chunk) => {
|
|
3164
3096
|
stderr += chunk;
|
|
3165
|
-
if (opts.stream)
|
|
3097
|
+
if (opts.stream) process8.stderr.write(chunk);
|
|
3166
3098
|
});
|
|
3167
3099
|
child.on("error", reject);
|
|
3168
3100
|
child.on("close", (code) => resolve2({ stdout, stderr, exitCode: code ?? 1 }));
|
|
@@ -3173,14 +3105,14 @@ function spawnCapture(command, args, opts = {}) {
|
|
|
3173
3105
|
}
|
|
3174
3106
|
|
|
3175
3107
|
// src/lib/remote.ts
|
|
3176
|
-
import
|
|
3108
|
+
import path18 from "node:path";
|
|
3177
3109
|
var VELA_ROOT = "/var/lib/vela";
|
|
3178
3110
|
var VELA_ETC = "/etc/vela";
|
|
3179
3111
|
var VELA_USER = "vela";
|
|
3180
3112
|
var SCRIPTS_DIR = `${VELA_ROOT}/scripts`;
|
|
3181
3113
|
var PROVISIONED_MARKER = `${VELA_ETC}/provisioned`;
|
|
3182
3114
|
function serverTemplatesDir() {
|
|
3183
|
-
return
|
|
3115
|
+
return path18.join(templatesDir(), "server");
|
|
3184
3116
|
}
|
|
3185
3117
|
async function syncServerScripts(session) {
|
|
3186
3118
|
await session.script(`mkdir -p "$1" && chmod 0755 "$1"`, { args: [SCRIPTS_DIR] });
|
|
@@ -3248,7 +3180,7 @@ var remotePaths = {
|
|
|
3248
3180
|
};
|
|
3249
3181
|
|
|
3250
3182
|
// src/lib/remote-env.ts
|
|
3251
|
-
import
|
|
3183
|
+
import fs18 from "node:fs";
|
|
3252
3184
|
import dotenv from "dotenv";
|
|
3253
3185
|
var KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
3254
3186
|
function isValidKey(key) {
|
|
@@ -3296,7 +3228,7 @@ function quote(value) {
|
|
|
3296
3228
|
return `"${escaped}"`;
|
|
3297
3229
|
}
|
|
3298
3230
|
function readLocalEnvFile(file) {
|
|
3299
|
-
const parsed = dotenv.parse(
|
|
3231
|
+
const parsed = dotenv.parse(fs18.readFileSync(file));
|
|
3300
3232
|
const result = {};
|
|
3301
3233
|
for (const [key, value] of Object.entries(parsed)) {
|
|
3302
3234
|
if (isValidKey(key)) result[key] = value;
|
|
@@ -3417,7 +3349,7 @@ function addTargetOptions(command, fallback) {
|
|
|
3417
3349
|
async function withTarget(raw, handlers, run = {}) {
|
|
3418
3350
|
const options = parseOptions(OptionsSchema, raw);
|
|
3419
3351
|
const target = parseTarget(options.target, "production");
|
|
3420
|
-
const
|
|
3352
|
+
const label4 = run.label ? `vela ${run.label}` : "this command";
|
|
3421
3353
|
if (target.kind === "preview") {
|
|
3422
3354
|
throw new Error(
|
|
3423
3355
|
`Preview targets are not supported yet.
|
|
@@ -3441,7 +3373,7 @@ DNS and certificates that \`vela provision\` does not set up yet.`
|
|
|
3441
3373
|
if (target.kind === "local") {
|
|
3442
3374
|
if (!handlers.local) {
|
|
3443
3375
|
throw new Error(
|
|
3444
|
-
`${
|
|
3376
|
+
`${label4} has no local target.` + (run.localHint ? `
|
|
3445
3377
|
|
|
3446
3378
|
${run.localHint}` : "")
|
|
3447
3379
|
);
|
|
@@ -3454,7 +3386,7 @@ ${run.localHint}` : "")
|
|
|
3454
3386
|
return;
|
|
3455
3387
|
}
|
|
3456
3388
|
if (!handlers.remote) {
|
|
3457
|
-
throw new Error(`${
|
|
3389
|
+
throw new Error(`${label4} only acts on ${pc5.cyan("local")}.`);
|
|
3458
3390
|
}
|
|
3459
3391
|
const binding = await ensureBinding(workspaceRootDir, target, {
|
|
3460
3392
|
server: options.server,
|
|
@@ -3502,7 +3434,7 @@ longer reach it. Remove it there first if that was not intended.`
|
|
|
3502
3434
|
return binding;
|
|
3503
3435
|
}
|
|
3504
3436
|
async function promptServer(target) {
|
|
3505
|
-
if (!
|
|
3437
|
+
if (!process9.stdout.isTTY || process9.env.CI) {
|
|
3506
3438
|
throw new Error(
|
|
3507
3439
|
`${target.name} is not bound to a server yet, and there is no terminal to ask on.
|
|
3508
3440
|
|
|
@@ -3518,19 +3450,19 @@ and commit ${pc5.cyan(".vela/project.json")}.`
|
|
|
3518
3450
|
});
|
|
3519
3451
|
if (p15.isCancel(value)) {
|
|
3520
3452
|
p15.cancel("Operation cancelled.");
|
|
3521
|
-
|
|
3453
|
+
process9.exit(0);
|
|
3522
3454
|
}
|
|
3523
3455
|
return value.trim();
|
|
3524
3456
|
}
|
|
3525
3457
|
async function promptDomain(target) {
|
|
3526
|
-
if (!
|
|
3458
|
+
if (!process9.stdout.isTTY || process9.env.CI) return void 0;
|
|
3527
3459
|
const value = await p15.text({
|
|
3528
3460
|
message: `Which hostname should ${target.name} be served on?`,
|
|
3529
3461
|
placeholder: "example.com \u2014 leave blank to decide later"
|
|
3530
3462
|
});
|
|
3531
3463
|
if (p15.isCancel(value)) {
|
|
3532
3464
|
p15.cancel("Operation cancelled.");
|
|
3533
|
-
|
|
3465
|
+
process9.exit(0);
|
|
3534
3466
|
}
|
|
3535
3467
|
return value.trim() || void 0;
|
|
3536
3468
|
}
|
|
@@ -3586,17 +3518,17 @@ function envFilePath(workspaceRootDir) {
|
|
|
3586
3518
|
import pc7 from "picocolors";
|
|
3587
3519
|
|
|
3588
3520
|
// src/lib/local-env.ts
|
|
3589
|
-
import
|
|
3521
|
+
import fs19 from "node:fs";
|
|
3590
3522
|
import * as p16 from "@clack/prompts";
|
|
3591
3523
|
import pc6 from "picocolors";
|
|
3592
3524
|
function readLocalEnv(envFile) {
|
|
3593
|
-
if (!
|
|
3525
|
+
if (!fs19.existsSync(envFile)) return {};
|
|
3594
3526
|
return readLocalEnvFile(envFile);
|
|
3595
3527
|
}
|
|
3596
3528
|
function editLocalEnv(envFile, edit) {
|
|
3597
|
-
const before =
|
|
3529
|
+
const before = fs19.existsSync(envFile) ? fs19.readFileSync(envFile, "utf8") : "";
|
|
3598
3530
|
const after = edit(before);
|
|
3599
|
-
if (after !== before)
|
|
3531
|
+
if (after !== before) fs19.writeFileSync(envFile, after);
|
|
3600
3532
|
}
|
|
3601
3533
|
function setLocalEnv(envFile, key, value) {
|
|
3602
3534
|
editLocalEnv(envFile, (content) => upsertEnvVar(content, key, value));
|
|
@@ -3669,7 +3601,7 @@ async function withRemotePocketbase(session, instance, fn) {
|
|
|
3669
3601
|
}
|
|
3670
3602
|
|
|
3671
3603
|
// src/lib/backup-target.ts
|
|
3672
|
-
async function withBackupTarget(raw,
|
|
3604
|
+
async function withBackupTarget(raw, label4, fn) {
|
|
3673
3605
|
await withTarget(
|
|
3674
3606
|
raw,
|
|
3675
3607
|
{
|
|
@@ -3723,13 +3655,13 @@ Set ${pc7.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc7.cyan("POCKETBASE_SUPERUS
|
|
|
3723
3655
|
);
|
|
3724
3656
|
}
|
|
3725
3657
|
},
|
|
3726
|
-
{ label:
|
|
3658
|
+
{ label: label4 }
|
|
3727
3659
|
);
|
|
3728
3660
|
}
|
|
3729
3661
|
|
|
3730
3662
|
// src/lib/s3-settings.ts
|
|
3731
|
-
import
|
|
3732
|
-
import
|
|
3663
|
+
import fs20 from "node:fs";
|
|
3664
|
+
import path19 from "node:path";
|
|
3733
3665
|
var VIRTUAL_HOSTED = [/\.amazonaws\.com$/i, /\.r2\.cloudflarestorage\.com$/i];
|
|
3734
3666
|
function defaultForcePathStyle(endpoint) {
|
|
3735
3667
|
let host;
|
|
@@ -3767,18 +3699,18 @@ async function hasLocalUploads(session, instance, workspaceRootDir) {
|
|
|
3767
3699
|
});
|
|
3768
3700
|
return result.stdout.trim().length > 0;
|
|
3769
3701
|
}
|
|
3770
|
-
return hasFile(
|
|
3702
|
+
return hasFile(path19.join(workspaceRootDir, DATA_DIR, "storage"));
|
|
3771
3703
|
}
|
|
3772
3704
|
function hasFile(dir) {
|
|
3773
3705
|
let entries;
|
|
3774
3706
|
try {
|
|
3775
|
-
entries =
|
|
3707
|
+
entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
3776
3708
|
} catch {
|
|
3777
3709
|
return false;
|
|
3778
3710
|
}
|
|
3779
3711
|
for (const entry of entries) {
|
|
3780
3712
|
if (entry.isFile()) return true;
|
|
3781
|
-
if (entry.isDirectory() && hasFile(
|
|
3713
|
+
if (entry.isDirectory() && hasFile(path19.join(dir, entry.name))) return true;
|
|
3782
3714
|
}
|
|
3783
3715
|
return false;
|
|
3784
3716
|
}
|
|
@@ -3851,7 +3783,7 @@ async function promptConfig(options, existing) {
|
|
|
3851
3783
|
const bucket = options.bucket ?? await text7("S3 bucket name", existing.bucket);
|
|
3852
3784
|
const region = options.region ?? await text7("S3 region", existing.region || "us-east-1");
|
|
3853
3785
|
const accessKey = options.accessKey ?? await text7("S3 access key", existing.accessKey);
|
|
3854
|
-
const secret = options.secret ??
|
|
3786
|
+
const secret = options.secret ?? process10.env.VELA_S3_SECRET ?? await password5("S3 secret key");
|
|
3855
3787
|
const forcePathStyle = options.forcePathStyle ?? await confirm3(
|
|
3856
3788
|
"Address the bucket in the path? (MinIO, Ceph and most self-hosted gateways need this)",
|
|
3857
3789
|
defaultForcePathStyle(endpoint)
|
|
@@ -3866,7 +3798,7 @@ async function text7(message, initialValue = "") {
|
|
|
3866
3798
|
});
|
|
3867
3799
|
if (p17.isCancel(value)) {
|
|
3868
3800
|
p17.cancel("Operation cancelled.");
|
|
3869
|
-
|
|
3801
|
+
process10.exit(0);
|
|
3870
3802
|
}
|
|
3871
3803
|
return value.trim();
|
|
3872
3804
|
}
|
|
@@ -3877,7 +3809,7 @@ async function password5(message) {
|
|
|
3877
3809
|
});
|
|
3878
3810
|
if (p17.isCancel(value)) {
|
|
3879
3811
|
p17.cancel("Operation cancelled.");
|
|
3880
|
-
|
|
3812
|
+
process10.exit(0);
|
|
3881
3813
|
}
|
|
3882
3814
|
return value;
|
|
3883
3815
|
}
|
|
@@ -3885,13 +3817,13 @@ async function confirm3(message, initialValue) {
|
|
|
3885
3817
|
const value = await p17.confirm({ message, initialValue });
|
|
3886
3818
|
if (p17.isCancel(value)) {
|
|
3887
3819
|
p17.cancel("Operation cancelled.");
|
|
3888
|
-
|
|
3820
|
+
process10.exit(0);
|
|
3889
3821
|
}
|
|
3890
3822
|
return value;
|
|
3891
3823
|
}
|
|
3892
3824
|
|
|
3893
3825
|
// src/commands/enable/smtp.ts
|
|
3894
|
-
import
|
|
3826
|
+
import process11 from "node:process";
|
|
3895
3827
|
import { Command as Command19 } from "commander";
|
|
3896
3828
|
import * as p18 from "@clack/prompts";
|
|
3897
3829
|
var smtp = new Command19("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
|
|
@@ -3920,7 +3852,7 @@ var smtp = new Command19("smtp").description("configure SMTP for transactional e
|
|
|
3920
3852
|
{
|
|
3921
3853
|
onCancel: () => {
|
|
3922
3854
|
p18.cancel("Operation cancelled.");
|
|
3923
|
-
|
|
3855
|
+
process11.exit(0);
|
|
3924
3856
|
}
|
|
3925
3857
|
}
|
|
3926
3858
|
);
|
|
@@ -3947,7 +3879,7 @@ var smtp = new Command19("smtp").description("configure SMTP for transactional e
|
|
|
3947
3879
|
);
|
|
3948
3880
|
|
|
3949
3881
|
// src/commands/enable/cms.ts
|
|
3950
|
-
import
|
|
3882
|
+
import process12 from "node:process";
|
|
3951
3883
|
import { Command as Command20 } from "commander";
|
|
3952
3884
|
import * as p19 from "@clack/prompts";
|
|
3953
3885
|
import pc9 from "picocolors";
|
|
@@ -3961,7 +3893,7 @@ Run ${pc9.cyan("vela bless")} to add a backend first.`
|
|
|
3961
3893
|
);
|
|
3962
3894
|
p19.log.message();
|
|
3963
3895
|
p19.cancel("Operation failed.");
|
|
3964
|
-
|
|
3896
|
+
process12.exitCode = 1;
|
|
3965
3897
|
return;
|
|
3966
3898
|
}
|
|
3967
3899
|
await runPattern(
|
|
@@ -4046,7 +3978,7 @@ import { Command as Command34 } from "commander";
|
|
|
4046
3978
|
import { Command as Command24 } from "commander";
|
|
4047
3979
|
|
|
4048
3980
|
// src/commands/disable/_shared.ts
|
|
4049
|
-
import
|
|
3981
|
+
import process13 from "node:process";
|
|
4050
3982
|
import * as p20 from "@clack/prompts";
|
|
4051
3983
|
async function runDisable(opts, flags, cmdArgs) {
|
|
4052
3984
|
if (!flags.yes) {
|
|
@@ -4056,7 +3988,7 @@ async function runDisable(opts, flags, cmdArgs) {
|
|
|
4056
3988
|
});
|
|
4057
3989
|
if (p20.isCancel(ok) || !ok) {
|
|
4058
3990
|
p20.cancel("Operation cancelled.");
|
|
4059
|
-
|
|
3991
|
+
process13.exit(0);
|
|
4060
3992
|
}
|
|
4061
3993
|
}
|
|
4062
3994
|
await runPattern(opts.slug, cmdArgs, { destructive: true }, opts.report);
|
|
@@ -4327,14 +4259,14 @@ import { Command as Command40 } from "commander";
|
|
|
4327
4259
|
import { Command as Command35 } from "commander";
|
|
4328
4260
|
|
|
4329
4261
|
// src/commands/destroy/_shared.ts
|
|
4330
|
-
import
|
|
4262
|
+
import process14 from "node:process";
|
|
4331
4263
|
import * as p22 from "@clack/prompts";
|
|
4332
4264
|
async function runDestroy(slug2, model, confirmMessage, report4, flags) {
|
|
4333
4265
|
if (!flags.yes) {
|
|
4334
4266
|
const ok = await p22.confirm({ message: confirmMessage, initialValue: false });
|
|
4335
4267
|
if (p22.isCancel(ok) || !ok) {
|
|
4336
4268
|
p22.cancel("Operation cancelled.");
|
|
4337
|
-
|
|
4269
|
+
process14.exit(0);
|
|
4338
4270
|
}
|
|
4339
4271
|
}
|
|
4340
4272
|
await runPattern(slug2, [model], { destructive: true, route: flags.route }, report4);
|
|
@@ -4437,7 +4369,7 @@ var scaffold2 = new Command38("scaffold").description("destroy a scaffold genera
|
|
|
4437
4369
|
);
|
|
4438
4370
|
|
|
4439
4371
|
// src/commands/destroy/deployment.ts
|
|
4440
|
-
import
|
|
4372
|
+
import process15 from "node:process";
|
|
4441
4373
|
import { Command as Command39 } from "commander";
|
|
4442
4374
|
import * as p23 from "@clack/prompts";
|
|
4443
4375
|
import pc11 from "picocolors";
|
|
@@ -4480,7 +4412,7 @@ async function confirm7(appName, targetName, envTag, purge) {
|
|
|
4480
4412
|
});
|
|
4481
4413
|
if (p23.isCancel(answer)) {
|
|
4482
4414
|
p23.cancel("Operation cancelled.");
|
|
4483
|
-
|
|
4415
|
+
process15.exit(0);
|
|
4484
4416
|
}
|
|
4485
4417
|
return;
|
|
4486
4418
|
}
|
|
@@ -4490,7 +4422,7 @@ async function confirm7(appName, targetName, envTag, purge) {
|
|
|
4490
4422
|
});
|
|
4491
4423
|
if (p23.isCancel(ok) || !ok) {
|
|
4492
4424
|
p23.cancel("Operation cancelled.");
|
|
4493
|
-
|
|
4425
|
+
process15.exit(0);
|
|
4494
4426
|
}
|
|
4495
4427
|
}
|
|
4496
4428
|
|
|
@@ -4543,13 +4475,13 @@ var add = new Command41("add").description("add ui components").argument("<compo
|
|
|
4543
4475
|
);
|
|
4544
4476
|
|
|
4545
4477
|
// src/commands/ui/base.ts
|
|
4546
|
-
import
|
|
4547
|
-
import
|
|
4478
|
+
import fs21 from "node:fs";
|
|
4479
|
+
import path20 from "node:path";
|
|
4548
4480
|
import { Command as Command42, InvalidArgumentError } from "commander";
|
|
4549
4481
|
var VALID_COLORS = ["slate", "gray", "zinc", "stone", "neutral"];
|
|
4550
4482
|
function findThemeFile(color) {
|
|
4551
|
-
const candidate =
|
|
4552
|
-
if (!
|
|
4483
|
+
const candidate = path20.join(templatesDir(), "ui", "css", `${color}.css`);
|
|
4484
|
+
if (!fs21.existsSync(candidate)) {
|
|
4553
4485
|
throw new Error(`Theme file not found for color: ${color}`);
|
|
4554
4486
|
}
|
|
4555
4487
|
return candidate;
|
|
@@ -4580,17 +4512,17 @@ var base = new Command42("base").description("change the base color").argument("
|
|
|
4580
4512
|
}).configureHelp(helpConfig).action(
|
|
4581
4513
|
(color) => runCommand(async () => {
|
|
4582
4514
|
const { workspaceRootDir } = await getWorkspace();
|
|
4583
|
-
const appCssPath =
|
|
4584
|
-
if (!
|
|
4585
|
-
throw new Error(`Could not find ${
|
|
4515
|
+
const appCssPath = path20.join(workspaceRootDir, "src", "app.css");
|
|
4516
|
+
if (!fs21.existsSync(appCssPath)) {
|
|
4517
|
+
throw new Error(`Could not find ${path20.relative(workspaceRootDir, appCssPath)}`);
|
|
4586
4518
|
}
|
|
4587
|
-
const themeContent =
|
|
4519
|
+
const themeContent = fs21.readFileSync(findThemeFile(color), "utf8");
|
|
4588
4520
|
const selectors = extractSelectors(themeContent);
|
|
4589
|
-
const appCss =
|
|
4590
|
-
|
|
4521
|
+
const appCss = fs21.readFileSync(appCssPath, "utf8");
|
|
4522
|
+
fs21.writeFileSync(appCssPath, applyTheme(appCss, selectors));
|
|
4591
4523
|
reportResult({
|
|
4592
4524
|
summary: `Set base color to ${color}.`,
|
|
4593
|
-
filesModified: [
|
|
4525
|
+
filesModified: [path20.relative(workspaceRootDir, appCssPath)],
|
|
4594
4526
|
nextSteps: [
|
|
4595
4527
|
"Run your dev server to preview the new palette.",
|
|
4596
4528
|
"Tweak individual CSS variables in src/app.css if you want to customize the theme further."
|
|
@@ -4606,13 +4538,13 @@ var ui = new Command43("ui").description("generate ui components").configureHelp
|
|
|
4606
4538
|
import { Command as Command46 } from "commander";
|
|
4607
4539
|
|
|
4608
4540
|
// src/commands/legal/terms.ts
|
|
4609
|
-
import
|
|
4610
|
-
import
|
|
4541
|
+
import fs22 from "node:fs";
|
|
4542
|
+
import path21 from "node:path";
|
|
4611
4543
|
import { Command as Command44 } from "commander";
|
|
4612
4544
|
import * as p25 from "@clack/prompts";
|
|
4613
4545
|
|
|
4614
4546
|
// src/commands/legal/shared.ts
|
|
4615
|
-
import
|
|
4547
|
+
import process16 from "node:process";
|
|
4616
4548
|
import * as p24 from "@clack/prompts";
|
|
4617
4549
|
var sharedFields = {
|
|
4618
4550
|
websiteUrl: () => p24.text({
|
|
@@ -4681,7 +4613,7 @@ var sharedFields = {
|
|
|
4681
4613
|
};
|
|
4682
4614
|
var onCancel = () => {
|
|
4683
4615
|
p24.cancel("Operation cancelled.");
|
|
4684
|
-
|
|
4616
|
+
process16.exit(0);
|
|
4685
4617
|
};
|
|
4686
4618
|
async function contactMethods(type) {
|
|
4687
4619
|
const selection = await p24.multiselect({
|
|
@@ -5266,22 +5198,22 @@ async function termsAction() {
|
|
|
5266
5198
|
mobileApp,
|
|
5267
5199
|
contact
|
|
5268
5200
|
});
|
|
5269
|
-
const termsPage =
|
|
5201
|
+
const termsPage = path21.join(
|
|
5270
5202
|
workspaceRootDir,
|
|
5271
5203
|
publicRoutesDir,
|
|
5272
5204
|
LEGAL_DIR,
|
|
5273
5205
|
"terms",
|
|
5274
5206
|
"+page.svelte"
|
|
5275
5207
|
);
|
|
5276
|
-
const termsPageTs =
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5208
|
+
const termsPageTs = path21.join(workspaceRootDir, publicRoutesDir, LEGAL_DIR, "terms", "+page.ts");
|
|
5209
|
+
fs22.mkdirSync(path21.dirname(termsPage), { recursive: true });
|
|
5210
|
+
fs22.writeFileSync(termsPage, html);
|
|
5211
|
+
fs22.writeFileSync(
|
|
5280
5212
|
termsPageTs,
|
|
5281
5213
|
pageMetaTagsLoader("Terms of Service", `Terms of Service for ${core.websiteName}`)
|
|
5282
5214
|
);
|
|
5283
|
-
const relativeTermsPage =
|
|
5284
|
-
const relativeTermsPageTs =
|
|
5215
|
+
const relativeTermsPage = path21.relative(workspaceRootDir, termsPage);
|
|
5216
|
+
const relativeTermsPageTs = path21.relative(workspaceRootDir, termsPageTs);
|
|
5285
5217
|
reportResult({
|
|
5286
5218
|
summary: "Generated placeholder terms and conditions.",
|
|
5287
5219
|
filesCreated: [relativeTermsPage, relativeTermsPageTs],
|
|
@@ -5295,8 +5227,8 @@ async function termsAction() {
|
|
|
5295
5227
|
var terms = new Command44("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
|
|
5296
5228
|
|
|
5297
5229
|
// src/commands/legal/privacy.ts
|
|
5298
|
-
import
|
|
5299
|
-
import
|
|
5230
|
+
import fs23 from "node:fs";
|
|
5231
|
+
import path22 from "node:path";
|
|
5300
5232
|
import { Command as Command45 } from "commander";
|
|
5301
5233
|
import * as p26 from "@clack/prompts";
|
|
5302
5234
|
var mapLabels = {
|
|
@@ -6009,28 +5941,28 @@ async function privacyAction() {
|
|
|
6009
5941
|
kids,
|
|
6010
5942
|
retention
|
|
6011
5943
|
});
|
|
6012
|
-
const privacyPage =
|
|
5944
|
+
const privacyPage = path22.join(
|
|
6013
5945
|
workspaceRootDir,
|
|
6014
5946
|
publicRoutesDir,
|
|
6015
5947
|
LEGAL_DIR,
|
|
6016
5948
|
"privacy",
|
|
6017
5949
|
"+page.svelte"
|
|
6018
5950
|
);
|
|
6019
|
-
const privacyPageTs =
|
|
5951
|
+
const privacyPageTs = path22.join(
|
|
6020
5952
|
workspaceRootDir,
|
|
6021
5953
|
publicRoutesDir,
|
|
6022
5954
|
LEGAL_DIR,
|
|
6023
5955
|
"privacy",
|
|
6024
5956
|
"+page.ts"
|
|
6025
5957
|
);
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
5958
|
+
fs23.mkdirSync(path22.dirname(privacyPage), { recursive: true });
|
|
5959
|
+
fs23.writeFileSync(privacyPage, html);
|
|
5960
|
+
fs23.writeFileSync(
|
|
6029
5961
|
privacyPageTs,
|
|
6030
5962
|
pageMetaTagsLoader("Privacy Policy", `Privacy Policy for ${core.websiteName}`)
|
|
6031
5963
|
);
|
|
6032
|
-
const relativePrivacyPage =
|
|
6033
|
-
const relativePrivacyPageTs =
|
|
5964
|
+
const relativePrivacyPage = path22.relative(workspaceRootDir, privacyPage);
|
|
5965
|
+
const relativePrivacyPageTs = path22.relative(workspaceRootDir, privacyPageTs);
|
|
6034
5966
|
reportResult({
|
|
6035
5967
|
summary: "Generated placeholder privacy policy.",
|
|
6036
5968
|
filesCreated: [relativePrivacyPage, relativePrivacyPageTs],
|
|
@@ -6050,70 +5982,12 @@ var legal = new Command46("legal").description("generate placeholder legal docum
|
|
|
6050
5982
|
import { Command as Command52 } from "commander";
|
|
6051
5983
|
|
|
6052
5984
|
// src/commands/fixtures/load.ts
|
|
6053
|
-
import fs25 from "node:fs";
|
|
6054
|
-
import path24 from "node:path";
|
|
6055
5985
|
import { Command as Command47 } from "commander";
|
|
6056
|
-
function getFixtureFiles(cwd) {
|
|
6057
|
-
const fixturesDir = path24.join(cwd, "data", "fixtures");
|
|
6058
|
-
if (!fs25.existsSync(fixturesDir)) return [];
|
|
6059
|
-
return fs25.readdirSync(fixturesDir).filter((file) => file.endsWith(".json")).map((file) => path24.join(fixturesDir, file)).sort((a, b) => a.localeCompare(b)).map((fixturePath) => {
|
|
6060
|
-
const file = path24.basename(fixturePath);
|
|
6061
|
-
const nameWithoutExt = file.replace(/\.json$/i, "");
|
|
6062
|
-
const collectionName = nameWithoutExt.replace(/^\d+[-_]?/, "");
|
|
6063
|
-
return { collectionName, fixturePath };
|
|
6064
|
-
});
|
|
6065
|
-
}
|
|
6066
|
-
async function loadFixtures(pb, workspaceRootDir) {
|
|
6067
|
-
const fixtureFiles = getFixtureFiles(workspaceRootDir);
|
|
6068
|
-
if (fixtureFiles.length === 0) return [];
|
|
6069
|
-
const loaded = [];
|
|
6070
|
-
for (const { collectionName, fixturePath } of fixtureFiles) {
|
|
6071
|
-
const shortName = collectionName.slice(0, 6);
|
|
6072
|
-
const existing = await pb.collection(collectionName).getFullList({
|
|
6073
|
-
filter: `id ~ "${FIXTURE_PREFIX}${shortName}%"`,
|
|
6074
|
-
fields: "id"
|
|
6075
|
-
});
|
|
6076
|
-
if (existing.length > 0) {
|
|
6077
|
-
throw new Error(
|
|
6078
|
-
`${collectionName} collection already has fixture records. Run \`vela fixtures reset\` to clear and reload, or \`vela fixtures clear\` first.`
|
|
6079
|
-
);
|
|
6080
|
-
}
|
|
6081
|
-
const items = JSON.parse(fs25.readFileSync(fixturePath, "utf8"));
|
|
6082
|
-
for (const fixture of items) {
|
|
6083
|
-
await pb.collection(collectionName).create(fixture);
|
|
6084
|
-
}
|
|
6085
|
-
loaded.push(`${path24.relative(workspaceRootDir, fixturePath)} (${items.length} records)`);
|
|
6086
|
-
}
|
|
6087
|
-
return loaded;
|
|
6088
|
-
}
|
|
6089
|
-
var load = new Command47("load").description("load fixtures into the database").configureHelp(helpConfig).action(
|
|
6090
|
-
() => runCommand(async () => {
|
|
6091
|
-
const { workspaceRootDir } = await getWorkspace();
|
|
6092
|
-
let loaded = [];
|
|
6093
|
-
await withPocketbase(workspaceRootDir, async (pb) => {
|
|
6094
|
-
loaded = await loadFixtures(pb, workspaceRootDir);
|
|
6095
|
-
});
|
|
6096
|
-
if (loaded.length === 0) {
|
|
6097
|
-
reportResult({
|
|
6098
|
-
summary: "No fixture files found in data/fixtures.",
|
|
6099
|
-
nextSteps: ["Run `vela fixtures generate` to create fixture files first."]
|
|
6100
|
-
});
|
|
6101
|
-
return;
|
|
6102
|
-
}
|
|
6103
|
-
reportResult({
|
|
6104
|
-
summary: `Loaded ${loaded.length} fixture file(s) into the database.`,
|
|
6105
|
-
recordsLoaded: loaded,
|
|
6106
|
-
nextSteps: [
|
|
6107
|
-
"Run `vela dev` to see the fixture data in the app.",
|
|
6108
|
-
"Run `vela fixtures clear` to remove the loaded fixture records."
|
|
6109
|
-
]
|
|
6110
|
-
});
|
|
6111
|
-
}, "Failed to load fixtures.")
|
|
6112
|
-
);
|
|
6113
5986
|
|
|
6114
|
-
// src/
|
|
6115
|
-
import
|
|
6116
|
-
import
|
|
5987
|
+
// src/lib/data.ts
|
|
5988
|
+
import fs24 from "node:fs";
|
|
5989
|
+
import path23 from "node:path";
|
|
5990
|
+
import { ClientResponseError } from "pocketbase";
|
|
6117
5991
|
|
|
6118
5992
|
// src/lib/collections.ts
|
|
6119
5993
|
function dependencyOrder(collections2, startingCollectionId) {
|
|
@@ -6147,10 +6021,114 @@ function dependencyOrder(collections2, startingCollectionId) {
|
|
|
6147
6021
|
return { ids: order, names: order.map((id) => nameById[id]) };
|
|
6148
6022
|
}
|
|
6149
6023
|
|
|
6150
|
-
// src/
|
|
6151
|
-
|
|
6024
|
+
// src/lib/data.ts
|
|
6025
|
+
function dataDir(cwd, kind) {
|
|
6026
|
+
return path23.join(cwd, DATA_DIR, kind);
|
|
6027
|
+
}
|
|
6028
|
+
function getDataFiles(cwd, kind) {
|
|
6029
|
+
const dir = dataDir(cwd, kind);
|
|
6030
|
+
if (!fs24.existsSync(dir)) return [];
|
|
6031
|
+
return fs24.readdirSync(dir).filter((file) => file.endsWith(".json")).sort((a, b) => a.localeCompare(b)).map((file) => ({
|
|
6032
|
+
collectionName: file.replace(/\.json$/i, "").replace(/^\d+[-_]?/, ""),
|
|
6033
|
+
filePath: path23.join(dir, file)
|
|
6034
|
+
}));
|
|
6035
|
+
}
|
|
6036
|
+
function getSeedFiles(cwd) {
|
|
6037
|
+
return getDataFiles(cwd, "seeds");
|
|
6038
|
+
}
|
|
6039
|
+
function getFixtureFiles(cwd) {
|
|
6040
|
+
return getDataFiles(cwd, "fixtures");
|
|
6041
|
+
}
|
|
6042
|
+
function readRecords(filePath) {
|
|
6043
|
+
return JSON.parse(fs24.readFileSync(filePath, "utf8"));
|
|
6044
|
+
}
|
|
6045
|
+
function readSeedIds(cwd) {
|
|
6046
|
+
const ids = /* @__PURE__ */ new Map();
|
|
6047
|
+
for (const { collectionName, filePath } of getSeedFiles(cwd)) {
|
|
6048
|
+
const list2 = ids.get(collectionName) ?? [];
|
|
6049
|
+
for (const record of readRecords(filePath)) {
|
|
6050
|
+
if (typeof record.id === "string" && record.id) list2.push(record.id);
|
|
6051
|
+
}
|
|
6052
|
+
ids.set(collectionName, list2);
|
|
6053
|
+
}
|
|
6054
|
+
return ids;
|
|
6055
|
+
}
|
|
6056
|
+
function fixtureFilter(collectionName) {
|
|
6057
|
+
return `id ~ "${FIXTURE_PREFIX}${collectionName.slice(0, 6)}%"`;
|
|
6058
|
+
}
|
|
6059
|
+
var DataLoadError = class extends Error {
|
|
6060
|
+
kind;
|
|
6061
|
+
file;
|
|
6062
|
+
constructor(kind, file, index, cause) {
|
|
6063
|
+
super(`${file}, record ${index + 1}: ${describeError(cause)}`);
|
|
6064
|
+
this.name = "DataLoadError";
|
|
6065
|
+
this.kind = kind;
|
|
6066
|
+
this.file = file;
|
|
6067
|
+
}
|
|
6068
|
+
};
|
|
6069
|
+
function describeError(e) {
|
|
6070
|
+
if (e instanceof ClientResponseError) {
|
|
6071
|
+
const data = e.response?.data;
|
|
6072
|
+
const details = data && typeof data === "object" ? Object.entries(data).map(
|
|
6073
|
+
([field, detail]) => `${field}: ${detail?.message ?? JSON.stringify(detail)}`
|
|
6074
|
+
) : [];
|
|
6075
|
+
return [e.message, ...details].join(" ");
|
|
6076
|
+
}
|
|
6077
|
+
return e instanceof Error ? e.message : String(e);
|
|
6078
|
+
}
|
|
6079
|
+
function label3(cwd, filePath, count) {
|
|
6080
|
+
return `${path23.relative(cwd, filePath)} (${count} records)`;
|
|
6081
|
+
}
|
|
6082
|
+
async function createRecords(pb, kind, cwd, { collectionName, filePath }) {
|
|
6083
|
+
const records = readRecords(filePath);
|
|
6084
|
+
for (const [index, record] of records.entries()) {
|
|
6085
|
+
try {
|
|
6086
|
+
await pb.collection(collectionName).create(record);
|
|
6087
|
+
} catch (e) {
|
|
6088
|
+
throw new DataLoadError(kind, path23.relative(cwd, filePath), index, e);
|
|
6089
|
+
}
|
|
6090
|
+
}
|
|
6091
|
+
return records.length;
|
|
6092
|
+
}
|
|
6093
|
+
async function loadSeeds(pb, cwd, seedFiles = getSeedFiles(cwd)) {
|
|
6094
|
+
const loaded = [];
|
|
6095
|
+
for (const file of seedFiles) {
|
|
6096
|
+
const count = await createRecords(pb, "seeds", cwd, file);
|
|
6097
|
+
loaded.push(label3(cwd, file.filePath, count));
|
|
6098
|
+
}
|
|
6099
|
+
return loaded;
|
|
6100
|
+
}
|
|
6101
|
+
async function clearSeeds(pb, cwd, seedFiles = getSeedFiles(cwd)) {
|
|
6102
|
+
const cleared = [];
|
|
6103
|
+
for (const { collectionName, filePath } of seedFiles) {
|
|
6104
|
+
const seeds2 = readRecords(filePath);
|
|
6105
|
+
for (const { id } of seeds2) {
|
|
6106
|
+
await pb.collection(collectionName).delete(id);
|
|
6107
|
+
}
|
|
6108
|
+
cleared.push(label3(cwd, filePath, seeds2.length));
|
|
6109
|
+
}
|
|
6110
|
+
return cleared;
|
|
6111
|
+
}
|
|
6112
|
+
async function loadFixtures(pb, cwd) {
|
|
6113
|
+
const loaded = [];
|
|
6114
|
+
for (const file of getFixtureFiles(cwd)) {
|
|
6115
|
+
const existing = await pb.collection(file.collectionName).getFullList({
|
|
6116
|
+
filter: fixtureFilter(file.collectionName),
|
|
6117
|
+
fields: "id"
|
|
6118
|
+
});
|
|
6119
|
+
if (existing.length > 0) {
|
|
6120
|
+
throw new Error(
|
|
6121
|
+
`${file.collectionName} collection already has fixture records. Run \`vela fixtures reset\` to clear and reload, or \`vela fixtures clear\` first.`
|
|
6122
|
+
);
|
|
6123
|
+
}
|
|
6124
|
+
const count = await createRecords(pb, "fixtures", cwd, file);
|
|
6125
|
+
loaded.push(label3(cwd, file.filePath, count));
|
|
6126
|
+
}
|
|
6127
|
+
return loaded;
|
|
6128
|
+
}
|
|
6129
|
+
async function clearFixtures(pb, cwd) {
|
|
6152
6130
|
const fixturePathByName = new Map(
|
|
6153
|
-
getFixtureFiles(
|
|
6131
|
+
getFixtureFiles(cwd).map((f) => [f.collectionName, f.filePath])
|
|
6154
6132
|
);
|
|
6155
6133
|
const cleared = [];
|
|
6156
6134
|
const fullList = await pb.collections.getFullList();
|
|
@@ -6165,9 +6143,8 @@ async function clearFixtures(pb, workspaceRootDir) {
|
|
|
6165
6143
|
const { names } = dependencyOrder(collections2);
|
|
6166
6144
|
const reversed = [...names].reverse();
|
|
6167
6145
|
for (const collectionName of reversed) {
|
|
6168
|
-
const shortName = collectionName.slice(0, 6);
|
|
6169
6146
|
const records = await pb.collection(collectionName).getFullList({
|
|
6170
|
-
filter:
|
|
6147
|
+
filter: fixtureFilter(collectionName),
|
|
6171
6148
|
fields: "id"
|
|
6172
6149
|
});
|
|
6173
6150
|
if (records.length === 0) continue;
|
|
@@ -6175,11 +6152,53 @@ async function clearFixtures(pb, workspaceRootDir) {
|
|
|
6175
6152
|
await pb.collection(collectionName).delete(id);
|
|
6176
6153
|
}
|
|
6177
6154
|
const fixturePath = fixturePathByName.get(collectionName);
|
|
6178
|
-
|
|
6179
|
-
|
|
6155
|
+
cleared.push(
|
|
6156
|
+
fixturePath ? label3(cwd, fixturePath, records.length) : `${collectionName} (${records.length} records)`
|
|
6157
|
+
);
|
|
6180
6158
|
}
|
|
6181
6159
|
return cleared;
|
|
6182
6160
|
}
|
|
6161
|
+
async function hasLoadedFixtures(pb) {
|
|
6162
|
+
const fullList = await pb.collections.getFullList();
|
|
6163
|
+
for (const collection of fullList) {
|
|
6164
|
+
if (collection.name.startsWith("_")) continue;
|
|
6165
|
+
const page = await pb.collection(collection.name).getList(1, 1, {
|
|
6166
|
+
filter: fixtureFilter(collection.name),
|
|
6167
|
+
fields: "id"
|
|
6168
|
+
});
|
|
6169
|
+
if (page.totalItems > 0) return true;
|
|
6170
|
+
}
|
|
6171
|
+
return false;
|
|
6172
|
+
}
|
|
6173
|
+
|
|
6174
|
+
// src/commands/fixtures/load.ts
|
|
6175
|
+
var load = new Command47("load").description("load fixtures into the database").configureHelp(helpConfig).action(
|
|
6176
|
+
() => runCommand(async () => {
|
|
6177
|
+
const { workspaceRootDir } = await getWorkspace();
|
|
6178
|
+
let loaded = [];
|
|
6179
|
+
await withPocketbase(workspaceRootDir, async (pb) => {
|
|
6180
|
+
loaded = await loadFixtures(pb, workspaceRootDir);
|
|
6181
|
+
});
|
|
6182
|
+
if (loaded.length === 0) {
|
|
6183
|
+
reportResult({
|
|
6184
|
+
summary: "No fixture files found in data/fixtures.",
|
|
6185
|
+
nextSteps: ["Run `vela fixtures generate` to create fixture files first."]
|
|
6186
|
+
});
|
|
6187
|
+
return;
|
|
6188
|
+
}
|
|
6189
|
+
reportResult({
|
|
6190
|
+
summary: `Loaded ${loaded.length} fixture file(s) into the database.`,
|
|
6191
|
+
recordsLoaded: loaded,
|
|
6192
|
+
nextSteps: [
|
|
6193
|
+
"Run `vela dev` to see the fixture data in the app.",
|
|
6194
|
+
"Run `vela fixtures clear` to remove the loaded fixture records."
|
|
6195
|
+
]
|
|
6196
|
+
});
|
|
6197
|
+
}, "Failed to load fixtures.")
|
|
6198
|
+
);
|
|
6199
|
+
|
|
6200
|
+
// src/commands/fixtures/clear.ts
|
|
6201
|
+
import { Command as Command48 } from "commander";
|
|
6183
6202
|
var clear = new Command48("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
|
|
6184
6203
|
() => runCommand(async () => {
|
|
6185
6204
|
const { workspaceRootDir } = await getWorkspace();
|
|
@@ -6240,8 +6259,8 @@ var reset = new Command49("reset").description("clear and reload fixtures").conf
|
|
|
6240
6259
|
);
|
|
6241
6260
|
|
|
6242
6261
|
// src/commands/fixtures/generate.ts
|
|
6243
|
-
import
|
|
6244
|
-
import
|
|
6262
|
+
import fs25 from "node:fs";
|
|
6263
|
+
import path24 from "node:path";
|
|
6245
6264
|
import { Command as Command50, InvalidArgumentError as InvalidArgumentError2 } from "commander";
|
|
6246
6265
|
import * as p27 from "@clack/prompts";
|
|
6247
6266
|
import { annotate } from "annotate-json-schema";
|
|
@@ -6267,19 +6286,6 @@ function parseSeed(value) {
|
|
|
6267
6286
|
}
|
|
6268
6287
|
return n;
|
|
6269
6288
|
}
|
|
6270
|
-
async function hasLoadedFixtures(pb) {
|
|
6271
|
-
const fullList = await pb.collections.getFullList();
|
|
6272
|
-
for (const collection of fullList) {
|
|
6273
|
-
if (collection.name.startsWith("_")) continue;
|
|
6274
|
-
const shortName = collection.name.slice(0, 6);
|
|
6275
|
-
const page = await pb.collection(collection.name).getList(1, 1, {
|
|
6276
|
-
filter: `id ~ "${FIXTURE_PREFIX}${shortName}%"`,
|
|
6277
|
-
fields: "id"
|
|
6278
|
-
});
|
|
6279
|
-
if (page.totalItems > 0) return true;
|
|
6280
|
-
}
|
|
6281
|
-
return false;
|
|
6282
|
-
}
|
|
6283
6289
|
async function loadCollections(pb) {
|
|
6284
6290
|
const list2 = await pb.collections.getFullList();
|
|
6285
6291
|
return list2.map((c) => ({
|
|
@@ -6290,10 +6296,10 @@ async function loadCollections(pb) {
|
|
|
6290
6296
|
}));
|
|
6291
6297
|
}
|
|
6292
6298
|
async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
6293
|
-
const fixturesDir =
|
|
6294
|
-
|
|
6295
|
-
for (const file of
|
|
6296
|
-
if (file.endsWith(".json"))
|
|
6299
|
+
const fixturesDir = dataDir(workspaceRootDir, "fixtures");
|
|
6300
|
+
fs25.mkdirSync(fixturesDir, { recursive: true });
|
|
6301
|
+
for (const file of fs25.readdirSync(fixturesDir)) {
|
|
6302
|
+
if (file.endsWith(".json")) fs25.unlinkSync(path24.join(fixturesDir, file));
|
|
6297
6303
|
}
|
|
6298
6304
|
if (opts.seed !== void 0) faker.seed(opts.seed);
|
|
6299
6305
|
const generator = createGenerator({
|
|
@@ -6304,8 +6310,11 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
|
6304
6310
|
const collections2 = await loadCollections(pb);
|
|
6305
6311
|
const eligible = collections2.filter((c) => !c.name.startsWith("_") && c.type !== "view");
|
|
6306
6312
|
const { ids } = dependencyOrder(eligible);
|
|
6313
|
+
const seedIds = readSeedIds(workspaceRootDir);
|
|
6307
6314
|
const recordIds = /* @__PURE__ */ new Map();
|
|
6308
|
-
|
|
6315
|
+
for (const collection of eligible) {
|
|
6316
|
+
recordIds.set(collection.id, [...seedIds.get(collection.name) ?? []]);
|
|
6317
|
+
}
|
|
6309
6318
|
const writtenFiles = [];
|
|
6310
6319
|
const warnings = [];
|
|
6311
6320
|
let fileIndex = 1;
|
|
@@ -6319,7 +6328,7 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
|
6319
6328
|
const target = collections2.find((c) => c.id === f.collectionId);
|
|
6320
6329
|
const targetLabel = target?.name ?? f.collectionId ?? "<unknown>";
|
|
6321
6330
|
warnings.push(
|
|
6322
|
-
`${collection.name}.${f.name} requires a ${targetLabel} record, but none
|
|
6331
|
+
`${collection.name}.${f.name} requires a ${targetLabel} record, but there are none in seeds or generated fixtures yet`
|
|
6323
6332
|
);
|
|
6324
6333
|
}
|
|
6325
6334
|
}
|
|
@@ -6357,8 +6366,8 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
|
6357
6366
|
items.push(record);
|
|
6358
6367
|
}
|
|
6359
6368
|
const filename = `${padZeros(fileIndex, 2)}-${collection.name}.json`;
|
|
6360
|
-
|
|
6361
|
-
writtenFiles.push(`${
|
|
6369
|
+
fs25.writeFileSync(path24.join(fixturesDir, filename), JSON.stringify(items, null, 2));
|
|
6370
|
+
writtenFiles.push(`${path24.join(DATA_DIR, "fixtures", filename)} (${items.length} records)`);
|
|
6362
6371
|
fileIndex++;
|
|
6363
6372
|
}
|
|
6364
6373
|
return { writtenFiles, warnings };
|
|
@@ -6467,19 +6476,7 @@ var fixtures = new Command52("fixtures").description("manage fixture data").conf
|
|
|
6467
6476
|
import { Command as Command56 } from "commander";
|
|
6468
6477
|
|
|
6469
6478
|
// src/commands/seeds/load.ts
|
|
6470
|
-
import fs27 from "node:fs";
|
|
6471
|
-
import path27 from "node:path";
|
|
6472
6479
|
import { Command as Command53 } from "commander";
|
|
6473
|
-
function getSeedFiles(cwd) {
|
|
6474
|
-
const seedsDir = path27.join(cwd, "data", "seeds");
|
|
6475
|
-
if (!fs27.existsSync(seedsDir)) return [];
|
|
6476
|
-
return fs27.readdirSync(seedsDir).filter((file) => file.endsWith(".json")).map((file) => path27.join(seedsDir, file)).sort((a, b) => a.localeCompare(b)).map((seedPath) => {
|
|
6477
|
-
const file = path27.basename(seedPath);
|
|
6478
|
-
const nameWithoutExt = file.replace(/\.json$/i, "");
|
|
6479
|
-
const collectionName = nameWithoutExt.replace(/^\d+[-_]?/, "");
|
|
6480
|
-
return { collectionName, seedPath };
|
|
6481
|
-
});
|
|
6482
|
-
}
|
|
6483
6480
|
var load2 = new Command53("load").description("load seeds into the database").option("-f, --force", "load even if target collections already have records").configureHelp(helpConfig).action(
|
|
6484
6481
|
(opts) => runCommand(async () => {
|
|
6485
6482
|
const { workspaceRootDir } = await getWorkspace();
|
|
@@ -6491,7 +6488,7 @@ var load2 = new Command53("load").description("load seeds into the database").op
|
|
|
6491
6488
|
});
|
|
6492
6489
|
return;
|
|
6493
6490
|
}
|
|
6494
|
-
|
|
6491
|
+
let loaded = [];
|
|
6495
6492
|
await withPocketbase(workspaceRootDir, async (pb) => {
|
|
6496
6493
|
if (!opts.force) {
|
|
6497
6494
|
for (const { collectionName } of seedFiles) {
|
|
@@ -6503,13 +6500,7 @@ var load2 = new Command53("load").description("load seeds into the database").op
|
|
|
6503
6500
|
}
|
|
6504
6501
|
}
|
|
6505
6502
|
}
|
|
6506
|
-
|
|
6507
|
-
const seeds2 = JSON.parse(fs27.readFileSync(seedPath, "utf8"));
|
|
6508
|
-
for (const seed of seeds2) {
|
|
6509
|
-
await pb.collection(collectionName).create(seed);
|
|
6510
|
-
}
|
|
6511
|
-
loaded.push(`${path27.relative(workspaceRootDir, seedPath)} (${seeds2.length} records)`);
|
|
6512
|
-
}
|
|
6503
|
+
loaded = await loadSeeds(pb, workspaceRootDir, seedFiles);
|
|
6513
6504
|
});
|
|
6514
6505
|
reportResult({
|
|
6515
6506
|
summary: `Loaded ${loaded.length} seed file(s) into the database.`,
|
|
@@ -6523,8 +6514,8 @@ var load2 = new Command53("load").description("load seeds into the database").op
|
|
|
6523
6514
|
);
|
|
6524
6515
|
|
|
6525
6516
|
// src/commands/seeds/save.ts
|
|
6526
|
-
import
|
|
6527
|
-
import
|
|
6517
|
+
import fs26 from "node:fs";
|
|
6518
|
+
import path25 from "node:path";
|
|
6528
6519
|
import { Command as Command54 } from "commander";
|
|
6529
6520
|
var padZeros2 = (num, length) => num.toString().padStart(length, "0");
|
|
6530
6521
|
function filterSystemFields(record, systemFieldNames) {
|
|
@@ -6539,15 +6530,15 @@ function filterSystemFields(record, systemFieldNames) {
|
|
|
6539
6530
|
var save = new Command54("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
|
|
6540
6531
|
(opts) => runCommand(async () => {
|
|
6541
6532
|
const { workspaceRootDir } = await getWorkspace();
|
|
6542
|
-
const seedsPath =
|
|
6533
|
+
const seedsPath = dataDir(workspaceRootDir, "seeds");
|
|
6543
6534
|
const existing = getSeedFiles(workspaceRootDir);
|
|
6544
6535
|
if (existing.length > 0 && !opts.force) {
|
|
6545
6536
|
throw new Error("Existing seed files found in data/seeds. Pass --force to overwrite.");
|
|
6546
6537
|
}
|
|
6547
|
-
|
|
6538
|
+
fs26.mkdirSync(seedsPath, { recursive: true });
|
|
6548
6539
|
if (opts.force) {
|
|
6549
|
-
for (const file of
|
|
6550
|
-
if (file.endsWith(".json"))
|
|
6540
|
+
for (const file of fs26.readdirSync(seedsPath)) {
|
|
6541
|
+
if (file.endsWith(".json")) fs26.unlinkSync(path25.join(seedsPath, file));
|
|
6551
6542
|
}
|
|
6552
6543
|
}
|
|
6553
6544
|
const saved = [];
|
|
@@ -6576,13 +6567,13 @@ var save = new Command54("save").description("save the current data as seeds").o
|
|
|
6576
6567
|
const filtered = records.map(
|
|
6577
6568
|
(r) => filterSystemFields(r, systemFieldNames)
|
|
6578
6569
|
);
|
|
6579
|
-
const relativeSeedPath =
|
|
6580
|
-
|
|
6570
|
+
const relativeSeedPath = path25.join(
|
|
6571
|
+
DATA_DIR,
|
|
6581
6572
|
"seeds",
|
|
6582
6573
|
`${padZeros2(count, 2)}-${collectionName}.json`
|
|
6583
6574
|
);
|
|
6584
|
-
const seedPath =
|
|
6585
|
-
|
|
6575
|
+
const seedPath = path25.join(workspaceRootDir, relativeSeedPath);
|
|
6576
|
+
fs26.writeFileSync(seedPath, JSON.stringify(filtered, null, 2));
|
|
6586
6577
|
saved.push(`${relativeSeedPath} (${filtered.length} records)`);
|
|
6587
6578
|
count++;
|
|
6588
6579
|
}
|
|
@@ -6608,20 +6599,7 @@ var save = new Command54("save").description("save the current data as seeds").o
|
|
|
6608
6599
|
);
|
|
6609
6600
|
|
|
6610
6601
|
// src/commands/seeds/clear.ts
|
|
6611
|
-
import fs29 from "node:fs";
|
|
6612
|
-
import path29 from "node:path";
|
|
6613
6602
|
import { Command as Command55 } from "commander";
|
|
6614
|
-
async function clearSeeds(pb, workspaceRootDir, seedFiles) {
|
|
6615
|
-
const cleared = [];
|
|
6616
|
-
for (const { collectionName, seedPath } of seedFiles) {
|
|
6617
|
-
const seeds2 = JSON.parse(fs29.readFileSync(seedPath, "utf8"));
|
|
6618
|
-
for (const { id } of seeds2) {
|
|
6619
|
-
await pb.collection(collectionName).delete(id);
|
|
6620
|
-
}
|
|
6621
|
-
cleared.push(`${path29.relative(workspaceRootDir, seedPath)} (${seeds2.length} records)`);
|
|
6622
|
-
}
|
|
6623
|
-
return cleared;
|
|
6624
|
-
}
|
|
6625
6603
|
var clear2 = new Command55("clear").description("clear seeded records").configureHelp(helpConfig).action(
|
|
6626
6604
|
() => runCommand(async () => {
|
|
6627
6605
|
const { workspaceRootDir } = await getWorkspace();
|
|
@@ -6695,14 +6673,14 @@ var login = new Command57("login").description("login to velastack.dev").configu
|
|
|
6695
6673
|
}, "Failed to login.")
|
|
6696
6674
|
);
|
|
6697
6675
|
async function issueApiKey(fetchCookie) {
|
|
6698
|
-
const
|
|
6676
|
+
const label4 = `CLI - ${os3.hostname()}`;
|
|
6699
6677
|
await fetchCookie(`${API_URL}/api-keys/new`, {
|
|
6700
6678
|
method: "POST",
|
|
6701
6679
|
headers: {
|
|
6702
6680
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
6703
6681
|
Origin: API_URL
|
|
6704
6682
|
},
|
|
6705
|
-
body: new URLSearchParams({ label:
|
|
6683
|
+
body: new URLSearchParams({ label: label4 }).toString()
|
|
6706
6684
|
});
|
|
6707
6685
|
const cookie = await fetchCookie.cookieJar.getCookieString(API_URL);
|
|
6708
6686
|
const apiKey = extractApiKey(cookie);
|
|
@@ -6715,7 +6693,7 @@ async function issueApiKey(fetchCookie) {
|
|
|
6715
6693
|
});
|
|
6716
6694
|
const data = await res.json();
|
|
6717
6695
|
for (const item of data.items) {
|
|
6718
|
-
if (item.label ===
|
|
6696
|
+
if (item.label === label4 && item.id !== id) {
|
|
6719
6697
|
await fetchCookie(`${API_URL}/api/collections/api_keys/records/${item.id}`, {
|
|
6720
6698
|
method: "DELETE",
|
|
6721
6699
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
@@ -6806,20 +6784,20 @@ import { Command as Command66 } from "commander";
|
|
|
6806
6784
|
import { Command as Command61 } from "commander";
|
|
6807
6785
|
|
|
6808
6786
|
// src/lib/migrate.ts
|
|
6809
|
-
import
|
|
6810
|
-
import
|
|
6787
|
+
import path26 from "node:path";
|
|
6788
|
+
import process17 from "node:process";
|
|
6811
6789
|
import { x as x2 } from "tinyexec";
|
|
6812
6790
|
async function runPocketbaseMigrate(args) {
|
|
6813
|
-
const cwd =
|
|
6791
|
+
const cwd = process17.cwd();
|
|
6814
6792
|
const { getBinaryPath } = await import("pocketbase-server");
|
|
6815
6793
|
const binaryPath = getBinaryPath();
|
|
6816
6794
|
await x2(
|
|
6817
6795
|
binaryPath,
|
|
6818
6796
|
[
|
|
6819
6797
|
"--dir",
|
|
6820
|
-
|
|
6798
|
+
path26.join(cwd, DATA_DIR),
|
|
6821
6799
|
"--migrationsDir",
|
|
6822
|
-
|
|
6800
|
+
path26.join(cwd, MIGRATIONS_DIR),
|
|
6823
6801
|
"migrate",
|
|
6824
6802
|
...args
|
|
6825
6803
|
],
|
|
@@ -6867,20 +6845,20 @@ var down = new Command62("down").alias("rollback").description("revert the last
|
|
|
6867
6845
|
);
|
|
6868
6846
|
|
|
6869
6847
|
// src/commands/migrate/create.ts
|
|
6870
|
-
import
|
|
6871
|
-
import
|
|
6872
|
-
import
|
|
6848
|
+
import fs27 from "node:fs";
|
|
6849
|
+
import path27 from "node:path";
|
|
6850
|
+
import process18 from "node:process";
|
|
6873
6851
|
import { Command as Command63 } from "commander";
|
|
6874
6852
|
var create2 = new Command63("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
|
|
6875
6853
|
(name) => runCommand(async () => {
|
|
6876
|
-
const cwd =
|
|
6854
|
+
const cwd = process18.cwd();
|
|
6877
6855
|
const before = listMigrationFiles(cwd);
|
|
6878
6856
|
await runPocketbaseMigrate(["create", name]);
|
|
6879
6857
|
const after = listMigrationFiles(cwd);
|
|
6880
6858
|
const added = [...after].filter((f) => !before.has(f));
|
|
6881
6859
|
reportResult({
|
|
6882
6860
|
summary: `Created blank migration ${name}.`,
|
|
6883
|
-
filesCreated: added.map((f) =>
|
|
6861
|
+
filesCreated: added.map((f) => path27.join(MIGRATIONS_DIR, f)),
|
|
6884
6862
|
nextSteps: [
|
|
6885
6863
|
`Open the new file in ${MIGRATIONS_DIR}/ and fill in the up/down handlers.`,
|
|
6886
6864
|
"Run `vela migrate up` to apply the migration once the handlers are written."
|
|
@@ -6889,19 +6867,19 @@ var create2 = new Command63("create").alias("new").description("create a new bla
|
|
|
6889
6867
|
}, "Failed to create migration.")
|
|
6890
6868
|
);
|
|
6891
6869
|
function listMigrationFiles(cwd) {
|
|
6892
|
-
const dir =
|
|
6893
|
-
if (!
|
|
6894
|
-
return new Set(
|
|
6870
|
+
const dir = path27.join(cwd, MIGRATIONS_DIR);
|
|
6871
|
+
if (!fs27.existsSync(dir)) return /* @__PURE__ */ new Set();
|
|
6872
|
+
return new Set(fs27.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
|
|
6895
6873
|
}
|
|
6896
6874
|
|
|
6897
6875
|
// src/commands/migrate/collections.ts
|
|
6898
|
-
import
|
|
6899
|
-
import
|
|
6900
|
-
import
|
|
6876
|
+
import fs28 from "node:fs";
|
|
6877
|
+
import path28 from "node:path";
|
|
6878
|
+
import process19 from "node:process";
|
|
6901
6879
|
import { Command as Command64 } from "commander";
|
|
6902
6880
|
var collections = new Command64("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
|
|
6903
6881
|
() => runCommand(async () => {
|
|
6904
|
-
const cwd =
|
|
6882
|
+
const cwd = process19.cwd();
|
|
6905
6883
|
const before = listMigrationFiles2(cwd);
|
|
6906
6884
|
await runPocketbaseMigrate(["collections"]);
|
|
6907
6885
|
const after = listMigrationFiles2(cwd);
|
|
@@ -6914,7 +6892,7 @@ var collections = new Command64("collections").alias("snapshot").description("sn
|
|
|
6914
6892
|
}
|
|
6915
6893
|
reportResult({
|
|
6916
6894
|
summary: "Snapshotted local collections into a new migration.",
|
|
6917
|
-
filesCreated: added.map((f) =>
|
|
6895
|
+
filesCreated: added.map((f) => path28.join(MIGRATIONS_DIR, f)),
|
|
6918
6896
|
nextSteps: [
|
|
6919
6897
|
`Review the generated snapshot in ${MIGRATIONS_DIR}/.`,
|
|
6920
6898
|
"Commit the snapshot so teammates pick up the new schema.",
|
|
@@ -6924,9 +6902,9 @@ var collections = new Command64("collections").alias("snapshot").description("sn
|
|
|
6924
6902
|
}, "Failed to snapshot collections.")
|
|
6925
6903
|
);
|
|
6926
6904
|
function listMigrationFiles2(cwd) {
|
|
6927
|
-
const dir =
|
|
6928
|
-
if (!
|
|
6929
|
-
return new Set(
|
|
6905
|
+
const dir = path28.join(cwd, MIGRATIONS_DIR);
|
|
6906
|
+
if (!fs28.existsSync(dir)) return /* @__PURE__ */ new Set();
|
|
6907
|
+
return new Set(fs28.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
|
|
6930
6908
|
}
|
|
6931
6909
|
|
|
6932
6910
|
// src/commands/migrate/history-sync.ts
|
|
@@ -6945,17 +6923,17 @@ var historySync = new Command65("history-sync").description("drop _migrations ro
|
|
|
6945
6923
|
var migrate = new Command66("migrate").description("manage database migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations.")).addCommand(up).addCommand(down).addCommand(create2).addCommand(collections).addCommand(historySync);
|
|
6946
6924
|
|
|
6947
6925
|
// src/commands/dev.ts
|
|
6948
|
-
import
|
|
6949
|
-
import
|
|
6950
|
-
import
|
|
6926
|
+
import fs29 from "node:fs";
|
|
6927
|
+
import path30 from "node:path";
|
|
6928
|
+
import process21 from "node:process";
|
|
6951
6929
|
import { performance } from "node:perf_hooks";
|
|
6952
6930
|
import { Command as Command67, InvalidArgumentError as InvalidArgumentError5 } from "commander";
|
|
6953
6931
|
import pc13 from "picocolors";
|
|
6954
|
-
import
|
|
6932
|
+
import PocketBase4 from "pocketbase";
|
|
6955
6933
|
|
|
6956
6934
|
// src/lib/vite.ts
|
|
6957
|
-
import
|
|
6958
|
-
import
|
|
6935
|
+
import path29 from "node:path";
|
|
6936
|
+
import process20 from "node:process";
|
|
6959
6937
|
import { createRequire as createRequire2 } from "node:module";
|
|
6960
6938
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
6961
6939
|
import pc12 from "picocolors";
|
|
@@ -6974,18 +6952,18 @@ function viteVersionError(version) {
|
|
|
6974
6952
|
}
|
|
6975
6953
|
function resolveProjectVite(cwd) {
|
|
6976
6954
|
try {
|
|
6977
|
-
return createRequire2(
|
|
6955
|
+
return createRequire2(path29.join(cwd, "package.json")).resolve("vite");
|
|
6978
6956
|
} catch {
|
|
6979
6957
|
return null;
|
|
6980
6958
|
}
|
|
6981
6959
|
}
|
|
6982
|
-
async function loadVite(cwd =
|
|
6960
|
+
async function loadVite(cwd = process20.cwd()) {
|
|
6983
6961
|
const entry = resolveProjectVite(cwd);
|
|
6984
6962
|
const vite = entry ? await import(pathToFileURL2(entry).href) : await import("vite");
|
|
6985
6963
|
const error = viteVersionError(vite.version);
|
|
6986
6964
|
if (error) {
|
|
6987
6965
|
console.error(`${pc12.redBright("\u2717")} ${error}`);
|
|
6988
|
-
|
|
6966
|
+
process20.exit(1);
|
|
6989
6967
|
}
|
|
6990
6968
|
return vite;
|
|
6991
6969
|
}
|
|
@@ -6999,38 +6977,38 @@ function parsePort(value) {
|
|
|
6999
6977
|
return port;
|
|
7000
6978
|
}
|
|
7001
6979
|
var dev = new Command67("dev").description("start the development server").option("--open [path]", "open the app in a browser once the server is ready").option("--host [host]", "expose the server on the network").option("--port <port>", "port to listen on", parsePort).option("--strictPort", "exit if the port is already in use instead of taking the next one").option("--cors", "enable CORS").option("--force", "re-bundle dependencies, ignoring the optimizer cache").configureHelp(helpConfig).action(async (options) => {
|
|
7002
|
-
const cwd =
|
|
7003
|
-
|
|
6980
|
+
const cwd = process21.cwd();
|
|
6981
|
+
process21.env.VELA_DATA_DIR ??= localDataDir(cwd);
|
|
7004
6982
|
const startTime = performance.now();
|
|
7005
6983
|
const { createServer, version } = await loadVite(cwd);
|
|
7006
|
-
const viteMetadataDir =
|
|
7007
|
-
const viteMetadataFile =
|
|
6984
|
+
const viteMetadataDir = path30.join(cwd, "node_modules", ".vite");
|
|
6985
|
+
const viteMetadataFile = path30.join(viteMetadataDir, "_pocketbase_metadata.json");
|
|
7008
6986
|
let pbProc;
|
|
7009
6987
|
const backend3 = hasBackend(cwd);
|
|
7010
|
-
const needsStart = backend3 && !
|
|
6988
|
+
const needsStart = backend3 && !process21.env.POCKETBASE_URL;
|
|
7011
6989
|
const cleanup = () => {
|
|
7012
6990
|
if (pbProc?.pid) pbProc.kill();
|
|
7013
|
-
if (
|
|
6991
|
+
if (fs29.existsSync(viteMetadataFile)) fs29.rmSync(viteMetadataFile);
|
|
7014
6992
|
};
|
|
7015
6993
|
if (needsStart) {
|
|
7016
|
-
const
|
|
6994
|
+
const dataDir2 = path30.join(cwd, DATA_DIR);
|
|
7017
6995
|
const started = await startPocketbaseServe({
|
|
7018
|
-
dataDir,
|
|
6996
|
+
dataDir: dataDir2,
|
|
7019
6997
|
migrationsDir: MIGRATIONS_DIR,
|
|
7020
|
-
hooksDir:
|
|
6998
|
+
hooksDir: path30.join(dataDir2, "hooks"),
|
|
7021
6999
|
dev: true,
|
|
7022
7000
|
stdio: "pipe"
|
|
7023
7001
|
});
|
|
7024
7002
|
pbProc = started.proc;
|
|
7025
|
-
|
|
7026
|
-
pbProc.stdout?.pipe(
|
|
7027
|
-
pbProc.stderr?.pipe(
|
|
7003
|
+
process21.env.POCKETBASE_URL = started.url;
|
|
7004
|
+
pbProc.stdout?.pipe(process21.stdout);
|
|
7005
|
+
pbProc.stderr?.pipe(process21.stderr);
|
|
7028
7006
|
pbProc.on("error", (err) => console.error("PocketBase error:", err));
|
|
7029
7007
|
pbProc.on("exit", (code) => console.log(`PocketBase exited with code ${code}`));
|
|
7030
|
-
|
|
7031
|
-
|
|
7008
|
+
process21.on("exit", cleanup);
|
|
7009
|
+
process21.on("SIGINT", () => {
|
|
7032
7010
|
cleanup();
|
|
7033
|
-
|
|
7011
|
+
process21.exit(0);
|
|
7034
7012
|
});
|
|
7035
7013
|
}
|
|
7036
7014
|
const serverOptions = {};
|
|
@@ -7048,25 +7026,25 @@ var dev = new Command67("dev").description("start the development server").optio
|
|
|
7048
7026
|
if (!backend3) return;
|
|
7049
7027
|
const { address, port: vitePort } = server.httpServer.address();
|
|
7050
7028
|
const viteHost = address === "::1" ? "localhost" : address;
|
|
7051
|
-
await
|
|
7052
|
-
await
|
|
7029
|
+
await fs29.promises.mkdir(viteMetadataDir, { recursive: true });
|
|
7030
|
+
await fs29.promises.writeFile(
|
|
7053
7031
|
viteMetadataFile,
|
|
7054
7032
|
JSON.stringify({
|
|
7055
|
-
pocketbaseUrl:
|
|
7033
|
+
pocketbaseUrl: process21.env.POCKETBASE_URL,
|
|
7056
7034
|
vitePort,
|
|
7057
7035
|
viteHost
|
|
7058
7036
|
})
|
|
7059
7037
|
);
|
|
7060
|
-
const pb = new
|
|
7038
|
+
const pb = new PocketBase4(process21.env.POCKETBASE_URL);
|
|
7061
7039
|
await pb.collection("_superusers").authWithPassword(
|
|
7062
|
-
|
|
7063
|
-
|
|
7040
|
+
process21.env.POCKETBASE_SUPERUSER_EMAIL,
|
|
7041
|
+
process21.env.POCKETBASE_SUPERUSER_PASSWORD
|
|
7064
7042
|
);
|
|
7065
7043
|
await pb.settings.update({ meta: { appURL: `http://${viteHost}:${vitePort}` } });
|
|
7066
7044
|
await startWatchingTypes(cwd, pb);
|
|
7067
7045
|
});
|
|
7068
7046
|
await server.listen();
|
|
7069
|
-
const hasExistingLogs =
|
|
7047
|
+
const hasExistingLogs = process21.stdout.bytesWritten > 0 || process21.stderr.bytesWritten > 0;
|
|
7070
7048
|
const startupDurationString = pc13.dim(
|
|
7071
7049
|
`ready in ${pc13.reset(pc13.bold(Math.ceil(performance.now() - startTime)))} ms`
|
|
7072
7050
|
);
|
|
@@ -7081,18 +7059,18 @@ var dev = new Command67("dev").description("start the development server").optio
|
|
|
7081
7059
|
});
|
|
7082
7060
|
async function startWatchingTypes(cwd, pb) {
|
|
7083
7061
|
const { processTypes } = await import("@velastack/pocketbase-codegen");
|
|
7084
|
-
const typesDir =
|
|
7085
|
-
const pocketbaseDir =
|
|
7086
|
-
const pocketbaseTypes =
|
|
7062
|
+
const typesDir = path30.resolve(cwd, ".svelte-kit", "types");
|
|
7063
|
+
const pocketbaseDir = path30.join(typesDir, "pocketbase");
|
|
7064
|
+
const pocketbaseTypes = path30.join(pocketbaseDir, "$types.d.ts");
|
|
7087
7065
|
const regenerate = () => processTypes(pb, typesDir).catch(() => {
|
|
7088
7066
|
});
|
|
7089
7067
|
await regenerate();
|
|
7090
7068
|
void (async () => {
|
|
7091
7069
|
for (; ; ) {
|
|
7092
7070
|
try {
|
|
7093
|
-
await
|
|
7094
|
-
for await (const event of
|
|
7095
|
-
if (event.eventType === "rename" && event.filename === "$types.d.ts" && !
|
|
7071
|
+
await fs29.promises.mkdir(pocketbaseDir, { recursive: true });
|
|
7072
|
+
for await (const event of fs29.promises.watch(pocketbaseDir)) {
|
|
7073
|
+
if (event.eventType === "rename" && event.filename === "$types.d.ts" && !fs29.existsSync(pocketbaseTypes)) {
|
|
7096
7074
|
setTimeout(regenerate, 100);
|
|
7097
7075
|
}
|
|
7098
7076
|
}
|
|
@@ -7104,9 +7082,9 @@ async function startWatchingTypes(cwd, pb) {
|
|
|
7104
7082
|
}
|
|
7105
7083
|
|
|
7106
7084
|
// src/commands/build.ts
|
|
7107
|
-
import
|
|
7108
|
-
import
|
|
7109
|
-
import
|
|
7085
|
+
import fs30 from "node:fs";
|
|
7086
|
+
import path31 from "node:path";
|
|
7087
|
+
import process23 from "node:process";
|
|
7110
7088
|
import { Command as Command68 } from "commander";
|
|
7111
7089
|
import * as p33 from "@clack/prompts";
|
|
7112
7090
|
import pc14 from "picocolors";
|
|
@@ -7121,10 +7099,10 @@ function applyBuildEnv(cwd, env2 = process.env) {
|
|
|
7121
7099
|
}
|
|
7122
7100
|
|
|
7123
7101
|
// src/lib/origin.ts
|
|
7124
|
-
import
|
|
7102
|
+
import process22 from "node:process";
|
|
7125
7103
|
function resolveOrigin(workspaceRootDir, envTag, config = {}) {
|
|
7126
7104
|
return normalizeOrigin(
|
|
7127
|
-
|
|
7105
|
+
process22.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
|
|
7128
7106
|
);
|
|
7129
7107
|
}
|
|
7130
7108
|
function normalizeOrigin(value) {
|
|
@@ -7140,32 +7118,32 @@ function normalizeOrigin(value) {
|
|
|
7140
7118
|
}
|
|
7141
7119
|
|
|
7142
7120
|
// src/commands/build.ts
|
|
7143
|
-
var PRERENDERED_DIR =
|
|
7121
|
+
var PRERENDERED_DIR = path31.join(".svelte-kit", "output", "prerendered");
|
|
7144
7122
|
var build = new Command68("build").description("build the app").configureHelp(helpConfig).option("-t, --target <target>", "which copy of the app to build for", PRODUCTION_TARGET).action(async (options) => {
|
|
7145
|
-
const cwd =
|
|
7123
|
+
const cwd = process23.cwd();
|
|
7146
7124
|
applyBuildEnv(cwd);
|
|
7147
7125
|
const origin = await originForBuild(cwd, options.target);
|
|
7148
|
-
if (origin)
|
|
7126
|
+
if (origin) process23.env.VELA_ORIGIN = origin;
|
|
7149
7127
|
let pbProc;
|
|
7150
|
-
const needsStart = hasBackend(cwd) && !
|
|
7128
|
+
const needsStart = hasBackend(cwd) && !process23.env.POCKETBASE_URL;
|
|
7151
7129
|
const cleanup = () => {
|
|
7152
7130
|
if (pbProc?.pid) pbProc.kill();
|
|
7153
7131
|
};
|
|
7154
7132
|
if (needsStart) {
|
|
7155
7133
|
await ensureSuperuser(cwd);
|
|
7156
|
-
const
|
|
7134
|
+
const dataDir2 = path31.join(cwd, DATA_DIR);
|
|
7157
7135
|
const started = await startPocketbaseServe({
|
|
7158
|
-
dataDir,
|
|
7136
|
+
dataDir: dataDir2,
|
|
7159
7137
|
migrationsDir: MIGRATIONS_DIR,
|
|
7160
|
-
hooksDir:
|
|
7138
|
+
hooksDir: path31.join(dataDir2, "hooks"),
|
|
7161
7139
|
dev: true
|
|
7162
7140
|
});
|
|
7163
7141
|
pbProc = started.proc;
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7142
|
+
process23.env.POCKETBASE_URL = started.url;
|
|
7143
|
+
process23.on("exit", cleanup);
|
|
7144
|
+
process23.on("SIGINT", () => {
|
|
7167
7145
|
cleanup();
|
|
7168
|
-
|
|
7146
|
+
process23.exit(0);
|
|
7169
7147
|
});
|
|
7170
7148
|
}
|
|
7171
7149
|
try {
|
|
@@ -7195,8 +7173,8 @@ async function originForBuild(cwd, target) {
|
|
|
7195
7173
|
}
|
|
7196
7174
|
}
|
|
7197
7175
|
function warnIfPrerendered(cwd) {
|
|
7198
|
-
const dir =
|
|
7199
|
-
if (!
|
|
7176
|
+
const dir = path31.join(cwd, PRERENDERED_DIR);
|
|
7177
|
+
if (!fs30.existsSync(dir) || fs30.readdirSync(dir).length === 0) return;
|
|
7200
7178
|
p33.log.warn(
|
|
7201
7179
|
`Prerendered pages were built with no domain configured, so their canonical
|
|
7202
7180
|
links point at SvelteKit's placeholder host rather than at this site.
|
|
@@ -7206,34 +7184,34 @@ Set one with ${pc14.cyan("vela deploy --domain example.com")}, or pass ${pc14.cy
|
|
|
7206
7184
|
}
|
|
7207
7185
|
|
|
7208
7186
|
// src/commands/preview.ts
|
|
7209
|
-
import
|
|
7210
|
-
import
|
|
7187
|
+
import path32 from "node:path";
|
|
7188
|
+
import process24 from "node:process";
|
|
7211
7189
|
import { Command as Command69 } from "commander";
|
|
7212
7190
|
import { x as x4 } from "tinyexec";
|
|
7213
7191
|
import { detect as detect6 } from "package-manager-detector";
|
|
7214
7192
|
import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
|
|
7215
7193
|
var preview = new Command69("preview").description("preview the built app").configureHelp(helpConfig).action(async () => {
|
|
7216
|
-
const cwd =
|
|
7217
|
-
|
|
7194
|
+
const cwd = process24.cwd();
|
|
7195
|
+
process24.env.VELA_DATA_DIR ??= localDataDir(cwd);
|
|
7218
7196
|
let pbProc;
|
|
7219
|
-
const needsStart = hasBackend(cwd) && !
|
|
7197
|
+
const needsStart = hasBackend(cwd) && !process24.env.POCKETBASE_URL;
|
|
7220
7198
|
const cleanup = () => {
|
|
7221
7199
|
if (pbProc?.pid) pbProc.kill();
|
|
7222
7200
|
};
|
|
7223
7201
|
if (needsStart) {
|
|
7224
|
-
const
|
|
7202
|
+
const dataDir2 = path32.join(cwd, DATA_DIR);
|
|
7225
7203
|
const started = await startPocketbaseServe({
|
|
7226
|
-
dataDir,
|
|
7204
|
+
dataDir: dataDir2,
|
|
7227
7205
|
migrationsDir: MIGRATIONS_DIR,
|
|
7228
|
-
hooksDir:
|
|
7206
|
+
hooksDir: path32.join(dataDir2, "hooks"),
|
|
7229
7207
|
dev: true
|
|
7230
7208
|
});
|
|
7231
7209
|
pbProc = started.proc;
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7210
|
+
process24.env.POCKETBASE_URL = started.url;
|
|
7211
|
+
process24.on("exit", cleanup);
|
|
7212
|
+
process24.on("SIGINT", () => {
|
|
7235
7213
|
cleanup();
|
|
7236
|
-
|
|
7214
|
+
process24.exit(0);
|
|
7237
7215
|
});
|
|
7238
7216
|
}
|
|
7239
7217
|
try {
|
|
@@ -7251,12 +7229,12 @@ var preview = new Command69("preview").description("preview the built app").conf
|
|
|
7251
7229
|
});
|
|
7252
7230
|
|
|
7253
7231
|
// src/commands/sync.ts
|
|
7254
|
-
import
|
|
7232
|
+
import path33 from "node:path";
|
|
7255
7233
|
import { Command as Command70 } from "commander";
|
|
7256
7234
|
var sync = new Command70("sync").description("sync types from the database").configureHelp(helpConfig).action(
|
|
7257
7235
|
() => runCommand(async () => {
|
|
7258
7236
|
const { workspaceRootDir } = await getWorkspace();
|
|
7259
|
-
const typesDir =
|
|
7237
|
+
const typesDir = path33.join(workspaceRootDir, ".svelte-kit", "types");
|
|
7260
7238
|
const { processTypes } = await import("@velastack/pocketbase-codegen");
|
|
7261
7239
|
await withPocketbase(workspaceRootDir, async (pb) => {
|
|
7262
7240
|
await processTypes(pb, typesDir);
|
|
@@ -7318,34 +7296,34 @@ var provision = addSshOptions(
|
|
|
7318
7296
|
);
|
|
7319
7297
|
|
|
7320
7298
|
// src/commands/deploy.ts
|
|
7321
|
-
import
|
|
7322
|
-
import
|
|
7299
|
+
import path36 from "node:path";
|
|
7300
|
+
import fs33 from "node:fs";
|
|
7323
7301
|
import { Command as Command72, Option as Option2 } from "commander";
|
|
7324
7302
|
import * as p35 from "@clack/prompts";
|
|
7325
7303
|
import pc16 from "picocolors";
|
|
7326
7304
|
import * as v7 from "valibot";
|
|
7327
7305
|
|
|
7328
7306
|
// src/lib/pocketbase-settings.ts
|
|
7329
|
-
import
|
|
7330
|
-
import
|
|
7331
|
-
import
|
|
7332
|
-
import
|
|
7307
|
+
import fs31 from "node:fs";
|
|
7308
|
+
import path34 from "node:path";
|
|
7309
|
+
import process25 from "node:process";
|
|
7310
|
+
import PocketBase5 from "pocketbase";
|
|
7333
7311
|
var COPIED_KEYS = ["appName", "senderName", "senderAddress"];
|
|
7334
7312
|
async function readLocalMeta(cwd) {
|
|
7335
|
-
const
|
|
7336
|
-
if (!
|
|
7337
|
-
const email3 =
|
|
7338
|
-
const password11 =
|
|
7313
|
+
const dataDir2 = path34.join(cwd, DATA_DIR);
|
|
7314
|
+
if (!fs31.existsSync(dataDir2)) return null;
|
|
7315
|
+
const email3 = process25.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
7316
|
+
const password11 = process25.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
7339
7317
|
if (!email3 || !password11) return null;
|
|
7340
7318
|
let proc;
|
|
7341
7319
|
try {
|
|
7342
7320
|
const started = await startPocketbaseServe({
|
|
7343
|
-
dataDir,
|
|
7321
|
+
dataDir: dataDir2,
|
|
7344
7322
|
migrationsDir: MIGRATIONS_DIR,
|
|
7345
|
-
hooksDir:
|
|
7323
|
+
hooksDir: path34.join(dataDir2, "hooks")
|
|
7346
7324
|
});
|
|
7347
7325
|
proc = started.proc;
|
|
7348
|
-
const pb = new
|
|
7326
|
+
const pb = new PocketBase5(started.url);
|
|
7349
7327
|
await authWithRetries(pb, email3, password11);
|
|
7350
7328
|
const settings = await pb.settings.getAll();
|
|
7351
7329
|
return settings.meta ?? null;
|
|
@@ -7384,8 +7362,8 @@ async function seedRemoteMeta(session, instance, local, appURL) {
|
|
|
7384
7362
|
}
|
|
7385
7363
|
|
|
7386
7364
|
// src/lib/artifact.ts
|
|
7387
|
-
import
|
|
7388
|
-
import
|
|
7365
|
+
import fs32 from "node:fs";
|
|
7366
|
+
import path35 from "node:path";
|
|
7389
7367
|
import { detect as detect7 } from "package-manager-detector";
|
|
7390
7368
|
import { resolveCommand as resolveCommand7 } from "package-manager-detector/commands";
|
|
7391
7369
|
var DEFAULT_OUTPUT_DIR = "build";
|
|
@@ -7422,11 +7400,11 @@ function collectArtifact(cwd, config = {}) {
|
|
|
7422
7400
|
const outputDir = config.outputDir ?? DEFAULT_OUTPUT_DIR;
|
|
7423
7401
|
const entries = [];
|
|
7424
7402
|
const add2 = (rel, remoteDir = "") => {
|
|
7425
|
-
const localPath =
|
|
7426
|
-
if (
|
|
7403
|
+
const localPath = path35.join(cwd, rel);
|
|
7404
|
+
if (fs32.existsSync(localPath)) entries.push({ localPath, remoteDir });
|
|
7427
7405
|
};
|
|
7428
|
-
const buildPath =
|
|
7429
|
-
if (!
|
|
7406
|
+
const buildPath = path35.join(cwd, outputDir);
|
|
7407
|
+
if (!fs32.existsSync(path35.join(buildPath, "index.js"))) {
|
|
7430
7408
|
throw new BuildError(
|
|
7431
7409
|
`No ${outputDir}/index.js after the build.
|
|
7432
7410
|
|
|
@@ -7439,8 +7417,8 @@ the adapter in your Vite or Svelte config, then build again.`
|
|
|
7439
7417
|
add2("package-lock.json");
|
|
7440
7418
|
add2(".npmrc");
|
|
7441
7419
|
add2(MIGRATIONS_DIR);
|
|
7442
|
-
const hooks =
|
|
7443
|
-
if (
|
|
7420
|
+
const hooks = path35.join(cwd, DATA_DIR, "hooks");
|
|
7421
|
+
if (fs32.existsSync(hooks)) entries.push({ localPath: hooks, remoteDir: "hooks" });
|
|
7444
7422
|
for (const extra of config.include ?? []) add2(extra);
|
|
7445
7423
|
return entries;
|
|
7446
7424
|
}
|
|
@@ -7705,7 +7683,7 @@ async function uploadRelease(session, instance, release, entries) {
|
|
|
7705
7683
|
}
|
|
7706
7684
|
function isDirectory(target) {
|
|
7707
7685
|
try {
|
|
7708
|
-
return
|
|
7686
|
+
return fs33.statSync(target).isDirectory();
|
|
7709
7687
|
} catch {
|
|
7710
7688
|
return false;
|
|
7711
7689
|
}
|
|
@@ -7713,7 +7691,7 @@ function isDirectory(target) {
|
|
|
7713
7691
|
async function reportEmptyEnvironment(session, instance, workspaceRootDir) {
|
|
7714
7692
|
const remote = await readRemoteEnv(session, instance);
|
|
7715
7693
|
if (Object.keys(remote).length > 0) return;
|
|
7716
|
-
if (!
|
|
7694
|
+
if (!fs33.existsSync(path36.join(workspaceRootDir, ".env"))) return;
|
|
7717
7695
|
p35.log.warn(
|
|
7718
7696
|
`This app has no production environment variables yet.
|
|
7719
7697
|
|
|
@@ -7723,8 +7701,8 @@ ${pc16.cyan("vela env set KEY")}, or copy a file across with ${pc16.cyan("vela e
|
|
|
7723
7701
|
}
|
|
7724
7702
|
|
|
7725
7703
|
// src/commands/link.ts
|
|
7726
|
-
import
|
|
7727
|
-
import
|
|
7704
|
+
import path37 from "node:path";
|
|
7705
|
+
import process26 from "node:process";
|
|
7728
7706
|
import { Command as Command73 } from "commander";
|
|
7729
7707
|
import * as p36 from "@clack/prompts";
|
|
7730
7708
|
|
|
@@ -7824,7 +7802,7 @@ async function pickExistingProject(projects) {
|
|
|
7824
7802
|
});
|
|
7825
7803
|
if (p36.isCancel(choice)) {
|
|
7826
7804
|
p36.cancel("Operation cancelled.");
|
|
7827
|
-
|
|
7805
|
+
process26.exit(0);
|
|
7828
7806
|
}
|
|
7829
7807
|
return choice;
|
|
7830
7808
|
}
|
|
@@ -7839,7 +7817,7 @@ async function pickTeam(teams3) {
|
|
|
7839
7817
|
});
|
|
7840
7818
|
if (p36.isCancel(choice)) {
|
|
7841
7819
|
p36.cancel("Operation cancelled.");
|
|
7842
|
-
|
|
7820
|
+
process26.exit(0);
|
|
7843
7821
|
}
|
|
7844
7822
|
return teams3.find((team) => team.id === choice);
|
|
7845
7823
|
}
|
|
@@ -7854,18 +7832,18 @@ async function promptProjectName(workspaceRootDir) {
|
|
|
7854
7832
|
});
|
|
7855
7833
|
if (p36.isCancel(value)) {
|
|
7856
7834
|
p36.cancel("Operation cancelled.");
|
|
7857
|
-
|
|
7835
|
+
process26.exit(0);
|
|
7858
7836
|
}
|
|
7859
7837
|
return value.trim();
|
|
7860
7838
|
}
|
|
7861
7839
|
function defaultProjectName2(workspaceRootDir) {
|
|
7862
7840
|
try {
|
|
7863
|
-
const pkg = readPackageJson(
|
|
7841
|
+
const pkg = readPackageJson(path37.join(workspaceRootDir, "package.json"));
|
|
7864
7842
|
const name = pkg.name;
|
|
7865
7843
|
if (typeof name === "string" && name.trim()) return name.trim();
|
|
7866
7844
|
} catch {
|
|
7867
7845
|
}
|
|
7868
|
-
return
|
|
7846
|
+
return path37.basename(workspaceRootDir);
|
|
7869
7847
|
}
|
|
7870
7848
|
|
|
7871
7849
|
// src/commands/env.ts
|
|
@@ -7909,7 +7887,7 @@ function report(keys, where) {
|
|
|
7909
7887
|
}
|
|
7910
7888
|
|
|
7911
7889
|
// src/commands/env/set.ts
|
|
7912
|
-
import
|
|
7890
|
+
import process27 from "node:process";
|
|
7913
7891
|
import { Command as Command75 } from "commander";
|
|
7914
7892
|
import * as p38 from "@clack/prompts";
|
|
7915
7893
|
import pc18 from "picocolors";
|
|
@@ -7951,7 +7929,7 @@ async function promptValue(key) {
|
|
|
7951
7929
|
});
|
|
7952
7930
|
if (p38.isCancel(value)) {
|
|
7953
7931
|
p38.cancel("Operation cancelled.");
|
|
7954
|
-
|
|
7932
|
+
process27.exit(0);
|
|
7955
7933
|
}
|
|
7956
7934
|
return value;
|
|
7957
7935
|
}
|
|
@@ -7996,9 +7974,9 @@ var envUnset = addTargetOptions(
|
|
|
7996
7974
|
);
|
|
7997
7975
|
|
|
7998
7976
|
// src/commands/env/import.ts
|
|
7999
|
-
import
|
|
8000
|
-
import
|
|
8001
|
-
import
|
|
7977
|
+
import fs34 from "node:fs";
|
|
7978
|
+
import path38 from "node:path";
|
|
7979
|
+
import process28 from "node:process";
|
|
8002
7980
|
import { Command as Command77 } from "commander";
|
|
8003
7981
|
import * as p40 from "@clack/prompts";
|
|
8004
7982
|
import pc20 from "picocolors";
|
|
@@ -8043,10 +8021,10 @@ var envImport = addTargetOptions(
|
|
|
8043
8021
|
)
|
|
8044
8022
|
);
|
|
8045
8023
|
function resolve(file) {
|
|
8046
|
-
return
|
|
8024
|
+
return path38.resolve(process28.cwd(), file);
|
|
8047
8025
|
}
|
|
8048
8026
|
function read(resolved, shown) {
|
|
8049
|
-
if (!
|
|
8027
|
+
if (!fs34.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
|
|
8050
8028
|
const incoming = readLocalEnvFile(resolved);
|
|
8051
8029
|
if (Object.keys(incoming).length === 0) p40.log.info(`${shown} has no variables to import.`);
|
|
8052
8030
|
return incoming;
|
|
@@ -8113,8 +8091,8 @@ function describe(state) {
|
|
|
8113
8091
|
...state.rolledBackAt ? [["Rolled back", state.rolledBackAt]] : [],
|
|
8114
8092
|
...state.gitSha ? [["Commit", state.gitSha.slice(0, 12)]] : []
|
|
8115
8093
|
];
|
|
8116
|
-
const width = Math.max(...rows.map(([
|
|
8117
|
-
return pc21.cyan(state.name) + "\n\n" + rows.map(([
|
|
8094
|
+
const width = Math.max(...rows.map(([label4]) => label4.length));
|
|
8095
|
+
return pc21.cyan(state.name) + "\n\n" + rows.map(([label4, value]) => ` ${label4.padEnd(width)} ${value}`).join("\n");
|
|
8118
8096
|
}
|
|
8119
8097
|
|
|
8120
8098
|
// src/commands/rollback.ts
|
|
@@ -8195,7 +8173,7 @@ var logs = addTargetOptions(
|
|
|
8195
8173
|
import { Command as Command83 } from "commander";
|
|
8196
8174
|
|
|
8197
8175
|
// src/commands/admin/create.ts
|
|
8198
|
-
import
|
|
8176
|
+
import process29 from "node:process";
|
|
8199
8177
|
import { Command as Command82 } from "commander";
|
|
8200
8178
|
import * as p43 from "@clack/prompts";
|
|
8201
8179
|
import pc23 from "picocolors";
|
|
@@ -8262,7 +8240,7 @@ async function upsertSuperuser(pb, email3, password11) {
|
|
|
8262
8240
|
});
|
|
8263
8241
|
if (p43.isCancel(confirmed) || !confirmed) {
|
|
8264
8242
|
p43.cancel("Operation cancelled.");
|
|
8265
|
-
|
|
8243
|
+
process29.exit(0);
|
|
8266
8244
|
}
|
|
8267
8245
|
await pb.collection("_superusers").update(existing, { password: password11, passwordConfirm: password11 });
|
|
8268
8246
|
p43.log.success(`Password updated for ${pc23.cyan(email3)}, you can sign in now`);
|
|
@@ -8286,7 +8264,7 @@ async function promptEmail() {
|
|
|
8286
8264
|
});
|
|
8287
8265
|
if (p43.isCancel(value)) {
|
|
8288
8266
|
p43.cancel("Operation cancelled.");
|
|
8289
|
-
|
|
8267
|
+
process29.exit(0);
|
|
8290
8268
|
}
|
|
8291
8269
|
return value.trim();
|
|
8292
8270
|
}
|
|
@@ -8297,7 +8275,7 @@ async function promptPassword2() {
|
|
|
8297
8275
|
});
|
|
8298
8276
|
if (p43.isCancel(value)) {
|
|
8299
8277
|
p43.cancel("Operation cancelled.");
|
|
8300
|
-
|
|
8278
|
+
process29.exit(0);
|
|
8301
8279
|
}
|
|
8302
8280
|
const again = await p43.password({
|
|
8303
8281
|
message: "Password again",
|
|
@@ -8305,7 +8283,7 @@ async function promptPassword2() {
|
|
|
8305
8283
|
});
|
|
8306
8284
|
if (p43.isCancel(again)) {
|
|
8307
8285
|
p43.cancel("Operation cancelled.");
|
|
8308
|
-
|
|
8286
|
+
process29.exit(0);
|
|
8309
8287
|
}
|
|
8310
8288
|
return value;
|
|
8311
8289
|
}
|
|
@@ -8317,8 +8295,8 @@ var admin = new Command83("admin").description("manage admin panel logins").conf
|
|
|
8317
8295
|
import { Command as Command89 } from "commander";
|
|
8318
8296
|
|
|
8319
8297
|
// src/commands/backup/create.ts
|
|
8320
|
-
import
|
|
8321
|
-
import
|
|
8298
|
+
import fs35 from "node:fs";
|
|
8299
|
+
import path39 from "node:path";
|
|
8322
8300
|
import { Command as Command84 } from "commander";
|
|
8323
8301
|
import * as p44 from "@clack/prompts";
|
|
8324
8302
|
import pc24 from "picocolors";
|
|
@@ -8472,12 +8450,12 @@ Your bucket's own versioning is what protects the uploaded files.`
|
|
|
8472
8450
|
}, "Failed to create the backup.")
|
|
8473
8451
|
);
|
|
8474
8452
|
async function download(ctx, key, outputDir) {
|
|
8475
|
-
const dir =
|
|
8476
|
-
|
|
8477
|
-
const destination =
|
|
8453
|
+
const dir = path39.resolve(ctx.workspaceRootDir, outputDir);
|
|
8454
|
+
fs35.mkdirSync(dir, { recursive: true });
|
|
8455
|
+
const destination = path39.join(dir, key);
|
|
8478
8456
|
if (!ctx.session) {
|
|
8479
|
-
|
|
8480
|
-
return
|
|
8457
|
+
fs35.copyFileSync(path39.join(ctx.workspaceRootDir, "data", "backups", key), destination);
|
|
8458
|
+
return path39.relative(ctx.workspaceRootDir, destination);
|
|
8481
8459
|
}
|
|
8482
8460
|
const spinner5 = p44.spinner();
|
|
8483
8461
|
spinner5.start(`Downloading ${key}`);
|
|
@@ -8488,7 +8466,7 @@ async function download(ctx, key, outputDir) {
|
|
|
8488
8466
|
throw error;
|
|
8489
8467
|
}
|
|
8490
8468
|
spinner5.stop(`Downloaded ${key}`);
|
|
8491
|
-
return
|
|
8469
|
+
return path39.relative(ctx.workspaceRootDir, destination);
|
|
8492
8470
|
}
|
|
8493
8471
|
|
|
8494
8472
|
// src/commands/backup/list.ts
|
|
@@ -8522,8 +8500,8 @@ Take one with ${pc25.cyan("vela backup create")}.`
|
|
|
8522
8500
|
);
|
|
8523
8501
|
|
|
8524
8502
|
// src/commands/backup/download.ts
|
|
8525
|
-
import
|
|
8526
|
-
import
|
|
8503
|
+
import fs36 from "node:fs";
|
|
8504
|
+
import path40 from "node:path";
|
|
8527
8505
|
import { Command as Command86 } from "commander";
|
|
8528
8506
|
import * as p46 from "@clack/prompts";
|
|
8529
8507
|
import pc26 from "picocolors";
|
|
@@ -8550,11 +8528,11 @@ Run ${pc26.cyan("vela backup list")} to see what it does have.`
|
|
|
8550
8528
|
Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
8551
8529
|
);
|
|
8552
8530
|
}
|
|
8553
|
-
const dir =
|
|
8554
|
-
|
|
8555
|
-
const destination =
|
|
8531
|
+
const dir = path40.resolve(ctx.workspaceRootDir, options.output);
|
|
8532
|
+
fs36.mkdirSync(dir, { recursive: true });
|
|
8533
|
+
const destination = path40.join(dir, key);
|
|
8556
8534
|
if (!ctx.session) {
|
|
8557
|
-
|
|
8535
|
+
fs36.copyFileSync(path40.join(ctx.workspaceRootDir, "data", "backups", key), destination);
|
|
8558
8536
|
} else {
|
|
8559
8537
|
const spinner5 = p46.spinner();
|
|
8560
8538
|
spinner5.start(`Downloading ${key} (${formatBytes(found.size)})`);
|
|
@@ -8568,14 +8546,14 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
|
8568
8546
|
}
|
|
8569
8547
|
reportResult({
|
|
8570
8548
|
summary: `Saved ${key} from ${ctx.targetName}.`,
|
|
8571
|
-
filesCreated: [
|
|
8549
|
+
filesCreated: [path40.relative(ctx.workspaceRootDir, destination)]
|
|
8572
8550
|
});
|
|
8573
8551
|
});
|
|
8574
8552
|
}, "Failed to download the backup.")
|
|
8575
8553
|
);
|
|
8576
8554
|
|
|
8577
8555
|
// src/commands/backup/delete.ts
|
|
8578
|
-
import
|
|
8556
|
+
import process30 from "node:process";
|
|
8579
8557
|
import { Command as Command87 } from "commander";
|
|
8580
8558
|
import * as p47 from "@clack/prompts";
|
|
8581
8559
|
import pc27 from "picocolors";
|
|
@@ -8601,7 +8579,7 @@ Run ${pc27.cyan("vela backup list")} to see what it does have.`
|
|
|
8601
8579
|
});
|
|
8602
8580
|
if (p47.isCancel(confirmed) || !confirmed) {
|
|
8603
8581
|
p47.cancel("Operation cancelled.");
|
|
8604
|
-
|
|
8582
|
+
process30.exit(0);
|
|
8605
8583
|
}
|
|
8606
8584
|
}
|
|
8607
8585
|
await ctx.pb.backups.delete(key);
|
|
@@ -8663,9 +8641,9 @@ Set one with ${pc28.cyan('vela backup schedule "0 3 * * *"')}.`
|
|
|
8663
8641
|
var backup = new Command89("backup").description("back up the database and uploads, locally or on a target").configureHelp(helpConfig).addCommand(backupCreate).addCommand(backupList).addCommand(backupDownload).addCommand(backupDelete).addCommand(backupSchedule);
|
|
8664
8642
|
|
|
8665
8643
|
// src/commands/restore.ts
|
|
8666
|
-
import
|
|
8667
|
-
import
|
|
8668
|
-
import
|
|
8644
|
+
import fs37 from "node:fs";
|
|
8645
|
+
import path41 from "node:path";
|
|
8646
|
+
import process31 from "node:process";
|
|
8669
8647
|
import { Command as Command90 } from "commander";
|
|
8670
8648
|
import * as p49 from "@clack/prompts";
|
|
8671
8649
|
import pc29 from "picocolors";
|
|
@@ -8685,7 +8663,7 @@ var restore = addTargetOptions(
|
|
|
8685
8663
|
`${ctx.targetName} was deployed without a database, so there is nothing to restore.`
|
|
8686
8664
|
);
|
|
8687
8665
|
}
|
|
8688
|
-
const local = source &&
|
|
8666
|
+
const local = source && fs37.existsSync(source) ? source : void 0;
|
|
8689
8667
|
const key = local ? void 0 : await resolveKey(ctx, source);
|
|
8690
8668
|
if (!options.yes) {
|
|
8691
8669
|
await confirm11(ctx.appName, ctx.targetName, ctx.envTag, local ?? key);
|
|
@@ -8707,7 +8685,7 @@ var restore = addTargetOptions(
|
|
|
8707
8685
|
});
|
|
8708
8686
|
p49.log.success(
|
|
8709
8687
|
`Restored ${pc29.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc29.cyan(
|
|
8710
|
-
local ?
|
|
8688
|
+
local ? path41.basename(local) : key
|
|
8711
8689
|
)}.`
|
|
8712
8690
|
);
|
|
8713
8691
|
if (result?.storageCarriedOver) {
|
|
@@ -8767,27 +8745,27 @@ Take one with ${pc29.cyan("vela backup create")}, or pass the path to an archive
|
|
|
8767
8745
|
});
|
|
8768
8746
|
if (p49.isCancel(chosen)) {
|
|
8769
8747
|
p49.cancel("Operation cancelled.");
|
|
8770
|
-
|
|
8748
|
+
process31.exit(0);
|
|
8771
8749
|
}
|
|
8772
8750
|
return chosen;
|
|
8773
8751
|
}
|
|
8774
8752
|
async function stage(ctx, file) {
|
|
8775
8753
|
const dir = remotePaths.restoreStage(ctx.instance);
|
|
8776
|
-
const remote = `${dir}/${
|
|
8754
|
+
const remote = `${dir}/${path41.basename(file)}`;
|
|
8777
8755
|
const spinner5 = p49.spinner();
|
|
8778
|
-
spinner5.start(`Uploading ${
|
|
8756
|
+
spinner5.start(`Uploading ${path41.basename(file)}`);
|
|
8779
8757
|
try {
|
|
8780
8758
|
await ctx.session.script(`mkdir -p "$1"`, { args: [dir] });
|
|
8781
8759
|
await ctx.session.upload([file], dir);
|
|
8782
8760
|
} catch (error) {
|
|
8783
|
-
spinner5.stop(`Could not upload ${
|
|
8761
|
+
spinner5.stop(`Could not upload ${path41.basename(file)}.`);
|
|
8784
8762
|
throw error;
|
|
8785
8763
|
}
|
|
8786
|
-
spinner5.stop(`Uploaded ${
|
|
8764
|
+
spinner5.stop(`Uploaded ${path41.basename(file)}`);
|
|
8787
8765
|
return remote;
|
|
8788
8766
|
}
|
|
8789
8767
|
async function confirm11(appName, targetName, envTag, from) {
|
|
8790
|
-
const what = `${pc29.cyan(`${appName} (${targetName})`)} from ${pc29.cyan(
|
|
8768
|
+
const what = `${pc29.cyan(`${appName} (${targetName})`)} from ${pc29.cyan(path41.basename(from))}`;
|
|
8791
8769
|
if (isProd(envTag)) {
|
|
8792
8770
|
const answer = await p49.text({
|
|
8793
8771
|
message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
|
|
@@ -8795,7 +8773,7 @@ async function confirm11(appName, targetName, envTag, from) {
|
|
|
8795
8773
|
});
|
|
8796
8774
|
if (p49.isCancel(answer)) {
|
|
8797
8775
|
p49.cancel("Operation cancelled.");
|
|
8798
|
-
|
|
8776
|
+
process31.exit(0);
|
|
8799
8777
|
}
|
|
8800
8778
|
return;
|
|
8801
8779
|
}
|
|
@@ -8805,7 +8783,7 @@ async function confirm11(appName, targetName, envTag, from) {
|
|
|
8805
8783
|
});
|
|
8806
8784
|
if (p49.isCancel(ok) || !ok) {
|
|
8807
8785
|
p49.cancel("Operation cancelled.");
|
|
8808
|
-
|
|
8786
|
+
process31.exit(0);
|
|
8809
8787
|
}
|
|
8810
8788
|
}
|
|
8811
8789
|
|
|
@@ -8898,61 +8876,90 @@ Release and domain are shown from what this project recorded.`
|
|
|
8898
8876
|
}
|
|
8899
8877
|
|
|
8900
8878
|
// src/commands/test.ts
|
|
8901
|
-
import
|
|
8902
|
-
import
|
|
8879
|
+
import path42 from "node:path";
|
|
8880
|
+
import process32 from "node:process";
|
|
8903
8881
|
import { Command as Command92 } from "commander";
|
|
8904
|
-
import
|
|
8882
|
+
import PocketBase6 from "pocketbase";
|
|
8905
8883
|
import pc31 from "picocolors";
|
|
8906
8884
|
import { x as x5 } from "tinyexec";
|
|
8907
8885
|
import { detect as detect8 } from "package-manager-detector";
|
|
8908
8886
|
import { resolveCommand as resolveCommand8 } from "package-manager-detector/commands";
|
|
8909
|
-
import
|
|
8887
|
+
import fs38 from "node:fs";
|
|
8910
8888
|
var testServer = new Command92("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
|
|
8911
|
-
const cwd =
|
|
8889
|
+
const cwd = process32.cwd();
|
|
8912
8890
|
const email3 = `test-${Math.random().toString(36).slice(2)}@example.com`;
|
|
8913
8891
|
const password11 = "password";
|
|
8914
|
-
const testDataDir =
|
|
8915
|
-
|
|
8892
|
+
const testDataDir = path42.join(cwd, "test-data");
|
|
8893
|
+
fs38.rmSync(testDataDir, { recursive: true, force: true });
|
|
8916
8894
|
const { stop, url } = await launchPocketbase(cwd, {
|
|
8917
8895
|
dir: testDataDir,
|
|
8918
|
-
migrationsDir:
|
|
8896
|
+
migrationsDir: path42.join(cwd, MIGRATIONS_DIR),
|
|
8919
8897
|
// The app's PocketBase hooks (slug generation, personal teams, …) are part
|
|
8920
8898
|
// of its behaviour; the suite runs against the same server dev and build
|
|
8921
8899
|
// start, so it loads them from the same place.
|
|
8922
|
-
hooksDir:
|
|
8900
|
+
hooksDir: path42.join(cwd, DATA_DIR, "hooks"),
|
|
8923
8901
|
email: email3,
|
|
8924
8902
|
password: password11
|
|
8925
8903
|
});
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8904
|
+
process32.env.POCKETBASE_URL = url;
|
|
8905
|
+
process32.env.POCKETBASE_SUPERUSER_EMAIL = email3;
|
|
8906
|
+
process32.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
|
|
8907
|
+
process32.env.VELA_DATA_DIR = testDataDir;
|
|
8908
|
+
process32.env.TEST = "true";
|
|
8931
8909
|
console.log(`${pc31.greenBright("\u2713")} Created test database`);
|
|
8910
|
+
let vite;
|
|
8911
|
+
let cleanedUp = false;
|
|
8912
|
+
const cleanupSync = () => {
|
|
8913
|
+
if (cleanedUp) return;
|
|
8914
|
+
cleanedUp = true;
|
|
8915
|
+
stop();
|
|
8916
|
+
fs38.rmSync(testDataDir, { recursive: true, force: true });
|
|
8917
|
+
};
|
|
8918
|
+
const cleanup = async () => {
|
|
8919
|
+
if (cleanedUp) return;
|
|
8920
|
+
await vite?.close().catch(() => {
|
|
8921
|
+
});
|
|
8922
|
+
cleanupSync();
|
|
8923
|
+
};
|
|
8924
|
+
const fail = async (message) => {
|
|
8925
|
+
console.error(`${pc31.redBright("\u2717")} ${message}`);
|
|
8926
|
+
await cleanup();
|
|
8927
|
+
process32.exit(1);
|
|
8928
|
+
};
|
|
8929
|
+
process32.on("exit", cleanupSync);
|
|
8930
|
+
process32.on("SIGINT", () => {
|
|
8931
|
+
cleanupSync();
|
|
8932
|
+
process32.exit(130);
|
|
8933
|
+
});
|
|
8934
|
+
const pb = new PocketBase6(url);
|
|
8935
|
+
try {
|
|
8936
|
+
await authWithRetries(pb, email3, password11);
|
|
8937
|
+
} catch (e) {
|
|
8938
|
+
await fail(`Auth failed: ${e.message}`);
|
|
8939
|
+
}
|
|
8940
|
+
try {
|
|
8941
|
+
const seeds2 = await loadSeeds(pb, cwd);
|
|
8942
|
+
if (seeds2.length > 0) {
|
|
8943
|
+
console.log(`${pc31.greenBright("\u2713")} Loaded ${seeds2.length} seed file(s)`);
|
|
8944
|
+
}
|
|
8945
|
+
const fixtures2 = await loadFixtures(pb, cwd);
|
|
8946
|
+
if (fixtures2.length > 0) {
|
|
8947
|
+
console.log(`${pc31.greenBright("\u2713")} Loaded ${fixtures2.length} fixture file(s)`);
|
|
8948
|
+
}
|
|
8949
|
+
} catch (e) {
|
|
8950
|
+
await fail(describeLoadFailure(e));
|
|
8951
|
+
}
|
|
8932
8952
|
const { createServer } = await loadVite(cwd);
|
|
8933
|
-
|
|
8953
|
+
vite = await createServer({
|
|
8934
8954
|
mode: "test",
|
|
8935
8955
|
plugins: [stubPagesPlugin()],
|
|
8936
8956
|
optimizeDeps: { noDiscovery: true }
|
|
8937
8957
|
});
|
|
8938
8958
|
const vitePort = await findFreePort();
|
|
8939
8959
|
await vite.listen(vitePort);
|
|
8940
|
-
|
|
8960
|
+
process32.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
|
|
8941
8961
|
console.log(`${pc31.greenBright("\u2713")} Started Vite: http://localhost:${vitePort}`);
|
|
8942
8962
|
console.log(`${pc31.greenBright("\u2713")} Started PocketBase: ${url}`);
|
|
8943
|
-
const cleanup = async () => {
|
|
8944
|
-
stop();
|
|
8945
|
-
await vite.close();
|
|
8946
|
-
fs41.rmSync(testDataDir, { recursive: true, force: true });
|
|
8947
|
-
};
|
|
8948
|
-
const pb = new PocketBase5(url);
|
|
8949
|
-
try {
|
|
8950
|
-
await authWithRetries(pb, email3, password11);
|
|
8951
|
-
} catch (e) {
|
|
8952
|
-
await cleanup();
|
|
8953
|
-
console.error(`${pc31.redBright("\u2717")} Auth failed: ${e.message}`);
|
|
8954
|
-
process33.exit(1);
|
|
8955
|
-
}
|
|
8956
8963
|
const extraArgs = (cmd.parent?.args ?? []).slice(1);
|
|
8957
8964
|
let filter = extraArgs.find((arg) => !arg.startsWith("-"));
|
|
8958
8965
|
const passthrough = filter ? extraArgs.filter((a) => a !== filter) : extraArgs;
|
|
@@ -8968,15 +8975,25 @@ var testServer = new Command92("test:server").description("run server tests").al
|
|
|
8968
8975
|
]);
|
|
8969
8976
|
const resolvedArgs = resolved.args.slice();
|
|
8970
8977
|
if (pm === "npm") resolvedArgs.unshift("--yes");
|
|
8971
|
-
await x5(resolved.command, resolvedArgs, {
|
|
8972
|
-
nodeOptions: { cwd, stdio: "inherit", env: { ...
|
|
8973
|
-
throwOnError: true
|
|
8978
|
+
const result = await x5(resolved.command, resolvedArgs, {
|
|
8979
|
+
nodeOptions: { cwd, stdio: "inherit", env: { ...process32.env, CI: "1" } }
|
|
8974
8980
|
});
|
|
8975
|
-
|
|
8981
|
+
process32.exitCode = result.exitCode ?? 1;
|
|
8982
|
+
} catch (e) {
|
|
8983
|
+
console.error(`${pc31.redBright("\u2717")} ${e.message}`);
|
|
8984
|
+
process32.exitCode = 1;
|
|
8976
8985
|
} finally {
|
|
8977
8986
|
await cleanup();
|
|
8978
8987
|
}
|
|
8979
8988
|
});
|
|
8989
|
+
function describeLoadFailure(e) {
|
|
8990
|
+
if (e instanceof DataLoadError) {
|
|
8991
|
+
const hint = e.kind === "fixtures" ? "Run `vela fixtures regen` to regenerate fixtures from the current schema." : `Check ${e.file} against the current schema.`;
|
|
8992
|
+
return `Failed to load ${e.message}
|
|
8993
|
+
${hint}`;
|
|
8994
|
+
}
|
|
8995
|
+
return `Failed to load test data: ${e.message}`;
|
|
8996
|
+
}
|
|
8980
8997
|
function stubPagesPlugin() {
|
|
8981
8998
|
const stub = `<script>export const render = () => '';</script>`;
|
|
8982
8999
|
return {
|
|
@@ -8995,8 +9012,8 @@ function stubPagesPlugin() {
|
|
|
8995
9012
|
}
|
|
8996
9013
|
|
|
8997
9014
|
// src/commands/routes.ts
|
|
8998
|
-
import
|
|
8999
|
-
import
|
|
9015
|
+
import fs39 from "node:fs";
|
|
9016
|
+
import path43 from "node:path";
|
|
9000
9017
|
import { Command as Command93 } from "commander";
|
|
9001
9018
|
var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
9002
9019
|
"GET",
|
|
@@ -9010,30 +9027,30 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
|
9010
9027
|
]);
|
|
9011
9028
|
var routes = new Command93("routes").description("list routes").configureHelp(helpConfig).action(async () => {
|
|
9012
9029
|
const { workspaceRootDir, routesDir } = await getWorkspace();
|
|
9013
|
-
const routesRoot =
|
|
9030
|
+
const routesRoot = path43.join(workspaceRootDir, routesDir);
|
|
9014
9031
|
const found = walk(routesRoot, routesRoot).filter((r) => r.methods.length > 0);
|
|
9015
9032
|
found.sort((a, b) => a.urlPattern.localeCompare(b.urlPattern));
|
|
9016
9033
|
printTable(found);
|
|
9017
9034
|
});
|
|
9018
9035
|
function walk(root, dir) {
|
|
9019
|
-
const entries =
|
|
9036
|
+
const entries = fs39.readdirSync(dir, { withFileTypes: true });
|
|
9020
9037
|
const routes2 = [];
|
|
9021
9038
|
const hasLeaf = entries.some((e) => e.isFile() && isRouteFile(e.name));
|
|
9022
9039
|
if (hasLeaf) {
|
|
9023
|
-
const id = "/" +
|
|
9040
|
+
const id = "/" + path43.relative(root, dir).split(path43.sep).filter(Boolean).join("/");
|
|
9024
9041
|
const urlPattern = id.replace(/\([^)]+\)\/?/g, "").replace(/\/$/, "") || "/";
|
|
9025
9042
|
const methods = /* @__PURE__ */ new Set();
|
|
9026
9043
|
for (const entry of entries) {
|
|
9027
9044
|
if (!entry.isFile()) continue;
|
|
9028
9045
|
if (entry.name.endsWith("+page.svelte")) methods.add("GET");
|
|
9029
9046
|
if (entry.name.endsWith("+server.ts") || entry.name.endsWith("+server.js") || entry.name.endsWith("+page.server.ts") || entry.name.endsWith("+page.server.js")) {
|
|
9030
|
-
extractMethods(
|
|
9047
|
+
extractMethods(path43.join(dir, entry.name)).forEach((m) => methods.add(m));
|
|
9031
9048
|
}
|
|
9032
9049
|
}
|
|
9033
9050
|
routes2.push({ id: id || "/", urlPattern, methods: [...methods] });
|
|
9034
9051
|
}
|
|
9035
9052
|
for (const entry of entries) {
|
|
9036
|
-
if (entry.isDirectory()) routes2.push(...walk(root,
|
|
9053
|
+
if (entry.isDirectory()) routes2.push(...walk(root, path43.join(dir, entry.name)));
|
|
9037
9054
|
}
|
|
9038
9055
|
return routes2;
|
|
9039
9056
|
}
|
|
@@ -9042,7 +9059,7 @@ function isRouteFile(name) {
|
|
|
9042
9059
|
}
|
|
9043
9060
|
function extractMethods(file) {
|
|
9044
9061
|
try {
|
|
9045
|
-
const content =
|
|
9062
|
+
const content = fs39.readFileSync(file, "utf8");
|
|
9046
9063
|
const methods = [];
|
|
9047
9064
|
const exportRegex = /export\s+(?:const|async\s+function|function)\s+(\w+)/g;
|
|
9048
9065
|
let match;
|
|
@@ -9083,13 +9100,13 @@ function printTable(routes2) {
|
|
|
9083
9100
|
}
|
|
9084
9101
|
|
|
9085
9102
|
// src/commands/i18n.ts
|
|
9086
|
-
import
|
|
9103
|
+
import process33 from "node:process";
|
|
9087
9104
|
import { Command as Command94 } from "commander";
|
|
9088
9105
|
import { x as x6 } from "tinyexec";
|
|
9089
9106
|
import { detect as detect9 } from "package-manager-detector";
|
|
9090
9107
|
import { resolveCommand as resolveCommand9 } from "package-manager-detector/commands";
|
|
9091
9108
|
async function runWuchale(extraArgs) {
|
|
9092
|
-
const cwd =
|
|
9109
|
+
const cwd = process33.cwd();
|
|
9093
9110
|
const pm = (await detect9({ cwd }))?.name ?? "npm";
|
|
9094
9111
|
const resolved = resolveCommand9(pm, "execute", ["wuchale", ...extraArgs]);
|
|
9095
9112
|
const args = resolved.args.slice();
|
|
@@ -9125,15 +9142,15 @@ import pc33 from "picocolors";
|
|
|
9125
9142
|
|
|
9126
9143
|
// src/lib/cms-backend.ts
|
|
9127
9144
|
import { createRequire as createRequire3 } from "node:module";
|
|
9128
|
-
import
|
|
9129
|
-
import
|
|
9145
|
+
import path44 from "node:path";
|
|
9146
|
+
import process34 from "node:process";
|
|
9130
9147
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
9131
9148
|
import pc32 from "picocolors";
|
|
9132
9149
|
var DEFAULT_PROJECT = "default";
|
|
9133
9150
|
async function loadBackendModule(root) {
|
|
9134
9151
|
let entry;
|
|
9135
9152
|
try {
|
|
9136
|
-
entry = createRequire3(
|
|
9153
|
+
entry = createRequire3(path44.join(root, "package.json")).resolve("@velastack/cms/backend");
|
|
9137
9154
|
} catch {
|
|
9138
9155
|
throw new Error(
|
|
9139
9156
|
`@velastack/cms is not installed in this project.
|
|
@@ -9143,16 +9160,16 @@ Run ${pc32.cyan("vela enable cms")} first.`
|
|
|
9143
9160
|
}
|
|
9144
9161
|
return await import(pathToFileURL3(entry).href);
|
|
9145
9162
|
}
|
|
9146
|
-
async function withCmsBackend(fn, cwd =
|
|
9163
|
+
async function withCmsBackend(fn, cwd = process34.cwd()) {
|
|
9147
9164
|
const root = findWorkspaceRoot(cwd);
|
|
9148
9165
|
if (!root) {
|
|
9149
9166
|
throw new Error("Could not find workspace root (no package.json found)");
|
|
9150
9167
|
}
|
|
9151
9168
|
const { createCmsBackend } = await loadBackendModule(root);
|
|
9152
|
-
const
|
|
9169
|
+
const dataDir2 = localDataDir(root);
|
|
9153
9170
|
const backend3 = createCmsBackend({
|
|
9154
|
-
dbPath:
|
|
9155
|
-
uploadDir:
|
|
9171
|
+
dbPath: path44.join(dataDir2, "cms.sqlite"),
|
|
9172
|
+
uploadDir: path44.join(dataDir2, "uploads")
|
|
9156
9173
|
});
|
|
9157
9174
|
try {
|
|
9158
9175
|
return await fn(backend3);
|
|
@@ -9258,19 +9275,20 @@ var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
|
|
|
9258
9275
|
"restore"
|
|
9259
9276
|
]);
|
|
9260
9277
|
var BACKEND_OPTIONAL_COMMANDS = /* @__PURE__ */ new Set(["dev", "build", "preview", "deploy"]);
|
|
9278
|
+
var SELF_CREDENTIALED_COMMANDS = /* @__PURE__ */ new Set(["test:server"]);
|
|
9261
9279
|
var program = new Command100().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
|
|
9262
9280
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
9263
9281
|
if (isStub(actionCommand)) return;
|
|
9264
|
-
const envRoot = findWorkspaceRoot() ??
|
|
9282
|
+
const envRoot = findWorkspaceRoot() ?? process35.cwd();
|
|
9265
9283
|
dotenv2.config({ path: nodePath.join(envRoot, ".env"), quiet: true });
|
|
9266
|
-
const
|
|
9267
|
-
if (NO_BACKEND_COMMMANDS.has(
|
|
9268
|
-
const top =
|
|
9284
|
+
const path45 = getCommandPath(actionCommand);
|
|
9285
|
+
if (NO_BACKEND_COMMMANDS.has(path45)) return;
|
|
9286
|
+
const top = path45.split(" ", 1)[0];
|
|
9269
9287
|
if (NO_BACKEND_COMMMANDS.has(top)) return;
|
|
9270
9288
|
if (!hasBackend()) {
|
|
9271
9289
|
if (BACKEND_OPTIONAL_COMMANDS.has(top)) return;
|
|
9272
9290
|
p54.log.error(
|
|
9273
|
-
`${pc36.cyan(`vela ${
|
|
9291
|
+
`${pc36.cyan(`vela ${path45}`)} needs a backend, and this project does not have one.
|
|
9274
9292
|
|
|
9275
9293
|
Static projects have no database to talk to.
|
|
9276
9294
|
|
|
@@ -9278,9 +9296,10 @@ To add a backend to this project, run ${pc36.cyan("vela bless")}.`
|
|
|
9278
9296
|
);
|
|
9279
9297
|
p54.log.message();
|
|
9280
9298
|
p54.cancel("Operation failed.");
|
|
9281
|
-
|
|
9299
|
+
process35.exit(1);
|
|
9282
9300
|
}
|
|
9283
|
-
if (
|
|
9301
|
+
if (SELF_CREDENTIALED_COMMANDS.has(path45)) return;
|
|
9302
|
+
if (!process35.env.POCKETBASE_SUPERUSER_EMAIL || !process35.env.POCKETBASE_SUPERUSER_PASSWORD) {
|
|
9284
9303
|
p54.log.error(
|
|
9285
9304
|
`PocketBase superuser credentials are required.
|
|
9286
9305
|
|
|
@@ -9291,7 +9310,7 @@ To set up an existing project, run ${pc36.cyan("vela bless")}.`
|
|
|
9291
9310
|
);
|
|
9292
9311
|
p54.log.message();
|
|
9293
9312
|
p54.cancel("Operation failed.");
|
|
9294
|
-
|
|
9313
|
+
process35.exit(1);
|
|
9295
9314
|
}
|
|
9296
9315
|
});
|
|
9297
9316
|
function getCommandPath(cmd) {
|
|
@@ -9345,14 +9364,5 @@ for (const command of [
|
|
|
9345
9364
|
}
|
|
9346
9365
|
|
|
9347
9366
|
// src/bin.ts
|
|
9348
|
-
|
|
9349
|
-
var delegatedExitCode = delegateToLocalCli({
|
|
9350
|
-
argv,
|
|
9351
|
-
selfPath: fileURLToPath2(import.meta.url),
|
|
9352
|
-
selfVersion: package_default.version
|
|
9353
|
-
});
|
|
9354
|
-
if (delegatedExitCode !== null) {
|
|
9355
|
-
process37.exit(delegatedExitCode);
|
|
9356
|
-
}
|
|
9357
|
-
program.parse(argv, { from: "user" });
|
|
9367
|
+
program.parse(normalizeArgv(process36.argv.slice(2)), { from: "user" });
|
|
9358
9368
|
//# sourceMappingURL=bin.js.map
|