vela 0.10.11 → 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 +798 -782
- package/dist/bin.js.map +4 -4
- package/package.json +2 -2
- 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",
|
|
@@ -41,7 +55,7 @@ var package_default = {
|
|
|
41
55
|
dependencies: {
|
|
42
56
|
"@clack/prompts": "^1.7.0",
|
|
43
57
|
"@faker-js/faker": "^10.6.0",
|
|
44
|
-
"@velastack/patterns": "^0.1.
|
|
58
|
+
"@velastack/patterns": "^0.1.9",
|
|
45
59
|
"@velastack/pocketbase-codegen": "^0.1.0",
|
|
46
60
|
"annotate-json-schema": "^0.1.0",
|
|
47
61
|
commander: "^13.1.0",
|
|
@@ -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
|
[
|
|
@@ -814,12 +746,13 @@ async function createSuperuser(cwd, email3, password11) {
|
|
|
814
746
|
async function launchPocketbase(cwd, {
|
|
815
747
|
dir,
|
|
816
748
|
migrationsDir,
|
|
749
|
+
hooksDir,
|
|
817
750
|
email: email3,
|
|
818
751
|
password: password11
|
|
819
752
|
}) {
|
|
820
753
|
const host = "localhost";
|
|
821
|
-
|
|
822
|
-
|
|
754
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
755
|
+
fs5.mkdirSync(migrationsDir, { recursive: true });
|
|
823
756
|
await execPackageBin(
|
|
824
757
|
cwd,
|
|
825
758
|
[
|
|
@@ -843,6 +776,7 @@ async function launchPocketbase(cwd, {
|
|
|
843
776
|
const { proc, url } = await startPocketbaseServe({
|
|
844
777
|
dataDir: dir,
|
|
845
778
|
migrationsDir,
|
|
779
|
+
hooksDir,
|
|
846
780
|
host,
|
|
847
781
|
stdio: "pipe"
|
|
848
782
|
});
|
|
@@ -857,11 +791,11 @@ function pocketbaseVersion() {
|
|
|
857
791
|
return pkg.version;
|
|
858
792
|
}
|
|
859
793
|
async function ensureSuperuser(cwd) {
|
|
860
|
-
const email3 =
|
|
861
|
-
const password11 =
|
|
794
|
+
const email3 = process4.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
795
|
+
const password11 = process4.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
862
796
|
if (!email3 || !password11) return;
|
|
863
|
-
const dir =
|
|
864
|
-
if (!
|
|
797
|
+
const dir = path4.join(cwd, DATA_DIR);
|
|
798
|
+
if (!fs5.existsSync(dir)) return;
|
|
865
799
|
const { getBinaryPath } = await import("pocketbase-server");
|
|
866
800
|
await x(
|
|
867
801
|
getBinaryPath(),
|
|
@@ -869,7 +803,7 @@ async function ensureSuperuser(cwd) {
|
|
|
869
803
|
"--dir",
|
|
870
804
|
dir,
|
|
871
805
|
"--migrationsDir",
|
|
872
|
-
|
|
806
|
+
path4.join(cwd, MIGRATIONS_DIR),
|
|
873
807
|
"superuser",
|
|
874
808
|
"upsert",
|
|
875
809
|
email3,
|
|
@@ -880,8 +814,8 @@ async function ensureSuperuser(cwd) {
|
|
|
880
814
|
}
|
|
881
815
|
|
|
882
816
|
// src/lib/env.ts
|
|
883
|
-
import
|
|
884
|
-
import
|
|
817
|
+
import fs6 from "node:fs";
|
|
818
|
+
import path5 from "node:path";
|
|
885
819
|
function addEnvVar(content, key, value) {
|
|
886
820
|
if (content.includes(`${key}=`)) return content;
|
|
887
821
|
return appendLine(content, `${key}=${value}`);
|
|
@@ -896,11 +830,11 @@ function appendLine(existing, line) {
|
|
|
896
830
|
return withNewline + line + "\n";
|
|
897
831
|
}
|
|
898
832
|
function writeEnvFile(cwd, vars, comments = []) {
|
|
899
|
-
const envPath =
|
|
900
|
-
let content =
|
|
833
|
+
const envPath = path5.join(cwd, ".env");
|
|
834
|
+
let content = fs6.existsSync(envPath) ? fs6.readFileSync(envPath, "utf8") : "";
|
|
901
835
|
for (const comment of comments) content = addEnvComment(content, comment);
|
|
902
836
|
for (const [key, value] of Object.entries(vars)) content = addEnvVar(content, key, value);
|
|
903
|
-
|
|
837
|
+
fs6.writeFileSync(envPath, content);
|
|
904
838
|
}
|
|
905
839
|
function upsertEnvVar(content, key, value) {
|
|
906
840
|
const line = `${key}=${quoteEnvValue(value)}`;
|
|
@@ -933,12 +867,12 @@ function quoteEnvValue(value) {
|
|
|
933
867
|
}
|
|
934
868
|
|
|
935
869
|
// src/lib/config-merge.ts
|
|
936
|
-
import fs9 from "node:fs";
|
|
937
|
-
import path8 from "node:path";
|
|
938
|
-
|
|
939
|
-
// src/lib/config-target.ts
|
|
940
870
|
import fs8 from "node:fs";
|
|
941
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";
|
|
942
876
|
import {
|
|
943
877
|
Project,
|
|
944
878
|
QuoteKind,
|
|
@@ -958,8 +892,8 @@ var SVELTE_CONFIG_CANDIDATES = [
|
|
|
958
892
|
];
|
|
959
893
|
function probeFirstExisting(root, candidates) {
|
|
960
894
|
for (const rel of candidates) {
|
|
961
|
-
const abs =
|
|
962
|
-
if (
|
|
895
|
+
const abs = path6.join(root, rel);
|
|
896
|
+
if (fs7.existsSync(abs)) return abs;
|
|
963
897
|
}
|
|
964
898
|
return null;
|
|
965
899
|
}
|
|
@@ -1035,7 +969,7 @@ function mergeSvelteConfig(projectRoot) {
|
|
|
1035
969
|
};
|
|
1036
970
|
}
|
|
1037
971
|
function mergeRunesIntoViteArg(vite, arg) {
|
|
1038
|
-
const file =
|
|
972
|
+
const file = path7.basename(vite.filePath);
|
|
1039
973
|
const compilerOptions = getOrCreateObjectLiteralProperty(arg, "compilerOptions", "{}");
|
|
1040
974
|
if (!compilerOptions) {
|
|
1041
975
|
return {
|
|
@@ -1054,8 +988,8 @@ function mergeRunesIntoViteArg(vite, arg) {
|
|
|
1054
988
|
return { applied: true, reason: "added runes compilerOption", file };
|
|
1055
989
|
}
|
|
1056
990
|
function mergeRunesIntoSvelteConfig(filePath) {
|
|
1057
|
-
const file =
|
|
1058
|
-
const original =
|
|
991
|
+
const file = path7.basename(filePath);
|
|
992
|
+
const original = fs8.readFileSync(filePath, "utf8");
|
|
1059
993
|
if (/runes\s*:/m.test(original)) {
|
|
1060
994
|
return { applied: false, reason: "runes already configured", file };
|
|
1061
995
|
}
|
|
@@ -1078,11 +1012,11 @@ function mergeRunesIntoSvelteConfig(filePath) {
|
|
|
1078
1012
|
}
|
|
1079
1013
|
const insertAt = anchor.index + anchor[0].length;
|
|
1080
1014
|
const updated = original.slice(0, insertAt) + RUNES_SNIPPET + original.slice(insertAt);
|
|
1081
|
-
|
|
1015
|
+
fs8.writeFileSync(filePath, updated);
|
|
1082
1016
|
return { applied: true, reason: "added runes compilerOption", file };
|
|
1083
1017
|
}
|
|
1084
1018
|
function mergeViteConfig(filePath) {
|
|
1085
|
-
if (!
|
|
1019
|
+
if (!fs8.existsSync(filePath)) {
|
|
1086
1020
|
return {
|
|
1087
1021
|
applied: false,
|
|
1088
1022
|
reason: "vite.config.ts not found",
|
|
@@ -1090,7 +1024,7 @@ function mergeViteConfig(filePath) {
|
|
|
1090
1024
|
// then add tailwindcss() to the plugins array`
|
|
1091
1025
|
};
|
|
1092
1026
|
}
|
|
1093
|
-
const original =
|
|
1027
|
+
const original = fs8.readFileSync(filePath, "utf8");
|
|
1094
1028
|
if (original.includes("@tailwindcss/vite")) {
|
|
1095
1029
|
return { applied: false, reason: "tailwindcss plugin already present" };
|
|
1096
1030
|
}
|
|
@@ -1109,14 +1043,14 @@ function mergeViteConfig(filePath) {
|
|
|
1109
1043
|
const trailing = withImport.slice(insertAt);
|
|
1110
1044
|
const prefix = /^\s*\]/.test(trailing) ? "tailwindcss()" : "tailwindcss(), ";
|
|
1111
1045
|
const updated = withImport.slice(0, insertAt) + prefix + withImport.slice(insertAt);
|
|
1112
|
-
|
|
1046
|
+
fs8.writeFileSync(filePath, updated);
|
|
1113
1047
|
return { applied: true, reason: "added @tailwindcss/vite plugin" };
|
|
1114
1048
|
}
|
|
1115
1049
|
function mergeTsconfig(filePath) {
|
|
1116
|
-
if (!
|
|
1050
|
+
if (!fs8.existsSync(filePath)) {
|
|
1117
1051
|
return { applied: false, reason: "tsconfig.json not found" };
|
|
1118
1052
|
}
|
|
1119
|
-
const original =
|
|
1053
|
+
const original = fs8.readFileSync(filePath, "utf8");
|
|
1120
1054
|
if (/rewriteRelativeImportExtensions/.test(original)) {
|
|
1121
1055
|
return { applied: false, reason: "rewriteRelativeImportExtensions already set" };
|
|
1122
1056
|
}
|
|
@@ -1132,7 +1066,7 @@ function mergeTsconfig(filePath) {
|
|
|
1132
1066
|
const indent = detectIndent(original, insertAt);
|
|
1133
1067
|
const updated = original.slice(0, insertAt) + `
|
|
1134
1068
|
${indent}"rewriteRelativeImportExtensions": true,` + original.slice(insertAt);
|
|
1135
|
-
|
|
1069
|
+
fs8.writeFileSync(filePath, updated);
|
|
1136
1070
|
return { applied: true, reason: "added rewriteRelativeImportExtensions" };
|
|
1137
1071
|
}
|
|
1138
1072
|
var GITIGNORE_ENTRIES = [
|
|
@@ -1144,7 +1078,7 @@ var GITIGNORE_ENTRIES = [
|
|
|
1144
1078
|
"vite.config.ts.timestamp-*"
|
|
1145
1079
|
];
|
|
1146
1080
|
function mergeGitignore(filePath) {
|
|
1147
|
-
const existing =
|
|
1081
|
+
const existing = fs8.existsSync(filePath) ? fs8.readFileSync(filePath, "utf8") : "";
|
|
1148
1082
|
const lines = existing.split("\n").map((l) => l.trim());
|
|
1149
1083
|
const missing = GITIGNORE_ENTRIES.filter((entry) => !lines.includes(entry));
|
|
1150
1084
|
if (missing.length === 0) {
|
|
@@ -1153,7 +1087,7 @@ function mergeGitignore(filePath) {
|
|
|
1153
1087
|
const needsNewline = existing.length > 0 && !existing.endsWith("\n");
|
|
1154
1088
|
const appended = `${existing}${needsNewline ? "\n" : ""}${missing.join("\n")}
|
|
1155
1089
|
`;
|
|
1156
|
-
|
|
1090
|
+
fs8.writeFileSync(filePath, appended);
|
|
1157
1091
|
return { applied: true, reason: `added ${missing.length} gitignore entries` };
|
|
1158
1092
|
}
|
|
1159
1093
|
function addImport(source, importLine) {
|
|
@@ -1178,14 +1112,14 @@ function detectIndent(source, atOffset) {
|
|
|
1178
1112
|
}
|
|
1179
1113
|
|
|
1180
1114
|
// src/lib/scaffold-detect.ts
|
|
1181
|
-
import
|
|
1182
|
-
import
|
|
1115
|
+
import fs9 from "node:fs";
|
|
1116
|
+
import path8 from "node:path";
|
|
1183
1117
|
var VANILLA_MARKER = "Welcome to SvelteKit";
|
|
1184
|
-
var PAGE_REL =
|
|
1118
|
+
var PAGE_REL = path8.join("src", "routes", "+page.svelte");
|
|
1185
1119
|
function isVanillaRoutes(cwd) {
|
|
1186
|
-
const pagePath =
|
|
1187
|
-
if (!
|
|
1188
|
-
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);
|
|
1189
1123
|
}
|
|
1190
1124
|
|
|
1191
1125
|
// src/lib/result-report.ts
|
|
@@ -1205,10 +1139,10 @@ function reportResult(report4) {
|
|
|
1205
1139
|
sections.push([extra.label, extra.items]);
|
|
1206
1140
|
}
|
|
1207
1141
|
const body = [];
|
|
1208
|
-
for (const [
|
|
1142
|
+
for (const [label4, items] of sections) {
|
|
1209
1143
|
if (!items || items.length === 0) continue;
|
|
1210
1144
|
if (body.length > 0) body.push("");
|
|
1211
|
-
body.push(`${
|
|
1145
|
+
body.push(`${label4}:`);
|
|
1212
1146
|
for (const item of items) body.push(`- ${item}`);
|
|
1213
1147
|
}
|
|
1214
1148
|
const failures = report4.failures ?? [];
|
|
@@ -1233,41 +1167,41 @@ ${failure.message}` : headline);
|
|
|
1233
1167
|
}
|
|
1234
1168
|
|
|
1235
1169
|
// src/lib/template-files.ts
|
|
1236
|
-
import
|
|
1237
|
-
import
|
|
1170
|
+
import fs10 from "node:fs";
|
|
1171
|
+
import path9 from "node:path";
|
|
1238
1172
|
var PUBLISH_SAFE_NAMES = {
|
|
1239
1173
|
".gitignore": "_gitignore",
|
|
1240
1174
|
".npmrc": "_npmrc"
|
|
1241
1175
|
};
|
|
1242
1176
|
function templateName(projectRelPath) {
|
|
1243
|
-
const safe = PUBLISH_SAFE_NAMES[
|
|
1177
|
+
const safe = PUBLISH_SAFE_NAMES[path9.basename(projectRelPath)];
|
|
1244
1178
|
if (!safe) return projectRelPath;
|
|
1245
|
-
const dir =
|
|
1246
|
-
return dir === "." ? safe :
|
|
1179
|
+
const dir = path9.dirname(projectRelPath);
|
|
1180
|
+
return dir === "." ? safe : path9.join(dir, safe);
|
|
1247
1181
|
}
|
|
1248
1182
|
function restoreTemplateNames(target) {
|
|
1249
1183
|
for (const [real, safe] of Object.entries(PUBLISH_SAFE_NAMES)) {
|
|
1250
|
-
const from =
|
|
1251
|
-
if (!
|
|
1252
|
-
|
|
1184
|
+
const from = path9.join(target, safe);
|
|
1185
|
+
if (!fs10.existsSync(from)) continue;
|
|
1186
|
+
fs10.renameSync(from, path9.join(target, real));
|
|
1253
1187
|
}
|
|
1254
1188
|
}
|
|
1255
1189
|
var TEMPLATE_SOURCE = /\.template\.([^.]+)$/;
|
|
1256
1190
|
function applyTemplateFiles(target, values) {
|
|
1257
1191
|
const written = [];
|
|
1258
1192
|
for (const source of findTemplateSources(target)) {
|
|
1259
|
-
const raw =
|
|
1193
|
+
const raw = fs10.readFileSync(source, "utf8");
|
|
1260
1194
|
const dest = source.replace(TEMPLATE_SOURCE, ".$1");
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
written.push(
|
|
1195
|
+
fs10.writeFileSync(dest, fillTemplatePlaceholders(raw, values));
|
|
1196
|
+
fs10.unlinkSync(source);
|
|
1197
|
+
written.push(path9.relative(target, dest));
|
|
1264
1198
|
}
|
|
1265
1199
|
return written.sort();
|
|
1266
1200
|
}
|
|
1267
1201
|
function findTemplateSources(dir) {
|
|
1268
1202
|
const found = [];
|
|
1269
|
-
for (const entry of
|
|
1270
|
-
const full =
|
|
1203
|
+
for (const entry of fs10.readdirSync(dir, { withFileTypes: true })) {
|
|
1204
|
+
const full = path9.join(dir, entry.name);
|
|
1271
1205
|
if (entry.isDirectory()) {
|
|
1272
1206
|
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
1273
1207
|
found.push(...findTemplateSources(full));
|
|
@@ -1337,7 +1271,7 @@ async function blessProject(cwdArg, options) {
|
|
|
1337
1271
|
{
|
|
1338
1272
|
onCancel: () => {
|
|
1339
1273
|
p4.cancel("Operation cancelled.");
|
|
1340
|
-
|
|
1274
|
+
process5.exit(0);
|
|
1341
1275
|
}
|
|
1342
1276
|
}
|
|
1343
1277
|
);
|
|
@@ -1370,22 +1304,22 @@ async function blessProject(cwdArg, options) {
|
|
|
1370
1304
|
printNextSteps(projectPath, packageManager);
|
|
1371
1305
|
}
|
|
1372
1306
|
function resolveProjectPath(cwdArg) {
|
|
1373
|
-
const projectPath =
|
|
1374
|
-
if (!
|
|
1307
|
+
const projectPath = path10.resolve(cwdArg);
|
|
1308
|
+
if (!fs11.existsSync(projectPath)) {
|
|
1375
1309
|
throw new Error(`Path does not exist: ${projectPath}`);
|
|
1376
1310
|
}
|
|
1377
|
-
if (!
|
|
1311
|
+
if (!fs11.existsSync(path10.join(projectPath, "package.json"))) {
|
|
1378
1312
|
throw new Error(`No package.json found at ${projectPath}`);
|
|
1379
1313
|
}
|
|
1380
|
-
if (!
|
|
1314
|
+
if (!fs11.existsSync(path10.join(projectPath, "src", "routes"))) {
|
|
1381
1315
|
throw new Error(`No src/routes directory found at ${projectPath}`);
|
|
1382
1316
|
}
|
|
1383
1317
|
return projectPath;
|
|
1384
1318
|
}
|
|
1385
1319
|
function assertNotAlreadyBlessed(projectPath) {
|
|
1386
|
-
const hooksPath =
|
|
1387
|
-
if (!
|
|
1388
|
-
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");
|
|
1389
1323
|
if (content.includes("@velastack/pocketbase")) {
|
|
1390
1324
|
throw new Error(
|
|
1391
1325
|
"This project already looks blessed (src/hooks.server.ts imports @velastack/pocketbase). Run `vela sync` instead."
|
|
@@ -1393,8 +1327,8 @@ function assertNotAlreadyBlessed(projectPath) {
|
|
|
1393
1327
|
}
|
|
1394
1328
|
}
|
|
1395
1329
|
function mergeDependencies(projectPath, templateDir) {
|
|
1396
|
-
const userPkgPath =
|
|
1397
|
-
const templatePkgPath =
|
|
1330
|
+
const userPkgPath = path10.join(projectPath, "package.json");
|
|
1331
|
+
const templatePkgPath = path10.join(templateDir, "package.template.json");
|
|
1398
1332
|
const userPkg = readPackageJson(userPkgPath);
|
|
1399
1333
|
const appName = typeof userPkg.name === "string" ? userPkg.name : "sveltekit";
|
|
1400
1334
|
const templatePkg = readTemplatePackageJson(templatePkgPath, {
|
|
@@ -1426,21 +1360,21 @@ ${lines.join("\n")}`);
|
|
|
1426
1360
|
function copyVelaOnlyFiles(templateDir, projectPath) {
|
|
1427
1361
|
const kept = [];
|
|
1428
1362
|
for (const file of VELA_ONLY_FILES) {
|
|
1429
|
-
const src =
|
|
1430
|
-
const dest =
|
|
1431
|
-
if (!
|
|
1432
|
-
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)) {
|
|
1433
1367
|
kept.push(file);
|
|
1434
1368
|
continue;
|
|
1435
1369
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1370
|
+
fs11.mkdirSync(path10.dirname(dest), { recursive: true });
|
|
1371
|
+
fs11.copyFileSync(src, dest);
|
|
1438
1372
|
}
|
|
1439
1373
|
reportKeptFiles(kept);
|
|
1440
1374
|
for (const rel of VELA_ONLY_DIRS) {
|
|
1441
|
-
const src =
|
|
1442
|
-
const dest =
|
|
1443
|
-
if (!
|
|
1375
|
+
const src = path10.join(templateDir, rel);
|
|
1376
|
+
const dest = path10.join(projectPath, rel);
|
|
1377
|
+
if (!fs11.existsSync(src)) continue;
|
|
1444
1378
|
copyDirShallow(src, dest);
|
|
1445
1379
|
}
|
|
1446
1380
|
}
|
|
@@ -1454,15 +1388,15 @@ ${lines.join("\n")}`
|
|
|
1454
1388
|
);
|
|
1455
1389
|
}
|
|
1456
1390
|
function copyDirShallow(src, dest) {
|
|
1457
|
-
|
|
1458
|
-
for (const entry of
|
|
1391
|
+
fs11.mkdirSync(dest, { recursive: true });
|
|
1392
|
+
for (const entry of fs11.readdirSync(src, { withFileTypes: true })) {
|
|
1459
1393
|
if (entry.name === ".DS_Store") continue;
|
|
1460
|
-
const srcChild =
|
|
1461
|
-
const destChild =
|
|
1394
|
+
const srcChild = path10.join(src, entry.name);
|
|
1395
|
+
const destChild = path10.join(dest, entry.name);
|
|
1462
1396
|
if (entry.isDirectory()) {
|
|
1463
1397
|
copyDirShallow(srcChild, destChild);
|
|
1464
|
-
} else if (entry.isFile() && !
|
|
1465
|
-
|
|
1398
|
+
} else if (entry.isFile() && !fs11.existsSync(destChild)) {
|
|
1399
|
+
fs11.copyFileSync(srcChild, destChild);
|
|
1466
1400
|
}
|
|
1467
1401
|
}
|
|
1468
1402
|
}
|
|
@@ -1470,9 +1404,9 @@ function mergeConfigFiles(projectPath) {
|
|
|
1470
1404
|
const runes = mergeSvelteConfig(projectPath);
|
|
1471
1405
|
const outcomes = [
|
|
1472
1406
|
[runes.file ?? "svelte.config", runes],
|
|
1473
|
-
["vite.config.ts", mergeViteConfig(
|
|
1474
|
-
["tsconfig.json", mergeTsconfig(
|
|
1475
|
-
[".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"))]
|
|
1476
1410
|
];
|
|
1477
1411
|
for (const [name, outcome] of outcomes) {
|
|
1478
1412
|
if (outcome.applied) {
|
|
@@ -1489,14 +1423,14 @@ ${pc3.cyan(outcome.snippet)}`
|
|
|
1489
1423
|
}
|
|
1490
1424
|
}
|
|
1491
1425
|
function mergeAppDts(templateDir, projectPath) {
|
|
1492
|
-
const dest =
|
|
1493
|
-
const templateFile =
|
|
1494
|
-
if (!
|
|
1495
|
-
if (!
|
|
1496
|
-
|
|
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);
|
|
1497
1431
|
return;
|
|
1498
1432
|
}
|
|
1499
|
-
const current =
|
|
1433
|
+
const current = fs11.readFileSync(dest, "utf8");
|
|
1500
1434
|
if (current.includes("namespace Superforms")) return;
|
|
1501
1435
|
const block = ` namespace Superforms {
|
|
1502
1436
|
type Message = {
|
|
@@ -1515,7 +1449,7 @@ ${pc3.cyan(block)}`
|
|
|
1515
1449
|
}
|
|
1516
1450
|
const insertAt = match.index + match[0].length;
|
|
1517
1451
|
const updated = current.slice(0, insertAt) + block + current.slice(insertAt);
|
|
1518
|
-
|
|
1452
|
+
fs11.writeFileSync(dest, updated);
|
|
1519
1453
|
}
|
|
1520
1454
|
function maybeReplaceRoutes(projectPath, templateDir, options) {
|
|
1521
1455
|
if (options.skipRoutes) {
|
|
@@ -1526,12 +1460,12 @@ function maybeReplaceRoutes(projectPath, templateDir, options) {
|
|
|
1526
1460
|
p4.log.info("Leaving src/routes alone (looks customized).");
|
|
1527
1461
|
return;
|
|
1528
1462
|
}
|
|
1529
|
-
const target =
|
|
1530
|
-
|
|
1531
|
-
const src =
|
|
1532
|
-
|
|
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, {
|
|
1533
1467
|
recursive: true,
|
|
1534
|
-
filter: (s) =>
|
|
1468
|
+
filter: (s) => path10.basename(s) !== ".DS_Store"
|
|
1535
1469
|
});
|
|
1536
1470
|
p4.log.success("Replaced src/routes with the vela template.");
|
|
1537
1471
|
}
|
|
@@ -1540,7 +1474,7 @@ function summarize(names) {
|
|
|
1540
1474
|
return `${names.slice(0, 3).join(", ")}, and ${names.length - 3} more`;
|
|
1541
1475
|
}
|
|
1542
1476
|
function printNextSteps(projectPath, packageManager) {
|
|
1543
|
-
const relative =
|
|
1477
|
+
const relative = path10.relative(process5.cwd(), projectPath);
|
|
1544
1478
|
const pm = packageManager ?? getUserAgent() ?? "npm";
|
|
1545
1479
|
const nextSteps = [];
|
|
1546
1480
|
if (relative !== "") {
|
|
@@ -1564,9 +1498,9 @@ function printNextSteps(projectPath, packageManager) {
|
|
|
1564
1498
|
}
|
|
1565
1499
|
|
|
1566
1500
|
// src/commands/create.ts
|
|
1567
|
-
import
|
|
1568
|
-
import
|
|
1569
|
-
import
|
|
1501
|
+
import fs12 from "node:fs";
|
|
1502
|
+
import path11 from "node:path";
|
|
1503
|
+
import process6 from "node:process";
|
|
1570
1504
|
import * as v3 from "valibot";
|
|
1571
1505
|
import { Command as Command3 } from "commander";
|
|
1572
1506
|
import * as p5 from "@clack/prompts";
|
|
@@ -1588,7 +1522,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
|
|
|
1588
1522
|
projectPath,
|
|
1589
1523
|
options
|
|
1590
1524
|
);
|
|
1591
|
-
const relative =
|
|
1525
|
+
const relative = path11.relative(process6.cwd(), directory);
|
|
1592
1526
|
const pm = packageManager ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
|
|
1593
1527
|
const nextSteps = [];
|
|
1594
1528
|
if (relative !== "") {
|
|
@@ -1627,7 +1561,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
|
|
|
1627
1561
|
async function createProject(cwdArg, options) {
|
|
1628
1562
|
const onCancel2 = () => {
|
|
1629
1563
|
p5.cancel("Operation cancelled.");
|
|
1630
|
-
|
|
1564
|
+
process6.exit(0);
|
|
1631
1565
|
};
|
|
1632
1566
|
const template = findProjectTemplate(options.template ?? DEFAULT_TEMPLATE);
|
|
1633
1567
|
if (!template.backend && (options.email || options.password)) {
|
|
@@ -1637,7 +1571,7 @@ async function createProject(cwdArg, options) {
|
|
|
1637
1571
|
}
|
|
1638
1572
|
let directory;
|
|
1639
1573
|
if (cwdArg) {
|
|
1640
|
-
directory =
|
|
1574
|
+
directory = path11.resolve(cwdArg);
|
|
1641
1575
|
} else {
|
|
1642
1576
|
const answer = await p5.text({
|
|
1643
1577
|
message: "Where would you like your project to be created?",
|
|
@@ -1645,16 +1579,16 @@ async function createProject(cwdArg, options) {
|
|
|
1645
1579
|
defaultValue: "./"
|
|
1646
1580
|
});
|
|
1647
1581
|
if (p5.isCancel(answer)) onCancel2();
|
|
1648
|
-
directory =
|
|
1582
|
+
directory = path11.resolve(answer);
|
|
1649
1583
|
}
|
|
1650
|
-
if (
|
|
1584
|
+
if (fs12.existsSync(directory) && fs12.readdirSync(directory).filter((f) => !f.startsWith(".git")).length > 0) {
|
|
1651
1585
|
const force = await p5.confirm({
|
|
1652
1586
|
message: "Directory not empty. Continue?",
|
|
1653
1587
|
initialValue: false
|
|
1654
1588
|
});
|
|
1655
1589
|
if (p5.isCancel(force) || !force) onCancel2();
|
|
1656
1590
|
}
|
|
1657
|
-
const dirName =
|
|
1591
|
+
const dirName = path11.basename(directory);
|
|
1658
1592
|
const { name } = await p5.group(
|
|
1659
1593
|
{
|
|
1660
1594
|
name: () => {
|
|
@@ -1672,7 +1606,7 @@ async function createProject(cwdArg, options) {
|
|
|
1672
1606
|
const projectPath = directory;
|
|
1673
1607
|
copyTemplate(template, projectPath);
|
|
1674
1608
|
applyTemplateFiles(projectPath, { appName: name, cliVersion: package_default.version });
|
|
1675
|
-
if (!
|
|
1609
|
+
if (!fs12.existsSync(path11.join(projectPath, "package.json"))) {
|
|
1676
1610
|
throw new Error(`Template ${template.name} is missing package.template.json`);
|
|
1677
1611
|
}
|
|
1678
1612
|
p5.log.success("Project created");
|
|
@@ -1734,11 +1668,11 @@ function promptCredentials(options, onCancel2) {
|
|
|
1734
1668
|
);
|
|
1735
1669
|
}
|
|
1736
1670
|
function copyTemplate(template, target) {
|
|
1737
|
-
|
|
1738
|
-
|
|
1671
|
+
fs12.mkdirSync(target, { recursive: true });
|
|
1672
|
+
fs12.cpSync(template.dir, target, {
|
|
1739
1673
|
recursive: true,
|
|
1740
1674
|
// The manifest describes the template to the CLI; it isn't part of the project.
|
|
1741
|
-
filter: (src) =>
|
|
1675
|
+
filter: (src) => path11.basename(src) !== ".DS_Store" && path11.relative(template.dir, src) !== TEMPLATE_MANIFEST
|
|
1742
1676
|
});
|
|
1743
1677
|
restoreTemplateNames(target);
|
|
1744
1678
|
}
|
|
@@ -1751,14 +1685,14 @@ import { Command as Command4 } from "commander";
|
|
|
1751
1685
|
import * as p11 from "@clack/prompts";
|
|
1752
1686
|
|
|
1753
1687
|
// src/lib/pattern-runner.ts
|
|
1754
|
-
import
|
|
1688
|
+
import path12 from "node:path";
|
|
1755
1689
|
import * as p6 from "@clack/prompts";
|
|
1756
1690
|
import { bySlug } from "@velastack/patterns";
|
|
1757
1691
|
function toRelative(root, filePath) {
|
|
1758
|
-
return
|
|
1692
|
+
return path12.isAbsolute(filePath) ? path12.relative(root, filePath) : filePath;
|
|
1759
1693
|
}
|
|
1760
1694
|
var isSuccess = (f) => (f.status ?? "success") === "success";
|
|
1761
|
-
async function runPattern(slug2,
|
|
1695
|
+
async function runPattern(slug2, argv, input, report4) {
|
|
1762
1696
|
const pattern = bySlug[slug2];
|
|
1763
1697
|
if (!pattern) {
|
|
1764
1698
|
throw new Error(`Unknown pattern: ${slug2}`);
|
|
@@ -1768,7 +1702,7 @@ async function runPattern(slug2, argv2, input, report4) {
|
|
|
1768
1702
|
let result;
|
|
1769
1703
|
try {
|
|
1770
1704
|
result = await pattern.generate({
|
|
1771
|
-
argv
|
|
1705
|
+
argv,
|
|
1772
1706
|
env: "runtime",
|
|
1773
1707
|
root: workspaceRootDir,
|
|
1774
1708
|
features,
|
|
@@ -1822,31 +1756,31 @@ async function runPattern(slug2, argv2, input, report4) {
|
|
|
1822
1756
|
}
|
|
1823
1757
|
|
|
1824
1758
|
// src/lib/ai-flow.ts
|
|
1825
|
-
import
|
|
1826
|
-
import
|
|
1759
|
+
import fs15 from "node:fs";
|
|
1760
|
+
import path15 from "node:path";
|
|
1827
1761
|
import * as p10 from "@clack/prompts";
|
|
1828
1762
|
import pc4 from "picocolors";
|
|
1829
1763
|
|
|
1830
1764
|
// src/lib/config.ts
|
|
1831
|
-
import
|
|
1765
|
+
import fs13 from "node:fs";
|
|
1832
1766
|
import os from "node:os";
|
|
1833
|
-
import
|
|
1834
|
-
var CONFIG_DIR =
|
|
1835
|
-
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");
|
|
1836
1770
|
function readConfig() {
|
|
1837
|
-
if (!
|
|
1771
|
+
if (!fs13.existsSync(CONFIG_PATH)) return null;
|
|
1838
1772
|
try {
|
|
1839
|
-
return JSON.parse(
|
|
1773
|
+
return JSON.parse(fs13.readFileSync(CONFIG_PATH, "utf8"));
|
|
1840
1774
|
} catch {
|
|
1841
1775
|
return null;
|
|
1842
1776
|
}
|
|
1843
1777
|
}
|
|
1844
1778
|
function writeConfig(config) {
|
|
1845
|
-
|
|
1846
|
-
|
|
1779
|
+
fs13.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
1780
|
+
fs13.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
1847
1781
|
}
|
|
1848
1782
|
function clearConfig() {
|
|
1849
|
-
if (
|
|
1783
|
+
if (fs13.existsSync(CONFIG_PATH)) fs13.unlinkSync(CONFIG_PATH);
|
|
1850
1784
|
}
|
|
1851
1785
|
function requireApiKey() {
|
|
1852
1786
|
const config = readConfig();
|
|
@@ -1857,16 +1791,16 @@ function requireApiKey() {
|
|
|
1857
1791
|
}
|
|
1858
1792
|
|
|
1859
1793
|
// src/lib/project-config.ts
|
|
1860
|
-
import
|
|
1861
|
-
import
|
|
1794
|
+
import fs14 from "node:fs";
|
|
1795
|
+
import path14 from "node:path";
|
|
1862
1796
|
function projectConfigPath(workspaceRootDir) {
|
|
1863
|
-
return
|
|
1797
|
+
return path14.join(workspaceRootDir, ".vela", "project.json");
|
|
1864
1798
|
}
|
|
1865
1799
|
function readProjectConfig(workspaceRootDir) {
|
|
1866
1800
|
const file = projectConfigPath(workspaceRootDir);
|
|
1867
|
-
if (!
|
|
1801
|
+
if (!fs14.existsSync(file)) return null;
|
|
1868
1802
|
try {
|
|
1869
|
-
const parsed = JSON.parse(
|
|
1803
|
+
const parsed = JSON.parse(fs14.readFileSync(file, "utf8"));
|
|
1870
1804
|
if (typeof parsed.projectId !== "string" || typeof parsed.teamId !== "string" || typeof parsed.projectName !== "string") {
|
|
1871
1805
|
return null;
|
|
1872
1806
|
}
|
|
@@ -1881,15 +1815,15 @@ function readProjectConfig(workspaceRootDir) {
|
|
|
1881
1815
|
}
|
|
1882
1816
|
function writeProjectConfig(workspaceRootDir, config) {
|
|
1883
1817
|
const file = projectConfigPath(workspaceRootDir);
|
|
1884
|
-
|
|
1818
|
+
fs14.mkdirSync(path14.dirname(file), { recursive: true });
|
|
1885
1819
|
let existing = {};
|
|
1886
|
-
if (
|
|
1820
|
+
if (fs14.existsSync(file)) {
|
|
1887
1821
|
try {
|
|
1888
|
-
existing = JSON.parse(
|
|
1822
|
+
existing = JSON.parse(fs14.readFileSync(file, "utf8"));
|
|
1889
1823
|
} catch {
|
|
1890
1824
|
}
|
|
1891
1825
|
}
|
|
1892
|
-
|
|
1826
|
+
fs14.writeFileSync(file, JSON.stringify({ ...existing, ...config }, null, 2) + "\n");
|
|
1893
1827
|
}
|
|
1894
1828
|
|
|
1895
1829
|
// src/lib/ai-client.ts
|
|
@@ -2014,7 +1948,7 @@ function typeArg(field) {
|
|
|
2014
1948
|
return null;
|
|
2015
1949
|
}
|
|
2016
1950
|
function collectionSpecToArgv(spec) {
|
|
2017
|
-
const
|
|
1951
|
+
const argv = [spec.name];
|
|
2018
1952
|
for (const field of spec.fields) {
|
|
2019
1953
|
const type = typeArg(field);
|
|
2020
1954
|
if (type === null) {
|
|
@@ -2024,9 +1958,9 @@ function collectionSpecToArgv(spec) {
|
|
|
2024
1958
|
continue;
|
|
2025
1959
|
}
|
|
2026
1960
|
const required = field.required ? "!" : "";
|
|
2027
|
-
|
|
1961
|
+
argv.push(`${field.name}:${type}${required}`);
|
|
2028
1962
|
}
|
|
2029
|
-
return
|
|
1963
|
+
return argv;
|
|
2030
1964
|
}
|
|
2031
1965
|
|
|
2032
1966
|
// src/lib/ai-grid.ts
|
|
@@ -2163,11 +2097,11 @@ function specToArgv(spec) {
|
|
|
2163
2097
|
return collectionSpecToArgv(spec);
|
|
2164
2098
|
}
|
|
2165
2099
|
function writeLayoutSidecar(workspaceRootDir, modelName, layout) {
|
|
2166
|
-
const dir =
|
|
2167
|
-
|
|
2168
|
-
const file =
|
|
2169
|
-
|
|
2170
|
-
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);
|
|
2171
2105
|
}
|
|
2172
2106
|
|
|
2173
2107
|
// src/commands/generate/form.ts
|
|
@@ -2179,7 +2113,7 @@ var form = new Command4("form").description("generate a form from a model").argu
|
|
|
2179
2113
|
"design the form with AI from a natural-language description (two stages: schema \u2192 layout)"
|
|
2180
2114
|
).allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
2181
2115
|
(model, fields, options) => runCommand(async () => {
|
|
2182
|
-
let
|
|
2116
|
+
let argv;
|
|
2183
2117
|
let modelName;
|
|
2184
2118
|
let sidecarPath = null;
|
|
2185
2119
|
if (options.ai) {
|
|
@@ -2196,14 +2130,14 @@ var form = new Command4("form").description("generate a form from a model").argu
|
|
|
2196
2130
|
p11.cancel("Aborted before any files were written.");
|
|
2197
2131
|
return;
|
|
2198
2132
|
}
|
|
2199
|
-
|
|
2133
|
+
argv = specToArgv(stage2.model);
|
|
2200
2134
|
modelName = stage2.model.name;
|
|
2201
2135
|
sidecarPath = writeLayoutSidecar(stage2.workspaceRootDir, modelName, layout);
|
|
2202
2136
|
} else {
|
|
2203
2137
|
if (!model) {
|
|
2204
2138
|
throw new Error("Missing required argument: model. Pass a model name or use --ai.");
|
|
2205
2139
|
}
|
|
2206
|
-
|
|
2140
|
+
argv = [model, ...fields];
|
|
2207
2141
|
modelName = model;
|
|
2208
2142
|
}
|
|
2209
2143
|
const slug2 = options.remote ? "generate-form-remote" : "generate-form";
|
|
@@ -2218,7 +2152,7 @@ var form = new Command4("form").description("generate a form from a model").argu
|
|
|
2218
2152
|
}
|
|
2219
2153
|
await runPattern(
|
|
2220
2154
|
slug2,
|
|
2221
|
-
|
|
2155
|
+
argv,
|
|
2222
2156
|
{ route: options.route },
|
|
2223
2157
|
{
|
|
2224
2158
|
summary: `Created ${modelName} form.`,
|
|
@@ -2238,7 +2172,7 @@ import { Command as Command5 } from "commander";
|
|
|
2238
2172
|
import * as p12 from "@clack/prompts";
|
|
2239
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(
|
|
2240
2174
|
(model, fields, options) => runCommand(async () => {
|
|
2241
|
-
let
|
|
2175
|
+
let argv;
|
|
2242
2176
|
let modelName;
|
|
2243
2177
|
if (options.ai) {
|
|
2244
2178
|
if (model) {
|
|
@@ -2249,18 +2183,18 @@ var schema = new Command5("schema").description("generate a schema from a model"
|
|
|
2249
2183
|
p12.cancel("Aborted before any files were written.");
|
|
2250
2184
|
return;
|
|
2251
2185
|
}
|
|
2252
|
-
|
|
2186
|
+
argv = specToArgv(stage2.model);
|
|
2253
2187
|
modelName = stage2.model.name;
|
|
2254
2188
|
} else {
|
|
2255
2189
|
if (!model) {
|
|
2256
2190
|
throw new Error("Missing required argument: model. Pass a model name or use --ai.");
|
|
2257
2191
|
}
|
|
2258
|
-
|
|
2192
|
+
argv = [model, ...fields];
|
|
2259
2193
|
modelName = model;
|
|
2260
2194
|
}
|
|
2261
2195
|
await runPattern(
|
|
2262
2196
|
"generate-schema",
|
|
2263
|
-
|
|
2197
|
+
argv,
|
|
2264
2198
|
{},
|
|
2265
2199
|
{
|
|
2266
2200
|
summary: `Created ${modelName} schema.`,
|
|
@@ -2315,7 +2249,7 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
|
|
|
2315
2249
|
"design the scaffold with AI from a natural-language description (two stages: schema \u2192 layout)"
|
|
2316
2250
|
).allowUnknownOption(true).configureHelp(helpConfig).action(
|
|
2317
2251
|
(model, fields, options) => runCommand(async () => {
|
|
2318
|
-
let
|
|
2252
|
+
let argv;
|
|
2319
2253
|
let modelName;
|
|
2320
2254
|
let sidecarPath = null;
|
|
2321
2255
|
if (options.ai) {
|
|
@@ -2332,14 +2266,14 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
|
|
|
2332
2266
|
p13.cancel("Aborted before any files were written.");
|
|
2333
2267
|
return;
|
|
2334
2268
|
}
|
|
2335
|
-
|
|
2269
|
+
argv = specToArgv(stage2.model);
|
|
2336
2270
|
modelName = stage2.model.name;
|
|
2337
2271
|
sidecarPath = writeLayoutSidecar(stage2.workspaceRootDir, modelName, layout);
|
|
2338
2272
|
} else {
|
|
2339
2273
|
if (!model) {
|
|
2340
2274
|
throw new Error("Missing required argument: model. Pass a model name or use --ai.");
|
|
2341
2275
|
}
|
|
2342
|
-
|
|
2276
|
+
argv = [model, ...fields];
|
|
2343
2277
|
modelName = model;
|
|
2344
2278
|
}
|
|
2345
2279
|
const slug2 = options.remote ? "generate-scaffold-remote" : "generate-scaffold";
|
|
@@ -2355,7 +2289,7 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
|
|
|
2355
2289
|
}
|
|
2356
2290
|
await runPattern(
|
|
2357
2291
|
slug2,
|
|
2358
|
-
|
|
2292
|
+
argv,
|
|
2359
2293
|
{ route: options.route },
|
|
2360
2294
|
{
|
|
2361
2295
|
summary: `Created ${modelName} scaffold.`,
|
|
@@ -2558,7 +2492,7 @@ var teams = new Command15("teams").description("enable team / multi-tenant suppo
|
|
|
2558
2492
|
);
|
|
2559
2493
|
|
|
2560
2494
|
// src/commands/enable/payments.ts
|
|
2561
|
-
import
|
|
2495
|
+
import process7 from "node:process";
|
|
2562
2496
|
import { Command as Command16 } from "commander";
|
|
2563
2497
|
import * as p14 from "@clack/prompts";
|
|
2564
2498
|
var PROVIDERS = [{ value: "stripe", label: "Stripe" }];
|
|
@@ -2604,12 +2538,12 @@ async function resolveProvider(value, source) {
|
|
|
2604
2538
|
});
|
|
2605
2539
|
if (p14.isCancel(selected)) {
|
|
2606
2540
|
p14.cancel("Operation cancelled.");
|
|
2607
|
-
|
|
2541
|
+
process7.exit(0);
|
|
2608
2542
|
}
|
|
2609
2543
|
return selected;
|
|
2610
2544
|
}
|
|
2611
2545
|
async function ensureWebhookSecret() {
|
|
2612
|
-
const existing =
|
|
2546
|
+
const existing = process7.env.STRIPE_WEBHOOK_SECRET;
|
|
2613
2547
|
if (existing) return existing;
|
|
2614
2548
|
p14.note(
|
|
2615
2549
|
[
|
|
@@ -2637,12 +2571,12 @@ async function ensurePriceId() {
|
|
|
2637
2571
|
});
|
|
2638
2572
|
if (p14.isCancel(value)) {
|
|
2639
2573
|
p14.cancel("Operation cancelled.");
|
|
2640
|
-
|
|
2574
|
+
process7.exit(0);
|
|
2641
2575
|
}
|
|
2642
2576
|
return (value ?? "").trim();
|
|
2643
2577
|
}
|
|
2644
2578
|
async function ensureKey(envVar, message) {
|
|
2645
|
-
const existing =
|
|
2579
|
+
const existing = process7.env[envVar];
|
|
2646
2580
|
if (existing) return existing;
|
|
2647
2581
|
return promptPassword(message);
|
|
2648
2582
|
}
|
|
@@ -2653,7 +2587,7 @@ async function promptPassword(message) {
|
|
|
2653
2587
|
});
|
|
2654
2588
|
if (p14.isCancel(value)) {
|
|
2655
2589
|
p14.cancel("Operation cancelled.");
|
|
2656
|
-
|
|
2590
|
+
process7.exit(0);
|
|
2657
2591
|
}
|
|
2658
2592
|
return value;
|
|
2659
2593
|
}
|
|
@@ -2685,20 +2619,20 @@ var subscriptions = new Command17("subscriptions").description("enable Stripe su
|
|
|
2685
2619
|
);
|
|
2686
2620
|
|
|
2687
2621
|
// src/commands/enable/s3.ts
|
|
2688
|
-
import
|
|
2622
|
+
import process10 from "node:process";
|
|
2689
2623
|
import { Command as Command18 } from "commander";
|
|
2690
2624
|
import * as p17 from "@clack/prompts";
|
|
2691
2625
|
import pc8 from "picocolors";
|
|
2692
2626
|
|
|
2693
2627
|
// src/lib/server-command.ts
|
|
2694
|
-
import
|
|
2628
|
+
import process9 from "node:process";
|
|
2695
2629
|
import * as v5 from "valibot";
|
|
2696
2630
|
import * as p15 from "@clack/prompts";
|
|
2697
2631
|
import pc5 from "picocolors";
|
|
2698
2632
|
|
|
2699
2633
|
// src/lib/deploy-config.ts
|
|
2700
|
-
import
|
|
2701
|
-
import
|
|
2634
|
+
import fs16 from "node:fs";
|
|
2635
|
+
import path16 from "node:path";
|
|
2702
2636
|
import crypto from "node:crypto";
|
|
2703
2637
|
import { pathToFileURL } from "node:url";
|
|
2704
2638
|
var CONFIG_BASENAMES = [
|
|
@@ -2709,8 +2643,8 @@ var CONFIG_BASENAMES = [
|
|
|
2709
2643
|
];
|
|
2710
2644
|
function findConfigFile(workspaceRootDir) {
|
|
2711
2645
|
for (const name of CONFIG_BASENAMES) {
|
|
2712
|
-
const file =
|
|
2713
|
-
if (
|
|
2646
|
+
const file = path16.join(workspaceRootDir, name);
|
|
2647
|
+
if (fs16.existsSync(file)) return file;
|
|
2714
2648
|
}
|
|
2715
2649
|
return null;
|
|
2716
2650
|
}
|
|
@@ -2718,49 +2652,49 @@ async function loadDeployConfig(workspaceRootDir) {
|
|
|
2718
2652
|
const file = findConfigFile(workspaceRootDir);
|
|
2719
2653
|
if (!file) return {};
|
|
2720
2654
|
if (file.endsWith(".json")) {
|
|
2721
|
-
return JSON.parse(
|
|
2655
|
+
return JSON.parse(fs16.readFileSync(file, "utf8"));
|
|
2722
2656
|
}
|
|
2723
2657
|
const url = file.endsWith(".ts") ? await transpileToTemp(file) : pathToFileURL(file).href;
|
|
2724
2658
|
try {
|
|
2725
2659
|
const mod = await import(url);
|
|
2726
2660
|
const config = mod.default;
|
|
2727
2661
|
if (!config || typeof config !== "object") {
|
|
2728
|
-
throw new Error(`${
|
|
2662
|
+
throw new Error(`${path16.basename(file)} must export a config object as its default export.`);
|
|
2729
2663
|
}
|
|
2730
2664
|
return config;
|
|
2731
2665
|
} finally {
|
|
2732
|
-
if (url !== pathToFileURL(file).href)
|
|
2666
|
+
if (url !== pathToFileURL(file).href) fs16.rmSync(new URL(url), { force: true });
|
|
2733
2667
|
}
|
|
2734
2668
|
}
|
|
2735
2669
|
async function transpileToTemp(file) {
|
|
2736
2670
|
const { ts } = await import("ts-morph");
|
|
2737
|
-
const source =
|
|
2671
|
+
const source = fs16.readFileSync(file, "utf8");
|
|
2738
2672
|
const { outputText } = ts.transpileModule(source, {
|
|
2739
2673
|
compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 }
|
|
2740
2674
|
});
|
|
2741
|
-
const temp =
|
|
2742
|
-
|
|
2675
|
+
const temp = path16.join(
|
|
2676
|
+
path16.dirname(file),
|
|
2743
2677
|
`.velastack.config.${crypto.randomBytes(4).toString("hex")}.mjs`
|
|
2744
2678
|
);
|
|
2745
|
-
|
|
2679
|
+
fs16.writeFileSync(temp, outputText);
|
|
2746
2680
|
return pathToFileURL(temp).href;
|
|
2747
2681
|
}
|
|
2748
2682
|
function projectFilePath(workspaceRootDir) {
|
|
2749
|
-
return
|
|
2683
|
+
return path16.join(workspaceRootDir, ".vela", "project.json");
|
|
2750
2684
|
}
|
|
2751
2685
|
function readProjectFile(workspaceRootDir) {
|
|
2752
2686
|
const file = projectFilePath(workspaceRootDir);
|
|
2753
|
-
if (!
|
|
2687
|
+
if (!fs16.existsSync(file)) return {};
|
|
2754
2688
|
try {
|
|
2755
|
-
return JSON.parse(
|
|
2689
|
+
return JSON.parse(fs16.readFileSync(file, "utf8"));
|
|
2756
2690
|
} catch {
|
|
2757
2691
|
return {};
|
|
2758
2692
|
}
|
|
2759
2693
|
}
|
|
2760
2694
|
function writeProjectFile(workspaceRootDir, data) {
|
|
2761
2695
|
const file = projectFilePath(workspaceRootDir);
|
|
2762
|
-
|
|
2763
|
-
|
|
2696
|
+
fs16.mkdirSync(path16.dirname(file), { recursive: true });
|
|
2697
|
+
fs16.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
|
|
2764
2698
|
}
|
|
2765
2699
|
function resolveAppIdentity(workspaceRootDir, config = {}) {
|
|
2766
2700
|
const project = readProjectFile(workspaceRootDir);
|
|
@@ -2785,11 +2719,11 @@ function readAppIdentity(workspaceRootDir, config = {}) {
|
|
|
2785
2719
|
}
|
|
2786
2720
|
function defaultProjectName(workspaceRootDir) {
|
|
2787
2721
|
try {
|
|
2788
|
-
const pkg = readPackageJson(
|
|
2722
|
+
const pkg = readPackageJson(path16.join(workspaceRootDir, "package.json"));
|
|
2789
2723
|
if (typeof pkg.name === "string" && pkg.name.trim()) return pkg.name.trim();
|
|
2790
2724
|
} catch {
|
|
2791
2725
|
}
|
|
2792
|
-
return
|
|
2726
|
+
return path16.basename(workspaceRootDir);
|
|
2793
2727
|
}
|
|
2794
2728
|
function slug(value) {
|
|
2795
2729
|
return value.toLowerCase().replace(/^@/, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 32) || "app";
|
|
@@ -2868,11 +2802,11 @@ function sshOptionsFrom(options) {
|
|
|
2868
2802
|
}
|
|
2869
2803
|
|
|
2870
2804
|
// src/lib/ssh.ts
|
|
2871
|
-
import
|
|
2805
|
+
import fs17 from "node:fs";
|
|
2872
2806
|
import os2 from "node:os";
|
|
2873
|
-
import
|
|
2807
|
+
import path17 from "node:path";
|
|
2874
2808
|
import crypto2 from "node:crypto";
|
|
2875
|
-
import
|
|
2809
|
+
import process8 from "node:process";
|
|
2876
2810
|
import { spawn as spawn2 } from "node:child_process";
|
|
2877
2811
|
var RemoteCommandError = class extends Error {
|
|
2878
2812
|
exitCode;
|
|
@@ -2913,9 +2847,9 @@ var SshSession = class {
|
|
|
2913
2847
|
}
|
|
2914
2848
|
async open() {
|
|
2915
2849
|
if (this.controlPath) return;
|
|
2916
|
-
const dir =
|
|
2917
|
-
|
|
2918
|
-
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`);
|
|
2919
2853
|
this.controlPath = socket;
|
|
2920
2854
|
const args = [
|
|
2921
2855
|
...this.sshArgs(),
|
|
@@ -3150,17 +3084,17 @@ function spawnCapture(command, args, opts = {}) {
|
|
|
3150
3084
|
const child = spawn2(command, args, {
|
|
3151
3085
|
stdio,
|
|
3152
3086
|
cwd: opts.cwd,
|
|
3153
|
-
env: opts.env ? { ...
|
|
3087
|
+
env: opts.env ? { ...process8.env, ...opts.env } : void 0
|
|
3154
3088
|
});
|
|
3155
3089
|
let stdout = "";
|
|
3156
3090
|
let stderr = "";
|
|
3157
3091
|
child.stdout?.on("data", (chunk) => {
|
|
3158
3092
|
stdout += chunk;
|
|
3159
|
-
if (opts.streamStdout)
|
|
3093
|
+
if (opts.streamStdout) process8.stdout.write(chunk);
|
|
3160
3094
|
});
|
|
3161
3095
|
child.stderr?.on("data", (chunk) => {
|
|
3162
3096
|
stderr += chunk;
|
|
3163
|
-
if (opts.stream)
|
|
3097
|
+
if (opts.stream) process8.stderr.write(chunk);
|
|
3164
3098
|
});
|
|
3165
3099
|
child.on("error", reject);
|
|
3166
3100
|
child.on("close", (code) => resolve2({ stdout, stderr, exitCode: code ?? 1 }));
|
|
@@ -3171,14 +3105,14 @@ function spawnCapture(command, args, opts = {}) {
|
|
|
3171
3105
|
}
|
|
3172
3106
|
|
|
3173
3107
|
// src/lib/remote.ts
|
|
3174
|
-
import
|
|
3108
|
+
import path18 from "node:path";
|
|
3175
3109
|
var VELA_ROOT = "/var/lib/vela";
|
|
3176
3110
|
var VELA_ETC = "/etc/vela";
|
|
3177
3111
|
var VELA_USER = "vela";
|
|
3178
3112
|
var SCRIPTS_DIR = `${VELA_ROOT}/scripts`;
|
|
3179
3113
|
var PROVISIONED_MARKER = `${VELA_ETC}/provisioned`;
|
|
3180
3114
|
function serverTemplatesDir() {
|
|
3181
|
-
return
|
|
3115
|
+
return path18.join(templatesDir(), "server");
|
|
3182
3116
|
}
|
|
3183
3117
|
async function syncServerScripts(session) {
|
|
3184
3118
|
await session.script(`mkdir -p "$1" && chmod 0755 "$1"`, { args: [SCRIPTS_DIR] });
|
|
@@ -3246,7 +3180,7 @@ var remotePaths = {
|
|
|
3246
3180
|
};
|
|
3247
3181
|
|
|
3248
3182
|
// src/lib/remote-env.ts
|
|
3249
|
-
import
|
|
3183
|
+
import fs18 from "node:fs";
|
|
3250
3184
|
import dotenv from "dotenv";
|
|
3251
3185
|
var KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
3252
3186
|
function isValidKey(key) {
|
|
@@ -3294,7 +3228,7 @@ function quote(value) {
|
|
|
3294
3228
|
return `"${escaped}"`;
|
|
3295
3229
|
}
|
|
3296
3230
|
function readLocalEnvFile(file) {
|
|
3297
|
-
const parsed = dotenv.parse(
|
|
3231
|
+
const parsed = dotenv.parse(fs18.readFileSync(file));
|
|
3298
3232
|
const result = {};
|
|
3299
3233
|
for (const [key, value] of Object.entries(parsed)) {
|
|
3300
3234
|
if (isValidKey(key)) result[key] = value;
|
|
@@ -3415,7 +3349,7 @@ function addTargetOptions(command, fallback) {
|
|
|
3415
3349
|
async function withTarget(raw, handlers, run = {}) {
|
|
3416
3350
|
const options = parseOptions(OptionsSchema, raw);
|
|
3417
3351
|
const target = parseTarget(options.target, "production");
|
|
3418
|
-
const
|
|
3352
|
+
const label4 = run.label ? `vela ${run.label}` : "this command";
|
|
3419
3353
|
if (target.kind === "preview") {
|
|
3420
3354
|
throw new Error(
|
|
3421
3355
|
`Preview targets are not supported yet.
|
|
@@ -3439,7 +3373,7 @@ DNS and certificates that \`vela provision\` does not set up yet.`
|
|
|
3439
3373
|
if (target.kind === "local") {
|
|
3440
3374
|
if (!handlers.local) {
|
|
3441
3375
|
throw new Error(
|
|
3442
|
-
`${
|
|
3376
|
+
`${label4} has no local target.` + (run.localHint ? `
|
|
3443
3377
|
|
|
3444
3378
|
${run.localHint}` : "")
|
|
3445
3379
|
);
|
|
@@ -3452,7 +3386,7 @@ ${run.localHint}` : "")
|
|
|
3452
3386
|
return;
|
|
3453
3387
|
}
|
|
3454
3388
|
if (!handlers.remote) {
|
|
3455
|
-
throw new Error(`${
|
|
3389
|
+
throw new Error(`${label4} only acts on ${pc5.cyan("local")}.`);
|
|
3456
3390
|
}
|
|
3457
3391
|
const binding = await ensureBinding(workspaceRootDir, target, {
|
|
3458
3392
|
server: options.server,
|
|
@@ -3500,7 +3434,7 @@ longer reach it. Remove it there first if that was not intended.`
|
|
|
3500
3434
|
return binding;
|
|
3501
3435
|
}
|
|
3502
3436
|
async function promptServer(target) {
|
|
3503
|
-
if (!
|
|
3437
|
+
if (!process9.stdout.isTTY || process9.env.CI) {
|
|
3504
3438
|
throw new Error(
|
|
3505
3439
|
`${target.name} is not bound to a server yet, and there is no terminal to ask on.
|
|
3506
3440
|
|
|
@@ -3516,19 +3450,19 @@ and commit ${pc5.cyan(".vela/project.json")}.`
|
|
|
3516
3450
|
});
|
|
3517
3451
|
if (p15.isCancel(value)) {
|
|
3518
3452
|
p15.cancel("Operation cancelled.");
|
|
3519
|
-
|
|
3453
|
+
process9.exit(0);
|
|
3520
3454
|
}
|
|
3521
3455
|
return value.trim();
|
|
3522
3456
|
}
|
|
3523
3457
|
async function promptDomain(target) {
|
|
3524
|
-
if (!
|
|
3458
|
+
if (!process9.stdout.isTTY || process9.env.CI) return void 0;
|
|
3525
3459
|
const value = await p15.text({
|
|
3526
3460
|
message: `Which hostname should ${target.name} be served on?`,
|
|
3527
3461
|
placeholder: "example.com \u2014 leave blank to decide later"
|
|
3528
3462
|
});
|
|
3529
3463
|
if (p15.isCancel(value)) {
|
|
3530
3464
|
p15.cancel("Operation cancelled.");
|
|
3531
|
-
|
|
3465
|
+
process9.exit(0);
|
|
3532
3466
|
}
|
|
3533
3467
|
return value.trim() || void 0;
|
|
3534
3468
|
}
|
|
@@ -3584,17 +3518,17 @@ function envFilePath(workspaceRootDir) {
|
|
|
3584
3518
|
import pc7 from "picocolors";
|
|
3585
3519
|
|
|
3586
3520
|
// src/lib/local-env.ts
|
|
3587
|
-
import
|
|
3521
|
+
import fs19 from "node:fs";
|
|
3588
3522
|
import * as p16 from "@clack/prompts";
|
|
3589
3523
|
import pc6 from "picocolors";
|
|
3590
3524
|
function readLocalEnv(envFile) {
|
|
3591
|
-
if (!
|
|
3525
|
+
if (!fs19.existsSync(envFile)) return {};
|
|
3592
3526
|
return readLocalEnvFile(envFile);
|
|
3593
3527
|
}
|
|
3594
3528
|
function editLocalEnv(envFile, edit) {
|
|
3595
|
-
const before =
|
|
3529
|
+
const before = fs19.existsSync(envFile) ? fs19.readFileSync(envFile, "utf8") : "";
|
|
3596
3530
|
const after = edit(before);
|
|
3597
|
-
if (after !== before)
|
|
3531
|
+
if (after !== before) fs19.writeFileSync(envFile, after);
|
|
3598
3532
|
}
|
|
3599
3533
|
function setLocalEnv(envFile, key, value) {
|
|
3600
3534
|
editLocalEnv(envFile, (content) => upsertEnvVar(content, key, value));
|
|
@@ -3667,7 +3601,7 @@ async function withRemotePocketbase(session, instance, fn) {
|
|
|
3667
3601
|
}
|
|
3668
3602
|
|
|
3669
3603
|
// src/lib/backup-target.ts
|
|
3670
|
-
async function withBackupTarget(raw,
|
|
3604
|
+
async function withBackupTarget(raw, label4, fn) {
|
|
3671
3605
|
await withTarget(
|
|
3672
3606
|
raw,
|
|
3673
3607
|
{
|
|
@@ -3721,13 +3655,13 @@ Set ${pc7.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc7.cyan("POCKETBASE_SUPERUS
|
|
|
3721
3655
|
);
|
|
3722
3656
|
}
|
|
3723
3657
|
},
|
|
3724
|
-
{ label:
|
|
3658
|
+
{ label: label4 }
|
|
3725
3659
|
);
|
|
3726
3660
|
}
|
|
3727
3661
|
|
|
3728
3662
|
// src/lib/s3-settings.ts
|
|
3729
|
-
import
|
|
3730
|
-
import
|
|
3663
|
+
import fs20 from "node:fs";
|
|
3664
|
+
import path19 from "node:path";
|
|
3731
3665
|
var VIRTUAL_HOSTED = [/\.amazonaws\.com$/i, /\.r2\.cloudflarestorage\.com$/i];
|
|
3732
3666
|
function defaultForcePathStyle(endpoint) {
|
|
3733
3667
|
let host;
|
|
@@ -3765,18 +3699,18 @@ async function hasLocalUploads(session, instance, workspaceRootDir) {
|
|
|
3765
3699
|
});
|
|
3766
3700
|
return result.stdout.trim().length > 0;
|
|
3767
3701
|
}
|
|
3768
|
-
return hasFile(
|
|
3702
|
+
return hasFile(path19.join(workspaceRootDir, DATA_DIR, "storage"));
|
|
3769
3703
|
}
|
|
3770
3704
|
function hasFile(dir) {
|
|
3771
3705
|
let entries;
|
|
3772
3706
|
try {
|
|
3773
|
-
entries =
|
|
3707
|
+
entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
3774
3708
|
} catch {
|
|
3775
3709
|
return false;
|
|
3776
3710
|
}
|
|
3777
3711
|
for (const entry of entries) {
|
|
3778
3712
|
if (entry.isFile()) return true;
|
|
3779
|
-
if (entry.isDirectory() && hasFile(
|
|
3713
|
+
if (entry.isDirectory() && hasFile(path19.join(dir, entry.name))) return true;
|
|
3780
3714
|
}
|
|
3781
3715
|
return false;
|
|
3782
3716
|
}
|
|
@@ -3849,7 +3783,7 @@ async function promptConfig(options, existing) {
|
|
|
3849
3783
|
const bucket = options.bucket ?? await text7("S3 bucket name", existing.bucket);
|
|
3850
3784
|
const region = options.region ?? await text7("S3 region", existing.region || "us-east-1");
|
|
3851
3785
|
const accessKey = options.accessKey ?? await text7("S3 access key", existing.accessKey);
|
|
3852
|
-
const secret = options.secret ??
|
|
3786
|
+
const secret = options.secret ?? process10.env.VELA_S3_SECRET ?? await password5("S3 secret key");
|
|
3853
3787
|
const forcePathStyle = options.forcePathStyle ?? await confirm3(
|
|
3854
3788
|
"Address the bucket in the path? (MinIO, Ceph and most self-hosted gateways need this)",
|
|
3855
3789
|
defaultForcePathStyle(endpoint)
|
|
@@ -3864,7 +3798,7 @@ async function text7(message, initialValue = "") {
|
|
|
3864
3798
|
});
|
|
3865
3799
|
if (p17.isCancel(value)) {
|
|
3866
3800
|
p17.cancel("Operation cancelled.");
|
|
3867
|
-
|
|
3801
|
+
process10.exit(0);
|
|
3868
3802
|
}
|
|
3869
3803
|
return value.trim();
|
|
3870
3804
|
}
|
|
@@ -3875,7 +3809,7 @@ async function password5(message) {
|
|
|
3875
3809
|
});
|
|
3876
3810
|
if (p17.isCancel(value)) {
|
|
3877
3811
|
p17.cancel("Operation cancelled.");
|
|
3878
|
-
|
|
3812
|
+
process10.exit(0);
|
|
3879
3813
|
}
|
|
3880
3814
|
return value;
|
|
3881
3815
|
}
|
|
@@ -3883,13 +3817,13 @@ async function confirm3(message, initialValue) {
|
|
|
3883
3817
|
const value = await p17.confirm({ message, initialValue });
|
|
3884
3818
|
if (p17.isCancel(value)) {
|
|
3885
3819
|
p17.cancel("Operation cancelled.");
|
|
3886
|
-
|
|
3820
|
+
process10.exit(0);
|
|
3887
3821
|
}
|
|
3888
3822
|
return value;
|
|
3889
3823
|
}
|
|
3890
3824
|
|
|
3891
3825
|
// src/commands/enable/smtp.ts
|
|
3892
|
-
import
|
|
3826
|
+
import process11 from "node:process";
|
|
3893
3827
|
import { Command as Command19 } from "commander";
|
|
3894
3828
|
import * as p18 from "@clack/prompts";
|
|
3895
3829
|
var smtp = new Command19("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
|
|
@@ -3918,7 +3852,7 @@ var smtp = new Command19("smtp").description("configure SMTP for transactional e
|
|
|
3918
3852
|
{
|
|
3919
3853
|
onCancel: () => {
|
|
3920
3854
|
p18.cancel("Operation cancelled.");
|
|
3921
|
-
|
|
3855
|
+
process11.exit(0);
|
|
3922
3856
|
}
|
|
3923
3857
|
}
|
|
3924
3858
|
);
|
|
@@ -3945,7 +3879,7 @@ var smtp = new Command19("smtp").description("configure SMTP for transactional e
|
|
|
3945
3879
|
);
|
|
3946
3880
|
|
|
3947
3881
|
// src/commands/enable/cms.ts
|
|
3948
|
-
import
|
|
3882
|
+
import process12 from "node:process";
|
|
3949
3883
|
import { Command as Command20 } from "commander";
|
|
3950
3884
|
import * as p19 from "@clack/prompts";
|
|
3951
3885
|
import pc9 from "picocolors";
|
|
@@ -3959,7 +3893,7 @@ Run ${pc9.cyan("vela bless")} to add a backend first.`
|
|
|
3959
3893
|
);
|
|
3960
3894
|
p19.log.message();
|
|
3961
3895
|
p19.cancel("Operation failed.");
|
|
3962
|
-
|
|
3896
|
+
process12.exitCode = 1;
|
|
3963
3897
|
return;
|
|
3964
3898
|
}
|
|
3965
3899
|
await runPattern(
|
|
@@ -4044,7 +3978,7 @@ import { Command as Command34 } from "commander";
|
|
|
4044
3978
|
import { Command as Command24 } from "commander";
|
|
4045
3979
|
|
|
4046
3980
|
// src/commands/disable/_shared.ts
|
|
4047
|
-
import
|
|
3981
|
+
import process13 from "node:process";
|
|
4048
3982
|
import * as p20 from "@clack/prompts";
|
|
4049
3983
|
async function runDisable(opts, flags, cmdArgs) {
|
|
4050
3984
|
if (!flags.yes) {
|
|
@@ -4054,7 +3988,7 @@ async function runDisable(opts, flags, cmdArgs) {
|
|
|
4054
3988
|
});
|
|
4055
3989
|
if (p20.isCancel(ok) || !ok) {
|
|
4056
3990
|
p20.cancel("Operation cancelled.");
|
|
4057
|
-
|
|
3991
|
+
process13.exit(0);
|
|
4058
3992
|
}
|
|
4059
3993
|
}
|
|
4060
3994
|
await runPattern(opts.slug, cmdArgs, { destructive: true }, opts.report);
|
|
@@ -4325,14 +4259,14 @@ import { Command as Command40 } from "commander";
|
|
|
4325
4259
|
import { Command as Command35 } from "commander";
|
|
4326
4260
|
|
|
4327
4261
|
// src/commands/destroy/_shared.ts
|
|
4328
|
-
import
|
|
4262
|
+
import process14 from "node:process";
|
|
4329
4263
|
import * as p22 from "@clack/prompts";
|
|
4330
4264
|
async function runDestroy(slug2, model, confirmMessage, report4, flags) {
|
|
4331
4265
|
if (!flags.yes) {
|
|
4332
4266
|
const ok = await p22.confirm({ message: confirmMessage, initialValue: false });
|
|
4333
4267
|
if (p22.isCancel(ok) || !ok) {
|
|
4334
4268
|
p22.cancel("Operation cancelled.");
|
|
4335
|
-
|
|
4269
|
+
process14.exit(0);
|
|
4336
4270
|
}
|
|
4337
4271
|
}
|
|
4338
4272
|
await runPattern(slug2, [model], { destructive: true, route: flags.route }, report4);
|
|
@@ -4435,7 +4369,7 @@ var scaffold2 = new Command38("scaffold").description("destroy a scaffold genera
|
|
|
4435
4369
|
);
|
|
4436
4370
|
|
|
4437
4371
|
// src/commands/destroy/deployment.ts
|
|
4438
|
-
import
|
|
4372
|
+
import process15 from "node:process";
|
|
4439
4373
|
import { Command as Command39 } from "commander";
|
|
4440
4374
|
import * as p23 from "@clack/prompts";
|
|
4441
4375
|
import pc11 from "picocolors";
|
|
@@ -4478,7 +4412,7 @@ async function confirm7(appName, targetName, envTag, purge) {
|
|
|
4478
4412
|
});
|
|
4479
4413
|
if (p23.isCancel(answer)) {
|
|
4480
4414
|
p23.cancel("Operation cancelled.");
|
|
4481
|
-
|
|
4415
|
+
process15.exit(0);
|
|
4482
4416
|
}
|
|
4483
4417
|
return;
|
|
4484
4418
|
}
|
|
@@ -4488,7 +4422,7 @@ async function confirm7(appName, targetName, envTag, purge) {
|
|
|
4488
4422
|
});
|
|
4489
4423
|
if (p23.isCancel(ok) || !ok) {
|
|
4490
4424
|
p23.cancel("Operation cancelled.");
|
|
4491
|
-
|
|
4425
|
+
process15.exit(0);
|
|
4492
4426
|
}
|
|
4493
4427
|
}
|
|
4494
4428
|
|
|
@@ -4541,13 +4475,13 @@ var add = new Command41("add").description("add ui components").argument("<compo
|
|
|
4541
4475
|
);
|
|
4542
4476
|
|
|
4543
4477
|
// src/commands/ui/base.ts
|
|
4544
|
-
import
|
|
4545
|
-
import
|
|
4478
|
+
import fs21 from "node:fs";
|
|
4479
|
+
import path20 from "node:path";
|
|
4546
4480
|
import { Command as Command42, InvalidArgumentError } from "commander";
|
|
4547
4481
|
var VALID_COLORS = ["slate", "gray", "zinc", "stone", "neutral"];
|
|
4548
4482
|
function findThemeFile(color) {
|
|
4549
|
-
const candidate =
|
|
4550
|
-
if (!
|
|
4483
|
+
const candidate = path20.join(templatesDir(), "ui", "css", `${color}.css`);
|
|
4484
|
+
if (!fs21.existsSync(candidate)) {
|
|
4551
4485
|
throw new Error(`Theme file not found for color: ${color}`);
|
|
4552
4486
|
}
|
|
4553
4487
|
return candidate;
|
|
@@ -4578,17 +4512,17 @@ var base = new Command42("base").description("change the base color").argument("
|
|
|
4578
4512
|
}).configureHelp(helpConfig).action(
|
|
4579
4513
|
(color) => runCommand(async () => {
|
|
4580
4514
|
const { workspaceRootDir } = await getWorkspace();
|
|
4581
|
-
const appCssPath =
|
|
4582
|
-
if (!
|
|
4583
|
-
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)}`);
|
|
4584
4518
|
}
|
|
4585
|
-
const themeContent =
|
|
4519
|
+
const themeContent = fs21.readFileSync(findThemeFile(color), "utf8");
|
|
4586
4520
|
const selectors = extractSelectors(themeContent);
|
|
4587
|
-
const appCss =
|
|
4588
|
-
|
|
4521
|
+
const appCss = fs21.readFileSync(appCssPath, "utf8");
|
|
4522
|
+
fs21.writeFileSync(appCssPath, applyTheme(appCss, selectors));
|
|
4589
4523
|
reportResult({
|
|
4590
4524
|
summary: `Set base color to ${color}.`,
|
|
4591
|
-
filesModified: [
|
|
4525
|
+
filesModified: [path20.relative(workspaceRootDir, appCssPath)],
|
|
4592
4526
|
nextSteps: [
|
|
4593
4527
|
"Run your dev server to preview the new palette.",
|
|
4594
4528
|
"Tweak individual CSS variables in src/app.css if you want to customize the theme further."
|
|
@@ -4604,13 +4538,13 @@ var ui = new Command43("ui").description("generate ui components").configureHelp
|
|
|
4604
4538
|
import { Command as Command46 } from "commander";
|
|
4605
4539
|
|
|
4606
4540
|
// src/commands/legal/terms.ts
|
|
4607
|
-
import
|
|
4608
|
-
import
|
|
4541
|
+
import fs22 from "node:fs";
|
|
4542
|
+
import path21 from "node:path";
|
|
4609
4543
|
import { Command as Command44 } from "commander";
|
|
4610
4544
|
import * as p25 from "@clack/prompts";
|
|
4611
4545
|
|
|
4612
4546
|
// src/commands/legal/shared.ts
|
|
4613
|
-
import
|
|
4547
|
+
import process16 from "node:process";
|
|
4614
4548
|
import * as p24 from "@clack/prompts";
|
|
4615
4549
|
var sharedFields = {
|
|
4616
4550
|
websiteUrl: () => p24.text({
|
|
@@ -4679,7 +4613,7 @@ var sharedFields = {
|
|
|
4679
4613
|
};
|
|
4680
4614
|
var onCancel = () => {
|
|
4681
4615
|
p24.cancel("Operation cancelled.");
|
|
4682
|
-
|
|
4616
|
+
process16.exit(0);
|
|
4683
4617
|
};
|
|
4684
4618
|
async function contactMethods(type) {
|
|
4685
4619
|
const selection = await p24.multiselect({
|
|
@@ -5264,22 +5198,22 @@ async function termsAction() {
|
|
|
5264
5198
|
mobileApp,
|
|
5265
5199
|
contact
|
|
5266
5200
|
});
|
|
5267
|
-
const termsPage =
|
|
5201
|
+
const termsPage = path21.join(
|
|
5268
5202
|
workspaceRootDir,
|
|
5269
5203
|
publicRoutesDir,
|
|
5270
5204
|
LEGAL_DIR,
|
|
5271
5205
|
"terms",
|
|
5272
5206
|
"+page.svelte"
|
|
5273
5207
|
);
|
|
5274
|
-
const termsPageTs =
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
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(
|
|
5278
5212
|
termsPageTs,
|
|
5279
5213
|
pageMetaTagsLoader("Terms of Service", `Terms of Service for ${core.websiteName}`)
|
|
5280
5214
|
);
|
|
5281
|
-
const relativeTermsPage =
|
|
5282
|
-
const relativeTermsPageTs =
|
|
5215
|
+
const relativeTermsPage = path21.relative(workspaceRootDir, termsPage);
|
|
5216
|
+
const relativeTermsPageTs = path21.relative(workspaceRootDir, termsPageTs);
|
|
5283
5217
|
reportResult({
|
|
5284
5218
|
summary: "Generated placeholder terms and conditions.",
|
|
5285
5219
|
filesCreated: [relativeTermsPage, relativeTermsPageTs],
|
|
@@ -5293,8 +5227,8 @@ async function termsAction() {
|
|
|
5293
5227
|
var terms = new Command44("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
|
|
5294
5228
|
|
|
5295
5229
|
// src/commands/legal/privacy.ts
|
|
5296
|
-
import
|
|
5297
|
-
import
|
|
5230
|
+
import fs23 from "node:fs";
|
|
5231
|
+
import path22 from "node:path";
|
|
5298
5232
|
import { Command as Command45 } from "commander";
|
|
5299
5233
|
import * as p26 from "@clack/prompts";
|
|
5300
5234
|
var mapLabels = {
|
|
@@ -6007,28 +5941,28 @@ async function privacyAction() {
|
|
|
6007
5941
|
kids,
|
|
6008
5942
|
retention
|
|
6009
5943
|
});
|
|
6010
|
-
const privacyPage =
|
|
5944
|
+
const privacyPage = path22.join(
|
|
6011
5945
|
workspaceRootDir,
|
|
6012
5946
|
publicRoutesDir,
|
|
6013
5947
|
LEGAL_DIR,
|
|
6014
5948
|
"privacy",
|
|
6015
5949
|
"+page.svelte"
|
|
6016
5950
|
);
|
|
6017
|
-
const privacyPageTs =
|
|
5951
|
+
const privacyPageTs = path22.join(
|
|
6018
5952
|
workspaceRootDir,
|
|
6019
5953
|
publicRoutesDir,
|
|
6020
5954
|
LEGAL_DIR,
|
|
6021
5955
|
"privacy",
|
|
6022
5956
|
"+page.ts"
|
|
6023
5957
|
);
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
5958
|
+
fs23.mkdirSync(path22.dirname(privacyPage), { recursive: true });
|
|
5959
|
+
fs23.writeFileSync(privacyPage, html);
|
|
5960
|
+
fs23.writeFileSync(
|
|
6027
5961
|
privacyPageTs,
|
|
6028
5962
|
pageMetaTagsLoader("Privacy Policy", `Privacy Policy for ${core.websiteName}`)
|
|
6029
5963
|
);
|
|
6030
|
-
const relativePrivacyPage =
|
|
6031
|
-
const relativePrivacyPageTs =
|
|
5964
|
+
const relativePrivacyPage = path22.relative(workspaceRootDir, privacyPage);
|
|
5965
|
+
const relativePrivacyPageTs = path22.relative(workspaceRootDir, privacyPageTs);
|
|
6032
5966
|
reportResult({
|
|
6033
5967
|
summary: "Generated placeholder privacy policy.",
|
|
6034
5968
|
filesCreated: [relativePrivacyPage, relativePrivacyPageTs],
|
|
@@ -6048,70 +5982,12 @@ var legal = new Command46("legal").description("generate placeholder legal docum
|
|
|
6048
5982
|
import { Command as Command52 } from "commander";
|
|
6049
5983
|
|
|
6050
5984
|
// src/commands/fixtures/load.ts
|
|
6051
|
-
import fs25 from "node:fs";
|
|
6052
|
-
import path24 from "node:path";
|
|
6053
5985
|
import { Command as Command47 } from "commander";
|
|
6054
|
-
function getFixtureFiles(cwd) {
|
|
6055
|
-
const fixturesDir = path24.join(cwd, "data", "fixtures");
|
|
6056
|
-
if (!fs25.existsSync(fixturesDir)) return [];
|
|
6057
|
-
return fs25.readdirSync(fixturesDir).filter((file) => file.endsWith(".json")).map((file) => path24.join(fixturesDir, file)).sort((a, b) => a.localeCompare(b)).map((fixturePath) => {
|
|
6058
|
-
const file = path24.basename(fixturePath);
|
|
6059
|
-
const nameWithoutExt = file.replace(/\.json$/i, "");
|
|
6060
|
-
const collectionName = nameWithoutExt.replace(/^\d+[-_]?/, "");
|
|
6061
|
-
return { collectionName, fixturePath };
|
|
6062
|
-
});
|
|
6063
|
-
}
|
|
6064
|
-
async function loadFixtures(pb, workspaceRootDir) {
|
|
6065
|
-
const fixtureFiles = getFixtureFiles(workspaceRootDir);
|
|
6066
|
-
if (fixtureFiles.length === 0) return [];
|
|
6067
|
-
const loaded = [];
|
|
6068
|
-
for (const { collectionName, fixturePath } of fixtureFiles) {
|
|
6069
|
-
const shortName = collectionName.slice(0, 6);
|
|
6070
|
-
const existing = await pb.collection(collectionName).getFullList({
|
|
6071
|
-
filter: `id ~ "${FIXTURE_PREFIX}${shortName}%"`,
|
|
6072
|
-
fields: "id"
|
|
6073
|
-
});
|
|
6074
|
-
if (existing.length > 0) {
|
|
6075
|
-
throw new Error(
|
|
6076
|
-
`${collectionName} collection already has fixture records. Run \`vela fixtures reset\` to clear and reload, or \`vela fixtures clear\` first.`
|
|
6077
|
-
);
|
|
6078
|
-
}
|
|
6079
|
-
const items = JSON.parse(fs25.readFileSync(fixturePath, "utf8"));
|
|
6080
|
-
for (const fixture of items) {
|
|
6081
|
-
await pb.collection(collectionName).create(fixture);
|
|
6082
|
-
}
|
|
6083
|
-
loaded.push(`${path24.relative(workspaceRootDir, fixturePath)} (${items.length} records)`);
|
|
6084
|
-
}
|
|
6085
|
-
return loaded;
|
|
6086
|
-
}
|
|
6087
|
-
var load = new Command47("load").description("load fixtures into the database").configureHelp(helpConfig).action(
|
|
6088
|
-
() => runCommand(async () => {
|
|
6089
|
-
const { workspaceRootDir } = await getWorkspace();
|
|
6090
|
-
let loaded = [];
|
|
6091
|
-
await withPocketbase(workspaceRootDir, async (pb) => {
|
|
6092
|
-
loaded = await loadFixtures(pb, workspaceRootDir);
|
|
6093
|
-
});
|
|
6094
|
-
if (loaded.length === 0) {
|
|
6095
|
-
reportResult({
|
|
6096
|
-
summary: "No fixture files found in data/fixtures.",
|
|
6097
|
-
nextSteps: ["Run `vela fixtures generate` to create fixture files first."]
|
|
6098
|
-
});
|
|
6099
|
-
return;
|
|
6100
|
-
}
|
|
6101
|
-
reportResult({
|
|
6102
|
-
summary: `Loaded ${loaded.length} fixture file(s) into the database.`,
|
|
6103
|
-
recordsLoaded: loaded,
|
|
6104
|
-
nextSteps: [
|
|
6105
|
-
"Run `vela dev` to see the fixture data in the app.",
|
|
6106
|
-
"Run `vela fixtures clear` to remove the loaded fixture records."
|
|
6107
|
-
]
|
|
6108
|
-
});
|
|
6109
|
-
}, "Failed to load fixtures.")
|
|
6110
|
-
);
|
|
6111
5986
|
|
|
6112
|
-
// src/
|
|
6113
|
-
import
|
|
6114
|
-
import
|
|
5987
|
+
// src/lib/data.ts
|
|
5988
|
+
import fs24 from "node:fs";
|
|
5989
|
+
import path23 from "node:path";
|
|
5990
|
+
import { ClientResponseError } from "pocketbase";
|
|
6115
5991
|
|
|
6116
5992
|
// src/lib/collections.ts
|
|
6117
5993
|
function dependencyOrder(collections2, startingCollectionId) {
|
|
@@ -6145,10 +6021,114 @@ function dependencyOrder(collections2, startingCollectionId) {
|
|
|
6145
6021
|
return { ids: order, names: order.map((id) => nameById[id]) };
|
|
6146
6022
|
}
|
|
6147
6023
|
|
|
6148
|
-
// src/
|
|
6149
|
-
|
|
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) {
|
|
6150
6130
|
const fixturePathByName = new Map(
|
|
6151
|
-
getFixtureFiles(
|
|
6131
|
+
getFixtureFiles(cwd).map((f) => [f.collectionName, f.filePath])
|
|
6152
6132
|
);
|
|
6153
6133
|
const cleared = [];
|
|
6154
6134
|
const fullList = await pb.collections.getFullList();
|
|
@@ -6163,9 +6143,8 @@ async function clearFixtures(pb, workspaceRootDir) {
|
|
|
6163
6143
|
const { names } = dependencyOrder(collections2);
|
|
6164
6144
|
const reversed = [...names].reverse();
|
|
6165
6145
|
for (const collectionName of reversed) {
|
|
6166
|
-
const shortName = collectionName.slice(0, 6);
|
|
6167
6146
|
const records = await pb.collection(collectionName).getFullList({
|
|
6168
|
-
filter:
|
|
6147
|
+
filter: fixtureFilter(collectionName),
|
|
6169
6148
|
fields: "id"
|
|
6170
6149
|
});
|
|
6171
6150
|
if (records.length === 0) continue;
|
|
@@ -6173,11 +6152,53 @@ async function clearFixtures(pb, workspaceRootDir) {
|
|
|
6173
6152
|
await pb.collection(collectionName).delete(id);
|
|
6174
6153
|
}
|
|
6175
6154
|
const fixturePath = fixturePathByName.get(collectionName);
|
|
6176
|
-
|
|
6177
|
-
|
|
6155
|
+
cleared.push(
|
|
6156
|
+
fixturePath ? label3(cwd, fixturePath, records.length) : `${collectionName} (${records.length} records)`
|
|
6157
|
+
);
|
|
6178
6158
|
}
|
|
6179
6159
|
return cleared;
|
|
6180
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";
|
|
6181
6202
|
var clear = new Command48("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
|
|
6182
6203
|
() => runCommand(async () => {
|
|
6183
6204
|
const { workspaceRootDir } = await getWorkspace();
|
|
@@ -6238,8 +6259,8 @@ var reset = new Command49("reset").description("clear and reload fixtures").conf
|
|
|
6238
6259
|
);
|
|
6239
6260
|
|
|
6240
6261
|
// src/commands/fixtures/generate.ts
|
|
6241
|
-
import
|
|
6242
|
-
import
|
|
6262
|
+
import fs25 from "node:fs";
|
|
6263
|
+
import path24 from "node:path";
|
|
6243
6264
|
import { Command as Command50, InvalidArgumentError as InvalidArgumentError2 } from "commander";
|
|
6244
6265
|
import * as p27 from "@clack/prompts";
|
|
6245
6266
|
import { annotate } from "annotate-json-schema";
|
|
@@ -6265,19 +6286,6 @@ function parseSeed(value) {
|
|
|
6265
6286
|
}
|
|
6266
6287
|
return n;
|
|
6267
6288
|
}
|
|
6268
|
-
async function hasLoadedFixtures(pb) {
|
|
6269
|
-
const fullList = await pb.collections.getFullList();
|
|
6270
|
-
for (const collection of fullList) {
|
|
6271
|
-
if (collection.name.startsWith("_")) continue;
|
|
6272
|
-
const shortName = collection.name.slice(0, 6);
|
|
6273
|
-
const page = await pb.collection(collection.name).getList(1, 1, {
|
|
6274
|
-
filter: `id ~ "${FIXTURE_PREFIX}${shortName}%"`,
|
|
6275
|
-
fields: "id"
|
|
6276
|
-
});
|
|
6277
|
-
if (page.totalItems > 0) return true;
|
|
6278
|
-
}
|
|
6279
|
-
return false;
|
|
6280
|
-
}
|
|
6281
6289
|
async function loadCollections(pb) {
|
|
6282
6290
|
const list2 = await pb.collections.getFullList();
|
|
6283
6291
|
return list2.map((c) => ({
|
|
@@ -6288,10 +6296,10 @@ async function loadCollections(pb) {
|
|
|
6288
6296
|
}));
|
|
6289
6297
|
}
|
|
6290
6298
|
async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
6291
|
-
const fixturesDir =
|
|
6292
|
-
|
|
6293
|
-
for (const file of
|
|
6294
|
-
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));
|
|
6295
6303
|
}
|
|
6296
6304
|
if (opts.seed !== void 0) faker.seed(opts.seed);
|
|
6297
6305
|
const generator = createGenerator({
|
|
@@ -6302,8 +6310,11 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
|
6302
6310
|
const collections2 = await loadCollections(pb);
|
|
6303
6311
|
const eligible = collections2.filter((c) => !c.name.startsWith("_") && c.type !== "view");
|
|
6304
6312
|
const { ids } = dependencyOrder(eligible);
|
|
6313
|
+
const seedIds = readSeedIds(workspaceRootDir);
|
|
6305
6314
|
const recordIds = /* @__PURE__ */ new Map();
|
|
6306
|
-
|
|
6315
|
+
for (const collection of eligible) {
|
|
6316
|
+
recordIds.set(collection.id, [...seedIds.get(collection.name) ?? []]);
|
|
6317
|
+
}
|
|
6307
6318
|
const writtenFiles = [];
|
|
6308
6319
|
const warnings = [];
|
|
6309
6320
|
let fileIndex = 1;
|
|
@@ -6317,7 +6328,7 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
|
6317
6328
|
const target = collections2.find((c) => c.id === f.collectionId);
|
|
6318
6329
|
const targetLabel = target?.name ?? f.collectionId ?? "<unknown>";
|
|
6319
6330
|
warnings.push(
|
|
6320
|
-
`${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`
|
|
6321
6332
|
);
|
|
6322
6333
|
}
|
|
6323
6334
|
}
|
|
@@ -6355,8 +6366,8 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
|
6355
6366
|
items.push(record);
|
|
6356
6367
|
}
|
|
6357
6368
|
const filename = `${padZeros(fileIndex, 2)}-${collection.name}.json`;
|
|
6358
|
-
|
|
6359
|
-
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)`);
|
|
6360
6371
|
fileIndex++;
|
|
6361
6372
|
}
|
|
6362
6373
|
return { writtenFiles, warnings };
|
|
@@ -6465,19 +6476,7 @@ var fixtures = new Command52("fixtures").description("manage fixture data").conf
|
|
|
6465
6476
|
import { Command as Command56 } from "commander";
|
|
6466
6477
|
|
|
6467
6478
|
// src/commands/seeds/load.ts
|
|
6468
|
-
import fs27 from "node:fs";
|
|
6469
|
-
import path27 from "node:path";
|
|
6470
6479
|
import { Command as Command53 } from "commander";
|
|
6471
|
-
function getSeedFiles(cwd) {
|
|
6472
|
-
const seedsDir = path27.join(cwd, "data", "seeds");
|
|
6473
|
-
if (!fs27.existsSync(seedsDir)) return [];
|
|
6474
|
-
return fs27.readdirSync(seedsDir).filter((file) => file.endsWith(".json")).map((file) => path27.join(seedsDir, file)).sort((a, b) => a.localeCompare(b)).map((seedPath) => {
|
|
6475
|
-
const file = path27.basename(seedPath);
|
|
6476
|
-
const nameWithoutExt = file.replace(/\.json$/i, "");
|
|
6477
|
-
const collectionName = nameWithoutExt.replace(/^\d+[-_]?/, "");
|
|
6478
|
-
return { collectionName, seedPath };
|
|
6479
|
-
});
|
|
6480
|
-
}
|
|
6481
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(
|
|
6482
6481
|
(opts) => runCommand(async () => {
|
|
6483
6482
|
const { workspaceRootDir } = await getWorkspace();
|
|
@@ -6489,7 +6488,7 @@ var load2 = new Command53("load").description("load seeds into the database").op
|
|
|
6489
6488
|
});
|
|
6490
6489
|
return;
|
|
6491
6490
|
}
|
|
6492
|
-
|
|
6491
|
+
let loaded = [];
|
|
6493
6492
|
await withPocketbase(workspaceRootDir, async (pb) => {
|
|
6494
6493
|
if (!opts.force) {
|
|
6495
6494
|
for (const { collectionName } of seedFiles) {
|
|
@@ -6501,13 +6500,7 @@ var load2 = new Command53("load").description("load seeds into the database").op
|
|
|
6501
6500
|
}
|
|
6502
6501
|
}
|
|
6503
6502
|
}
|
|
6504
|
-
|
|
6505
|
-
const seeds2 = JSON.parse(fs27.readFileSync(seedPath, "utf8"));
|
|
6506
|
-
for (const seed of seeds2) {
|
|
6507
|
-
await pb.collection(collectionName).create(seed);
|
|
6508
|
-
}
|
|
6509
|
-
loaded.push(`${path27.relative(workspaceRootDir, seedPath)} (${seeds2.length} records)`);
|
|
6510
|
-
}
|
|
6503
|
+
loaded = await loadSeeds(pb, workspaceRootDir, seedFiles);
|
|
6511
6504
|
});
|
|
6512
6505
|
reportResult({
|
|
6513
6506
|
summary: `Loaded ${loaded.length} seed file(s) into the database.`,
|
|
@@ -6521,8 +6514,8 @@ var load2 = new Command53("load").description("load seeds into the database").op
|
|
|
6521
6514
|
);
|
|
6522
6515
|
|
|
6523
6516
|
// src/commands/seeds/save.ts
|
|
6524
|
-
import
|
|
6525
|
-
import
|
|
6517
|
+
import fs26 from "node:fs";
|
|
6518
|
+
import path25 from "node:path";
|
|
6526
6519
|
import { Command as Command54 } from "commander";
|
|
6527
6520
|
var padZeros2 = (num, length) => num.toString().padStart(length, "0");
|
|
6528
6521
|
function filterSystemFields(record, systemFieldNames) {
|
|
@@ -6537,15 +6530,15 @@ function filterSystemFields(record, systemFieldNames) {
|
|
|
6537
6530
|
var save = new Command54("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
|
|
6538
6531
|
(opts) => runCommand(async () => {
|
|
6539
6532
|
const { workspaceRootDir } = await getWorkspace();
|
|
6540
|
-
const seedsPath =
|
|
6533
|
+
const seedsPath = dataDir(workspaceRootDir, "seeds");
|
|
6541
6534
|
const existing = getSeedFiles(workspaceRootDir);
|
|
6542
6535
|
if (existing.length > 0 && !opts.force) {
|
|
6543
6536
|
throw new Error("Existing seed files found in data/seeds. Pass --force to overwrite.");
|
|
6544
6537
|
}
|
|
6545
|
-
|
|
6538
|
+
fs26.mkdirSync(seedsPath, { recursive: true });
|
|
6546
6539
|
if (opts.force) {
|
|
6547
|
-
for (const file of
|
|
6548
|
-
if (file.endsWith(".json"))
|
|
6540
|
+
for (const file of fs26.readdirSync(seedsPath)) {
|
|
6541
|
+
if (file.endsWith(".json")) fs26.unlinkSync(path25.join(seedsPath, file));
|
|
6549
6542
|
}
|
|
6550
6543
|
}
|
|
6551
6544
|
const saved = [];
|
|
@@ -6574,13 +6567,13 @@ var save = new Command54("save").description("save the current data as seeds").o
|
|
|
6574
6567
|
const filtered = records.map(
|
|
6575
6568
|
(r) => filterSystemFields(r, systemFieldNames)
|
|
6576
6569
|
);
|
|
6577
|
-
const relativeSeedPath =
|
|
6578
|
-
|
|
6570
|
+
const relativeSeedPath = path25.join(
|
|
6571
|
+
DATA_DIR,
|
|
6579
6572
|
"seeds",
|
|
6580
6573
|
`${padZeros2(count, 2)}-${collectionName}.json`
|
|
6581
6574
|
);
|
|
6582
|
-
const seedPath =
|
|
6583
|
-
|
|
6575
|
+
const seedPath = path25.join(workspaceRootDir, relativeSeedPath);
|
|
6576
|
+
fs26.writeFileSync(seedPath, JSON.stringify(filtered, null, 2));
|
|
6584
6577
|
saved.push(`${relativeSeedPath} (${filtered.length} records)`);
|
|
6585
6578
|
count++;
|
|
6586
6579
|
}
|
|
@@ -6606,20 +6599,7 @@ var save = new Command54("save").description("save the current data as seeds").o
|
|
|
6606
6599
|
);
|
|
6607
6600
|
|
|
6608
6601
|
// src/commands/seeds/clear.ts
|
|
6609
|
-
import fs29 from "node:fs";
|
|
6610
|
-
import path29 from "node:path";
|
|
6611
6602
|
import { Command as Command55 } from "commander";
|
|
6612
|
-
async function clearSeeds(pb, workspaceRootDir, seedFiles) {
|
|
6613
|
-
const cleared = [];
|
|
6614
|
-
for (const { collectionName, seedPath } of seedFiles) {
|
|
6615
|
-
const seeds2 = JSON.parse(fs29.readFileSync(seedPath, "utf8"));
|
|
6616
|
-
for (const { id } of seeds2) {
|
|
6617
|
-
await pb.collection(collectionName).delete(id);
|
|
6618
|
-
}
|
|
6619
|
-
cleared.push(`${path29.relative(workspaceRootDir, seedPath)} (${seeds2.length} records)`);
|
|
6620
|
-
}
|
|
6621
|
-
return cleared;
|
|
6622
|
-
}
|
|
6623
6603
|
var clear2 = new Command55("clear").description("clear seeded records").configureHelp(helpConfig).action(
|
|
6624
6604
|
() => runCommand(async () => {
|
|
6625
6605
|
const { workspaceRootDir } = await getWorkspace();
|
|
@@ -6693,14 +6673,14 @@ var login = new Command57("login").description("login to velastack.dev").configu
|
|
|
6693
6673
|
}, "Failed to login.")
|
|
6694
6674
|
);
|
|
6695
6675
|
async function issueApiKey(fetchCookie) {
|
|
6696
|
-
const
|
|
6676
|
+
const label4 = `CLI - ${os3.hostname()}`;
|
|
6697
6677
|
await fetchCookie(`${API_URL}/api-keys/new`, {
|
|
6698
6678
|
method: "POST",
|
|
6699
6679
|
headers: {
|
|
6700
6680
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
6701
6681
|
Origin: API_URL
|
|
6702
6682
|
},
|
|
6703
|
-
body: new URLSearchParams({ label:
|
|
6683
|
+
body: new URLSearchParams({ label: label4 }).toString()
|
|
6704
6684
|
});
|
|
6705
6685
|
const cookie = await fetchCookie.cookieJar.getCookieString(API_URL);
|
|
6706
6686
|
const apiKey = extractApiKey(cookie);
|
|
@@ -6713,7 +6693,7 @@ async function issueApiKey(fetchCookie) {
|
|
|
6713
6693
|
});
|
|
6714
6694
|
const data = await res.json();
|
|
6715
6695
|
for (const item of data.items) {
|
|
6716
|
-
if (item.label ===
|
|
6696
|
+
if (item.label === label4 && item.id !== id) {
|
|
6717
6697
|
await fetchCookie(`${API_URL}/api/collections/api_keys/records/${item.id}`, {
|
|
6718
6698
|
method: "DELETE",
|
|
6719
6699
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
@@ -6804,20 +6784,20 @@ import { Command as Command66 } from "commander";
|
|
|
6804
6784
|
import { Command as Command61 } from "commander";
|
|
6805
6785
|
|
|
6806
6786
|
// src/lib/migrate.ts
|
|
6807
|
-
import
|
|
6808
|
-
import
|
|
6787
|
+
import path26 from "node:path";
|
|
6788
|
+
import process17 from "node:process";
|
|
6809
6789
|
import { x as x2 } from "tinyexec";
|
|
6810
6790
|
async function runPocketbaseMigrate(args) {
|
|
6811
|
-
const cwd =
|
|
6791
|
+
const cwd = process17.cwd();
|
|
6812
6792
|
const { getBinaryPath } = await import("pocketbase-server");
|
|
6813
6793
|
const binaryPath = getBinaryPath();
|
|
6814
6794
|
await x2(
|
|
6815
6795
|
binaryPath,
|
|
6816
6796
|
[
|
|
6817
6797
|
"--dir",
|
|
6818
|
-
|
|
6798
|
+
path26.join(cwd, DATA_DIR),
|
|
6819
6799
|
"--migrationsDir",
|
|
6820
|
-
|
|
6800
|
+
path26.join(cwd, MIGRATIONS_DIR),
|
|
6821
6801
|
"migrate",
|
|
6822
6802
|
...args
|
|
6823
6803
|
],
|
|
@@ -6865,20 +6845,20 @@ var down = new Command62("down").alias("rollback").description("revert the last
|
|
|
6865
6845
|
);
|
|
6866
6846
|
|
|
6867
6847
|
// src/commands/migrate/create.ts
|
|
6868
|
-
import
|
|
6869
|
-
import
|
|
6870
|
-
import
|
|
6848
|
+
import fs27 from "node:fs";
|
|
6849
|
+
import path27 from "node:path";
|
|
6850
|
+
import process18 from "node:process";
|
|
6871
6851
|
import { Command as Command63 } from "commander";
|
|
6872
6852
|
var create2 = new Command63("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
|
|
6873
6853
|
(name) => runCommand(async () => {
|
|
6874
|
-
const cwd =
|
|
6854
|
+
const cwd = process18.cwd();
|
|
6875
6855
|
const before = listMigrationFiles(cwd);
|
|
6876
6856
|
await runPocketbaseMigrate(["create", name]);
|
|
6877
6857
|
const after = listMigrationFiles(cwd);
|
|
6878
6858
|
const added = [...after].filter((f) => !before.has(f));
|
|
6879
6859
|
reportResult({
|
|
6880
6860
|
summary: `Created blank migration ${name}.`,
|
|
6881
|
-
filesCreated: added.map((f) =>
|
|
6861
|
+
filesCreated: added.map((f) => path27.join(MIGRATIONS_DIR, f)),
|
|
6882
6862
|
nextSteps: [
|
|
6883
6863
|
`Open the new file in ${MIGRATIONS_DIR}/ and fill in the up/down handlers.`,
|
|
6884
6864
|
"Run `vela migrate up` to apply the migration once the handlers are written."
|
|
@@ -6887,19 +6867,19 @@ var create2 = new Command63("create").alias("new").description("create a new bla
|
|
|
6887
6867
|
}, "Failed to create migration.")
|
|
6888
6868
|
);
|
|
6889
6869
|
function listMigrationFiles(cwd) {
|
|
6890
|
-
const dir =
|
|
6891
|
-
if (!
|
|
6892
|
-
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)));
|
|
6893
6873
|
}
|
|
6894
6874
|
|
|
6895
6875
|
// src/commands/migrate/collections.ts
|
|
6896
|
-
import
|
|
6897
|
-
import
|
|
6898
|
-
import
|
|
6876
|
+
import fs28 from "node:fs";
|
|
6877
|
+
import path28 from "node:path";
|
|
6878
|
+
import process19 from "node:process";
|
|
6899
6879
|
import { Command as Command64 } from "commander";
|
|
6900
6880
|
var collections = new Command64("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
|
|
6901
6881
|
() => runCommand(async () => {
|
|
6902
|
-
const cwd =
|
|
6882
|
+
const cwd = process19.cwd();
|
|
6903
6883
|
const before = listMigrationFiles2(cwd);
|
|
6904
6884
|
await runPocketbaseMigrate(["collections"]);
|
|
6905
6885
|
const after = listMigrationFiles2(cwd);
|
|
@@ -6912,7 +6892,7 @@ var collections = new Command64("collections").alias("snapshot").description("sn
|
|
|
6912
6892
|
}
|
|
6913
6893
|
reportResult({
|
|
6914
6894
|
summary: "Snapshotted local collections into a new migration.",
|
|
6915
|
-
filesCreated: added.map((f) =>
|
|
6895
|
+
filesCreated: added.map((f) => path28.join(MIGRATIONS_DIR, f)),
|
|
6916
6896
|
nextSteps: [
|
|
6917
6897
|
`Review the generated snapshot in ${MIGRATIONS_DIR}/.`,
|
|
6918
6898
|
"Commit the snapshot so teammates pick up the new schema.",
|
|
@@ -6922,9 +6902,9 @@ var collections = new Command64("collections").alias("snapshot").description("sn
|
|
|
6922
6902
|
}, "Failed to snapshot collections.")
|
|
6923
6903
|
);
|
|
6924
6904
|
function listMigrationFiles2(cwd) {
|
|
6925
|
-
const dir =
|
|
6926
|
-
if (!
|
|
6927
|
-
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)));
|
|
6928
6908
|
}
|
|
6929
6909
|
|
|
6930
6910
|
// src/commands/migrate/history-sync.ts
|
|
@@ -6943,17 +6923,17 @@ var historySync = new Command65("history-sync").description("drop _migrations ro
|
|
|
6943
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);
|
|
6944
6924
|
|
|
6945
6925
|
// src/commands/dev.ts
|
|
6946
|
-
import
|
|
6947
|
-
import
|
|
6948
|
-
import
|
|
6926
|
+
import fs29 from "node:fs";
|
|
6927
|
+
import path30 from "node:path";
|
|
6928
|
+
import process21 from "node:process";
|
|
6949
6929
|
import { performance } from "node:perf_hooks";
|
|
6950
6930
|
import { Command as Command67, InvalidArgumentError as InvalidArgumentError5 } from "commander";
|
|
6951
6931
|
import pc13 from "picocolors";
|
|
6952
|
-
import
|
|
6932
|
+
import PocketBase4 from "pocketbase";
|
|
6953
6933
|
|
|
6954
6934
|
// src/lib/vite.ts
|
|
6955
|
-
import
|
|
6956
|
-
import
|
|
6935
|
+
import path29 from "node:path";
|
|
6936
|
+
import process20 from "node:process";
|
|
6957
6937
|
import { createRequire as createRequire2 } from "node:module";
|
|
6958
6938
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
6959
6939
|
import pc12 from "picocolors";
|
|
@@ -6972,18 +6952,18 @@ function viteVersionError(version) {
|
|
|
6972
6952
|
}
|
|
6973
6953
|
function resolveProjectVite(cwd) {
|
|
6974
6954
|
try {
|
|
6975
|
-
return createRequire2(
|
|
6955
|
+
return createRequire2(path29.join(cwd, "package.json")).resolve("vite");
|
|
6976
6956
|
} catch {
|
|
6977
6957
|
return null;
|
|
6978
6958
|
}
|
|
6979
6959
|
}
|
|
6980
|
-
async function loadVite(cwd =
|
|
6960
|
+
async function loadVite(cwd = process20.cwd()) {
|
|
6981
6961
|
const entry = resolveProjectVite(cwd);
|
|
6982
6962
|
const vite = entry ? await import(pathToFileURL2(entry).href) : await import("vite");
|
|
6983
6963
|
const error = viteVersionError(vite.version);
|
|
6984
6964
|
if (error) {
|
|
6985
6965
|
console.error(`${pc12.redBright("\u2717")} ${error}`);
|
|
6986
|
-
|
|
6966
|
+
process20.exit(1);
|
|
6987
6967
|
}
|
|
6988
6968
|
return vite;
|
|
6989
6969
|
}
|
|
@@ -6997,38 +6977,38 @@ function parsePort(value) {
|
|
|
6997
6977
|
return port;
|
|
6998
6978
|
}
|
|
6999
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) => {
|
|
7000
|
-
const cwd =
|
|
7001
|
-
|
|
6980
|
+
const cwd = process21.cwd();
|
|
6981
|
+
process21.env.VELA_DATA_DIR ??= localDataDir(cwd);
|
|
7002
6982
|
const startTime = performance.now();
|
|
7003
6983
|
const { createServer, version } = await loadVite(cwd);
|
|
7004
|
-
const viteMetadataDir =
|
|
7005
|
-
const viteMetadataFile =
|
|
6984
|
+
const viteMetadataDir = path30.join(cwd, "node_modules", ".vite");
|
|
6985
|
+
const viteMetadataFile = path30.join(viteMetadataDir, "_pocketbase_metadata.json");
|
|
7006
6986
|
let pbProc;
|
|
7007
6987
|
const backend3 = hasBackend(cwd);
|
|
7008
|
-
const needsStart = backend3 && !
|
|
6988
|
+
const needsStart = backend3 && !process21.env.POCKETBASE_URL;
|
|
7009
6989
|
const cleanup = () => {
|
|
7010
6990
|
if (pbProc?.pid) pbProc.kill();
|
|
7011
|
-
if (
|
|
6991
|
+
if (fs29.existsSync(viteMetadataFile)) fs29.rmSync(viteMetadataFile);
|
|
7012
6992
|
};
|
|
7013
6993
|
if (needsStart) {
|
|
7014
|
-
const
|
|
6994
|
+
const dataDir2 = path30.join(cwd, DATA_DIR);
|
|
7015
6995
|
const started = await startPocketbaseServe({
|
|
7016
|
-
dataDir,
|
|
6996
|
+
dataDir: dataDir2,
|
|
7017
6997
|
migrationsDir: MIGRATIONS_DIR,
|
|
7018
|
-
hooksDir:
|
|
6998
|
+
hooksDir: path30.join(dataDir2, "hooks"),
|
|
7019
6999
|
dev: true,
|
|
7020
7000
|
stdio: "pipe"
|
|
7021
7001
|
});
|
|
7022
7002
|
pbProc = started.proc;
|
|
7023
|
-
|
|
7024
|
-
pbProc.stdout?.pipe(
|
|
7025
|
-
pbProc.stderr?.pipe(
|
|
7003
|
+
process21.env.POCKETBASE_URL = started.url;
|
|
7004
|
+
pbProc.stdout?.pipe(process21.stdout);
|
|
7005
|
+
pbProc.stderr?.pipe(process21.stderr);
|
|
7026
7006
|
pbProc.on("error", (err) => console.error("PocketBase error:", err));
|
|
7027
7007
|
pbProc.on("exit", (code) => console.log(`PocketBase exited with code ${code}`));
|
|
7028
|
-
|
|
7029
|
-
|
|
7008
|
+
process21.on("exit", cleanup);
|
|
7009
|
+
process21.on("SIGINT", () => {
|
|
7030
7010
|
cleanup();
|
|
7031
|
-
|
|
7011
|
+
process21.exit(0);
|
|
7032
7012
|
});
|
|
7033
7013
|
}
|
|
7034
7014
|
const serverOptions = {};
|
|
@@ -7046,25 +7026,25 @@ var dev = new Command67("dev").description("start the development server").optio
|
|
|
7046
7026
|
if (!backend3) return;
|
|
7047
7027
|
const { address, port: vitePort } = server.httpServer.address();
|
|
7048
7028
|
const viteHost = address === "::1" ? "localhost" : address;
|
|
7049
|
-
await
|
|
7050
|
-
await
|
|
7029
|
+
await fs29.promises.mkdir(viteMetadataDir, { recursive: true });
|
|
7030
|
+
await fs29.promises.writeFile(
|
|
7051
7031
|
viteMetadataFile,
|
|
7052
7032
|
JSON.stringify({
|
|
7053
|
-
pocketbaseUrl:
|
|
7033
|
+
pocketbaseUrl: process21.env.POCKETBASE_URL,
|
|
7054
7034
|
vitePort,
|
|
7055
7035
|
viteHost
|
|
7056
7036
|
})
|
|
7057
7037
|
);
|
|
7058
|
-
const pb = new
|
|
7038
|
+
const pb = new PocketBase4(process21.env.POCKETBASE_URL);
|
|
7059
7039
|
await pb.collection("_superusers").authWithPassword(
|
|
7060
|
-
|
|
7061
|
-
|
|
7040
|
+
process21.env.POCKETBASE_SUPERUSER_EMAIL,
|
|
7041
|
+
process21.env.POCKETBASE_SUPERUSER_PASSWORD
|
|
7062
7042
|
);
|
|
7063
7043
|
await pb.settings.update({ meta: { appURL: `http://${viteHost}:${vitePort}` } });
|
|
7064
7044
|
await startWatchingTypes(cwd, pb);
|
|
7065
7045
|
});
|
|
7066
7046
|
await server.listen();
|
|
7067
|
-
const hasExistingLogs =
|
|
7047
|
+
const hasExistingLogs = process21.stdout.bytesWritten > 0 || process21.stderr.bytesWritten > 0;
|
|
7068
7048
|
const startupDurationString = pc13.dim(
|
|
7069
7049
|
`ready in ${pc13.reset(pc13.bold(Math.ceil(performance.now() - startTime)))} ms`
|
|
7070
7050
|
);
|
|
@@ -7079,18 +7059,18 @@ var dev = new Command67("dev").description("start the development server").optio
|
|
|
7079
7059
|
});
|
|
7080
7060
|
async function startWatchingTypes(cwd, pb) {
|
|
7081
7061
|
const { processTypes } = await import("@velastack/pocketbase-codegen");
|
|
7082
|
-
const typesDir =
|
|
7083
|
-
const pocketbaseDir =
|
|
7084
|
-
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");
|
|
7085
7065
|
const regenerate = () => processTypes(pb, typesDir).catch(() => {
|
|
7086
7066
|
});
|
|
7087
7067
|
await regenerate();
|
|
7088
7068
|
void (async () => {
|
|
7089
7069
|
for (; ; ) {
|
|
7090
7070
|
try {
|
|
7091
|
-
await
|
|
7092
|
-
for await (const event of
|
|
7093
|
-
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)) {
|
|
7094
7074
|
setTimeout(regenerate, 100);
|
|
7095
7075
|
}
|
|
7096
7076
|
}
|
|
@@ -7102,9 +7082,9 @@ async function startWatchingTypes(cwd, pb) {
|
|
|
7102
7082
|
}
|
|
7103
7083
|
|
|
7104
7084
|
// src/commands/build.ts
|
|
7105
|
-
import
|
|
7106
|
-
import
|
|
7107
|
-
import
|
|
7085
|
+
import fs30 from "node:fs";
|
|
7086
|
+
import path31 from "node:path";
|
|
7087
|
+
import process23 from "node:process";
|
|
7108
7088
|
import { Command as Command68 } from "commander";
|
|
7109
7089
|
import * as p33 from "@clack/prompts";
|
|
7110
7090
|
import pc14 from "picocolors";
|
|
@@ -7119,10 +7099,10 @@ function applyBuildEnv(cwd, env2 = process.env) {
|
|
|
7119
7099
|
}
|
|
7120
7100
|
|
|
7121
7101
|
// src/lib/origin.ts
|
|
7122
|
-
import
|
|
7102
|
+
import process22 from "node:process";
|
|
7123
7103
|
function resolveOrigin(workspaceRootDir, envTag, config = {}) {
|
|
7124
7104
|
return normalizeOrigin(
|
|
7125
|
-
|
|
7105
|
+
process22.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
|
|
7126
7106
|
);
|
|
7127
7107
|
}
|
|
7128
7108
|
function normalizeOrigin(value) {
|
|
@@ -7138,32 +7118,32 @@ function normalizeOrigin(value) {
|
|
|
7138
7118
|
}
|
|
7139
7119
|
|
|
7140
7120
|
// src/commands/build.ts
|
|
7141
|
-
var PRERENDERED_DIR =
|
|
7121
|
+
var PRERENDERED_DIR = path31.join(".svelte-kit", "output", "prerendered");
|
|
7142
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) => {
|
|
7143
|
-
const cwd =
|
|
7123
|
+
const cwd = process23.cwd();
|
|
7144
7124
|
applyBuildEnv(cwd);
|
|
7145
7125
|
const origin = await originForBuild(cwd, options.target);
|
|
7146
|
-
if (origin)
|
|
7126
|
+
if (origin) process23.env.VELA_ORIGIN = origin;
|
|
7147
7127
|
let pbProc;
|
|
7148
|
-
const needsStart = hasBackend(cwd) && !
|
|
7128
|
+
const needsStart = hasBackend(cwd) && !process23.env.POCKETBASE_URL;
|
|
7149
7129
|
const cleanup = () => {
|
|
7150
7130
|
if (pbProc?.pid) pbProc.kill();
|
|
7151
7131
|
};
|
|
7152
7132
|
if (needsStart) {
|
|
7153
7133
|
await ensureSuperuser(cwd);
|
|
7154
|
-
const
|
|
7134
|
+
const dataDir2 = path31.join(cwd, DATA_DIR);
|
|
7155
7135
|
const started = await startPocketbaseServe({
|
|
7156
|
-
dataDir,
|
|
7136
|
+
dataDir: dataDir2,
|
|
7157
7137
|
migrationsDir: MIGRATIONS_DIR,
|
|
7158
|
-
hooksDir:
|
|
7138
|
+
hooksDir: path31.join(dataDir2, "hooks"),
|
|
7159
7139
|
dev: true
|
|
7160
7140
|
});
|
|
7161
7141
|
pbProc = started.proc;
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7142
|
+
process23.env.POCKETBASE_URL = started.url;
|
|
7143
|
+
process23.on("exit", cleanup);
|
|
7144
|
+
process23.on("SIGINT", () => {
|
|
7165
7145
|
cleanup();
|
|
7166
|
-
|
|
7146
|
+
process23.exit(0);
|
|
7167
7147
|
});
|
|
7168
7148
|
}
|
|
7169
7149
|
try {
|
|
@@ -7193,8 +7173,8 @@ async function originForBuild(cwd, target) {
|
|
|
7193
7173
|
}
|
|
7194
7174
|
}
|
|
7195
7175
|
function warnIfPrerendered(cwd) {
|
|
7196
|
-
const dir =
|
|
7197
|
-
if (!
|
|
7176
|
+
const dir = path31.join(cwd, PRERENDERED_DIR);
|
|
7177
|
+
if (!fs30.existsSync(dir) || fs30.readdirSync(dir).length === 0) return;
|
|
7198
7178
|
p33.log.warn(
|
|
7199
7179
|
`Prerendered pages were built with no domain configured, so their canonical
|
|
7200
7180
|
links point at SvelteKit's placeholder host rather than at this site.
|
|
@@ -7204,34 +7184,34 @@ Set one with ${pc14.cyan("vela deploy --domain example.com")}, or pass ${pc14.cy
|
|
|
7204
7184
|
}
|
|
7205
7185
|
|
|
7206
7186
|
// src/commands/preview.ts
|
|
7207
|
-
import
|
|
7208
|
-
import
|
|
7187
|
+
import path32 from "node:path";
|
|
7188
|
+
import process24 from "node:process";
|
|
7209
7189
|
import { Command as Command69 } from "commander";
|
|
7210
7190
|
import { x as x4 } from "tinyexec";
|
|
7211
7191
|
import { detect as detect6 } from "package-manager-detector";
|
|
7212
7192
|
import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
|
|
7213
7193
|
var preview = new Command69("preview").description("preview the built app").configureHelp(helpConfig).action(async () => {
|
|
7214
|
-
const cwd =
|
|
7215
|
-
|
|
7194
|
+
const cwd = process24.cwd();
|
|
7195
|
+
process24.env.VELA_DATA_DIR ??= localDataDir(cwd);
|
|
7216
7196
|
let pbProc;
|
|
7217
|
-
const needsStart = hasBackend(cwd) && !
|
|
7197
|
+
const needsStart = hasBackend(cwd) && !process24.env.POCKETBASE_URL;
|
|
7218
7198
|
const cleanup = () => {
|
|
7219
7199
|
if (pbProc?.pid) pbProc.kill();
|
|
7220
7200
|
};
|
|
7221
7201
|
if (needsStart) {
|
|
7222
|
-
const
|
|
7202
|
+
const dataDir2 = path32.join(cwd, DATA_DIR);
|
|
7223
7203
|
const started = await startPocketbaseServe({
|
|
7224
|
-
dataDir,
|
|
7204
|
+
dataDir: dataDir2,
|
|
7225
7205
|
migrationsDir: MIGRATIONS_DIR,
|
|
7226
|
-
hooksDir:
|
|
7206
|
+
hooksDir: path32.join(dataDir2, "hooks"),
|
|
7227
7207
|
dev: true
|
|
7228
7208
|
});
|
|
7229
7209
|
pbProc = started.proc;
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7210
|
+
process24.env.POCKETBASE_URL = started.url;
|
|
7211
|
+
process24.on("exit", cleanup);
|
|
7212
|
+
process24.on("SIGINT", () => {
|
|
7233
7213
|
cleanup();
|
|
7234
|
-
|
|
7214
|
+
process24.exit(0);
|
|
7235
7215
|
});
|
|
7236
7216
|
}
|
|
7237
7217
|
try {
|
|
@@ -7249,12 +7229,12 @@ var preview = new Command69("preview").description("preview the built app").conf
|
|
|
7249
7229
|
});
|
|
7250
7230
|
|
|
7251
7231
|
// src/commands/sync.ts
|
|
7252
|
-
import
|
|
7232
|
+
import path33 from "node:path";
|
|
7253
7233
|
import { Command as Command70 } from "commander";
|
|
7254
7234
|
var sync = new Command70("sync").description("sync types from the database").configureHelp(helpConfig).action(
|
|
7255
7235
|
() => runCommand(async () => {
|
|
7256
7236
|
const { workspaceRootDir } = await getWorkspace();
|
|
7257
|
-
const typesDir =
|
|
7237
|
+
const typesDir = path33.join(workspaceRootDir, ".svelte-kit", "types");
|
|
7258
7238
|
const { processTypes } = await import("@velastack/pocketbase-codegen");
|
|
7259
7239
|
await withPocketbase(workspaceRootDir, async (pb) => {
|
|
7260
7240
|
await processTypes(pb, typesDir);
|
|
@@ -7316,34 +7296,34 @@ var provision = addSshOptions(
|
|
|
7316
7296
|
);
|
|
7317
7297
|
|
|
7318
7298
|
// src/commands/deploy.ts
|
|
7319
|
-
import
|
|
7320
|
-
import
|
|
7299
|
+
import path36 from "node:path";
|
|
7300
|
+
import fs33 from "node:fs";
|
|
7321
7301
|
import { Command as Command72, Option as Option2 } from "commander";
|
|
7322
7302
|
import * as p35 from "@clack/prompts";
|
|
7323
7303
|
import pc16 from "picocolors";
|
|
7324
7304
|
import * as v7 from "valibot";
|
|
7325
7305
|
|
|
7326
7306
|
// src/lib/pocketbase-settings.ts
|
|
7327
|
-
import
|
|
7328
|
-
import
|
|
7329
|
-
import
|
|
7330
|
-
import
|
|
7307
|
+
import fs31 from "node:fs";
|
|
7308
|
+
import path34 from "node:path";
|
|
7309
|
+
import process25 from "node:process";
|
|
7310
|
+
import PocketBase5 from "pocketbase";
|
|
7331
7311
|
var COPIED_KEYS = ["appName", "senderName", "senderAddress"];
|
|
7332
7312
|
async function readLocalMeta(cwd) {
|
|
7333
|
-
const
|
|
7334
|
-
if (!
|
|
7335
|
-
const email3 =
|
|
7336
|
-
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;
|
|
7337
7317
|
if (!email3 || !password11) return null;
|
|
7338
7318
|
let proc;
|
|
7339
7319
|
try {
|
|
7340
7320
|
const started = await startPocketbaseServe({
|
|
7341
|
-
dataDir,
|
|
7321
|
+
dataDir: dataDir2,
|
|
7342
7322
|
migrationsDir: MIGRATIONS_DIR,
|
|
7343
|
-
hooksDir:
|
|
7323
|
+
hooksDir: path34.join(dataDir2, "hooks")
|
|
7344
7324
|
});
|
|
7345
7325
|
proc = started.proc;
|
|
7346
|
-
const pb = new
|
|
7326
|
+
const pb = new PocketBase5(started.url);
|
|
7347
7327
|
await authWithRetries(pb, email3, password11);
|
|
7348
7328
|
const settings = await pb.settings.getAll();
|
|
7349
7329
|
return settings.meta ?? null;
|
|
@@ -7382,8 +7362,8 @@ async function seedRemoteMeta(session, instance, local, appURL) {
|
|
|
7382
7362
|
}
|
|
7383
7363
|
|
|
7384
7364
|
// src/lib/artifact.ts
|
|
7385
|
-
import
|
|
7386
|
-
import
|
|
7365
|
+
import fs32 from "node:fs";
|
|
7366
|
+
import path35 from "node:path";
|
|
7387
7367
|
import { detect as detect7 } from "package-manager-detector";
|
|
7388
7368
|
import { resolveCommand as resolveCommand7 } from "package-manager-detector/commands";
|
|
7389
7369
|
var DEFAULT_OUTPUT_DIR = "build";
|
|
@@ -7420,11 +7400,11 @@ function collectArtifact(cwd, config = {}) {
|
|
|
7420
7400
|
const outputDir = config.outputDir ?? DEFAULT_OUTPUT_DIR;
|
|
7421
7401
|
const entries = [];
|
|
7422
7402
|
const add2 = (rel, remoteDir = "") => {
|
|
7423
|
-
const localPath =
|
|
7424
|
-
if (
|
|
7403
|
+
const localPath = path35.join(cwd, rel);
|
|
7404
|
+
if (fs32.existsSync(localPath)) entries.push({ localPath, remoteDir });
|
|
7425
7405
|
};
|
|
7426
|
-
const buildPath =
|
|
7427
|
-
if (!
|
|
7406
|
+
const buildPath = path35.join(cwd, outputDir);
|
|
7407
|
+
if (!fs32.existsSync(path35.join(buildPath, "index.js"))) {
|
|
7428
7408
|
throw new BuildError(
|
|
7429
7409
|
`No ${outputDir}/index.js after the build.
|
|
7430
7410
|
|
|
@@ -7437,8 +7417,8 @@ the adapter in your Vite or Svelte config, then build again.`
|
|
|
7437
7417
|
add2("package-lock.json");
|
|
7438
7418
|
add2(".npmrc");
|
|
7439
7419
|
add2(MIGRATIONS_DIR);
|
|
7440
|
-
const hooks =
|
|
7441
|
-
if (
|
|
7420
|
+
const hooks = path35.join(cwd, DATA_DIR, "hooks");
|
|
7421
|
+
if (fs32.existsSync(hooks)) entries.push({ localPath: hooks, remoteDir: "hooks" });
|
|
7442
7422
|
for (const extra of config.include ?? []) add2(extra);
|
|
7443
7423
|
return entries;
|
|
7444
7424
|
}
|
|
@@ -7703,7 +7683,7 @@ async function uploadRelease(session, instance, release, entries) {
|
|
|
7703
7683
|
}
|
|
7704
7684
|
function isDirectory(target) {
|
|
7705
7685
|
try {
|
|
7706
|
-
return
|
|
7686
|
+
return fs33.statSync(target).isDirectory();
|
|
7707
7687
|
} catch {
|
|
7708
7688
|
return false;
|
|
7709
7689
|
}
|
|
@@ -7711,7 +7691,7 @@ function isDirectory(target) {
|
|
|
7711
7691
|
async function reportEmptyEnvironment(session, instance, workspaceRootDir) {
|
|
7712
7692
|
const remote = await readRemoteEnv(session, instance);
|
|
7713
7693
|
if (Object.keys(remote).length > 0) return;
|
|
7714
|
-
if (!
|
|
7694
|
+
if (!fs33.existsSync(path36.join(workspaceRootDir, ".env"))) return;
|
|
7715
7695
|
p35.log.warn(
|
|
7716
7696
|
`This app has no production environment variables yet.
|
|
7717
7697
|
|
|
@@ -7721,8 +7701,8 @@ ${pc16.cyan("vela env set KEY")}, or copy a file across with ${pc16.cyan("vela e
|
|
|
7721
7701
|
}
|
|
7722
7702
|
|
|
7723
7703
|
// src/commands/link.ts
|
|
7724
|
-
import
|
|
7725
|
-
import
|
|
7704
|
+
import path37 from "node:path";
|
|
7705
|
+
import process26 from "node:process";
|
|
7726
7706
|
import { Command as Command73 } from "commander";
|
|
7727
7707
|
import * as p36 from "@clack/prompts";
|
|
7728
7708
|
|
|
@@ -7822,7 +7802,7 @@ async function pickExistingProject(projects) {
|
|
|
7822
7802
|
});
|
|
7823
7803
|
if (p36.isCancel(choice)) {
|
|
7824
7804
|
p36.cancel("Operation cancelled.");
|
|
7825
|
-
|
|
7805
|
+
process26.exit(0);
|
|
7826
7806
|
}
|
|
7827
7807
|
return choice;
|
|
7828
7808
|
}
|
|
@@ -7837,7 +7817,7 @@ async function pickTeam(teams3) {
|
|
|
7837
7817
|
});
|
|
7838
7818
|
if (p36.isCancel(choice)) {
|
|
7839
7819
|
p36.cancel("Operation cancelled.");
|
|
7840
|
-
|
|
7820
|
+
process26.exit(0);
|
|
7841
7821
|
}
|
|
7842
7822
|
return teams3.find((team) => team.id === choice);
|
|
7843
7823
|
}
|
|
@@ -7852,18 +7832,18 @@ async function promptProjectName(workspaceRootDir) {
|
|
|
7852
7832
|
});
|
|
7853
7833
|
if (p36.isCancel(value)) {
|
|
7854
7834
|
p36.cancel("Operation cancelled.");
|
|
7855
|
-
|
|
7835
|
+
process26.exit(0);
|
|
7856
7836
|
}
|
|
7857
7837
|
return value.trim();
|
|
7858
7838
|
}
|
|
7859
7839
|
function defaultProjectName2(workspaceRootDir) {
|
|
7860
7840
|
try {
|
|
7861
|
-
const pkg = readPackageJson(
|
|
7841
|
+
const pkg = readPackageJson(path37.join(workspaceRootDir, "package.json"));
|
|
7862
7842
|
const name = pkg.name;
|
|
7863
7843
|
if (typeof name === "string" && name.trim()) return name.trim();
|
|
7864
7844
|
} catch {
|
|
7865
7845
|
}
|
|
7866
|
-
return
|
|
7846
|
+
return path37.basename(workspaceRootDir);
|
|
7867
7847
|
}
|
|
7868
7848
|
|
|
7869
7849
|
// src/commands/env.ts
|
|
@@ -7907,7 +7887,7 @@ function report(keys, where) {
|
|
|
7907
7887
|
}
|
|
7908
7888
|
|
|
7909
7889
|
// src/commands/env/set.ts
|
|
7910
|
-
import
|
|
7890
|
+
import process27 from "node:process";
|
|
7911
7891
|
import { Command as Command75 } from "commander";
|
|
7912
7892
|
import * as p38 from "@clack/prompts";
|
|
7913
7893
|
import pc18 from "picocolors";
|
|
@@ -7949,7 +7929,7 @@ async function promptValue(key) {
|
|
|
7949
7929
|
});
|
|
7950
7930
|
if (p38.isCancel(value)) {
|
|
7951
7931
|
p38.cancel("Operation cancelled.");
|
|
7952
|
-
|
|
7932
|
+
process27.exit(0);
|
|
7953
7933
|
}
|
|
7954
7934
|
return value;
|
|
7955
7935
|
}
|
|
@@ -7994,9 +7974,9 @@ var envUnset = addTargetOptions(
|
|
|
7994
7974
|
);
|
|
7995
7975
|
|
|
7996
7976
|
// src/commands/env/import.ts
|
|
7997
|
-
import
|
|
7998
|
-
import
|
|
7999
|
-
import
|
|
7977
|
+
import fs34 from "node:fs";
|
|
7978
|
+
import path38 from "node:path";
|
|
7979
|
+
import process28 from "node:process";
|
|
8000
7980
|
import { Command as Command77 } from "commander";
|
|
8001
7981
|
import * as p40 from "@clack/prompts";
|
|
8002
7982
|
import pc20 from "picocolors";
|
|
@@ -8041,10 +8021,10 @@ var envImport = addTargetOptions(
|
|
|
8041
8021
|
)
|
|
8042
8022
|
);
|
|
8043
8023
|
function resolve(file) {
|
|
8044
|
-
return
|
|
8024
|
+
return path38.resolve(process28.cwd(), file);
|
|
8045
8025
|
}
|
|
8046
8026
|
function read(resolved, shown) {
|
|
8047
|
-
if (!
|
|
8027
|
+
if (!fs34.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
|
|
8048
8028
|
const incoming = readLocalEnvFile(resolved);
|
|
8049
8029
|
if (Object.keys(incoming).length === 0) p40.log.info(`${shown} has no variables to import.`);
|
|
8050
8030
|
return incoming;
|
|
@@ -8111,8 +8091,8 @@ function describe(state) {
|
|
|
8111
8091
|
...state.rolledBackAt ? [["Rolled back", state.rolledBackAt]] : [],
|
|
8112
8092
|
...state.gitSha ? [["Commit", state.gitSha.slice(0, 12)]] : []
|
|
8113
8093
|
];
|
|
8114
|
-
const width = Math.max(...rows.map(([
|
|
8115
|
-
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");
|
|
8116
8096
|
}
|
|
8117
8097
|
|
|
8118
8098
|
// src/commands/rollback.ts
|
|
@@ -8193,7 +8173,7 @@ var logs = addTargetOptions(
|
|
|
8193
8173
|
import { Command as Command83 } from "commander";
|
|
8194
8174
|
|
|
8195
8175
|
// src/commands/admin/create.ts
|
|
8196
|
-
import
|
|
8176
|
+
import process29 from "node:process";
|
|
8197
8177
|
import { Command as Command82 } from "commander";
|
|
8198
8178
|
import * as p43 from "@clack/prompts";
|
|
8199
8179
|
import pc23 from "picocolors";
|
|
@@ -8260,7 +8240,7 @@ async function upsertSuperuser(pb, email3, password11) {
|
|
|
8260
8240
|
});
|
|
8261
8241
|
if (p43.isCancel(confirmed) || !confirmed) {
|
|
8262
8242
|
p43.cancel("Operation cancelled.");
|
|
8263
|
-
|
|
8243
|
+
process29.exit(0);
|
|
8264
8244
|
}
|
|
8265
8245
|
await pb.collection("_superusers").update(existing, { password: password11, passwordConfirm: password11 });
|
|
8266
8246
|
p43.log.success(`Password updated for ${pc23.cyan(email3)}, you can sign in now`);
|
|
@@ -8284,7 +8264,7 @@ async function promptEmail() {
|
|
|
8284
8264
|
});
|
|
8285
8265
|
if (p43.isCancel(value)) {
|
|
8286
8266
|
p43.cancel("Operation cancelled.");
|
|
8287
|
-
|
|
8267
|
+
process29.exit(0);
|
|
8288
8268
|
}
|
|
8289
8269
|
return value.trim();
|
|
8290
8270
|
}
|
|
@@ -8295,7 +8275,7 @@ async function promptPassword2() {
|
|
|
8295
8275
|
});
|
|
8296
8276
|
if (p43.isCancel(value)) {
|
|
8297
8277
|
p43.cancel("Operation cancelled.");
|
|
8298
|
-
|
|
8278
|
+
process29.exit(0);
|
|
8299
8279
|
}
|
|
8300
8280
|
const again = await p43.password({
|
|
8301
8281
|
message: "Password again",
|
|
@@ -8303,7 +8283,7 @@ async function promptPassword2() {
|
|
|
8303
8283
|
});
|
|
8304
8284
|
if (p43.isCancel(again)) {
|
|
8305
8285
|
p43.cancel("Operation cancelled.");
|
|
8306
|
-
|
|
8286
|
+
process29.exit(0);
|
|
8307
8287
|
}
|
|
8308
8288
|
return value;
|
|
8309
8289
|
}
|
|
@@ -8315,8 +8295,8 @@ var admin = new Command83("admin").description("manage admin panel logins").conf
|
|
|
8315
8295
|
import { Command as Command89 } from "commander";
|
|
8316
8296
|
|
|
8317
8297
|
// src/commands/backup/create.ts
|
|
8318
|
-
import
|
|
8319
|
-
import
|
|
8298
|
+
import fs35 from "node:fs";
|
|
8299
|
+
import path39 from "node:path";
|
|
8320
8300
|
import { Command as Command84 } from "commander";
|
|
8321
8301
|
import * as p44 from "@clack/prompts";
|
|
8322
8302
|
import pc24 from "picocolors";
|
|
@@ -8470,12 +8450,12 @@ Your bucket's own versioning is what protects the uploaded files.`
|
|
|
8470
8450
|
}, "Failed to create the backup.")
|
|
8471
8451
|
);
|
|
8472
8452
|
async function download(ctx, key, outputDir) {
|
|
8473
|
-
const dir =
|
|
8474
|
-
|
|
8475
|
-
const destination =
|
|
8453
|
+
const dir = path39.resolve(ctx.workspaceRootDir, outputDir);
|
|
8454
|
+
fs35.mkdirSync(dir, { recursive: true });
|
|
8455
|
+
const destination = path39.join(dir, key);
|
|
8476
8456
|
if (!ctx.session) {
|
|
8477
|
-
|
|
8478
|
-
return
|
|
8457
|
+
fs35.copyFileSync(path39.join(ctx.workspaceRootDir, "data", "backups", key), destination);
|
|
8458
|
+
return path39.relative(ctx.workspaceRootDir, destination);
|
|
8479
8459
|
}
|
|
8480
8460
|
const spinner5 = p44.spinner();
|
|
8481
8461
|
spinner5.start(`Downloading ${key}`);
|
|
@@ -8486,7 +8466,7 @@ async function download(ctx, key, outputDir) {
|
|
|
8486
8466
|
throw error;
|
|
8487
8467
|
}
|
|
8488
8468
|
spinner5.stop(`Downloaded ${key}`);
|
|
8489
|
-
return
|
|
8469
|
+
return path39.relative(ctx.workspaceRootDir, destination);
|
|
8490
8470
|
}
|
|
8491
8471
|
|
|
8492
8472
|
// src/commands/backup/list.ts
|
|
@@ -8520,8 +8500,8 @@ Take one with ${pc25.cyan("vela backup create")}.`
|
|
|
8520
8500
|
);
|
|
8521
8501
|
|
|
8522
8502
|
// src/commands/backup/download.ts
|
|
8523
|
-
import
|
|
8524
|
-
import
|
|
8503
|
+
import fs36 from "node:fs";
|
|
8504
|
+
import path40 from "node:path";
|
|
8525
8505
|
import { Command as Command86 } from "commander";
|
|
8526
8506
|
import * as p46 from "@clack/prompts";
|
|
8527
8507
|
import pc26 from "picocolors";
|
|
@@ -8548,11 +8528,11 @@ Run ${pc26.cyan("vela backup list")} to see what it does have.`
|
|
|
8548
8528
|
Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
8549
8529
|
);
|
|
8550
8530
|
}
|
|
8551
|
-
const dir =
|
|
8552
|
-
|
|
8553
|
-
const destination =
|
|
8531
|
+
const dir = path40.resolve(ctx.workspaceRootDir, options.output);
|
|
8532
|
+
fs36.mkdirSync(dir, { recursive: true });
|
|
8533
|
+
const destination = path40.join(dir, key);
|
|
8554
8534
|
if (!ctx.session) {
|
|
8555
|
-
|
|
8535
|
+
fs36.copyFileSync(path40.join(ctx.workspaceRootDir, "data", "backups", key), destination);
|
|
8556
8536
|
} else {
|
|
8557
8537
|
const spinner5 = p46.spinner();
|
|
8558
8538
|
spinner5.start(`Downloading ${key} (${formatBytes(found.size)})`);
|
|
@@ -8566,14 +8546,14 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
|
8566
8546
|
}
|
|
8567
8547
|
reportResult({
|
|
8568
8548
|
summary: `Saved ${key} from ${ctx.targetName}.`,
|
|
8569
|
-
filesCreated: [
|
|
8549
|
+
filesCreated: [path40.relative(ctx.workspaceRootDir, destination)]
|
|
8570
8550
|
});
|
|
8571
8551
|
});
|
|
8572
8552
|
}, "Failed to download the backup.")
|
|
8573
8553
|
);
|
|
8574
8554
|
|
|
8575
8555
|
// src/commands/backup/delete.ts
|
|
8576
|
-
import
|
|
8556
|
+
import process30 from "node:process";
|
|
8577
8557
|
import { Command as Command87 } from "commander";
|
|
8578
8558
|
import * as p47 from "@clack/prompts";
|
|
8579
8559
|
import pc27 from "picocolors";
|
|
@@ -8599,7 +8579,7 @@ Run ${pc27.cyan("vela backup list")} to see what it does have.`
|
|
|
8599
8579
|
});
|
|
8600
8580
|
if (p47.isCancel(confirmed) || !confirmed) {
|
|
8601
8581
|
p47.cancel("Operation cancelled.");
|
|
8602
|
-
|
|
8582
|
+
process30.exit(0);
|
|
8603
8583
|
}
|
|
8604
8584
|
}
|
|
8605
8585
|
await ctx.pb.backups.delete(key);
|
|
@@ -8661,9 +8641,9 @@ Set one with ${pc28.cyan('vela backup schedule "0 3 * * *"')}.`
|
|
|
8661
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);
|
|
8662
8642
|
|
|
8663
8643
|
// src/commands/restore.ts
|
|
8664
|
-
import
|
|
8665
|
-
import
|
|
8666
|
-
import
|
|
8644
|
+
import fs37 from "node:fs";
|
|
8645
|
+
import path41 from "node:path";
|
|
8646
|
+
import process31 from "node:process";
|
|
8667
8647
|
import { Command as Command90 } from "commander";
|
|
8668
8648
|
import * as p49 from "@clack/prompts";
|
|
8669
8649
|
import pc29 from "picocolors";
|
|
@@ -8683,7 +8663,7 @@ var restore = addTargetOptions(
|
|
|
8683
8663
|
`${ctx.targetName} was deployed without a database, so there is nothing to restore.`
|
|
8684
8664
|
);
|
|
8685
8665
|
}
|
|
8686
|
-
const local = source &&
|
|
8666
|
+
const local = source && fs37.existsSync(source) ? source : void 0;
|
|
8687
8667
|
const key = local ? void 0 : await resolveKey(ctx, source);
|
|
8688
8668
|
if (!options.yes) {
|
|
8689
8669
|
await confirm11(ctx.appName, ctx.targetName, ctx.envTag, local ?? key);
|
|
@@ -8705,7 +8685,7 @@ var restore = addTargetOptions(
|
|
|
8705
8685
|
});
|
|
8706
8686
|
p49.log.success(
|
|
8707
8687
|
`Restored ${pc29.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc29.cyan(
|
|
8708
|
-
local ?
|
|
8688
|
+
local ? path41.basename(local) : key
|
|
8709
8689
|
)}.`
|
|
8710
8690
|
);
|
|
8711
8691
|
if (result?.storageCarriedOver) {
|
|
@@ -8765,27 +8745,27 @@ Take one with ${pc29.cyan("vela backup create")}, or pass the path to an archive
|
|
|
8765
8745
|
});
|
|
8766
8746
|
if (p49.isCancel(chosen)) {
|
|
8767
8747
|
p49.cancel("Operation cancelled.");
|
|
8768
|
-
|
|
8748
|
+
process31.exit(0);
|
|
8769
8749
|
}
|
|
8770
8750
|
return chosen;
|
|
8771
8751
|
}
|
|
8772
8752
|
async function stage(ctx, file) {
|
|
8773
8753
|
const dir = remotePaths.restoreStage(ctx.instance);
|
|
8774
|
-
const remote = `${dir}/${
|
|
8754
|
+
const remote = `${dir}/${path41.basename(file)}`;
|
|
8775
8755
|
const spinner5 = p49.spinner();
|
|
8776
|
-
spinner5.start(`Uploading ${
|
|
8756
|
+
spinner5.start(`Uploading ${path41.basename(file)}`);
|
|
8777
8757
|
try {
|
|
8778
8758
|
await ctx.session.script(`mkdir -p "$1"`, { args: [dir] });
|
|
8779
8759
|
await ctx.session.upload([file], dir);
|
|
8780
8760
|
} catch (error) {
|
|
8781
|
-
spinner5.stop(`Could not upload ${
|
|
8761
|
+
spinner5.stop(`Could not upload ${path41.basename(file)}.`);
|
|
8782
8762
|
throw error;
|
|
8783
8763
|
}
|
|
8784
|
-
spinner5.stop(`Uploaded ${
|
|
8764
|
+
spinner5.stop(`Uploaded ${path41.basename(file)}`);
|
|
8785
8765
|
return remote;
|
|
8786
8766
|
}
|
|
8787
8767
|
async function confirm11(appName, targetName, envTag, from) {
|
|
8788
|
-
const what = `${pc29.cyan(`${appName} (${targetName})`)} from ${pc29.cyan(
|
|
8768
|
+
const what = `${pc29.cyan(`${appName} (${targetName})`)} from ${pc29.cyan(path41.basename(from))}`;
|
|
8789
8769
|
if (isProd(envTag)) {
|
|
8790
8770
|
const answer = await p49.text({
|
|
8791
8771
|
message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
|
|
@@ -8793,7 +8773,7 @@ async function confirm11(appName, targetName, envTag, from) {
|
|
|
8793
8773
|
});
|
|
8794
8774
|
if (p49.isCancel(answer)) {
|
|
8795
8775
|
p49.cancel("Operation cancelled.");
|
|
8796
|
-
|
|
8776
|
+
process31.exit(0);
|
|
8797
8777
|
}
|
|
8798
8778
|
return;
|
|
8799
8779
|
}
|
|
@@ -8803,7 +8783,7 @@ async function confirm11(appName, targetName, envTag, from) {
|
|
|
8803
8783
|
});
|
|
8804
8784
|
if (p49.isCancel(ok) || !ok) {
|
|
8805
8785
|
p49.cancel("Operation cancelled.");
|
|
8806
|
-
|
|
8786
|
+
process31.exit(0);
|
|
8807
8787
|
}
|
|
8808
8788
|
}
|
|
8809
8789
|
|
|
@@ -8896,57 +8876,90 @@ Release and domain are shown from what this project recorded.`
|
|
|
8896
8876
|
}
|
|
8897
8877
|
|
|
8898
8878
|
// src/commands/test.ts
|
|
8899
|
-
import
|
|
8900
|
-
import
|
|
8879
|
+
import path42 from "node:path";
|
|
8880
|
+
import process32 from "node:process";
|
|
8901
8881
|
import { Command as Command92 } from "commander";
|
|
8902
|
-
import
|
|
8882
|
+
import PocketBase6 from "pocketbase";
|
|
8903
8883
|
import pc31 from "picocolors";
|
|
8904
8884
|
import { x as x5 } from "tinyexec";
|
|
8905
8885
|
import { detect as detect8 } from "package-manager-detector";
|
|
8906
8886
|
import { resolveCommand as resolveCommand8 } from "package-manager-detector/commands";
|
|
8907
|
-
import
|
|
8887
|
+
import fs38 from "node:fs";
|
|
8908
8888
|
var testServer = new Command92("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
|
|
8909
|
-
const cwd =
|
|
8889
|
+
const cwd = process32.cwd();
|
|
8910
8890
|
const email3 = `test-${Math.random().toString(36).slice(2)}@example.com`;
|
|
8911
8891
|
const password11 = "password";
|
|
8912
|
-
const testDataDir =
|
|
8913
|
-
|
|
8892
|
+
const testDataDir = path42.join(cwd, "test-data");
|
|
8893
|
+
fs38.rmSync(testDataDir, { recursive: true, force: true });
|
|
8914
8894
|
const { stop, url } = await launchPocketbase(cwd, {
|
|
8915
8895
|
dir: testDataDir,
|
|
8916
|
-
migrationsDir:
|
|
8896
|
+
migrationsDir: path42.join(cwd, MIGRATIONS_DIR),
|
|
8897
|
+
// The app's PocketBase hooks (slug generation, personal teams, …) are part
|
|
8898
|
+
// of its behaviour; the suite runs against the same server dev and build
|
|
8899
|
+
// start, so it loads them from the same place.
|
|
8900
|
+
hooksDir: path42.join(cwd, DATA_DIR, "hooks"),
|
|
8917
8901
|
email: email3,
|
|
8918
8902
|
password: password11
|
|
8919
8903
|
});
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
|
|
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";
|
|
8925
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
|
+
}
|
|
8926
8952
|
const { createServer } = await loadVite(cwd);
|
|
8927
|
-
|
|
8953
|
+
vite = await createServer({
|
|
8928
8954
|
mode: "test",
|
|
8929
8955
|
plugins: [stubPagesPlugin()],
|
|
8930
8956
|
optimizeDeps: { noDiscovery: true }
|
|
8931
8957
|
});
|
|
8932
8958
|
const vitePort = await findFreePort();
|
|
8933
8959
|
await vite.listen(vitePort);
|
|
8934
|
-
|
|
8960
|
+
process32.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
|
|
8935
8961
|
console.log(`${pc31.greenBright("\u2713")} Started Vite: http://localhost:${vitePort}`);
|
|
8936
8962
|
console.log(`${pc31.greenBright("\u2713")} Started PocketBase: ${url}`);
|
|
8937
|
-
const cleanup = async () => {
|
|
8938
|
-
stop();
|
|
8939
|
-
await vite.close();
|
|
8940
|
-
fs41.rmSync(testDataDir, { recursive: true, force: true });
|
|
8941
|
-
};
|
|
8942
|
-
const pb = new PocketBase5(url);
|
|
8943
|
-
try {
|
|
8944
|
-
await authWithRetries(pb, email3, password11);
|
|
8945
|
-
} catch (e) {
|
|
8946
|
-
await cleanup();
|
|
8947
|
-
console.error(`${pc31.redBright("\u2717")} Auth failed: ${e.message}`);
|
|
8948
|
-
process33.exit(1);
|
|
8949
|
-
}
|
|
8950
8963
|
const extraArgs = (cmd.parent?.args ?? []).slice(1);
|
|
8951
8964
|
let filter = extraArgs.find((arg) => !arg.startsWith("-"));
|
|
8952
8965
|
const passthrough = filter ? extraArgs.filter((a) => a !== filter) : extraArgs;
|
|
@@ -8962,15 +8975,25 @@ var testServer = new Command92("test:server").description("run server tests").al
|
|
|
8962
8975
|
]);
|
|
8963
8976
|
const resolvedArgs = resolved.args.slice();
|
|
8964
8977
|
if (pm === "npm") resolvedArgs.unshift("--yes");
|
|
8965
|
-
await x5(resolved.command, resolvedArgs, {
|
|
8966
|
-
nodeOptions: { cwd, stdio: "inherit", env: { ...
|
|
8967
|
-
throwOnError: true
|
|
8978
|
+
const result = await x5(resolved.command, resolvedArgs, {
|
|
8979
|
+
nodeOptions: { cwd, stdio: "inherit", env: { ...process32.env, CI: "1" } }
|
|
8968
8980
|
});
|
|
8969
|
-
|
|
8981
|
+
process32.exitCode = result.exitCode ?? 1;
|
|
8982
|
+
} catch (e) {
|
|
8983
|
+
console.error(`${pc31.redBright("\u2717")} ${e.message}`);
|
|
8984
|
+
process32.exitCode = 1;
|
|
8970
8985
|
} finally {
|
|
8971
8986
|
await cleanup();
|
|
8972
8987
|
}
|
|
8973
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
|
+
}
|
|
8974
8997
|
function stubPagesPlugin() {
|
|
8975
8998
|
const stub = `<script>export const render = () => '';</script>`;
|
|
8976
8999
|
return {
|
|
@@ -8989,8 +9012,8 @@ function stubPagesPlugin() {
|
|
|
8989
9012
|
}
|
|
8990
9013
|
|
|
8991
9014
|
// src/commands/routes.ts
|
|
8992
|
-
import
|
|
8993
|
-
import
|
|
9015
|
+
import fs39 from "node:fs";
|
|
9016
|
+
import path43 from "node:path";
|
|
8994
9017
|
import { Command as Command93 } from "commander";
|
|
8995
9018
|
var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
8996
9019
|
"GET",
|
|
@@ -9004,30 +9027,30 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
|
9004
9027
|
]);
|
|
9005
9028
|
var routes = new Command93("routes").description("list routes").configureHelp(helpConfig).action(async () => {
|
|
9006
9029
|
const { workspaceRootDir, routesDir } = await getWorkspace();
|
|
9007
|
-
const routesRoot =
|
|
9030
|
+
const routesRoot = path43.join(workspaceRootDir, routesDir);
|
|
9008
9031
|
const found = walk(routesRoot, routesRoot).filter((r) => r.methods.length > 0);
|
|
9009
9032
|
found.sort((a, b) => a.urlPattern.localeCompare(b.urlPattern));
|
|
9010
9033
|
printTable(found);
|
|
9011
9034
|
});
|
|
9012
9035
|
function walk(root, dir) {
|
|
9013
|
-
const entries =
|
|
9036
|
+
const entries = fs39.readdirSync(dir, { withFileTypes: true });
|
|
9014
9037
|
const routes2 = [];
|
|
9015
9038
|
const hasLeaf = entries.some((e) => e.isFile() && isRouteFile(e.name));
|
|
9016
9039
|
if (hasLeaf) {
|
|
9017
|
-
const id = "/" +
|
|
9040
|
+
const id = "/" + path43.relative(root, dir).split(path43.sep).filter(Boolean).join("/");
|
|
9018
9041
|
const urlPattern = id.replace(/\([^)]+\)\/?/g, "").replace(/\/$/, "") || "/";
|
|
9019
9042
|
const methods = /* @__PURE__ */ new Set();
|
|
9020
9043
|
for (const entry of entries) {
|
|
9021
9044
|
if (!entry.isFile()) continue;
|
|
9022
9045
|
if (entry.name.endsWith("+page.svelte")) methods.add("GET");
|
|
9023
9046
|
if (entry.name.endsWith("+server.ts") || entry.name.endsWith("+server.js") || entry.name.endsWith("+page.server.ts") || entry.name.endsWith("+page.server.js")) {
|
|
9024
|
-
extractMethods(
|
|
9047
|
+
extractMethods(path43.join(dir, entry.name)).forEach((m) => methods.add(m));
|
|
9025
9048
|
}
|
|
9026
9049
|
}
|
|
9027
9050
|
routes2.push({ id: id || "/", urlPattern, methods: [...methods] });
|
|
9028
9051
|
}
|
|
9029
9052
|
for (const entry of entries) {
|
|
9030
|
-
if (entry.isDirectory()) routes2.push(...walk(root,
|
|
9053
|
+
if (entry.isDirectory()) routes2.push(...walk(root, path43.join(dir, entry.name)));
|
|
9031
9054
|
}
|
|
9032
9055
|
return routes2;
|
|
9033
9056
|
}
|
|
@@ -9036,7 +9059,7 @@ function isRouteFile(name) {
|
|
|
9036
9059
|
}
|
|
9037
9060
|
function extractMethods(file) {
|
|
9038
9061
|
try {
|
|
9039
|
-
const content =
|
|
9062
|
+
const content = fs39.readFileSync(file, "utf8");
|
|
9040
9063
|
const methods = [];
|
|
9041
9064
|
const exportRegex = /export\s+(?:const|async\s+function|function)\s+(\w+)/g;
|
|
9042
9065
|
let match;
|
|
@@ -9077,13 +9100,13 @@ function printTable(routes2) {
|
|
|
9077
9100
|
}
|
|
9078
9101
|
|
|
9079
9102
|
// src/commands/i18n.ts
|
|
9080
|
-
import
|
|
9103
|
+
import process33 from "node:process";
|
|
9081
9104
|
import { Command as Command94 } from "commander";
|
|
9082
9105
|
import { x as x6 } from "tinyexec";
|
|
9083
9106
|
import { detect as detect9 } from "package-manager-detector";
|
|
9084
9107
|
import { resolveCommand as resolveCommand9 } from "package-manager-detector/commands";
|
|
9085
9108
|
async function runWuchale(extraArgs) {
|
|
9086
|
-
const cwd =
|
|
9109
|
+
const cwd = process33.cwd();
|
|
9087
9110
|
const pm = (await detect9({ cwd }))?.name ?? "npm";
|
|
9088
9111
|
const resolved = resolveCommand9(pm, "execute", ["wuchale", ...extraArgs]);
|
|
9089
9112
|
const args = resolved.args.slice();
|
|
@@ -9119,15 +9142,15 @@ import pc33 from "picocolors";
|
|
|
9119
9142
|
|
|
9120
9143
|
// src/lib/cms-backend.ts
|
|
9121
9144
|
import { createRequire as createRequire3 } from "node:module";
|
|
9122
|
-
import
|
|
9123
|
-
import
|
|
9145
|
+
import path44 from "node:path";
|
|
9146
|
+
import process34 from "node:process";
|
|
9124
9147
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
9125
9148
|
import pc32 from "picocolors";
|
|
9126
9149
|
var DEFAULT_PROJECT = "default";
|
|
9127
9150
|
async function loadBackendModule(root) {
|
|
9128
9151
|
let entry;
|
|
9129
9152
|
try {
|
|
9130
|
-
entry = createRequire3(
|
|
9153
|
+
entry = createRequire3(path44.join(root, "package.json")).resolve("@velastack/cms/backend");
|
|
9131
9154
|
} catch {
|
|
9132
9155
|
throw new Error(
|
|
9133
9156
|
`@velastack/cms is not installed in this project.
|
|
@@ -9137,16 +9160,16 @@ Run ${pc32.cyan("vela enable cms")} first.`
|
|
|
9137
9160
|
}
|
|
9138
9161
|
return await import(pathToFileURL3(entry).href);
|
|
9139
9162
|
}
|
|
9140
|
-
async function withCmsBackend(fn, cwd =
|
|
9163
|
+
async function withCmsBackend(fn, cwd = process34.cwd()) {
|
|
9141
9164
|
const root = findWorkspaceRoot(cwd);
|
|
9142
9165
|
if (!root) {
|
|
9143
9166
|
throw new Error("Could not find workspace root (no package.json found)");
|
|
9144
9167
|
}
|
|
9145
9168
|
const { createCmsBackend } = await loadBackendModule(root);
|
|
9146
|
-
const
|
|
9169
|
+
const dataDir2 = localDataDir(root);
|
|
9147
9170
|
const backend3 = createCmsBackend({
|
|
9148
|
-
dbPath:
|
|
9149
|
-
uploadDir:
|
|
9171
|
+
dbPath: path44.join(dataDir2, "cms.sqlite"),
|
|
9172
|
+
uploadDir: path44.join(dataDir2, "uploads")
|
|
9150
9173
|
});
|
|
9151
9174
|
try {
|
|
9152
9175
|
return await fn(backend3);
|
|
@@ -9252,19 +9275,20 @@ var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
|
|
|
9252
9275
|
"restore"
|
|
9253
9276
|
]);
|
|
9254
9277
|
var BACKEND_OPTIONAL_COMMANDS = /* @__PURE__ */ new Set(["dev", "build", "preview", "deploy"]);
|
|
9278
|
+
var SELF_CREDENTIALED_COMMANDS = /* @__PURE__ */ new Set(["test:server"]);
|
|
9255
9279
|
var program = new Command100().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
|
|
9256
9280
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
9257
9281
|
if (isStub(actionCommand)) return;
|
|
9258
|
-
const envRoot = findWorkspaceRoot() ??
|
|
9282
|
+
const envRoot = findWorkspaceRoot() ?? process35.cwd();
|
|
9259
9283
|
dotenv2.config({ path: nodePath.join(envRoot, ".env"), quiet: true });
|
|
9260
|
-
const
|
|
9261
|
-
if (NO_BACKEND_COMMMANDS.has(
|
|
9262
|
-
const top =
|
|
9284
|
+
const path45 = getCommandPath(actionCommand);
|
|
9285
|
+
if (NO_BACKEND_COMMMANDS.has(path45)) return;
|
|
9286
|
+
const top = path45.split(" ", 1)[0];
|
|
9263
9287
|
if (NO_BACKEND_COMMMANDS.has(top)) return;
|
|
9264
9288
|
if (!hasBackend()) {
|
|
9265
9289
|
if (BACKEND_OPTIONAL_COMMANDS.has(top)) return;
|
|
9266
9290
|
p54.log.error(
|
|
9267
|
-
`${pc36.cyan(`vela ${
|
|
9291
|
+
`${pc36.cyan(`vela ${path45}`)} needs a backend, and this project does not have one.
|
|
9268
9292
|
|
|
9269
9293
|
Static projects have no database to talk to.
|
|
9270
9294
|
|
|
@@ -9272,9 +9296,10 @@ To add a backend to this project, run ${pc36.cyan("vela bless")}.`
|
|
|
9272
9296
|
);
|
|
9273
9297
|
p54.log.message();
|
|
9274
9298
|
p54.cancel("Operation failed.");
|
|
9275
|
-
|
|
9299
|
+
process35.exit(1);
|
|
9276
9300
|
}
|
|
9277
|
-
if (
|
|
9301
|
+
if (SELF_CREDENTIALED_COMMANDS.has(path45)) return;
|
|
9302
|
+
if (!process35.env.POCKETBASE_SUPERUSER_EMAIL || !process35.env.POCKETBASE_SUPERUSER_PASSWORD) {
|
|
9278
9303
|
p54.log.error(
|
|
9279
9304
|
`PocketBase superuser credentials are required.
|
|
9280
9305
|
|
|
@@ -9285,7 +9310,7 @@ To set up an existing project, run ${pc36.cyan("vela bless")}.`
|
|
|
9285
9310
|
);
|
|
9286
9311
|
p54.log.message();
|
|
9287
9312
|
p54.cancel("Operation failed.");
|
|
9288
|
-
|
|
9313
|
+
process35.exit(1);
|
|
9289
9314
|
}
|
|
9290
9315
|
});
|
|
9291
9316
|
function getCommandPath(cmd) {
|
|
@@ -9339,14 +9364,5 @@ for (const command of [
|
|
|
9339
9364
|
}
|
|
9340
9365
|
|
|
9341
9366
|
// src/bin.ts
|
|
9342
|
-
|
|
9343
|
-
var delegatedExitCode = delegateToLocalCli({
|
|
9344
|
-
argv,
|
|
9345
|
-
selfPath: fileURLToPath2(import.meta.url),
|
|
9346
|
-
selfVersion: package_default.version
|
|
9347
|
-
});
|
|
9348
|
-
if (delegatedExitCode !== null) {
|
|
9349
|
-
process37.exit(delegatedExitCode);
|
|
9350
|
-
}
|
|
9351
|
-
program.parse(argv, { from: "user" });
|
|
9367
|
+
program.parse(normalizeArgv(process36.argv.slice(2)), { from: "user" });
|
|
9352
9368
|
//# sourceMappingURL=bin.js.map
|