vela 0.13.2 → 0.13.4
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 +353 -311
- package/dist/bin.js.map +4 -4
- package/package.json +4 -4
package/dist/bin.js
CHANGED
|
@@ -21,7 +21,7 @@ import pc42 from "picocolors";
|
|
|
21
21
|
// package.json
|
|
22
22
|
var package_default = {
|
|
23
23
|
name: "vela",
|
|
24
|
-
version: "0.13.
|
|
24
|
+
version: "0.13.4",
|
|
25
25
|
type: "module",
|
|
26
26
|
description: "A CLI for creating and updating SvelteKit projects",
|
|
27
27
|
license: "MIT",
|
|
@@ -57,7 +57,7 @@ var package_default = {
|
|
|
57
57
|
dependencies: {
|
|
58
58
|
"@clack/prompts": "^1.7.0",
|
|
59
59
|
"@faker-js/faker": "^10.6.0",
|
|
60
|
-
"@velastack/patterns": "^0.2.
|
|
60
|
+
"@velastack/patterns": "^0.2.11",
|
|
61
61
|
"@velastack/pocketbase-codegen": "^0.1.0",
|
|
62
62
|
"annotate-json-schema": "^0.1.0",
|
|
63
63
|
commander: "^13.1.0",
|
|
@@ -80,11 +80,11 @@ var package_default = {
|
|
|
80
80
|
},
|
|
81
81
|
devDependencies: {
|
|
82
82
|
"@types/cross-spawn": "^6.0.6",
|
|
83
|
-
"@types/node": "^
|
|
83
|
+
"@types/node": "^26.5.1",
|
|
84
84
|
esbuild: "^0.28.2",
|
|
85
85
|
prettier: "^3.9.6",
|
|
86
86
|
shellcheck: "^4.1.0",
|
|
87
|
-
typescript: "^
|
|
87
|
+
typescript: "^7.0.2",
|
|
88
88
|
vite: "^8.2.2",
|
|
89
89
|
vitest: "^5.0.1"
|
|
90
90
|
},
|
|
@@ -236,8 +236,8 @@ function stubCommand(name, description, fullName) {
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
// src/lib/workspace.ts
|
|
239
|
-
import
|
|
240
|
-
import
|
|
239
|
+
import fs3 from "node:fs";
|
|
240
|
+
import path2 from "node:path";
|
|
241
241
|
import process3 from "node:process";
|
|
242
242
|
|
|
243
243
|
// src/lib/constants.ts
|
|
@@ -254,8 +254,36 @@ var API_URL = (process2.env.VELA_API_URL?.trim() || "https://velastack.dev").rep
|
|
|
254
254
|
var FIXTURE_PREFIX = "vela";
|
|
255
255
|
var TEMPLATE_INDEX_URL = process2.env.VELA_TEMPLATE_INDEX_URL?.trim() || "https://templates.velastack.app/index.json";
|
|
256
256
|
|
|
257
|
-
// src/lib/
|
|
257
|
+
// src/lib/components-json.ts
|
|
258
258
|
import fs from "node:fs";
|
|
259
|
+
import path from "node:path";
|
|
260
|
+
function readComponentsJson(root) {
|
|
261
|
+
const file = path.join(root, "components.json");
|
|
262
|
+
if (!fs.existsSync(file)) return void 0;
|
|
263
|
+
try {
|
|
264
|
+
const parsed = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
265
|
+
return parsed && typeof parsed === "object" ? parsed : void 0;
|
|
266
|
+
} catch {
|
|
267
|
+
return void 0;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
function componentsJsonHints(config) {
|
|
271
|
+
const hints = [];
|
|
272
|
+
if (!config.style) {
|
|
273
|
+
hints.push(
|
|
274
|
+
'components.json has no "style": shadcn-svelte defaults to "nova", while vela ships "vega". Add "style": "vega" so new components match.'
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
if (!config.iconLibrary) {
|
|
278
|
+
hints.push(
|
|
279
|
+
`components.json has no "iconLibrary": add "iconLibrary": "lucide", the library vela's components use.`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
return hints;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// src/lib/package-json.ts
|
|
286
|
+
import fs2 from "node:fs";
|
|
259
287
|
var DEP_KINDS = ["dependencies", "devDependencies"];
|
|
260
288
|
function mergePackageJson(user, template) {
|
|
261
289
|
const merged = structuredClone(user);
|
|
@@ -315,8 +343,8 @@ function dropTemplateAdapters(user, template) {
|
|
|
315
343
|
}
|
|
316
344
|
return copy;
|
|
317
345
|
}
|
|
318
|
-
function readPackageJson(
|
|
319
|
-
return JSON.parse(
|
|
346
|
+
function readPackageJson(path48) {
|
|
347
|
+
return JSON.parse(fs2.readFileSync(path48, "utf8"));
|
|
320
348
|
}
|
|
321
349
|
var PACKAGE_NAME_PLACEHOLDER = /~TODO~/g;
|
|
322
350
|
var APP_NAME_PLACEHOLDER = /~APP_NAME~/g;
|
|
@@ -334,12 +362,12 @@ function fillTemplatePlaceholders(raw, values) {
|
|
|
334
362
|
function escapeSingleQuoted(value) {
|
|
335
363
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
336
364
|
}
|
|
337
|
-
function readTemplatePackageJson(
|
|
338
|
-
const raw = fillTemplatePlaceholders(
|
|
365
|
+
function readTemplatePackageJson(path48, values) {
|
|
366
|
+
const raw = fillTemplatePlaceholders(fs2.readFileSync(path48, "utf8"), values);
|
|
339
367
|
return JSON.parse(raw);
|
|
340
368
|
}
|
|
341
|
-
function writePackageJson(
|
|
342
|
-
|
|
369
|
+
function writePackageJson(path48, pkg) {
|
|
370
|
+
fs2.writeFileSync(path48, JSON.stringify(pkg, null, " ") + "\n");
|
|
343
371
|
}
|
|
344
372
|
function toValidPackageName(name) {
|
|
345
373
|
return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9~.-]+/g, "-");
|
|
@@ -353,44 +381,40 @@ function sortKeys(obj) {
|
|
|
353
381
|
// src/lib/workspace.ts
|
|
354
382
|
function findWorkspaceRoot(from = process3.cwd()) {
|
|
355
383
|
let currentDir = from;
|
|
356
|
-
while (currentDir !==
|
|
357
|
-
if (
|
|
358
|
-
currentDir =
|
|
384
|
+
while (currentDir !== path2.parse(currentDir).root) {
|
|
385
|
+
if (fs3.existsSync(path2.join(currentDir, "package.json"))) return currentDir;
|
|
386
|
+
currentDir = path2.dirname(currentDir);
|
|
359
387
|
}
|
|
360
388
|
return null;
|
|
361
389
|
}
|
|
362
390
|
function hasBackend(from = process3.cwd()) {
|
|
363
391
|
const root = findWorkspaceRoot(from);
|
|
364
|
-
return root !== null &&
|
|
392
|
+
return root !== null && fs3.existsSync(path2.join(root, DATA_DIR));
|
|
365
393
|
}
|
|
366
394
|
function hasApiRoutes(root) {
|
|
367
|
-
const dir =
|
|
368
|
-
if (!
|
|
369
|
-
return
|
|
395
|
+
const dir = path2.join(root, "src", "routes", "api");
|
|
396
|
+
if (!fs3.existsSync(dir)) return false;
|
|
397
|
+
return fs3.readdirSync(dir).some((entry) => entry !== "README.md");
|
|
370
398
|
}
|
|
371
399
|
function localDataDir(from = process3.cwd()) {
|
|
372
|
-
return
|
|
400
|
+
return path2.join(findWorkspaceRoot(from) ?? from, DATA_DIR);
|
|
373
401
|
}
|
|
374
402
|
async function getWorkspace() {
|
|
375
403
|
const workspaceRootDir = findWorkspaceRoot();
|
|
376
404
|
if (!workspaceRootDir) {
|
|
377
405
|
throw new Error("Could not find workspace root (no package.json found)");
|
|
378
406
|
}
|
|
379
|
-
const routesDir =
|
|
380
|
-
const fullRoutesPath =
|
|
381
|
-
if (!
|
|
407
|
+
const routesDir = path2.join("src", "routes");
|
|
408
|
+
const fullRoutesPath = path2.join(workspaceRootDir, routesDir);
|
|
409
|
+
if (!fs3.existsSync(fullRoutesPath)) {
|
|
382
410
|
throw new Error("Could not find src/routes directory");
|
|
383
411
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
const isAppMode = fs2.existsSync(appRoutesPath);
|
|
391
|
-
if (isAppMode) appRoutesDir = path.join(routesDir, APP_DIR);
|
|
392
|
-
const isPaymentsMode = fs2.existsSync(
|
|
393
|
-
path.join(workspaceRootDir, routesDir, "webhooks", "stripe")
|
|
412
|
+
const routeGroups = detectRouteGroups(workspaceRootDir);
|
|
413
|
+
const publicRoutesDir = path2.join(routesDir, routeGroups.public ?? "");
|
|
414
|
+
const isAppMode = routeGroups.app !== null;
|
|
415
|
+
const appRoutesDir = routeGroups.app ? path2.join(routesDir, routeGroups.app) : void 0;
|
|
416
|
+
const isPaymentsMode = fs3.existsSync(
|
|
417
|
+
path2.join(workspaceRootDir, routesDir, "webhooks", "stripe")
|
|
394
418
|
);
|
|
395
419
|
const features = detectFeatures(workspaceRootDir, { isAppMode, isPaymentsMode });
|
|
396
420
|
return {
|
|
@@ -398,14 +422,25 @@ async function getWorkspace() {
|
|
|
398
422
|
routesDir,
|
|
399
423
|
publicRoutesDir,
|
|
400
424
|
appRoutesDir,
|
|
425
|
+
routeGroups,
|
|
401
426
|
isAppMode,
|
|
402
427
|
isPaymentsMode,
|
|
403
428
|
features
|
|
404
429
|
};
|
|
405
430
|
}
|
|
431
|
+
function detectRouteGroups(root) {
|
|
432
|
+
const group8 = (name) => fs3.existsSync(path2.join(root, "src", "routes", name)) ? name : null;
|
|
433
|
+
return { public: group8(PUBLIC_DIR), app: group8(APP_DIR) };
|
|
434
|
+
}
|
|
435
|
+
function detectUi(root) {
|
|
436
|
+
const pkg = readPackageJson(path2.join(root, "package.json"));
|
|
437
|
+
const hasDep = (name) => Boolean(pkg.dependencies?.[name] || pkg.devDependencies?.[name]);
|
|
438
|
+
const shadcn = readComponentsJson(root) !== void 0 && (hasDep("shadcn-svelte") || hasDep("bits-ui"));
|
|
439
|
+
return shadcn ? "shadcn" : "plain";
|
|
440
|
+
}
|
|
406
441
|
function detectFeatures(root, { isAppMode, isPaymentsMode }) {
|
|
407
|
-
const has = (rel) =>
|
|
408
|
-
const pkg = readPackageJson(
|
|
442
|
+
const has = (rel) => fs3.existsSync(path2.join(root, rel));
|
|
443
|
+
const pkg = readPackageJson(path2.join(root, "package.json"));
|
|
409
444
|
const hasDep = (name) => Boolean(pkg.dependencies?.[name] || pkg.devDependencies?.[name]);
|
|
410
445
|
return {
|
|
411
446
|
auth: isAppMode,
|
|
@@ -418,7 +453,8 @@ function detectFeatures(root, { isAppMode, isPaymentsMode }) {
|
|
|
418
453
|
blog: hasDep("mdsvex"),
|
|
419
454
|
contentNegotiation: hasDep("sveltekit-negotiate"),
|
|
420
455
|
cms: hasDep("@velastack/cms"),
|
|
421
|
-
workflows: has("src/lib/server/workflows.ts")
|
|
456
|
+
workflows: has("src/lib/server/workflows.ts"),
|
|
457
|
+
ui: detectUi(root)
|
|
422
458
|
};
|
|
423
459
|
}
|
|
424
460
|
|
|
@@ -460,46 +496,46 @@ function toFlag(key) {
|
|
|
460
496
|
}
|
|
461
497
|
|
|
462
498
|
// src/lib/templates.ts
|
|
463
|
-
import
|
|
464
|
-
import
|
|
499
|
+
import fs7 from "node:fs";
|
|
500
|
+
import path6 from "node:path";
|
|
465
501
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
466
502
|
|
|
467
503
|
// src/lib/template-files.ts
|
|
468
|
-
import
|
|
469
|
-
import
|
|
504
|
+
import fs4 from "node:fs";
|
|
505
|
+
import path3 from "node:path";
|
|
470
506
|
var PUBLISH_SAFE_NAMES = {
|
|
471
507
|
".gitignore": "_gitignore",
|
|
472
508
|
".npmrc": "_npmrc"
|
|
473
509
|
};
|
|
474
510
|
function templateName(projectRelPath) {
|
|
475
|
-
const safe = PUBLISH_SAFE_NAMES[
|
|
511
|
+
const safe = PUBLISH_SAFE_NAMES[path3.basename(projectRelPath)];
|
|
476
512
|
if (!safe) return projectRelPath;
|
|
477
|
-
const dir =
|
|
478
|
-
return dir === "." ? safe :
|
|
513
|
+
const dir = path3.dirname(projectRelPath);
|
|
514
|
+
return dir === "." ? safe : path3.join(dir, safe);
|
|
479
515
|
}
|
|
480
516
|
function restoreTemplateNames(target) {
|
|
481
517
|
for (const [real, safe] of Object.entries(PUBLISH_SAFE_NAMES)) {
|
|
482
|
-
const from =
|
|
483
|
-
if (!
|
|
484
|
-
|
|
518
|
+
const from = path3.join(target, safe);
|
|
519
|
+
if (!fs4.existsSync(from)) continue;
|
|
520
|
+
fs4.renameSync(from, path3.join(target, real));
|
|
485
521
|
}
|
|
486
522
|
}
|
|
487
523
|
var TEMPLATE_SOURCE = /\.template\.([^.]+)$/;
|
|
488
524
|
function applyTemplateFiles(target, values) {
|
|
489
525
|
const written = [];
|
|
490
526
|
for (const source of findTemplateSources(target)) {
|
|
491
|
-
const raw =
|
|
527
|
+
const raw = fs4.readFileSync(source, "utf8");
|
|
492
528
|
const dest = source.replace(TEMPLATE_SOURCE, ".$1");
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
written.push(
|
|
529
|
+
fs4.writeFileSync(dest, fillTemplatePlaceholders(raw, values));
|
|
530
|
+
fs4.unlinkSync(source);
|
|
531
|
+
written.push(path3.relative(target, dest));
|
|
496
532
|
}
|
|
497
533
|
return written.sort();
|
|
498
534
|
}
|
|
499
535
|
function findTemplateSources(dir) {
|
|
500
536
|
const found = [];
|
|
501
|
-
for (const entry of
|
|
502
|
-
const full =
|
|
537
|
+
for (const entry of fs4.readdirSync(dir, { withFileTypes: true })) {
|
|
538
|
+
const full = path3.join(dir, entry.name);
|
|
503
539
|
if (entry.isDirectory()) {
|
|
504
540
|
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
505
541
|
found.push(...findTemplateSources(full));
|
|
@@ -511,38 +547,38 @@ function findTemplateSources(dir) {
|
|
|
511
547
|
}
|
|
512
548
|
|
|
513
549
|
// src/lib/template-registry.ts
|
|
514
|
-
import
|
|
550
|
+
import fs6 from "node:fs";
|
|
515
551
|
import os2 from "node:os";
|
|
516
|
-
import
|
|
552
|
+
import path5 from "node:path";
|
|
517
553
|
import { createHash } from "node:crypto";
|
|
518
554
|
import { fileURLToPath } from "node:url";
|
|
519
555
|
import * as v2 from "valibot";
|
|
520
556
|
import * as tar from "tar";
|
|
521
557
|
|
|
522
558
|
// src/lib/config.ts
|
|
523
|
-
import
|
|
559
|
+
import fs5 from "node:fs";
|
|
524
560
|
import os from "node:os";
|
|
525
|
-
import
|
|
561
|
+
import path4 from "node:path";
|
|
526
562
|
import process4 from "node:process";
|
|
527
563
|
function configDir() {
|
|
528
|
-
return
|
|
564
|
+
return path4.join(os.homedir(), ".vela");
|
|
529
565
|
}
|
|
530
566
|
var CONFIG_DIR = configDir();
|
|
531
|
-
var CONFIG_PATH =
|
|
567
|
+
var CONFIG_PATH = path4.join(CONFIG_DIR, "config.json");
|
|
532
568
|
function readConfig() {
|
|
533
|
-
if (!
|
|
569
|
+
if (!fs5.existsSync(CONFIG_PATH)) return null;
|
|
534
570
|
try {
|
|
535
|
-
return JSON.parse(
|
|
571
|
+
return JSON.parse(fs5.readFileSync(CONFIG_PATH, "utf8"));
|
|
536
572
|
} catch {
|
|
537
573
|
return null;
|
|
538
574
|
}
|
|
539
575
|
}
|
|
540
576
|
function writeConfig(config) {
|
|
541
|
-
|
|
542
|
-
|
|
577
|
+
fs5.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
578
|
+
fs5.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
543
579
|
}
|
|
544
580
|
function clearConfig() {
|
|
545
|
-
if (
|
|
581
|
+
if (fs5.existsSync(CONFIG_PATH)) fs5.unlinkSync(CONFIG_PATH);
|
|
546
582
|
}
|
|
547
583
|
function readApiKey() {
|
|
548
584
|
const fromEnv = process4.env.VELA_API_KEY?.trim();
|
|
@@ -588,16 +624,16 @@ var indexSchema = v2.object({
|
|
|
588
624
|
templates: v2.array(v2.unknown())
|
|
589
625
|
});
|
|
590
626
|
function cacheRoot() {
|
|
591
|
-
return
|
|
627
|
+
return path5.join(configDir(), CACHE_DIR_NAME);
|
|
592
628
|
}
|
|
593
629
|
function indexCachePath() {
|
|
594
|
-
return
|
|
630
|
+
return path5.join(cacheRoot(), INDEX_CACHE_FILE);
|
|
595
631
|
}
|
|
596
632
|
function readCachedIndex(url) {
|
|
597
633
|
const file = indexCachePath();
|
|
598
|
-
if (!
|
|
634
|
+
if (!fs6.existsSync(file)) return null;
|
|
599
635
|
try {
|
|
600
|
-
const cached2 = JSON.parse(
|
|
636
|
+
const cached2 = JSON.parse(fs6.readFileSync(file, "utf8"));
|
|
601
637
|
if (cached2.url !== url) return null;
|
|
602
638
|
return cached2;
|
|
603
639
|
} catch {
|
|
@@ -605,8 +641,8 @@ function readCachedIndex(url) {
|
|
|
605
641
|
}
|
|
606
642
|
}
|
|
607
643
|
function writeCachedIndex(cached2) {
|
|
608
|
-
|
|
609
|
-
|
|
644
|
+
fs6.mkdirSync(cacheRoot(), { recursive: true });
|
|
645
|
+
fs6.writeFileSync(indexCachePath(), JSON.stringify(cached2, null, 2));
|
|
610
646
|
}
|
|
611
647
|
function parseTemplateIndex(text19, url) {
|
|
612
648
|
let parsed;
|
|
@@ -633,7 +669,7 @@ function isFileUrl(url) {
|
|
|
633
669
|
}
|
|
634
670
|
async function readBytes(url, options) {
|
|
635
671
|
if (isFileUrl(url)) {
|
|
636
|
-
return new Uint8Array(
|
|
672
|
+
return new Uint8Array(fs6.readFileSync(fileURLToPath(url)));
|
|
637
673
|
}
|
|
638
674
|
const res = await fetch(url, {
|
|
639
675
|
headers: options.headers,
|
|
@@ -671,7 +707,7 @@ function sha256(bytes) {
|
|
|
671
707
|
return createHash("sha256").update(bytes).digest("hex");
|
|
672
708
|
}
|
|
673
709
|
function tarballCachePath(entry) {
|
|
674
|
-
return
|
|
710
|
+
return path5.join(
|
|
675
711
|
cacheRoot(),
|
|
676
712
|
TARBALL_CACHE_DIR,
|
|
677
713
|
`${entry.name}-${entry.sha256.slice(0, 12)}.tgz`
|
|
@@ -681,8 +717,8 @@ async function downloadTemplate(entry, indexUrl, options = {}) {
|
|
|
681
717
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS * 6;
|
|
682
718
|
const cacheFile = tarballCachePath(entry);
|
|
683
719
|
let haveTarball = false;
|
|
684
|
-
if (
|
|
685
|
-
const cached2 = new Uint8Array(
|
|
720
|
+
if (fs6.existsSync(cacheFile)) {
|
|
721
|
+
const cached2 = new Uint8Array(fs6.readFileSync(cacheFile));
|
|
686
722
|
haveTarball = sha256(cached2) === entry.sha256;
|
|
687
723
|
}
|
|
688
724
|
if (!haveTarball) {
|
|
@@ -699,14 +735,14 @@ async function downloadTemplate(entry, indexUrl, options = {}) {
|
|
|
699
735
|
`Downloaded template ${entry.name} did not match its checksum (expected ${entry.sha256}, got ${digest}). Try again, or set VELA_TEMPLATE_INDEX_URL to a registry you trust.`
|
|
700
736
|
);
|
|
701
737
|
}
|
|
702
|
-
|
|
703
|
-
|
|
738
|
+
fs6.mkdirSync(path5.dirname(cacheFile), { recursive: true });
|
|
739
|
+
fs6.writeFileSync(cacheFile, fetched);
|
|
704
740
|
}
|
|
705
|
-
const dir =
|
|
741
|
+
const dir = fs6.mkdtempSync(path5.join(os2.tmpdir(), `vela-template-${entry.name}-`));
|
|
706
742
|
try {
|
|
707
743
|
await tar.extract({ file: cacheFile, cwd: dir, strip: 1 });
|
|
708
744
|
} catch (e) {
|
|
709
|
-
|
|
745
|
+
fs6.rmSync(dir, { recursive: true, force: true });
|
|
710
746
|
throw new Error(`Could not unpack template ${entry.name}: ${e.message}`);
|
|
711
747
|
}
|
|
712
748
|
return dir;
|
|
@@ -718,25 +754,25 @@ var DEFAULT_TEMPLATE = "minimal";
|
|
|
718
754
|
var DEFAULT_CATEGORY = "starter";
|
|
719
755
|
var cached;
|
|
720
756
|
function templatesDir() {
|
|
721
|
-
let dir =
|
|
722
|
-
const { root } =
|
|
757
|
+
let dir = path6.dirname(fileURLToPath2(import.meta.url));
|
|
758
|
+
const { root } = path6.parse(dir);
|
|
723
759
|
while (dir !== root) {
|
|
724
|
-
const candidate =
|
|
760
|
+
const candidate = path6.join(dir, "templates");
|
|
725
761
|
if (holdsManifest(candidate)) return candidate;
|
|
726
|
-
dir =
|
|
762
|
+
dir = path6.dirname(dir);
|
|
727
763
|
}
|
|
728
764
|
throw new Error("Could not locate the templates directory");
|
|
729
765
|
}
|
|
730
766
|
function holdsManifest(dir) {
|
|
731
|
-
if (!
|
|
732
|
-
return
|
|
733
|
-
(entry) => entry.isDirectory() &&
|
|
767
|
+
if (!fs7.existsSync(dir)) return false;
|
|
768
|
+
return fs7.readdirSync(dir, { withFileTypes: true }).some(
|
|
769
|
+
(entry) => entry.isDirectory() && fs7.existsSync(path6.join(dir, entry.name, TEMPLATE_MANIFEST))
|
|
734
770
|
);
|
|
735
771
|
}
|
|
736
772
|
function listProjectTemplates() {
|
|
737
773
|
if (cached) return cached;
|
|
738
774
|
const root = templatesDir();
|
|
739
|
-
cached =
|
|
775
|
+
cached = fs7.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));
|
|
740
776
|
return cached;
|
|
741
777
|
}
|
|
742
778
|
function projectTemplateNames(options = {}) {
|
|
@@ -809,25 +845,25 @@ async function resolveTemplate(template) {
|
|
|
809
845
|
...info,
|
|
810
846
|
dir,
|
|
811
847
|
cleanup() {
|
|
812
|
-
|
|
848
|
+
fs7.rmSync(dir, { recursive: true, force: true });
|
|
813
849
|
}
|
|
814
850
|
};
|
|
815
851
|
}
|
|
816
852
|
function copyTemplate(template, target) {
|
|
817
|
-
|
|
818
|
-
|
|
853
|
+
fs7.mkdirSync(target, { recursive: true });
|
|
854
|
+
fs7.cpSync(template.dir, target, {
|
|
819
855
|
recursive: true,
|
|
820
856
|
// The manifest describes the template to the CLI; it isn't part of the project.
|
|
821
|
-
filter: (src) =>
|
|
857
|
+
filter: (src) => path6.basename(src) !== ".DS_Store" && path6.relative(template.dir, src) !== TEMPLATE_MANIFEST
|
|
822
858
|
});
|
|
823
859
|
restoreTemplateNames(target);
|
|
824
860
|
}
|
|
825
861
|
function readManifest(root, name) {
|
|
826
|
-
const manifestPath =
|
|
827
|
-
if (!
|
|
862
|
+
const manifestPath = path6.join(root, name, TEMPLATE_MANIFEST);
|
|
863
|
+
if (!fs7.existsSync(manifestPath)) return void 0;
|
|
828
864
|
let parsed;
|
|
829
865
|
try {
|
|
830
|
-
parsed = JSON.parse(
|
|
866
|
+
parsed = JSON.parse(fs7.readFileSync(manifestPath, "utf8"));
|
|
831
867
|
} catch (e) {
|
|
832
868
|
throw new Error(
|
|
833
869
|
`Template ${name} has an unreadable ${TEMPLATE_MANIFEST}: ${e.message}`
|
|
@@ -850,7 +886,7 @@ function readManifest(root, name) {
|
|
|
850
886
|
price: typeof manifest.price === "number" ? manifest.price : void 0,
|
|
851
887
|
nextSteps: optionalStringArray(manifest.nextSteps),
|
|
852
888
|
cms: typeof manifest.cms === "boolean" ? manifest.cms : void 0,
|
|
853
|
-
dir:
|
|
889
|
+
dir: path6.join(root, name)
|
|
854
890
|
};
|
|
855
891
|
}
|
|
856
892
|
function optionalString(value) {
|
|
@@ -863,8 +899,8 @@ function optionalStringArray(value) {
|
|
|
863
899
|
}
|
|
864
900
|
|
|
865
901
|
// src/lib/package-manager.ts
|
|
866
|
-
import
|
|
867
|
-
import
|
|
902
|
+
import fs8 from "node:fs";
|
|
903
|
+
import path7 from "node:path";
|
|
868
904
|
import process5 from "node:process";
|
|
869
905
|
import { exec } from "tinyexec";
|
|
870
906
|
import { Option } from "commander";
|
|
@@ -934,9 +970,9 @@ async function installDependencies(agent, cwd, { exitOnFailure = true } = {}) {
|
|
|
934
970
|
}
|
|
935
971
|
function addPnpmBuildDependencies(cwd, packageManager2, allowedPackages) {
|
|
936
972
|
if (!packageManager2 || packageManager2 !== "pnpm") return;
|
|
937
|
-
const pkgPath =
|
|
938
|
-
if (!
|
|
939
|
-
const pkg = JSON.parse(
|
|
973
|
+
const pkgPath = path7.join(cwd, "package.json");
|
|
974
|
+
if (!fs8.existsSync(pkgPath)) return;
|
|
975
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
940
976
|
pkg.pnpm ??= {};
|
|
941
977
|
pkg.pnpm.onlyBuiltDependencies ??= [];
|
|
942
978
|
for (const name of allowedPackages) {
|
|
@@ -944,13 +980,13 @@ function addPnpmBuildDependencies(cwd, packageManager2, allowedPackages) {
|
|
|
944
980
|
pkg.pnpm.onlyBuiltDependencies.push(name);
|
|
945
981
|
}
|
|
946
982
|
}
|
|
947
|
-
|
|
983
|
+
fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, " ") + "\n");
|
|
948
984
|
}
|
|
949
985
|
|
|
950
986
|
// src/lib/pocketbase.ts
|
|
951
|
-
import
|
|
987
|
+
import fs9 from "node:fs";
|
|
952
988
|
import net from "node:net";
|
|
953
|
-
import
|
|
989
|
+
import path8 from "node:path";
|
|
954
990
|
import process6 from "node:process";
|
|
955
991
|
import { createRequire } from "node:module";
|
|
956
992
|
import { spawn } from "node:child_process";
|
|
@@ -1063,9 +1099,9 @@ async function authWithRetries(pb, email3, password11, attempts = 3) {
|
|
|
1063
1099
|
}
|
|
1064
1100
|
}
|
|
1065
1101
|
function getPocketbaseMetadata(cwd) {
|
|
1066
|
-
const metadataPath =
|
|
1067
|
-
if (
|
|
1068
|
-
return JSON.parse(
|
|
1102
|
+
const metadataPath = path8.join(cwd, "node_modules", ".vite", "_pocketbase_metadata.json");
|
|
1103
|
+
if (fs9.existsSync(metadataPath)) {
|
|
1104
|
+
return JSON.parse(fs9.readFileSync(metadataPath, "utf8"));
|
|
1069
1105
|
}
|
|
1070
1106
|
return null;
|
|
1071
1107
|
}
|
|
@@ -1078,12 +1114,12 @@ async function execPackageBin(cwd, args, stdio = "pipe") {
|
|
|
1078
1114
|
return x(command, resolvedArgs, { nodeOptions: { cwd, stdio }, throwOnError: true });
|
|
1079
1115
|
}
|
|
1080
1116
|
async function withPocketbase(cwd, fn, creds) {
|
|
1081
|
-
const dir =
|
|
1082
|
-
const migrationsDir =
|
|
1117
|
+
const dir = path8.join(cwd, DATA_DIR);
|
|
1118
|
+
const migrationsDir = path8.join(cwd, MIGRATIONS_DIR);
|
|
1083
1119
|
const host = "localhost";
|
|
1084
1120
|
const email3 = creds?.email ?? process6.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
1085
1121
|
const password11 = creds?.password ?? process6.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
1086
|
-
if (!
|
|
1122
|
+
if (!fs9.existsSync(dir)) {
|
|
1087
1123
|
throw new Error("PocketBase data directory does not exist");
|
|
1088
1124
|
}
|
|
1089
1125
|
const metadata = getPocketbaseMetadata(cwd);
|
|
@@ -1108,10 +1144,10 @@ async function withPocketbase(cwd, fn, creds) {
|
|
|
1108
1144
|
}
|
|
1109
1145
|
}
|
|
1110
1146
|
async function createSuperuser(cwd, email3, password11) {
|
|
1111
|
-
const dir =
|
|
1112
|
-
const migrationsDir =
|
|
1113
|
-
|
|
1114
|
-
|
|
1147
|
+
const dir = path8.join(cwd, DATA_DIR);
|
|
1148
|
+
const migrationsDir = path8.join(cwd, MIGRATIONS_DIR);
|
|
1149
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
1150
|
+
fs9.mkdirSync(migrationsDir, { recursive: true });
|
|
1115
1151
|
await execPackageBin(
|
|
1116
1152
|
cwd,
|
|
1117
1153
|
[
|
|
@@ -1136,8 +1172,8 @@ async function launchPocketbase(cwd, {
|
|
|
1136
1172
|
password: password11
|
|
1137
1173
|
}) {
|
|
1138
1174
|
const host = "localhost";
|
|
1139
|
-
|
|
1140
|
-
|
|
1175
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
1176
|
+
fs9.mkdirSync(migrationsDir, { recursive: true });
|
|
1141
1177
|
await execPackageBin(
|
|
1142
1178
|
cwd,
|
|
1143
1179
|
[
|
|
@@ -1179,8 +1215,8 @@ async function ensureSuperuser(cwd) {
|
|
|
1179
1215
|
const email3 = process6.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
1180
1216
|
const password11 = process6.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
1181
1217
|
if (!email3 || !password11) return;
|
|
1182
|
-
const dir =
|
|
1183
|
-
if (!
|
|
1218
|
+
const dir = path8.join(cwd, DATA_DIR);
|
|
1219
|
+
if (!fs9.existsSync(dir)) return;
|
|
1184
1220
|
const { getBinaryPath } = await import("pocketbase-server");
|
|
1185
1221
|
await x(
|
|
1186
1222
|
getBinaryPath(),
|
|
@@ -1188,7 +1224,7 @@ async function ensureSuperuser(cwd) {
|
|
|
1188
1224
|
"--dir",
|
|
1189
1225
|
dir,
|
|
1190
1226
|
"--migrationsDir",
|
|
1191
|
-
|
|
1227
|
+
path8.join(cwd, MIGRATIONS_DIR),
|
|
1192
1228
|
"superuser",
|
|
1193
1229
|
"upsert",
|
|
1194
1230
|
email3,
|
|
@@ -1199,8 +1235,8 @@ async function ensureSuperuser(cwd) {
|
|
|
1199
1235
|
}
|
|
1200
1236
|
|
|
1201
1237
|
// src/lib/env.ts
|
|
1202
|
-
import
|
|
1203
|
-
import
|
|
1238
|
+
import fs10 from "node:fs";
|
|
1239
|
+
import path9 from "node:path";
|
|
1204
1240
|
function addEnvVar(content, key, value) {
|
|
1205
1241
|
if (content.includes(`${key}=`)) return content;
|
|
1206
1242
|
return appendLine(content, `${key}=${value}`);
|
|
@@ -1215,11 +1251,11 @@ function appendLine(existing, line) {
|
|
|
1215
1251
|
return withNewline + line + "\n";
|
|
1216
1252
|
}
|
|
1217
1253
|
function writeEnvFile(cwd, vars, comments = []) {
|
|
1218
|
-
const envPath =
|
|
1219
|
-
let content =
|
|
1254
|
+
const envPath = path9.join(cwd, ".env");
|
|
1255
|
+
let content = fs10.existsSync(envPath) ? fs10.readFileSync(envPath, "utf8") : "";
|
|
1220
1256
|
for (const comment of comments) content = addEnvComment(content, comment);
|
|
1221
1257
|
for (const [key, value] of Object.entries(vars)) content = addEnvVar(content, key, value);
|
|
1222
|
-
|
|
1258
|
+
fs10.writeFileSync(envPath, content);
|
|
1223
1259
|
}
|
|
1224
1260
|
function upsertEnvVar(content, key, value) {
|
|
1225
1261
|
const line = `${key}=${quoteEnvValue(value)}`;
|
|
@@ -1252,7 +1288,7 @@ function quoteEnvValue(value) {
|
|
|
1252
1288
|
}
|
|
1253
1289
|
|
|
1254
1290
|
// src/lib/app-css.ts
|
|
1255
|
-
import
|
|
1291
|
+
import fs11 from "node:fs";
|
|
1256
1292
|
var SHADCN_TAILWIND_CSS = "shadcn-svelte/tailwind.css";
|
|
1257
1293
|
var SHADCN_TAILWIND_IMPORT = `@import '${SHADCN_TAILWIND_CSS}';`;
|
|
1258
1294
|
function hasShadcnImport(css) {
|
|
@@ -1278,41 +1314,13 @@ ${css}`;
|
|
|
1278
1314
|
return lines.join("\n");
|
|
1279
1315
|
}
|
|
1280
1316
|
function ensureShadcnImport(appCssPath) {
|
|
1281
|
-
if (!
|
|
1282
|
-
const css =
|
|
1317
|
+
if (!fs11.existsSync(appCssPath)) return false;
|
|
1318
|
+
const css = fs11.readFileSync(appCssPath, "utf8");
|
|
1283
1319
|
if (hasShadcnImport(css)) return false;
|
|
1284
|
-
|
|
1320
|
+
fs11.writeFileSync(appCssPath, insertShadcnImport(css));
|
|
1285
1321
|
return true;
|
|
1286
1322
|
}
|
|
1287
1323
|
|
|
1288
|
-
// src/lib/components-json.ts
|
|
1289
|
-
import fs11 from "node:fs";
|
|
1290
|
-
import path9 from "node:path";
|
|
1291
|
-
function readComponentsJson(root) {
|
|
1292
|
-
const file = path9.join(root, "components.json");
|
|
1293
|
-
if (!fs11.existsSync(file)) return void 0;
|
|
1294
|
-
try {
|
|
1295
|
-
const parsed = JSON.parse(fs11.readFileSync(file, "utf8"));
|
|
1296
|
-
return parsed && typeof parsed === "object" ? parsed : void 0;
|
|
1297
|
-
} catch {
|
|
1298
|
-
return void 0;
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
function componentsJsonHints(config) {
|
|
1302
|
-
const hints = [];
|
|
1303
|
-
if (!config.style) {
|
|
1304
|
-
hints.push(
|
|
1305
|
-
'components.json has no "style": shadcn-svelte defaults to "nova", while vela ships "vega". Add "style": "vega" so new components match.'
|
|
1306
|
-
);
|
|
1307
|
-
}
|
|
1308
|
-
if (!config.iconLibrary) {
|
|
1309
|
-
hints.push(
|
|
1310
|
-
`components.json has no "iconLibrary": add "iconLibrary": "lucide", the library vela's components use.`
|
|
1311
|
-
);
|
|
1312
|
-
}
|
|
1313
|
-
return hints;
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
1324
|
// src/lib/config-merge.ts
|
|
1317
1325
|
import fs13 from "node:fs";
|
|
1318
1326
|
import path11 from "node:path";
|
|
@@ -2691,8 +2699,8 @@ async function runPattern(slug2, argv, input, report4) {
|
|
|
2691
2699
|
throw new Error(`Unknown pattern: ${slug2}`);
|
|
2692
2700
|
}
|
|
2693
2701
|
checkProviderInput(pattern, argv, input);
|
|
2694
|
-
const { workspaceRootDir, features } = await getWorkspace();
|
|
2695
|
-
const
|
|
2702
|
+
const { workspaceRootDir, features, routeGroups } = await getWorkspace();
|
|
2703
|
+
const log50 = p9.taskLog({ title: report4.task.title });
|
|
2696
2704
|
let result;
|
|
2697
2705
|
try {
|
|
2698
2706
|
result = await pattern.generate({
|
|
@@ -2700,6 +2708,7 @@ async function runPattern(slug2, argv, input, report4) {
|
|
|
2700
2708
|
env: "runtime",
|
|
2701
2709
|
root: workspaceRootDir,
|
|
2702
2710
|
features,
|
|
2711
|
+
routeGroups,
|
|
2703
2712
|
input,
|
|
2704
2713
|
// Patterns no longer read the schema themselves: @velastack/pocketbase-codegen
|
|
2705
2714
|
// takes an injected client, and only the CLI knows how to reach (or spawn)
|
|
@@ -2712,11 +2721,11 @@ async function runPattern(slug2, argv, input, report4) {
|
|
|
2712
2721
|
});
|
|
2713
2722
|
return collections2;
|
|
2714
2723
|
},
|
|
2715
|
-
logger: { info: (message) =>
|
|
2724
|
+
logger: { info: (message) => log50.message(message) }
|
|
2716
2725
|
});
|
|
2717
|
-
|
|
2726
|
+
log50.success(report4.task.success);
|
|
2718
2727
|
} catch (e) {
|
|
2719
|
-
|
|
2728
|
+
log50.error(report4.task.error);
|
|
2720
2729
|
throw e;
|
|
2721
2730
|
}
|
|
2722
2731
|
const rel = (f) => toRelative(workspaceRootDir, f);
|
|
@@ -2749,9 +2758,34 @@ async function runPattern(slug2, argv, input, report4) {
|
|
|
2749
2758
|
});
|
|
2750
2759
|
}
|
|
2751
2760
|
|
|
2761
|
+
// src/lib/form-ui.ts
|
|
2762
|
+
import path17 from "node:path";
|
|
2763
|
+
var UIS = ["shadcn", "plain"];
|
|
2764
|
+
function detectFormInput(root) {
|
|
2765
|
+
const pkg = readPackageJson(path17.join(root, "package.json"));
|
|
2766
|
+
const hasDep = (name) => Boolean(pkg.dependencies?.[name] || pkg.devDependencies?.[name]);
|
|
2767
|
+
return {
|
|
2768
|
+
flash: hasDep("sveltekit-flash-message"),
|
|
2769
|
+
serverTests: hasDep("supertest")
|
|
2770
|
+
};
|
|
2771
|
+
}
|
|
2772
|
+
function resolveFormInput(root, detectedUi, requested) {
|
|
2773
|
+
const detected = detectFormInput(root);
|
|
2774
|
+
if (requested === void 0) return detected;
|
|
2775
|
+
if (!UIS.includes(requested)) {
|
|
2776
|
+
throw new Error(`Unknown --ui "${requested}". Expected one of: ${UIS.join(", ")}.`);
|
|
2777
|
+
}
|
|
2778
|
+
if (requested === "shadcn" && detectedUi !== "shadcn") {
|
|
2779
|
+
throw new Error(
|
|
2780
|
+
"--ui shadcn needs a shadcn-svelte project (a components.json and the shadcn-svelte package). Run `vela bless` to set one up, or use --ui plain."
|
|
2781
|
+
);
|
|
2782
|
+
}
|
|
2783
|
+
return { ...detected, ui: requested };
|
|
2784
|
+
}
|
|
2785
|
+
|
|
2752
2786
|
// src/lib/ai-flow.ts
|
|
2753
2787
|
import fs18 from "node:fs";
|
|
2754
|
-
import
|
|
2788
|
+
import path18 from "node:path";
|
|
2755
2789
|
import * as p13 from "@clack/prompts";
|
|
2756
2790
|
import pc4 from "picocolors";
|
|
2757
2791
|
|
|
@@ -3026,17 +3060,20 @@ function specToArgv(spec) {
|
|
|
3026
3060
|
return collectionSpecToArgv(spec);
|
|
3027
3061
|
}
|
|
3028
3062
|
function writeLayoutSidecar(workspaceRootDir, modelName, layout) {
|
|
3029
|
-
const dir =
|
|
3063
|
+
const dir = path18.join(workspaceRootDir, "data", "ai-form-layouts");
|
|
3030
3064
|
fs18.mkdirSync(dir, { recursive: true });
|
|
3031
|
-
const file =
|
|
3065
|
+
const file = path18.join(dir, `${modelName}.json`);
|
|
3032
3066
|
fs18.writeFileSync(file, JSON.stringify(layout, null, 2) + "\n");
|
|
3033
|
-
return
|
|
3067
|
+
return path18.relative(workspaceRootDir, file);
|
|
3034
3068
|
}
|
|
3035
3069
|
|
|
3036
3070
|
// src/commands/generate/form.ts
|
|
3037
3071
|
var form = new Command5("form").description("generate a form from a model").argument("[model]", 'model name (e.g. "contact")').argument("[fields...]", 'field definitions (e.g. "name:text", "email:email")').option("--remote", "generate a form backed by a remote PocketBase collection").option(
|
|
3038
3072
|
"--route <route>",
|
|
3039
|
-
'place the form at a custom route (e.g. "(app)/[team_id]/projects/new"). Defaults to the model name under (app)
|
|
3073
|
+
'place the form at a custom route (e.g. "(app)/[team_id]/projects/new"). Defaults to the model name under the (app) or (public) group, or src/routes when it has neither.'
|
|
3074
|
+
).option(
|
|
3075
|
+
"--ui <ui>",
|
|
3076
|
+
'markup to generate: "shadcn" components or "plain" HTML. Defaults to shadcn when the project has shadcn-svelte, plain otherwise.'
|
|
3040
3077
|
).option(
|
|
3041
3078
|
"--ai <description>",
|
|
3042
3079
|
"design the form with AI from a natural-language description (two stages: schema \u2192 layout)"
|
|
@@ -3069,6 +3106,11 @@ var form = new Command5("form").description("generate a form from a model").argu
|
|
|
3069
3106
|
argv = [model, ...fields];
|
|
3070
3107
|
modelName = model;
|
|
3071
3108
|
}
|
|
3109
|
+
const { workspaceRootDir, features } = await getWorkspace();
|
|
3110
|
+
const formInput = resolveFormInput(workspaceRootDir, features.ui, options.ui);
|
|
3111
|
+
if (features.ui === "plain" && !options.ui) {
|
|
3112
|
+
p14.log.info("shadcn-svelte not detected: generating a plain HTML form.");
|
|
3113
|
+
}
|
|
3072
3114
|
const slug2 = options.remote ? "generate-form-remote" : "generate-form";
|
|
3073
3115
|
const nextSteps = [
|
|
3074
3116
|
"Edit the form fields and validation in the generated +page.svelte.",
|
|
@@ -3082,7 +3124,7 @@ var form = new Command5("form").description("generate a form from a model").argu
|
|
|
3082
3124
|
await runPattern(
|
|
3083
3125
|
slug2,
|
|
3084
3126
|
argv,
|
|
3085
|
-
{ route: options.route },
|
|
3127
|
+
{ route: options.route, ...formInput },
|
|
3086
3128
|
{
|
|
3087
3129
|
summary: `Created ${modelName} form.`,
|
|
3088
3130
|
nextSteps,
|
|
@@ -3172,7 +3214,7 @@ import { Command as Command8 } from "commander";
|
|
|
3172
3214
|
import * as p16 from "@clack/prompts";
|
|
3173
3215
|
var scaffold = new Command8("scaffold").description("generate a full CRUD scaffold (model, forms, list, detail)").argument("[model]", "model name").argument("[fields...]", "field definitions").option("--remote", "generate a scaffold backed by a remote PocketBase collection").option(
|
|
3174
3216
|
"--route <route>",
|
|
3175
|
-
'place the scaffold at a custom route (e.g. "(app)/[team_id]/projects"). Defaults to the pluralized model name under (app)
|
|
3217
|
+
'place the scaffold at a custom route (e.g. "(app)/[team_id]/projects"). Defaults to the pluralized model name under the (app) or (public) group, or src/routes when it has neither.'
|
|
3176
3218
|
).option(
|
|
3177
3219
|
"--ai <description>",
|
|
3178
3220
|
"design the scaffold with AI from a natural-language description (two stages: schema \u2192 layout)"
|
|
@@ -3644,7 +3686,7 @@ import pc5 from "picocolors";
|
|
|
3644
3686
|
|
|
3645
3687
|
// src/lib/deploy-config.ts
|
|
3646
3688
|
import fs19 from "node:fs";
|
|
3647
|
-
import
|
|
3689
|
+
import path19 from "node:path";
|
|
3648
3690
|
import crypto from "node:crypto";
|
|
3649
3691
|
import { pathToFileURL } from "node:url";
|
|
3650
3692
|
var CONFIG_BASENAMES = [
|
|
@@ -3655,7 +3697,7 @@ var CONFIG_BASENAMES = [
|
|
|
3655
3697
|
];
|
|
3656
3698
|
function findConfigFile(workspaceRootDir) {
|
|
3657
3699
|
for (const name of CONFIG_BASENAMES) {
|
|
3658
|
-
const file =
|
|
3700
|
+
const file = path19.join(workspaceRootDir, name);
|
|
3659
3701
|
if (fs19.existsSync(file)) return file;
|
|
3660
3702
|
}
|
|
3661
3703
|
return null;
|
|
@@ -3671,7 +3713,7 @@ async function loadDeployConfig(workspaceRootDir) {
|
|
|
3671
3713
|
const mod = await import(url);
|
|
3672
3714
|
const config = mod.default;
|
|
3673
3715
|
if (!config || typeof config !== "object") {
|
|
3674
|
-
throw new Error(`${
|
|
3716
|
+
throw new Error(`${path19.basename(file)} must export a config object as its default export.`);
|
|
3675
3717
|
}
|
|
3676
3718
|
return config;
|
|
3677
3719
|
} finally {
|
|
@@ -3684,15 +3726,15 @@ async function transpileToTemp(file) {
|
|
|
3684
3726
|
const { outputText } = ts.transpileModule(source, {
|
|
3685
3727
|
compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 }
|
|
3686
3728
|
});
|
|
3687
|
-
const temp =
|
|
3688
|
-
|
|
3729
|
+
const temp = path19.join(
|
|
3730
|
+
path19.dirname(file),
|
|
3689
3731
|
`.velastack.config.${crypto.randomBytes(4).toString("hex")}.mjs`
|
|
3690
3732
|
);
|
|
3691
3733
|
fs19.writeFileSync(temp, outputText);
|
|
3692
3734
|
return pathToFileURL(temp).href;
|
|
3693
3735
|
}
|
|
3694
3736
|
function projectFilePath(workspaceRootDir) {
|
|
3695
|
-
return
|
|
3737
|
+
return path19.join(workspaceRootDir, ".vela", "project.json");
|
|
3696
3738
|
}
|
|
3697
3739
|
function readProjectFile(workspaceRootDir) {
|
|
3698
3740
|
const file = projectFilePath(workspaceRootDir);
|
|
@@ -3705,7 +3747,7 @@ function readProjectFile(workspaceRootDir) {
|
|
|
3705
3747
|
}
|
|
3706
3748
|
function writeProjectFile(workspaceRootDir, data) {
|
|
3707
3749
|
const file = projectFilePath(workspaceRootDir);
|
|
3708
|
-
fs19.mkdirSync(
|
|
3750
|
+
fs19.mkdirSync(path19.dirname(file), { recursive: true });
|
|
3709
3751
|
fs19.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
|
|
3710
3752
|
}
|
|
3711
3753
|
function resolveAppIdentity(workspaceRootDir, config = {}) {
|
|
@@ -3731,11 +3773,11 @@ function readAppIdentity(workspaceRootDir, config = {}) {
|
|
|
3731
3773
|
}
|
|
3732
3774
|
function defaultProjectName(workspaceRootDir) {
|
|
3733
3775
|
try {
|
|
3734
|
-
const pkg = readPackageJson(
|
|
3776
|
+
const pkg = readPackageJson(path19.join(workspaceRootDir, "package.json"));
|
|
3735
3777
|
if (typeof pkg.name === "string" && pkg.name.trim()) return pkg.name.trim();
|
|
3736
3778
|
} catch {
|
|
3737
3779
|
}
|
|
3738
|
-
return
|
|
3780
|
+
return path19.basename(workspaceRootDir);
|
|
3739
3781
|
}
|
|
3740
3782
|
function slug(value) {
|
|
3741
3783
|
return value.toLowerCase().replace(/^@/, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 32) || "app";
|
|
@@ -3807,14 +3849,14 @@ function randomSuffix() {
|
|
|
3807
3849
|
|
|
3808
3850
|
// src/lib/artifact.ts
|
|
3809
3851
|
import fs21 from "node:fs";
|
|
3810
|
-
import
|
|
3852
|
+
import path21 from "node:path";
|
|
3811
3853
|
import { detect as detect4 } from "package-manager-detector";
|
|
3812
3854
|
import { resolveCommand as resolveCommand4 } from "package-manager-detector/commands";
|
|
3813
3855
|
|
|
3814
3856
|
// src/lib/ssh.ts
|
|
3815
3857
|
import fs20 from "node:fs";
|
|
3816
3858
|
import os4 from "node:os";
|
|
3817
|
-
import
|
|
3859
|
+
import path20 from "node:path";
|
|
3818
3860
|
import crypto3 from "node:crypto";
|
|
3819
3861
|
import process13 from "node:process";
|
|
3820
3862
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -3857,9 +3899,9 @@ var SshSession = class {
|
|
|
3857
3899
|
}
|
|
3858
3900
|
async open() {
|
|
3859
3901
|
if (this.controlPath) return;
|
|
3860
|
-
const dir =
|
|
3902
|
+
const dir = path20.join(os4.tmpdir(), "vela-ssh");
|
|
3861
3903
|
fs20.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
3862
|
-
const socket =
|
|
3904
|
+
const socket = path20.join(dir, `${crypto3.randomBytes(6).toString("hex")}.sock`);
|
|
3863
3905
|
this.controlPath = socket;
|
|
3864
3906
|
const args = [
|
|
3865
3907
|
...this.sshArgs(),
|
|
@@ -4149,11 +4191,11 @@ function collectArtifact(cwd, config = {}) {
|
|
|
4149
4191
|
const outputDir = config.outputDir ?? DEFAULT_OUTPUT_DIR;
|
|
4150
4192
|
const entries = [];
|
|
4151
4193
|
const add2 = (rel, remoteDir = "") => {
|
|
4152
|
-
const localPath =
|
|
4194
|
+
const localPath = path21.join(cwd, rel);
|
|
4153
4195
|
if (fs21.existsSync(localPath)) entries.push({ localPath, remoteDir });
|
|
4154
4196
|
};
|
|
4155
|
-
const buildPath =
|
|
4156
|
-
if (!fs21.existsSync(
|
|
4197
|
+
const buildPath = path21.join(cwd, outputDir);
|
|
4198
|
+
if (!fs21.existsSync(path21.join(buildPath, "index.js"))) {
|
|
4157
4199
|
throw new BuildError(
|
|
4158
4200
|
`No ${outputDir}/index.js to deploy.
|
|
4159
4201
|
|
|
@@ -4167,7 +4209,7 @@ matches where it writes), then deploy again.`
|
|
|
4167
4209
|
add2("package-lock.json");
|
|
4168
4210
|
add2(".npmrc");
|
|
4169
4211
|
add2(MIGRATIONS_DIR);
|
|
4170
|
-
const hooks =
|
|
4212
|
+
const hooks = path21.join(cwd, DATA_DIR, "hooks");
|
|
4171
4213
|
if (fs21.existsSync(hooks)) entries.push({ localPath: hooks, remoteDir: "hooks" });
|
|
4172
4214
|
for (const extra of config.include ?? []) add2(extra);
|
|
4173
4215
|
return entries;
|
|
@@ -4210,7 +4252,7 @@ function sshOptionsFrom(options) {
|
|
|
4210
4252
|
// src/lib/remote.ts
|
|
4211
4253
|
import crypto4 from "node:crypto";
|
|
4212
4254
|
import fs22 from "node:fs";
|
|
4213
|
-
import
|
|
4255
|
+
import path22 from "node:path";
|
|
4214
4256
|
import process14 from "node:process";
|
|
4215
4257
|
var VELA_ROOT = "/var/lib/vela";
|
|
4216
4258
|
var VELA_ETC = "/etc/vela";
|
|
@@ -4223,19 +4265,19 @@ function instanceHasBackend(state) {
|
|
|
4223
4265
|
return state.backend ?? Boolean(state.pbPort);
|
|
4224
4266
|
}
|
|
4225
4267
|
function serverTemplatesDir() {
|
|
4226
|
-
return
|
|
4268
|
+
return path22.join(templatesDir(), "server");
|
|
4227
4269
|
}
|
|
4228
4270
|
var DIGEST_LENGTH = 12;
|
|
4229
4271
|
function serverScriptsDigest(dir = serverTemplatesDir()) {
|
|
4230
4272
|
const hash = crypto4.createHash("sha256");
|
|
4231
4273
|
for (const file of listFiles(dir).sort()) {
|
|
4232
|
-
hash.update(file).update("\0").update(fs22.readFileSync(
|
|
4274
|
+
hash.update(file).update("\0").update(fs22.readFileSync(path22.join(dir, file))).update("\0");
|
|
4233
4275
|
}
|
|
4234
4276
|
return hash.digest("hex").slice(0, DIGEST_LENGTH);
|
|
4235
4277
|
}
|
|
4236
4278
|
function listFiles(root, prefix = "") {
|
|
4237
4279
|
const files = [];
|
|
4238
|
-
for (const entry of fs22.readdirSync(
|
|
4280
|
+
for (const entry of fs22.readdirSync(path22.join(root, prefix), { withFileTypes: true })) {
|
|
4239
4281
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
4240
4282
|
if (entry.isDirectory()) files.push(...listFiles(root, rel));
|
|
4241
4283
|
else if (entry.isFile()) files.push(rel);
|
|
@@ -4875,7 +4917,7 @@ Set ${pc7.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc7.cyan("POCKETBASE_SUPERUS
|
|
|
4875
4917
|
|
|
4876
4918
|
// src/lib/s3-settings.ts
|
|
4877
4919
|
import fs25 from "node:fs";
|
|
4878
|
-
import
|
|
4920
|
+
import path23 from "node:path";
|
|
4879
4921
|
var VIRTUAL_HOSTED = [/\.amazonaws\.com$/i, /\.r2\.cloudflarestorage\.com$/i];
|
|
4880
4922
|
function defaultForcePathStyle(endpoint) {
|
|
4881
4923
|
let host;
|
|
@@ -4913,7 +4955,7 @@ async function hasLocalUploads(session, instance, workspaceRootDir) {
|
|
|
4913
4955
|
});
|
|
4914
4956
|
return result.stdout.trim().length > 0;
|
|
4915
4957
|
}
|
|
4916
|
-
return hasFile(
|
|
4958
|
+
return hasFile(path23.join(workspaceRootDir, DATA_DIR, "storage"));
|
|
4917
4959
|
}
|
|
4918
4960
|
function hasFile(dir) {
|
|
4919
4961
|
let entries;
|
|
@@ -4924,7 +4966,7 @@ function hasFile(dir) {
|
|
|
4924
4966
|
}
|
|
4925
4967
|
for (const entry of entries) {
|
|
4926
4968
|
if (entry.isFile()) return true;
|
|
4927
|
-
if (entry.isDirectory() && hasFile(
|
|
4969
|
+
if (entry.isDirectory() && hasFile(path23.join(dir, entry.name))) return true;
|
|
4928
4970
|
}
|
|
4929
4971
|
return false;
|
|
4930
4972
|
}
|
|
@@ -5964,18 +6006,18 @@ function uiAddReport(requested, outcome) {
|
|
|
5964
6006
|
var add = new Command48("add").description("add ui components (shadcn-svelte items and vela components such as data-table)").argument("<components...>", "the components to add").option("--overwrite", "replace components that already exist", false).configureHelp(helpConfig).action(
|
|
5965
6007
|
(components, options) => runCommand(async () => {
|
|
5966
6008
|
const { workspaceRootDir } = await getWorkspace();
|
|
5967
|
-
const
|
|
6009
|
+
const log50 = p29.taskLog({ title: "Adding UI components..." });
|
|
5968
6010
|
let outcome;
|
|
5969
6011
|
try {
|
|
5970
6012
|
outcome = await installComponents({
|
|
5971
6013
|
root: workspaceRootDir,
|
|
5972
6014
|
components,
|
|
5973
6015
|
overwrite: options.overwrite,
|
|
5974
|
-
logger: { info: (message) =>
|
|
6016
|
+
logger: { info: (message) => log50.message(message) }
|
|
5975
6017
|
});
|
|
5976
|
-
|
|
6018
|
+
log50.success("UI components ready");
|
|
5977
6019
|
} catch (e) {
|
|
5978
|
-
|
|
6020
|
+
log50.error("Could not add UI components");
|
|
5979
6021
|
throw e;
|
|
5980
6022
|
}
|
|
5981
6023
|
reportResult(uiAddReport(components, outcome));
|
|
@@ -5989,13 +6031,13 @@ import { applyBaseColor } from "@velastack/patterns";
|
|
|
5989
6031
|
var base = new Command49("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
|
|
5990
6032
|
(color) => runCommand(async () => {
|
|
5991
6033
|
const { workspaceRootDir } = await getWorkspace();
|
|
5992
|
-
const
|
|
6034
|
+
const log50 = p30.taskLog({ title: `Applying the ${color} palette...` });
|
|
5993
6035
|
let outcome;
|
|
5994
6036
|
try {
|
|
5995
6037
|
outcome = await applyBaseColor({ root: workspaceRootDir, color });
|
|
5996
|
-
|
|
6038
|
+
log50.success("Palette applied");
|
|
5997
6039
|
} catch (e) {
|
|
5998
|
-
|
|
6040
|
+
log50.error("Could not change the base color");
|
|
5999
6041
|
throw e;
|
|
6000
6042
|
}
|
|
6001
6043
|
reportResult({
|
|
@@ -6102,14 +6144,14 @@ var style = new Command51("style").description("switch the shadcn-svelte style,
|
|
|
6102
6144
|
const { workspaceRootDir } = await getWorkspace();
|
|
6103
6145
|
const spinner8 = p32.spinner();
|
|
6104
6146
|
spinner8.start(`Reading the ${name} registry...`);
|
|
6105
|
-
let
|
|
6147
|
+
let log50;
|
|
6106
6148
|
let outcome;
|
|
6107
6149
|
try {
|
|
6108
6150
|
outcome = await switchStyle({
|
|
6109
6151
|
root: workspaceRootDir,
|
|
6110
6152
|
style: name,
|
|
6111
6153
|
font: options.font,
|
|
6112
|
-
logger: { info: (message) =>
|
|
6154
|
+
logger: { info: (message) => log50?.message(message) },
|
|
6113
6155
|
confirm: async (components) => {
|
|
6114
6156
|
spinner8.stop(`Read the ${name} registry`);
|
|
6115
6157
|
if (components.length > 0) {
|
|
@@ -6126,13 +6168,13 @@ ${components.map((c) => `- ${c}`).join("\n")}`
|
|
|
6126
6168
|
const ok = await p32.confirm({ message: `Switch to ${name}?`, initialValue: false });
|
|
6127
6169
|
if (p32.isCancel(ok) || !ok) return false;
|
|
6128
6170
|
}
|
|
6129
|
-
|
|
6171
|
+
log50 = p32.taskLog({ title: `Switching to the ${name} style...` });
|
|
6130
6172
|
return true;
|
|
6131
6173
|
}
|
|
6132
6174
|
});
|
|
6133
6175
|
} catch (e) {
|
|
6134
6176
|
spinner8.stop(`Could not switch to ${name}`);
|
|
6135
|
-
|
|
6177
|
+
log50?.error("Could not switch style");
|
|
6136
6178
|
throw e;
|
|
6137
6179
|
}
|
|
6138
6180
|
spinner8.stop(`Read the ${name} registry`);
|
|
@@ -6144,7 +6186,7 @@ ${components.map((c) => `- ${c}`).join("\n")}`
|
|
|
6144
6186
|
p32.cancel("Operation cancelled.");
|
|
6145
6187
|
return;
|
|
6146
6188
|
}
|
|
6147
|
-
|
|
6189
|
+
log50?.success("Style switched");
|
|
6148
6190
|
reportResult(uiStyleReport(outcome));
|
|
6149
6191
|
}, "Failed to switch style.")
|
|
6150
6192
|
);
|
|
@@ -6156,13 +6198,13 @@ import { applyTheme } from "@velastack/patterns";
|
|
|
6156
6198
|
var theme = new Command52("theme").description("change the accent color, keeping the base palette").argument("<accent>", `accent to use (${THEMES.join(", ")})`).configureHelp(helpConfig).action(
|
|
6157
6199
|
(accent) => runCommand(async () => {
|
|
6158
6200
|
const { workspaceRootDir } = await getWorkspace();
|
|
6159
|
-
const
|
|
6201
|
+
const log50 = p33.taskLog({ title: `Applying the ${accent} accent...` });
|
|
6160
6202
|
let outcome;
|
|
6161
6203
|
try {
|
|
6162
6204
|
outcome = await applyTheme({ root: workspaceRootDir, theme: accent });
|
|
6163
|
-
|
|
6205
|
+
log50.success("Accent applied");
|
|
6164
6206
|
} catch (e) {
|
|
6165
|
-
|
|
6207
|
+
log50.error("Could not change the accent");
|
|
6166
6208
|
throw e;
|
|
6167
6209
|
}
|
|
6168
6210
|
reportResult({
|
|
@@ -6185,7 +6227,7 @@ import { Command as Command56 } from "commander";
|
|
|
6185
6227
|
|
|
6186
6228
|
// src/commands/legal/terms.ts
|
|
6187
6229
|
import fs26 from "node:fs";
|
|
6188
|
-
import
|
|
6230
|
+
import path24 from "node:path";
|
|
6189
6231
|
import { Command as Command54 } from "commander";
|
|
6190
6232
|
import * as p35 from "@clack/prompts";
|
|
6191
6233
|
|
|
@@ -6844,22 +6886,22 @@ async function termsAction() {
|
|
|
6844
6886
|
mobileApp,
|
|
6845
6887
|
contact
|
|
6846
6888
|
});
|
|
6847
|
-
const termsPage =
|
|
6889
|
+
const termsPage = path24.join(
|
|
6848
6890
|
workspaceRootDir,
|
|
6849
6891
|
publicRoutesDir,
|
|
6850
6892
|
LEGAL_DIR,
|
|
6851
6893
|
"terms",
|
|
6852
6894
|
"+page.svelte"
|
|
6853
6895
|
);
|
|
6854
|
-
const termsPageTs =
|
|
6855
|
-
fs26.mkdirSync(
|
|
6896
|
+
const termsPageTs = path24.join(workspaceRootDir, publicRoutesDir, LEGAL_DIR, "terms", "+page.ts");
|
|
6897
|
+
fs26.mkdirSync(path24.dirname(termsPage), { recursive: true });
|
|
6856
6898
|
fs26.writeFileSync(termsPage, html);
|
|
6857
6899
|
fs26.writeFileSync(
|
|
6858
6900
|
termsPageTs,
|
|
6859
6901
|
pageMetaTagsLoader("Terms of Service", `Terms of Service for ${core.websiteName}`)
|
|
6860
6902
|
);
|
|
6861
|
-
const relativeTermsPage =
|
|
6862
|
-
const relativeTermsPageTs =
|
|
6903
|
+
const relativeTermsPage = path24.relative(workspaceRootDir, termsPage);
|
|
6904
|
+
const relativeTermsPageTs = path24.relative(workspaceRootDir, termsPageTs);
|
|
6863
6905
|
reportResult({
|
|
6864
6906
|
summary: "Generated placeholder terms and conditions.",
|
|
6865
6907
|
filesCreated: [relativeTermsPage, relativeTermsPageTs],
|
|
@@ -6874,7 +6916,7 @@ var terms = new Command54("terms").description("generate placeholder terms and c
|
|
|
6874
6916
|
|
|
6875
6917
|
// src/commands/legal/privacy.ts
|
|
6876
6918
|
import fs27 from "node:fs";
|
|
6877
|
-
import
|
|
6919
|
+
import path25 from "node:path";
|
|
6878
6920
|
import { Command as Command55 } from "commander";
|
|
6879
6921
|
import * as p36 from "@clack/prompts";
|
|
6880
6922
|
var mapLabels = {
|
|
@@ -7587,28 +7629,28 @@ async function privacyAction() {
|
|
|
7587
7629
|
kids,
|
|
7588
7630
|
retention
|
|
7589
7631
|
});
|
|
7590
|
-
const privacyPage =
|
|
7632
|
+
const privacyPage = path25.join(
|
|
7591
7633
|
workspaceRootDir,
|
|
7592
7634
|
publicRoutesDir,
|
|
7593
7635
|
LEGAL_DIR,
|
|
7594
7636
|
"privacy",
|
|
7595
7637
|
"+page.svelte"
|
|
7596
7638
|
);
|
|
7597
|
-
const privacyPageTs =
|
|
7639
|
+
const privacyPageTs = path25.join(
|
|
7598
7640
|
workspaceRootDir,
|
|
7599
7641
|
publicRoutesDir,
|
|
7600
7642
|
LEGAL_DIR,
|
|
7601
7643
|
"privacy",
|
|
7602
7644
|
"+page.ts"
|
|
7603
7645
|
);
|
|
7604
|
-
fs27.mkdirSync(
|
|
7646
|
+
fs27.mkdirSync(path25.dirname(privacyPage), { recursive: true });
|
|
7605
7647
|
fs27.writeFileSync(privacyPage, html);
|
|
7606
7648
|
fs27.writeFileSync(
|
|
7607
7649
|
privacyPageTs,
|
|
7608
7650
|
pageMetaTagsLoader("Privacy Policy", `Privacy Policy for ${core.websiteName}`)
|
|
7609
7651
|
);
|
|
7610
|
-
const relativePrivacyPage =
|
|
7611
|
-
const relativePrivacyPageTs =
|
|
7652
|
+
const relativePrivacyPage = path25.relative(workspaceRootDir, privacyPage);
|
|
7653
|
+
const relativePrivacyPageTs = path25.relative(workspaceRootDir, privacyPageTs);
|
|
7612
7654
|
reportResult({
|
|
7613
7655
|
summary: "Generated placeholder privacy policy.",
|
|
7614
7656
|
filesCreated: [relativePrivacyPage, relativePrivacyPageTs],
|
|
@@ -7632,7 +7674,7 @@ import { Command as Command57 } from "commander";
|
|
|
7632
7674
|
|
|
7633
7675
|
// src/lib/data.ts
|
|
7634
7676
|
import fs28 from "node:fs";
|
|
7635
|
-
import
|
|
7677
|
+
import path26 from "node:path";
|
|
7636
7678
|
import { ClientResponseError } from "pocketbase";
|
|
7637
7679
|
|
|
7638
7680
|
// src/lib/collections.ts
|
|
@@ -7669,14 +7711,14 @@ function dependencyOrder(collections2, startingCollectionId) {
|
|
|
7669
7711
|
|
|
7670
7712
|
// src/lib/data.ts
|
|
7671
7713
|
function dataDir(cwd, kind) {
|
|
7672
|
-
return
|
|
7714
|
+
return path26.join(cwd, DATA_DIR, kind);
|
|
7673
7715
|
}
|
|
7674
7716
|
function getDataFiles(cwd, kind) {
|
|
7675
7717
|
const dir = dataDir(cwd, kind);
|
|
7676
7718
|
if (!fs28.existsSync(dir)) return [];
|
|
7677
7719
|
return fs28.readdirSync(dir).filter((file) => file.endsWith(".json")).sort((a, b) => a.localeCompare(b)).map((file) => ({
|
|
7678
7720
|
collectionName: file.replace(/\.json$/i, "").replace(/^\d+[-_]?/, ""),
|
|
7679
|
-
filePath:
|
|
7721
|
+
filePath: path26.join(dir, file)
|
|
7680
7722
|
}));
|
|
7681
7723
|
}
|
|
7682
7724
|
function getSeedFiles(cwd) {
|
|
@@ -7723,7 +7765,7 @@ function describeError(e) {
|
|
|
7723
7765
|
return e instanceof Error ? e.message : String(e);
|
|
7724
7766
|
}
|
|
7725
7767
|
function label3(cwd, filePath, count) {
|
|
7726
|
-
return `${
|
|
7768
|
+
return `${path26.relative(cwd, filePath)} (${count} records)`;
|
|
7727
7769
|
}
|
|
7728
7770
|
async function createRecords(pb, kind, cwd, { collectionName, filePath }) {
|
|
7729
7771
|
const records = readRecords(filePath);
|
|
@@ -7731,7 +7773,7 @@ async function createRecords(pb, kind, cwd, { collectionName, filePath }) {
|
|
|
7731
7773
|
try {
|
|
7732
7774
|
await pb.collection(collectionName).create(record);
|
|
7733
7775
|
} catch (e) {
|
|
7734
|
-
throw new DataLoadError(kind,
|
|
7776
|
+
throw new DataLoadError(kind, path26.relative(cwd, filePath), index, e);
|
|
7735
7777
|
}
|
|
7736
7778
|
}
|
|
7737
7779
|
return records.length;
|
|
@@ -7906,7 +7948,7 @@ var reset = new Command59("reset").description("clear and reload fixtures").conf
|
|
|
7906
7948
|
|
|
7907
7949
|
// src/commands/fixtures/generate.ts
|
|
7908
7950
|
import fs29 from "node:fs";
|
|
7909
|
-
import
|
|
7951
|
+
import path27 from "node:path";
|
|
7910
7952
|
import { Command as Command60, InvalidArgumentError } from "commander";
|
|
7911
7953
|
import * as p37 from "@clack/prompts";
|
|
7912
7954
|
import { annotate } from "annotate-json-schema";
|
|
@@ -7945,7 +7987,7 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
|
7945
7987
|
const fixturesDir = dataDir(workspaceRootDir, "fixtures");
|
|
7946
7988
|
fs29.mkdirSync(fixturesDir, { recursive: true });
|
|
7947
7989
|
for (const file of fs29.readdirSync(fixturesDir)) {
|
|
7948
|
-
if (file.endsWith(".json")) fs29.unlinkSync(
|
|
7990
|
+
if (file.endsWith(".json")) fs29.unlinkSync(path27.join(fixturesDir, file));
|
|
7949
7991
|
}
|
|
7950
7992
|
if (opts.seed !== void 0) faker.seed(opts.seed);
|
|
7951
7993
|
const generator = createGenerator({
|
|
@@ -8012,8 +8054,8 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
|
|
|
8012
8054
|
items.push(record);
|
|
8013
8055
|
}
|
|
8014
8056
|
const filename = `${padZeros(fileIndex, 2)}-${collection.name}.json`;
|
|
8015
|
-
fs29.writeFileSync(
|
|
8016
|
-
writtenFiles.push(`${
|
|
8057
|
+
fs29.writeFileSync(path27.join(fixturesDir, filename), JSON.stringify(items, null, 2));
|
|
8058
|
+
writtenFiles.push(`${path27.join(DATA_DIR, "fixtures", filename)} (${items.length} records)`);
|
|
8017
8059
|
fileIndex++;
|
|
8018
8060
|
}
|
|
8019
8061
|
return { writtenFiles, warnings };
|
|
@@ -8161,7 +8203,7 @@ var load2 = new Command63("load").description("load seeds into the database").op
|
|
|
8161
8203
|
|
|
8162
8204
|
// src/commands/seeds/save.ts
|
|
8163
8205
|
import fs30 from "node:fs";
|
|
8164
|
-
import
|
|
8206
|
+
import path28 from "node:path";
|
|
8165
8207
|
import { Command as Command64 } from "commander";
|
|
8166
8208
|
var padZeros2 = (num, length) => num.toString().padStart(length, "0");
|
|
8167
8209
|
function filterSystemFields(record, systemFieldNames) {
|
|
@@ -8184,7 +8226,7 @@ var save = new Command64("save").description("save the current data as seeds").o
|
|
|
8184
8226
|
fs30.mkdirSync(seedsPath, { recursive: true });
|
|
8185
8227
|
if (opts.force) {
|
|
8186
8228
|
for (const file of fs30.readdirSync(seedsPath)) {
|
|
8187
|
-
if (file.endsWith(".json")) fs30.unlinkSync(
|
|
8229
|
+
if (file.endsWith(".json")) fs30.unlinkSync(path28.join(seedsPath, file));
|
|
8188
8230
|
}
|
|
8189
8231
|
}
|
|
8190
8232
|
const saved = [];
|
|
@@ -8213,12 +8255,12 @@ var save = new Command64("save").description("save the current data as seeds").o
|
|
|
8213
8255
|
const filtered = records.map(
|
|
8214
8256
|
(r) => filterSystemFields(r, systemFieldNames)
|
|
8215
8257
|
);
|
|
8216
|
-
const relativeSeedPath =
|
|
8258
|
+
const relativeSeedPath = path28.join(
|
|
8217
8259
|
DATA_DIR,
|
|
8218
8260
|
"seeds",
|
|
8219
8261
|
`${padZeros2(count, 2)}-${collectionName}.json`
|
|
8220
8262
|
);
|
|
8221
|
-
const seedPath =
|
|
8263
|
+
const seedPath = path28.join(workspaceRootDir, relativeSeedPath);
|
|
8222
8264
|
fs30.writeFileSync(seedPath, JSON.stringify(filtered, null, 2));
|
|
8223
8265
|
saved.push(`${relativeSeedPath} (${filtered.length} records)`);
|
|
8224
8266
|
count++;
|
|
@@ -8357,7 +8399,7 @@ import { Command as Command75 } from "commander";
|
|
|
8357
8399
|
import { Command as Command70 } from "commander";
|
|
8358
8400
|
|
|
8359
8401
|
// src/lib/migrate.ts
|
|
8360
|
-
import
|
|
8402
|
+
import path29 from "node:path";
|
|
8361
8403
|
import process23 from "node:process";
|
|
8362
8404
|
import { x as x2 } from "tinyexec";
|
|
8363
8405
|
async function runPocketbaseMigrate(args) {
|
|
@@ -8368,9 +8410,9 @@ async function runPocketbaseMigrate(args) {
|
|
|
8368
8410
|
binaryPath,
|
|
8369
8411
|
[
|
|
8370
8412
|
"--dir",
|
|
8371
|
-
|
|
8413
|
+
path29.join(cwd, DATA_DIR),
|
|
8372
8414
|
"--migrationsDir",
|
|
8373
|
-
|
|
8415
|
+
path29.join(cwd, MIGRATIONS_DIR),
|
|
8374
8416
|
"migrate",
|
|
8375
8417
|
...args
|
|
8376
8418
|
],
|
|
@@ -8419,7 +8461,7 @@ var down = new Command71("down").alias("rollback").description("revert the last
|
|
|
8419
8461
|
|
|
8420
8462
|
// src/commands/migrate/create.ts
|
|
8421
8463
|
import fs31 from "node:fs";
|
|
8422
|
-
import
|
|
8464
|
+
import path30 from "node:path";
|
|
8423
8465
|
import process24 from "node:process";
|
|
8424
8466
|
import { Command as Command72 } from "commander";
|
|
8425
8467
|
var create2 = new Command72("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
|
|
@@ -8431,7 +8473,7 @@ var create2 = new Command72("create").alias("new").description("create a new bla
|
|
|
8431
8473
|
const added = [...after].filter((f) => !before.has(f));
|
|
8432
8474
|
reportResult({
|
|
8433
8475
|
summary: `Created blank migration ${name}.`,
|
|
8434
|
-
filesCreated: added.map((f) =>
|
|
8476
|
+
filesCreated: added.map((f) => path30.join(MIGRATIONS_DIR, f)),
|
|
8435
8477
|
nextSteps: [
|
|
8436
8478
|
`Open the new file in ${MIGRATIONS_DIR}/ and fill in the up/down handlers.`,
|
|
8437
8479
|
"Run `vela migrate up` to apply the migration once the handlers are written."
|
|
@@ -8440,14 +8482,14 @@ var create2 = new Command72("create").alias("new").description("create a new bla
|
|
|
8440
8482
|
}, "Failed to create migration.")
|
|
8441
8483
|
);
|
|
8442
8484
|
function listMigrationFiles(cwd) {
|
|
8443
|
-
const dir =
|
|
8485
|
+
const dir = path30.join(cwd, MIGRATIONS_DIR);
|
|
8444
8486
|
if (!fs31.existsSync(dir)) return /* @__PURE__ */ new Set();
|
|
8445
8487
|
return new Set(fs31.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
|
|
8446
8488
|
}
|
|
8447
8489
|
|
|
8448
8490
|
// src/commands/migrate/collections.ts
|
|
8449
8491
|
import fs32 from "node:fs";
|
|
8450
|
-
import
|
|
8492
|
+
import path31 from "node:path";
|
|
8451
8493
|
import process25 from "node:process";
|
|
8452
8494
|
import { Command as Command73 } from "commander";
|
|
8453
8495
|
var collections = new Command73("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
|
|
@@ -8465,7 +8507,7 @@ var collections = new Command73("collections").alias("snapshot").description("sn
|
|
|
8465
8507
|
}
|
|
8466
8508
|
reportResult({
|
|
8467
8509
|
summary: "Snapshotted local collections into a new migration.",
|
|
8468
|
-
filesCreated: added.map((f) =>
|
|
8510
|
+
filesCreated: added.map((f) => path31.join(MIGRATIONS_DIR, f)),
|
|
8469
8511
|
nextSteps: [
|
|
8470
8512
|
`Review the generated snapshot in ${MIGRATIONS_DIR}/.`,
|
|
8471
8513
|
"Commit the snapshot so teammates pick up the new schema.",
|
|
@@ -8475,7 +8517,7 @@ var collections = new Command73("collections").alias("snapshot").description("sn
|
|
|
8475
8517
|
}, "Failed to snapshot collections.")
|
|
8476
8518
|
);
|
|
8477
8519
|
function listMigrationFiles2(cwd) {
|
|
8478
|
-
const dir =
|
|
8520
|
+
const dir = path31.join(cwd, MIGRATIONS_DIR);
|
|
8479
8521
|
if (!fs32.existsSync(dir)) return /* @__PURE__ */ new Set();
|
|
8480
8522
|
return new Set(fs32.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
|
|
8481
8523
|
}
|
|
@@ -8497,7 +8539,7 @@ var migrate = new Command75("migrate").description("manage database migrations")
|
|
|
8497
8539
|
|
|
8498
8540
|
// src/commands/dev.ts
|
|
8499
8541
|
import fs33 from "node:fs";
|
|
8500
|
-
import
|
|
8542
|
+
import path33 from "node:path";
|
|
8501
8543
|
import process27 from "node:process";
|
|
8502
8544
|
import { performance } from "node:perf_hooks";
|
|
8503
8545
|
import { Command as Command76, InvalidArgumentError as InvalidArgumentError4 } from "commander";
|
|
@@ -8529,7 +8571,7 @@ function createPocketbaseLogFilter() {
|
|
|
8529
8571
|
}
|
|
8530
8572
|
|
|
8531
8573
|
// src/lib/vite.ts
|
|
8532
|
-
import
|
|
8574
|
+
import path32 from "node:path";
|
|
8533
8575
|
import process26 from "node:process";
|
|
8534
8576
|
import { createRequire as createRequire2 } from "node:module";
|
|
8535
8577
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
@@ -8549,7 +8591,7 @@ function viteVersionError(version) {
|
|
|
8549
8591
|
}
|
|
8550
8592
|
function resolveProjectVite(cwd) {
|
|
8551
8593
|
try {
|
|
8552
|
-
return createRequire2(
|
|
8594
|
+
return createRequire2(path32.join(cwd, "package.json")).resolve("vite");
|
|
8553
8595
|
} catch {
|
|
8554
8596
|
return null;
|
|
8555
8597
|
}
|
|
@@ -8578,8 +8620,8 @@ var dev = new Command76("dev").description("start the development server").optio
|
|
|
8578
8620
|
process27.env.VELA_DATA_DIR ??= localDataDir(cwd);
|
|
8579
8621
|
const startTime = performance.now();
|
|
8580
8622
|
const { createServer, version } = await loadVite(cwd);
|
|
8581
|
-
const viteMetadataDir =
|
|
8582
|
-
const viteMetadataFile =
|
|
8623
|
+
const viteMetadataDir = path33.join(cwd, "node_modules", ".vite");
|
|
8624
|
+
const viteMetadataFile = path33.join(viteMetadataDir, "_pocketbase_metadata.json");
|
|
8583
8625
|
let pbProc;
|
|
8584
8626
|
const backend3 = hasBackend(cwd);
|
|
8585
8627
|
const needsStart = backend3 && !process27.env.POCKETBASE_URL;
|
|
@@ -8588,11 +8630,11 @@ var dev = new Command76("dev").description("start the development server").optio
|
|
|
8588
8630
|
if (fs33.existsSync(viteMetadataFile)) fs33.rmSync(viteMetadataFile);
|
|
8589
8631
|
};
|
|
8590
8632
|
if (needsStart) {
|
|
8591
|
-
const dataDir2 =
|
|
8633
|
+
const dataDir2 = path33.join(cwd, DATA_DIR);
|
|
8592
8634
|
const started = await startPocketbaseServe({
|
|
8593
8635
|
dataDir: dataDir2,
|
|
8594
8636
|
migrationsDir: MIGRATIONS_DIR,
|
|
8595
|
-
hooksDir:
|
|
8637
|
+
hooksDir: path33.join(dataDir2, "hooks"),
|
|
8596
8638
|
dev: true,
|
|
8597
8639
|
stdio: "pipe"
|
|
8598
8640
|
});
|
|
@@ -8657,9 +8699,9 @@ var dev = new Command76("dev").description("start the development server").optio
|
|
|
8657
8699
|
});
|
|
8658
8700
|
async function startWatchingTypes(cwd, pb) {
|
|
8659
8701
|
const { processTypes } = await import("@velastack/pocketbase-codegen");
|
|
8660
|
-
const typesDir =
|
|
8661
|
-
const pocketbaseDir =
|
|
8662
|
-
const pocketbaseTypes =
|
|
8702
|
+
const typesDir = path33.resolve(cwd, ".svelte-kit", "types");
|
|
8703
|
+
const pocketbaseDir = path33.join(typesDir, "pocketbase");
|
|
8704
|
+
const pocketbaseTypes = path33.join(pocketbaseDir, "$types.d.ts");
|
|
8663
8705
|
const regenerate = () => processTypes(pb, typesDir).catch(() => {
|
|
8664
8706
|
});
|
|
8665
8707
|
await regenerate();
|
|
@@ -8681,7 +8723,7 @@ async function startWatchingTypes(cwd, pb) {
|
|
|
8681
8723
|
|
|
8682
8724
|
// src/commands/build.ts
|
|
8683
8725
|
import fs34 from "node:fs";
|
|
8684
|
-
import
|
|
8726
|
+
import path34 from "node:path";
|
|
8685
8727
|
import process29 from "node:process";
|
|
8686
8728
|
import { Command as Command77 } from "commander";
|
|
8687
8729
|
import * as p42 from "@clack/prompts";
|
|
@@ -8719,7 +8761,7 @@ function splitHosts(value) {
|
|
|
8719
8761
|
}
|
|
8720
8762
|
|
|
8721
8763
|
// src/commands/build.ts
|
|
8722
|
-
var PRERENDERED_DIR =
|
|
8764
|
+
var PRERENDERED_DIR = path34.join(".svelte-kit", "output", "prerendered");
|
|
8723
8765
|
var build = new Command77("build").description("build the app").configureHelp(helpConfig).option("-t, --target <target>", "which copy of the app to build for", PRODUCTION_TARGET).action(async (options) => {
|
|
8724
8766
|
const cwd = process29.cwd();
|
|
8725
8767
|
applyBuildEnv(cwd);
|
|
@@ -8732,11 +8774,11 @@ var build = new Command77("build").description("build the app").configureHelp(he
|
|
|
8732
8774
|
};
|
|
8733
8775
|
if (needsStart) {
|
|
8734
8776
|
await ensureSuperuser(cwd);
|
|
8735
|
-
const dataDir2 =
|
|
8777
|
+
const dataDir2 = path34.join(cwd, DATA_DIR);
|
|
8736
8778
|
const started = await startPocketbaseServe({
|
|
8737
8779
|
dataDir: dataDir2,
|
|
8738
8780
|
migrationsDir: MIGRATIONS_DIR,
|
|
8739
|
-
hooksDir:
|
|
8781
|
+
hooksDir: path34.join(dataDir2, "hooks"),
|
|
8740
8782
|
dev: true
|
|
8741
8783
|
});
|
|
8742
8784
|
pbProc = started.proc;
|
|
@@ -8775,7 +8817,7 @@ async function originForBuild(cwd, target) {
|
|
|
8775
8817
|
}
|
|
8776
8818
|
}
|
|
8777
8819
|
function warnIfPrerendered(cwd) {
|
|
8778
|
-
const dir =
|
|
8820
|
+
const dir = path34.join(cwd, PRERENDERED_DIR);
|
|
8779
8821
|
if (!fs34.existsSync(dir) || fs34.readdirSync(dir).length === 0) return;
|
|
8780
8822
|
p42.log.warn(
|
|
8781
8823
|
`Prerendered pages were built with no domain configured, so their canonical
|
|
@@ -8786,7 +8828,7 @@ Set one with ${pc16.cyan("vela deploy --domain example.com")}, or pass ${pc16.cy
|
|
|
8786
8828
|
}
|
|
8787
8829
|
|
|
8788
8830
|
// src/commands/preview.ts
|
|
8789
|
-
import
|
|
8831
|
+
import path35 from "node:path";
|
|
8790
8832
|
import process30 from "node:process";
|
|
8791
8833
|
import { Command as Command78 } from "commander";
|
|
8792
8834
|
import { x as x4 } from "tinyexec";
|
|
@@ -8801,11 +8843,11 @@ var preview = new Command78("preview").description("preview the built app").conf
|
|
|
8801
8843
|
if (pbProc?.pid) pbProc.kill();
|
|
8802
8844
|
};
|
|
8803
8845
|
if (needsStart) {
|
|
8804
|
-
const dataDir2 =
|
|
8846
|
+
const dataDir2 = path35.join(cwd, DATA_DIR);
|
|
8805
8847
|
const started = await startPocketbaseServe({
|
|
8806
8848
|
dataDir: dataDir2,
|
|
8807
8849
|
migrationsDir: MIGRATIONS_DIR,
|
|
8808
|
-
hooksDir:
|
|
8850
|
+
hooksDir: path35.join(dataDir2, "hooks"),
|
|
8809
8851
|
dev: true
|
|
8810
8852
|
});
|
|
8811
8853
|
pbProc = started.proc;
|
|
@@ -8831,12 +8873,12 @@ var preview = new Command78("preview").description("preview the built app").conf
|
|
|
8831
8873
|
});
|
|
8832
8874
|
|
|
8833
8875
|
// src/commands/sync.ts
|
|
8834
|
-
import
|
|
8876
|
+
import path36 from "node:path";
|
|
8835
8877
|
import { Command as Command79 } from "commander";
|
|
8836
8878
|
var sync = new Command79("sync").description("sync types from the database").configureHelp(helpConfig).action(
|
|
8837
8879
|
() => runCommand(async () => {
|
|
8838
8880
|
const { workspaceRootDir } = await getWorkspace();
|
|
8839
|
-
const typesDir =
|
|
8881
|
+
const typesDir = path36.join(workspaceRootDir, ".svelte-kit", "types");
|
|
8840
8882
|
const { processTypes } = await import("@velastack/pocketbase-codegen");
|
|
8841
8883
|
await withPocketbase(workspaceRootDir, async (pb) => {
|
|
8842
8884
|
await processTypes(pb, typesDir);
|
|
@@ -8898,7 +8940,7 @@ var provision = addSshOptions(
|
|
|
8898
8940
|
);
|
|
8899
8941
|
|
|
8900
8942
|
// src/commands/deploy.ts
|
|
8901
|
-
import
|
|
8943
|
+
import path39 from "node:path";
|
|
8902
8944
|
import fs37 from "node:fs";
|
|
8903
8945
|
import { Command as Command81, Option as Option2 } from "commander";
|
|
8904
8946
|
import * as p44 from "@clack/prompts";
|
|
@@ -8907,12 +8949,12 @@ import * as v8 from "valibot";
|
|
|
8907
8949
|
|
|
8908
8950
|
// src/lib/pocketbase-settings.ts
|
|
8909
8951
|
import fs35 from "node:fs";
|
|
8910
|
-
import
|
|
8952
|
+
import path37 from "node:path";
|
|
8911
8953
|
import process31 from "node:process";
|
|
8912
8954
|
import PocketBase5 from "pocketbase";
|
|
8913
8955
|
var COPIED_KEYS = ["appName", "senderName", "senderAddress"];
|
|
8914
8956
|
async function readLocalMeta(cwd) {
|
|
8915
|
-
const dataDir2 =
|
|
8957
|
+
const dataDir2 = path37.join(cwd, DATA_DIR);
|
|
8916
8958
|
if (!fs35.existsSync(dataDir2)) return null;
|
|
8917
8959
|
const email3 = process31.env.POCKETBASE_SUPERUSER_EMAIL;
|
|
8918
8960
|
const password11 = process31.env.POCKETBASE_SUPERUSER_PASSWORD;
|
|
@@ -8922,7 +8964,7 @@ async function readLocalMeta(cwd) {
|
|
|
8922
8964
|
const started = await startPocketbaseServe({
|
|
8923
8965
|
dataDir: dataDir2,
|
|
8924
8966
|
migrationsDir: MIGRATIONS_DIR,
|
|
8925
|
-
hooksDir:
|
|
8967
|
+
hooksDir: path37.join(dataDir2, "hooks")
|
|
8926
8968
|
});
|
|
8927
8969
|
proc = started.proc;
|
|
8928
8970
|
const pb = new PocketBase5(started.url);
|
|
@@ -8965,7 +9007,7 @@ async function seedRemoteMeta(session, instance, local, appURL) {
|
|
|
8965
9007
|
|
|
8966
9008
|
// src/lib/adapter.ts
|
|
8967
9009
|
import fs36 from "node:fs";
|
|
8968
|
-
import
|
|
9010
|
+
import path38 from "node:path";
|
|
8969
9011
|
import {
|
|
8970
9012
|
Project as Project2,
|
|
8971
9013
|
QuoteKind as QuoteKind2,
|
|
@@ -9021,7 +9063,7 @@ function resolveKitTarget(root) {
|
|
|
9021
9063
|
}
|
|
9022
9064
|
const sveltePath = probeFirstExisting(root, SVELTE_CONFIG_CANDIDATES);
|
|
9023
9065
|
if (sveltePath) {
|
|
9024
|
-
const name =
|
|
9066
|
+
const name = path38.basename(sveltePath);
|
|
9025
9067
|
if (sveltePath.endsWith(".cjs")) {
|
|
9026
9068
|
throw new AdapterError(`${name} is CommonJS, which vela does not edit.`);
|
|
9027
9069
|
}
|
|
@@ -9041,7 +9083,7 @@ function resolveKitTarget(root) {
|
|
|
9041
9083
|
};
|
|
9042
9084
|
}
|
|
9043
9085
|
if (vite?.sveltekitCall) {
|
|
9044
|
-
const name =
|
|
9086
|
+
const name = path38.basename(vite.filePath);
|
|
9045
9087
|
if (vite.nonObjectArg) {
|
|
9046
9088
|
throw new AdapterError(`${name} passes sveltekit() something other than an object literal.`);
|
|
9047
9089
|
}
|
|
@@ -9094,7 +9136,7 @@ function inspectAdapter(target) {
|
|
|
9094
9136
|
async function ensureNodeAdapter(root, { install = true } = {}) {
|
|
9095
9137
|
const target = resolveKitTarget(root);
|
|
9096
9138
|
const { info, importDecl } = inspectAdapter(target);
|
|
9097
|
-
const name =
|
|
9139
|
+
const name = path38.basename(target.filePath);
|
|
9098
9140
|
const outcome = {
|
|
9099
9141
|
previous: info.kind,
|
|
9100
9142
|
removedDeps: [],
|
|
@@ -9127,7 +9169,7 @@ vela deploy runs the app as a Node server, which needs ${ADAPTER_NODE}:`
|
|
|
9127
9169
|
break;
|
|
9128
9170
|
}
|
|
9129
9171
|
if (outcome.configFile) saveTarget(target);
|
|
9130
|
-
const pkgPath =
|
|
9172
|
+
const pkgPath = path38.join(root, "package.json");
|
|
9131
9173
|
if (fs36.existsSync(pkgPath)) {
|
|
9132
9174
|
const pkg = readPackageJson(pkgPath);
|
|
9133
9175
|
const { changed, removed } = adoptNodeAdapter(pkg);
|
|
@@ -9180,7 +9222,7 @@ function addAdapter(target) {
|
|
|
9180
9222
|
const taken = importOf(target.sourceFile, "adapter") ?? target.sourceFile.getVariableDeclaration("adapter");
|
|
9181
9223
|
if (taken) {
|
|
9182
9224
|
throw new AdapterError(
|
|
9183
|
-
`${
|
|
9225
|
+
`${path38.basename(target.filePath)} already binds the name \`adapter\` to something that is not the SvelteKit adapter.`
|
|
9184
9226
|
);
|
|
9185
9227
|
}
|
|
9186
9228
|
target.sourceFile.addImportDeclaration({
|
|
@@ -9591,7 +9633,7 @@ function isDirectory(target) {
|
|
|
9591
9633
|
async function reportEmptyEnvironment(session, instance, workspaceRootDir) {
|
|
9592
9634
|
const remote = await readRemoteEnv(session, instance);
|
|
9593
9635
|
if (Object.keys(remote).length > 0) return;
|
|
9594
|
-
if (!fs37.existsSync(
|
|
9636
|
+
if (!fs37.existsSync(path39.join(workspaceRootDir, ".env"))) return;
|
|
9595
9637
|
p44.log.warn(
|
|
9596
9638
|
`This app has no production environment variables yet.
|
|
9597
9639
|
|
|
@@ -9609,7 +9651,7 @@ async function serverTimeOrLocal(session) {
|
|
|
9609
9651
|
}
|
|
9610
9652
|
|
|
9611
9653
|
// src/commands/link.ts
|
|
9612
|
-
import
|
|
9654
|
+
import path40 from "node:path";
|
|
9613
9655
|
import process32 from "node:process";
|
|
9614
9656
|
import { Command as Command82 } from "commander";
|
|
9615
9657
|
import * as p45 from "@clack/prompts";
|
|
@@ -9672,12 +9714,12 @@ async function promptProjectName(workspaceRootDir) {
|
|
|
9672
9714
|
}
|
|
9673
9715
|
function defaultProjectName2(workspaceRootDir) {
|
|
9674
9716
|
try {
|
|
9675
|
-
const pkg = readPackageJson(
|
|
9717
|
+
const pkg = readPackageJson(path40.join(workspaceRootDir, "package.json"));
|
|
9676
9718
|
const name = pkg.name;
|
|
9677
9719
|
if (typeof name === "string" && name.trim()) return name.trim();
|
|
9678
9720
|
} catch {
|
|
9679
9721
|
}
|
|
9680
|
-
return
|
|
9722
|
+
return path40.basename(workspaceRootDir);
|
|
9681
9723
|
}
|
|
9682
9724
|
|
|
9683
9725
|
// src/commands/env.ts
|
|
@@ -9809,7 +9851,7 @@ var envUnset = addTargetOptions(
|
|
|
9809
9851
|
|
|
9810
9852
|
// src/commands/env/import.ts
|
|
9811
9853
|
import fs38 from "node:fs";
|
|
9812
|
-
import
|
|
9854
|
+
import path41 from "node:path";
|
|
9813
9855
|
import process34 from "node:process";
|
|
9814
9856
|
import { Command as Command86 } from "commander";
|
|
9815
9857
|
import * as p49 from "@clack/prompts";
|
|
@@ -9855,7 +9897,7 @@ var envImport = addTargetOptions(
|
|
|
9855
9897
|
)
|
|
9856
9898
|
);
|
|
9857
9899
|
function resolve(file) {
|
|
9858
|
-
return
|
|
9900
|
+
return path41.resolve(process34.cwd(), file);
|
|
9859
9901
|
}
|
|
9860
9902
|
function read(resolved, shown) {
|
|
9861
9903
|
if (!fs38.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
|
|
@@ -10137,7 +10179,7 @@ import { Command as Command98 } from "commander";
|
|
|
10137
10179
|
|
|
10138
10180
|
// src/commands/backup/create.ts
|
|
10139
10181
|
import fs39 from "node:fs";
|
|
10140
|
-
import
|
|
10182
|
+
import path42 from "node:path";
|
|
10141
10183
|
import { Command as Command93 } from "commander";
|
|
10142
10184
|
import * as p53 from "@clack/prompts";
|
|
10143
10185
|
import pc26 from "picocolors";
|
|
@@ -10291,12 +10333,12 @@ Your bucket's own versioning is what protects the uploaded files.`
|
|
|
10291
10333
|
}, "Failed to create the backup.")
|
|
10292
10334
|
);
|
|
10293
10335
|
async function download(ctx, key, outputDir) {
|
|
10294
|
-
const dir =
|
|
10336
|
+
const dir = path42.resolve(ctx.workspaceRootDir, outputDir);
|
|
10295
10337
|
fs39.mkdirSync(dir, { recursive: true });
|
|
10296
|
-
const destination =
|
|
10338
|
+
const destination = path42.join(dir, key);
|
|
10297
10339
|
if (!ctx.session) {
|
|
10298
|
-
fs39.copyFileSync(
|
|
10299
|
-
return
|
|
10340
|
+
fs39.copyFileSync(path42.join(ctx.workspaceRootDir, "data", "backups", key), destination);
|
|
10341
|
+
return path42.relative(ctx.workspaceRootDir, destination);
|
|
10300
10342
|
}
|
|
10301
10343
|
const spinner8 = p53.spinner();
|
|
10302
10344
|
spinner8.start(`Downloading ${key}`);
|
|
@@ -10307,7 +10349,7 @@ async function download(ctx, key, outputDir) {
|
|
|
10307
10349
|
throw error;
|
|
10308
10350
|
}
|
|
10309
10351
|
spinner8.stop(`Downloaded ${key}`);
|
|
10310
|
-
return
|
|
10352
|
+
return path42.relative(ctx.workspaceRootDir, destination);
|
|
10311
10353
|
}
|
|
10312
10354
|
|
|
10313
10355
|
// src/commands/backup/list.ts
|
|
@@ -10342,7 +10384,7 @@ Take one with ${pc27.cyan("vela backup create")}.`
|
|
|
10342
10384
|
|
|
10343
10385
|
// src/commands/backup/download.ts
|
|
10344
10386
|
import fs40 from "node:fs";
|
|
10345
|
-
import
|
|
10387
|
+
import path43 from "node:path";
|
|
10346
10388
|
import { Command as Command95 } from "commander";
|
|
10347
10389
|
import * as p55 from "@clack/prompts";
|
|
10348
10390
|
import pc28 from "picocolors";
|
|
@@ -10369,11 +10411,11 @@ Run ${pc28.cyan("vela backup list")} to see what it does have.`
|
|
|
10369
10411
|
Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
10370
10412
|
);
|
|
10371
10413
|
}
|
|
10372
|
-
const dir =
|
|
10414
|
+
const dir = path43.resolve(ctx.workspaceRootDir, options.output);
|
|
10373
10415
|
fs40.mkdirSync(dir, { recursive: true });
|
|
10374
|
-
const destination =
|
|
10416
|
+
const destination = path43.join(dir, key);
|
|
10375
10417
|
if (!ctx.session) {
|
|
10376
|
-
fs40.copyFileSync(
|
|
10418
|
+
fs40.copyFileSync(path43.join(ctx.workspaceRootDir, "data", "backups", key), destination);
|
|
10377
10419
|
} else {
|
|
10378
10420
|
const spinner8 = p55.spinner();
|
|
10379
10421
|
spinner8.start(`Downloading ${key} (${formatBytes(found.size)})`);
|
|
@@ -10387,7 +10429,7 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
|
|
|
10387
10429
|
}
|
|
10388
10430
|
reportResult({
|
|
10389
10431
|
summary: `Saved ${key} from ${ctx.targetName}.`,
|
|
10390
|
-
filesCreated: [
|
|
10432
|
+
filesCreated: [path43.relative(ctx.workspaceRootDir, destination)]
|
|
10391
10433
|
});
|
|
10392
10434
|
});
|
|
10393
10435
|
}, "Failed to download the backup.")
|
|
@@ -10483,7 +10525,7 @@ var backup = new Command98("backup").description("back up the database and uploa
|
|
|
10483
10525
|
|
|
10484
10526
|
// src/commands/restore.ts
|
|
10485
10527
|
import fs41 from "node:fs";
|
|
10486
|
-
import
|
|
10528
|
+
import path44 from "node:path";
|
|
10487
10529
|
import process37 from "node:process";
|
|
10488
10530
|
import { Command as Command99 } from "commander";
|
|
10489
10531
|
import * as p58 from "@clack/prompts";
|
|
@@ -10529,7 +10571,7 @@ var restore = addLockWaitOption(
|
|
|
10529
10571
|
});
|
|
10530
10572
|
p58.log.success(
|
|
10531
10573
|
`Restored ${pc31.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc31.cyan(
|
|
10532
|
-
local ?
|
|
10574
|
+
local ? path44.basename(local) : key
|
|
10533
10575
|
)}.`
|
|
10534
10576
|
);
|
|
10535
10577
|
if (result?.storageCarriedOver) {
|
|
@@ -10595,21 +10637,21 @@ Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive
|
|
|
10595
10637
|
}
|
|
10596
10638
|
async function stage(ctx, file) {
|
|
10597
10639
|
const dir = remotePaths.restoreStage(ctx.instance);
|
|
10598
|
-
const remote = `${dir}/${
|
|
10640
|
+
const remote = `${dir}/${path44.basename(file)}`;
|
|
10599
10641
|
const spinner8 = p58.spinner();
|
|
10600
|
-
spinner8.start(`Uploading ${
|
|
10642
|
+
spinner8.start(`Uploading ${path44.basename(file)}`);
|
|
10601
10643
|
try {
|
|
10602
10644
|
await ctx.session.script(`mkdir -p "$1"`, { args: [dir] });
|
|
10603
10645
|
await ctx.session.upload([file], dir);
|
|
10604
10646
|
} catch (error) {
|
|
10605
|
-
spinner8.stop(`Could not upload ${
|
|
10647
|
+
spinner8.stop(`Could not upload ${path44.basename(file)}.`);
|
|
10606
10648
|
throw error;
|
|
10607
10649
|
}
|
|
10608
|
-
spinner8.stop(`Uploaded ${
|
|
10650
|
+
spinner8.stop(`Uploaded ${path44.basename(file)}`);
|
|
10609
10651
|
return remote;
|
|
10610
10652
|
}
|
|
10611
10653
|
async function confirm13(appName, targetName, envTag, from) {
|
|
10612
|
-
const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(
|
|
10654
|
+
const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(path44.basename(from))}`;
|
|
10613
10655
|
if (isProd(envTag)) {
|
|
10614
10656
|
const answer = await p58.text({
|
|
10615
10657
|
message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
|
|
@@ -10720,7 +10762,7 @@ Release and domain are shown from what this project recorded.`
|
|
|
10720
10762
|
}
|
|
10721
10763
|
|
|
10722
10764
|
// src/commands/test.ts
|
|
10723
|
-
import
|
|
10765
|
+
import path45 from "node:path";
|
|
10724
10766
|
import process38 from "node:process";
|
|
10725
10767
|
import { Command as Command101 } from "commander";
|
|
10726
10768
|
import PocketBase6 from "pocketbase";
|
|
@@ -10733,15 +10775,15 @@ var testServer = new Command101("test:server").description("run server tests").a
|
|
|
10733
10775
|
const cwd = process38.cwd();
|
|
10734
10776
|
const email3 = `test-${Math.random().toString(36).slice(2)}@example.com`;
|
|
10735
10777
|
const password11 = "password";
|
|
10736
|
-
const testDataDir =
|
|
10778
|
+
const testDataDir = path45.join(cwd, "test-data");
|
|
10737
10779
|
fs42.rmSync(testDataDir, { recursive: true, force: true });
|
|
10738
10780
|
const { stop, url } = await launchPocketbase(cwd, {
|
|
10739
10781
|
dir: testDataDir,
|
|
10740
|
-
migrationsDir:
|
|
10782
|
+
migrationsDir: path45.join(cwd, MIGRATIONS_DIR),
|
|
10741
10783
|
// The app's PocketBase hooks (slug generation, personal teams, …) are part
|
|
10742
10784
|
// of its behaviour; the suite runs against the same server dev and build
|
|
10743
10785
|
// start, so it loads them from the same place.
|
|
10744
|
-
hooksDir:
|
|
10786
|
+
hooksDir: path45.join(cwd, DATA_DIR, "hooks"),
|
|
10745
10787
|
email: email3,
|
|
10746
10788
|
password: password11
|
|
10747
10789
|
});
|
|
@@ -10859,7 +10901,7 @@ function stubPagesPlugin() {
|
|
|
10859
10901
|
|
|
10860
10902
|
// src/commands/routes.ts
|
|
10861
10903
|
import fs43 from "node:fs";
|
|
10862
|
-
import
|
|
10904
|
+
import path46 from "node:path";
|
|
10863
10905
|
import { Command as Command102 } from "commander";
|
|
10864
10906
|
var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
10865
10907
|
"GET",
|
|
@@ -10873,7 +10915,7 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
|
10873
10915
|
]);
|
|
10874
10916
|
var routes = new Command102("routes").description("list routes").configureHelp(helpConfig).action(async () => {
|
|
10875
10917
|
const { workspaceRootDir, routesDir } = await getWorkspace();
|
|
10876
|
-
const routesRoot =
|
|
10918
|
+
const routesRoot = path46.join(workspaceRootDir, routesDir);
|
|
10877
10919
|
const found = walk(routesRoot, routesRoot).filter((r) => r.methods.length > 0);
|
|
10878
10920
|
found.sort((a, b) => a.urlPattern.localeCompare(b.urlPattern));
|
|
10879
10921
|
printTable(found);
|
|
@@ -10883,20 +10925,20 @@ function walk(root, dir) {
|
|
|
10883
10925
|
const routes2 = [];
|
|
10884
10926
|
const hasLeaf = entries.some((e) => e.isFile() && isRouteFile(e.name));
|
|
10885
10927
|
if (hasLeaf) {
|
|
10886
|
-
const id = "/" +
|
|
10928
|
+
const id = "/" + path46.relative(root, dir).split(path46.sep).filter(Boolean).join("/");
|
|
10887
10929
|
const urlPattern = id.replace(/\([^)]+\)\/?/g, "").replace(/\/$/, "") || "/";
|
|
10888
10930
|
const methods = /* @__PURE__ */ new Set();
|
|
10889
10931
|
for (const entry of entries) {
|
|
10890
10932
|
if (!entry.isFile()) continue;
|
|
10891
10933
|
if (entry.name.endsWith("+page.svelte")) methods.add("GET");
|
|
10892
10934
|
if (entry.name.endsWith("+server.ts") || entry.name.endsWith("+server.js") || entry.name.endsWith("+page.server.ts") || entry.name.endsWith("+page.server.js")) {
|
|
10893
|
-
extractMethods(
|
|
10935
|
+
extractMethods(path46.join(dir, entry.name)).forEach((m) => methods.add(m));
|
|
10894
10936
|
}
|
|
10895
10937
|
}
|
|
10896
10938
|
routes2.push({ id: id || "/", urlPattern, methods: [...methods] });
|
|
10897
10939
|
}
|
|
10898
10940
|
for (const entry of entries) {
|
|
10899
|
-
if (entry.isDirectory()) routes2.push(...walk(root,
|
|
10941
|
+
if (entry.isDirectory()) routes2.push(...walk(root, path46.join(dir, entry.name)));
|
|
10900
10942
|
}
|
|
10901
10943
|
return routes2;
|
|
10902
10944
|
}
|
|
@@ -11084,7 +11126,7 @@ import pc36 from "picocolors";
|
|
|
11084
11126
|
|
|
11085
11127
|
// src/lib/cms-backend.ts
|
|
11086
11128
|
import { createRequire as createRequire3 } from "node:module";
|
|
11087
|
-
import
|
|
11129
|
+
import path47 from "node:path";
|
|
11088
11130
|
import process41 from "node:process";
|
|
11089
11131
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
11090
11132
|
import pc35 from "picocolors";
|
|
@@ -11092,7 +11134,7 @@ var DEFAULT_PROJECT = "default";
|
|
|
11092
11134
|
async function loadBackendModule(root) {
|
|
11093
11135
|
let entry;
|
|
11094
11136
|
try {
|
|
11095
|
-
entry = createRequire3(
|
|
11137
|
+
entry = createRequire3(path47.join(root, "package.json")).resolve("@velastack/cms/backend");
|
|
11096
11138
|
} catch {
|
|
11097
11139
|
throw new Error(
|
|
11098
11140
|
`@velastack/cms is not installed in this project.
|
|
@@ -11110,8 +11152,8 @@ async function withCmsBackend(fn, cwd = process41.cwd()) {
|
|
|
11110
11152
|
const { createCmsBackend } = await loadBackendModule(root);
|
|
11111
11153
|
const dataDir2 = localDataDir(root);
|
|
11112
11154
|
const backend3 = createCmsBackend({
|
|
11113
|
-
dbPath:
|
|
11114
|
-
uploadDir:
|
|
11155
|
+
dbPath: path47.join(dataDir2, "cms.sqlite"),
|
|
11156
|
+
uploadDir: path47.join(dataDir2, "uploads")
|
|
11115
11157
|
});
|
|
11116
11158
|
try {
|
|
11117
11159
|
return await fn(backend3);
|
|
@@ -11372,14 +11414,14 @@ program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
|
11372
11414
|
if (isStub(actionCommand)) return;
|
|
11373
11415
|
const envRoot = findWorkspaceRoot() ?? process45.cwd();
|
|
11374
11416
|
dotenv2.config({ path: nodePath.join(envRoot, ".env"), quiet: true });
|
|
11375
|
-
const
|
|
11376
|
-
if (NO_BACKEND_COMMMANDS.has(
|
|
11377
|
-
const top =
|
|
11417
|
+
const path48 = getCommandPath(actionCommand);
|
|
11418
|
+
if (NO_BACKEND_COMMMANDS.has(path48)) return;
|
|
11419
|
+
const top = path48.split(" ", 1)[0];
|
|
11378
11420
|
if (NO_BACKEND_COMMMANDS.has(top)) return;
|
|
11379
11421
|
if (!hasBackend()) {
|
|
11380
11422
|
if (BACKEND_OPTIONAL_COMMANDS.has(top)) return;
|
|
11381
11423
|
p67.log.error(
|
|
11382
|
-
`${pc42.cyan(`vela ${
|
|
11424
|
+
`${pc42.cyan(`vela ${path48}`)} needs a backend, and this project does not have one.
|
|
11383
11425
|
|
|
11384
11426
|
Static projects have no database to talk to.
|
|
11385
11427
|
|
|
@@ -11389,7 +11431,7 @@ To add a backend to this project, run ${pc42.cyan("vela bless")}.`
|
|
|
11389
11431
|
p67.cancel("Operation failed.");
|
|
11390
11432
|
process45.exit(1);
|
|
11391
11433
|
}
|
|
11392
|
-
if (SELF_CREDENTIALED_COMMANDS.has(
|
|
11434
|
+
if (SELF_CREDENTIALED_COMMANDS.has(path48)) return;
|
|
11393
11435
|
if (!process45.env.POCKETBASE_SUPERUSER_EMAIL || !process45.env.POCKETBASE_SUPERUSER_PASSWORD) {
|
|
11394
11436
|
p67.log.error(
|
|
11395
11437
|
`PocketBase superuser credentials are required.
|