@buding0904/vitepad 0.3.1 → 0.3.2

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/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import fs2 from 'fs/promises';
1
+ import fs3 from 'fs/promises';
2
2
  import os from 'os';
3
- import path2 from 'path';
3
+ import path3 from 'path';
4
4
  import process2 from 'process';
5
5
  import { fileURLToPath, pathToFileURL } from 'url';
6
6
  import { createServer, mergeConfig, normalizePath, createLogger } from 'vite';
@@ -9,8 +9,8 @@ import { spawn } from 'child_process';
9
9
  import { createRequire } from 'module';
10
10
 
11
11
  // src/runtime/index.ts
12
- var packageRoot = path2.resolve(fileURLToPath(new URL("..", import.meta.url)));
13
- var requireFromPackage = createRequire(path2.join(packageRoot, "package.json"));
12
+ var packageRoot = path3.resolve(fileURLToPath(new URL("..", import.meta.url)));
13
+ var requireFromPackage = createRequire(path3.join(packageRoot, "package.json"));
14
14
  var linkedPeerPackages = ["vite"];
15
15
  var log = {
16
16
  framework(requested, resolved) {
@@ -41,14 +41,11 @@ async function resolveFramework(spec, options) {
41
41
  }
42
42
  const resolved = await resolveFrameworkPackages(spec.name, spec.version);
43
43
  const cacheDir = frameworkCacheDir(spec.name, resolved.version);
44
- const nodeModules = path2.join(cacheDir, "node_modules");
44
+ const nodeModules = path3.join(cacheDir, "node_modules");
45
45
  const installed = await isInstalled(cacheDir, resolved.packages);
46
- if (options.forceInstall && await pathExists(cacheDir)) {
47
- await fs2.rm(cacheDir, { recursive: true, force: true });
48
- }
49
46
  log.framework(`${spec.name}@${spec.version}`, `${spec.name}@${resolved.version}`);
50
47
  const cacheStatus = options.forceInstall ? "miss" : installed ? "hit" : "miss";
51
- if (options.forceInstall || !installed) {
48
+ if (!installed) {
52
49
  log.install(resolved.packages);
53
50
  await installFrameworkCache(cacheDir, resolved.packages);
54
51
  }
@@ -260,33 +257,33 @@ function packageLinks(nodeModulesOrPackageNames, maybePackageNames) {
260
257
  const packageNames = maybePackageNames ?? [];
261
258
  return packageNames.map((packageName) => ({
262
259
  name: packageName,
263
- source: path2.join(nodeModules, packageName)
260
+ source: path3.join(nodeModules, packageName)
264
261
  }));
265
262
  }
266
263
  function resolveInstalledPackageDir(packageName) {
267
264
  const packageJson = requireFromPackage.resolve(`${packageName}/package.json`);
268
- return path2.dirname(packageJson);
265
+ return path3.dirname(packageJson);
269
266
  }
270
267
  function frameworkCacheDir(framework, version) {
271
- const base = process.env.VITEPAD_CACHE_DIR || (process.env.XDG_CACHE_HOME ? path2.join(process.env.XDG_CACHE_HOME, "vitepad") : path2.join(os.homedir(), ".cache", "vitepad"));
272
- return path2.join(base, "frameworks", `${framework}-${sanitizeCacheKey(version)}`);
268
+ const base = process.env.VITEPAD_CACHE_DIR || (process.env.XDG_CACHE_HOME ? path3.join(process.env.XDG_CACHE_HOME, "vitepad") : path3.join(os.homedir(), ".cache", "vitepad"));
269
+ return path3.join(base, "frameworks", `${framework}-${sanitizeCacheKey(version)}`);
273
270
  }
274
271
  function sanitizeCacheKey(value) {
275
272
  return value.replace(/[^a-zA-Z0-9._-]/g, "_");
276
273
  }
277
274
  async function isInstalled(cacheDir, packages) {
278
- if (!await pathExists(path2.join(cacheDir, "node_modules"))) return false;
275
+ if (!await pathExists(path3.join(cacheDir, "node_modules"))) return false;
279
276
  for (const pkg of packages) {
280
277
  const { name } = splitPackageSpec(pkg);
281
- if (!await pathExists(path2.join(cacheDir, "node_modules", name))) {
278
+ if (!await pathExists(path3.join(cacheDir, "node_modules", name))) {
282
279
  return false;
283
280
  }
284
281
  }
285
282
  return true;
286
283
  }
287
284
  async function installFrameworkCache(cacheDir, packages) {
288
- await fs2.mkdir(cacheDir, { recursive: true });
289
- await fs2.writeFile(path2.join(cacheDir, "package.json"), JSON.stringify({
285
+ await fs3.mkdir(cacheDir, { recursive: true });
286
+ await fs3.writeFile(path3.join(cacheDir, "package.json"), JSON.stringify({
290
287
  private: true,
291
288
  type: "module",
292
289
  dependencies: Object.fromEntries(packages.map((pkg) => packageToDependency(pkg)))
@@ -326,12 +323,12 @@ ${output.trim()}`));
326
323
  });
327
324
  }
328
325
  async function linkPeerPackages(cacheDir) {
329
- await fs2.mkdir(path2.join(cacheDir, "node_modules"), { recursive: true });
326
+ await fs3.mkdir(path3.join(cacheDir, "node_modules"), { recursive: true });
330
327
  for (const packageName of linkedPeerPackages) {
331
328
  try {
332
329
  await linkPackage({
333
330
  source: resolveInstalledPackageDir(packageName),
334
- target: path2.join(cacheDir, "node_modules", packageName)
331
+ target: path3.join(cacheDir, "node_modules", packageName)
335
332
  });
336
333
  } catch (error) {
337
334
  const message = error instanceof Error ? error.message : String(error);
@@ -341,16 +338,16 @@ ${message}`);
341
338
  }
342
339
  }
343
340
  async function linkPackage(input) {
344
- const source = await fs2.realpath(input.source);
345
- const existing = await fs2.lstat(input.target).catch(() => null);
341
+ const source = await fs3.realpath(input.source);
342
+ const existing = await fs3.lstat(input.target).catch(() => null);
346
343
  if (existing) {
347
344
  if (existing.isSymbolicLink()) {
348
- const current = await fs2.realpath(input.target).catch(() => null);
345
+ const current = await fs3.realpath(input.target).catch(() => null);
349
346
  if (current === source) return;
350
347
  }
351
- await fs2.rm(input.target, { recursive: true, force: true });
348
+ await fs3.rm(input.target, { recursive: true, force: true });
352
349
  }
353
- await fs2.symlink(source, input.target, "dir");
350
+ await fs3.symlink(source, input.target, "dir");
354
351
  }
355
352
  function createProgress(label) {
356
353
  const width = 18;
@@ -386,16 +383,37 @@ function splitPackageSpec(spec) {
386
383
  return { name: spec.slice(0, at), version: spec.slice(at + 1) };
387
384
  }
388
385
  async function importCachePackage(cacheDir, packageName) {
389
- const requireFromCache = createRequire(path2.join(cacheDir, "package.json"));
386
+ const requireFromCache = createRequire(path3.join(cacheDir, "package.json"));
390
387
  const resolved = requireFromCache.resolve(packageName);
391
388
  return import(pathToFileURL(resolved).href);
392
389
  }
393
390
  async function pathExists(file) {
394
- return fs2.access(file).then(() => true, () => false);
391
+ return fs3.access(file).then(() => true, () => false);
392
+ }
393
+ async function packageVersion() {
394
+ const packageJson = await readPackageJson();
395
+ if (typeof packageJson.version === "string") return packageJson.version;
396
+ throw new Error("Failed to read vitepad version from package.json.");
397
+ }
398
+ async function readPackageJson() {
399
+ let current = path3.dirname(fileURLToPath(import.meta.url));
400
+ while (true) {
401
+ const packageJsonPath = path3.join(current, "package.json");
402
+ const source = await fs3.readFile(packageJsonPath, "utf8").catch(() => null);
403
+ if (source) {
404
+ const packageJson = JSON.parse(source);
405
+ if (packageJson.name === "@buding0904/vitepad") return packageJson;
406
+ }
407
+ const parent = path3.dirname(current);
408
+ if (parent === current) {
409
+ throw new Error("Failed to locate vitepad package.json.");
410
+ }
411
+ current = parent;
412
+ }
395
413
  }
396
414
 
397
415
  // src/runtime/index.ts
398
- var rootDir = path2.resolve(fileURLToPath(new URL("..", import.meta.url)));
416
+ var rootDir = path3.resolve(fileURLToPath(new URL("..", import.meta.url)));
399
417
  var supportedComponentExts = /* @__PURE__ */ new Set([".jsx", ".tsx", ".vue", ".svelte"]);
400
418
  var supportedMainExts = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"]);
401
419
  var frameworkValues = /* @__PURE__ */ new Set(["auto", "react", "preact", "solid", "vue", "svelte", "vanilla"]);
@@ -405,17 +423,21 @@ async function run(argv) {
405
423
  console.log(helpText());
406
424
  return;
407
425
  }
426
+ if (options.version) {
427
+ console.log(await packageVersion());
428
+ return;
429
+ }
408
430
  if (!options.entry) {
409
431
  throw new Error(helpText("Missing entry file."));
410
432
  }
411
- const entry = path2.resolve(process2.cwd(), options.entry);
412
- const stat = await fs2.stat(entry).catch(() => null);
433
+ const entry = path3.resolve(process2.cwd(), options.entry);
434
+ const stat = await fs3.stat(entry).catch(() => null);
413
435
  if (!stat?.isFile()) {
414
436
  throw new Error(`Entry file does not exist: ${entry}`);
415
437
  }
416
- const extension = path2.extname(entry).toLowerCase();
438
+ const extension = path3.extname(entry).toLowerCase();
417
439
  const mode = inferMode(extension);
418
- const source = await fs2.readFile(entry, "utf8");
440
+ const source = await fs3.readFile(entry, "utf8");
419
441
  const framework = inferFramework({
420
442
  extension,
421
443
  source,
@@ -423,8 +445,8 @@ async function run(argv) {
423
445
  version: options.frameworkVersion
424
446
  });
425
447
  validateCombination({ mode, framework: framework.name, extension });
426
- const resolvedFramework = await resolveFramework(framework, { forceInstall: options.forceInstall });
427
- await setupEditorPackages(path2.dirname(entry), resolvedFramework.editorPackageLinks);
448
+ const resolvedFramework = await resolveFramework(framework, { forceInstall: false });
449
+ await setupEditorPackages(path3.dirname(entry), resolvedFramework.editorPackageLinks);
428
450
  const workspace = await createWorkspace({
429
451
  entry,
430
452
  mode,
@@ -438,7 +460,8 @@ async function run(argv) {
438
460
  server: {
439
461
  host: options.host,
440
462
  port: options.port,
441
- open: options.open,
463
+ strictPort: options.strictPort,
464
+ open: false,
442
465
  watch: {
443
466
  ignored: (file) => normalizePath(file).startsWith(`${normalizePath(workspace)}/`)
444
467
  },
@@ -446,7 +469,7 @@ async function run(argv) {
446
469
  allow: [
447
470
  rootDir,
448
471
  process2.cwd(),
449
- path2.dirname(entry),
472
+ path3.dirname(entry),
450
473
  workspace,
451
474
  ...resolvedFramework.cacheDir ? [resolvedFramework.cacheDir] : []
452
475
  ]
@@ -458,13 +481,13 @@ async function run(argv) {
458
481
  ...resolvedFramework.aliases,
459
482
  {
460
483
  find: "@",
461
- replacement: path2.dirname(entry)
484
+ replacement: path3.dirname(entry)
462
485
  }
463
486
  ],
464
487
  dedupe: frameworkDedupe(resolvedFramework.name)
465
488
  },
466
489
  optimizeDeps: {
467
- entries: [path2.join(workspace, "src/main.js")],
490
+ entries: [path3.join(workspace, "src/main.js")],
468
491
  include: frameworkOptimizeDeps(resolvedFramework.name)
469
492
  },
470
493
  customLogger: createVitepadLogger()
@@ -486,22 +509,24 @@ function parseArgs(argv) {
486
509
  const options = {
487
510
  framework: "auto",
488
511
  frameworkVersion: "latest",
489
- forceInstall: false,
490
512
  port: 8e3,
513
+ strictPort: false,
491
514
  host: "0.0.0.0",
492
- open: "/",
493
- help: false
515
+ help: false,
516
+ version: false
494
517
  };
495
518
  for (let index = 0; index < argv.length; index += 1) {
496
519
  const arg = argv[index];
497
520
  if (arg === "-h" || arg === "--help") {
498
521
  options.help = true;
522
+ } else if (arg === "-v" || arg === "--version") {
523
+ options.version = true;
499
524
  } else if (arg === "--framework" || arg === "-f") {
500
525
  Object.assign(options, parseFramework(readValue(argv, ++index, arg)));
501
526
  } else if (arg.startsWith("--framework=")) {
502
527
  Object.assign(options, parseFramework(arg.slice("--framework=".length)));
503
- } else if (arg === "--force-install") {
504
- options.forceInstall = true;
528
+ } else if (arg === "--strictPort") {
529
+ options.strictPort = true;
505
530
  } else if (arg === "--port" || arg === "-p") {
506
531
  options.port = Number(readValue(argv, ++index, arg));
507
532
  } else if (arg.startsWith("--port=")) {
@@ -510,10 +535,6 @@ function parseArgs(argv) {
510
535
  options.host = readValue(argv, ++index, arg);
511
536
  } else if (arg.startsWith("--host=")) {
512
537
  options.host = arg.slice("--host=".length);
513
- } else if (arg === "--no-open") {
514
- options.open = false;
515
- } else if (arg === "--open") {
516
- options.open = "/";
517
538
  } else if (arg === "--config" || arg === "-c") {
518
539
  options.config = readValue(argv, ++index, arg);
519
540
  } else if (arg.startsWith("--config=")) {
@@ -577,31 +598,29 @@ function validateCombination(input) {
577
598
  }
578
599
  }
579
600
  async function createWorkspace(input) {
580
- const workspace = await fs2.mkdtemp(path2.join(await fs2.realpath(os.tmpdir()), "vitepad-"));
581
- const srcDir = path2.join(workspace, "src");
582
- const nodeModulesDir = path2.join(workspace, "node_modules");
583
- await fs2.mkdir(srcDir, { recursive: true });
584
- await fs2.mkdir(nodeModulesDir, { recursive: true });
601
+ const workspace = await fs3.mkdtemp(path3.join(await fs3.realpath(os.tmpdir()), "vitepad-"));
602
+ const srcDir = path3.join(workspace, "src");
603
+ const nodeModulesDir = path3.join(workspace, "node_modules");
604
+ await fs3.mkdir(srcDir, { recursive: true });
605
+ await fs3.mkdir(nodeModulesDir, { recursive: true });
585
606
  await Promise.all([
586
- fs2.writeFile(path2.join(workspace, "index.html"), htmlTemplate()),
587
- fs2.writeFile(path2.join(srcDir, "main.js"), mainTemplate(input)),
607
+ fs3.writeFile(path3.join(workspace, "index.html"), htmlTemplate()),
608
+ fs3.writeFile(path3.join(srcDir, "main.js"), mainTemplate(input)),
588
609
  ...input.packageLinks.map((link) => linkWorkspacePackage(nodeModulesDir, link))
589
610
  ]);
590
611
  return workspace;
591
612
  }
592
613
  async function linkWorkspacePackage(nodeModulesDir, link) {
593
- const source = await fs2.realpath(link.source);
594
- const target = path2.join(nodeModulesDir, link.name);
595
- await fs2.mkdir(path2.dirname(target), { recursive: true });
596
- await fs2.symlink(source, target, "dir");
614
+ const source = await fs3.realpath(link.source);
615
+ const target = path3.join(nodeModulesDir, link.name);
616
+ await fs3.mkdir(path3.dirname(target), { recursive: true });
617
+ await fs3.symlink(source, target, "dir");
597
618
  }
598
619
  async function setupEditorPackages(projectDir, links) {
599
620
  if (links.length === 0) return;
600
- const nodeModulesDir = path2.join(projectDir, "node_modules");
601
- await fs2.mkdir(nodeModulesDir, { recursive: true });
602
621
  const linked = [];
603
622
  for (const link of links) {
604
- const result = await linkEditorPackage(nodeModulesDir, link);
623
+ const result = await linkEditorPackage(projectDir, link);
605
624
  if (result === "linked") {
606
625
  linked.push(link.name);
607
626
  }
@@ -610,21 +629,35 @@ async function setupEditorPackages(projectDir, links) {
610
629
  console.log(`${pc2.cyan("vitepad")} ${pc2.green("editor")} linked ${linked.map((name) => pc2.cyan(name)).join(pc2.gray(", "))}`);
611
630
  }
612
631
  }
613
- async function linkEditorPackage(nodeModulesDir, link) {
614
- const source = await fs2.realpath(link.source);
615
- const target = path2.join(nodeModulesDir, link.name);
616
- await fs2.mkdir(path2.dirname(target), { recursive: true });
617
- const existing = await fs2.lstat(target).catch(() => null);
632
+ async function linkEditorPackage(projectDir, link) {
633
+ const source = await fs3.realpath(link.source);
634
+ const existingResolvablePackage = await findResolvablePackage(projectDir, link.name);
635
+ if (existingResolvablePackage) return "skipped";
636
+ const nodeModulesDir = path3.join(projectDir, "node_modules");
637
+ const target = path3.join(nodeModulesDir, link.name);
638
+ await fs3.mkdir(path3.dirname(target), { recursive: true });
639
+ const existing = await fs3.lstat(target).catch(() => null);
618
640
  if (existing) {
619
641
  if (existing.isSymbolicLink()) {
620
- const current = await fs2.realpath(target).catch(() => null);
642
+ const current = await fs3.realpath(target).catch(() => null);
621
643
  if (current === source) return "skipped";
622
644
  }
623
645
  return "skipped";
624
646
  }
625
- await fs2.symlink(source, target, "dir");
647
+ await fs3.symlink(source, target, "dir");
626
648
  return "linked";
627
649
  }
650
+ async function findResolvablePackage(fromDir, packageName) {
651
+ let current = path3.resolve(fromDir);
652
+ while (true) {
653
+ const candidate = path3.join(current, "node_modules", packageName);
654
+ const existing = await fs3.lstat(candidate).catch(() => null);
655
+ if (existing) return candidate;
656
+ const parent = path3.dirname(current);
657
+ if (parent === current) return null;
658
+ current = parent;
659
+ }
660
+ }
628
661
  function htmlTemplate() {
629
662
  return `<!doctype html>
630
663
  <html lang="en">
@@ -693,7 +726,7 @@ export default app
693
726
  }
694
727
  async function loadUserConfig(configFile) {
695
728
  if (!configFile) return {};
696
- const resolved = path2.resolve(process2.cwd(), configFile);
729
+ const resolved = path3.resolve(process2.cwd(), configFile);
697
730
  const configModule = await import(pathToFileURL(resolved).href);
698
731
  return configModule.default ?? configModule;
699
732
  }
@@ -757,10 +790,9 @@ Entries:
757
790
  Options:
758
791
  -f, --framework <name> auto, react, preact, solid, vue, svelte, vanilla
759
792
  Version specs are supported, e.g. react@18, vue@3.4.
760
- --force-install Reinstall the selected framework cache.
761
793
  -p, --port <number> Dev server port. Default: 8000
794
+ --strictPort Exit if the configured port is already in use.
762
795
  --host <host> Dev server host. Default: 0.0.0.0
763
- --no-open Do not open the browser automatically.
764
796
  -c, --config <file> Merge an extra Vite config file.
765
797
  -h, --help Show help.
766
798
  `;