@moonsjs/vite 0.1.10 → 0.1.12

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.
@@ -8,7 +8,7 @@ import {
8
8
  toWebRequest2,
9
9
  sendNodeResponse2,
10
10
  installDevMiddleware2
11
- } from "../index-qz9sc74p.js";
11
+ } from "../index-h66m8653.js";
12
12
 
13
13
  // src/server/handler.ts
14
14
  import {
@@ -467,9 +467,9 @@ function warnPayloadFindings(payload, scan, warned) {
467
467
  }
468
468
  }
469
469
  // src/server/node-server.ts
470
- import { existsSync, readFileSync, statSync } from "node:fs";
470
+ import { existsSync, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
471
471
  import { createServer } from "node:http";
472
- import { extname, join, resolve, sep } from "node:path";
472
+ import { extname as extname2, join, resolve, sep } from "node:path";
473
473
 
474
474
  // src/server/isr.ts
475
475
  import { renameSync, writeFileSync } from "node:fs";
@@ -510,6 +510,14 @@ async function runRevalidate(options) {
510
510
  log(`[moons] isr: TIDAK menulis ${options.pathname} — memuat ${labels}`);
511
511
  return;
512
512
  }
513
+ if (options.storage !== undefined) {
514
+ await options.storage.write(options.pathname, new TextEncoder().encode(html));
515
+ return;
516
+ }
517
+ if (options.file === undefined) {
518
+ log(`[moons] isr: lewati ${options.pathname} — tanpa file/storage tujuan`);
519
+ return;
520
+ }
513
521
  const tmp = `${options.file}.tmp-${process.pid}`;
514
522
  writeFileSync(tmp, html);
515
523
  renameSync(tmp, options.file);
@@ -518,6 +526,50 @@ async function runRevalidate(options) {
518
526
  }
519
527
  }
520
528
 
529
+ // src/server/storage.ts
530
+ import { mkdirSync, readFileSync, renameSync as renameSync2, statSync, writeFileSync as writeFileSync2 } from "node:fs";
531
+ import { dirname, extname } from "node:path";
532
+ function createFileStorage(clientDir) {
533
+ return {
534
+ async read(pathname) {
535
+ const file = resolveStaticFile(clientDir, pathname);
536
+ if (file === null) {
537
+ return null;
538
+ }
539
+ const stat = statSync(file);
540
+ return { body: readFileSync(file), mtimeMs: stat.mtimeMs };
541
+ },
542
+ async write(pathname, body) {
543
+ const target = staticFileTarget(clientDir, pathname);
544
+ if (target === null) {
545
+ throw new Error(`[moons] isr: path tidak valid untuk ditulis: ${pathname}`);
546
+ }
547
+ mkdirSync(dirname(target), { recursive: true });
548
+ const tmp = `${target}.tmp-${process.pid}`;
549
+ writeFileSync2(tmp, body);
550
+ renameSync2(tmp, target);
551
+ }
552
+ };
553
+ }
554
+ function contentTypeForPathname(pathname) {
555
+ const ext = extname(pathname.split("?")[0] ?? "").toLowerCase();
556
+ return MIME[ext] ?? MIME[".html"] ?? "text/html; charset=utf-8";
557
+ }
558
+ var MIME = {
559
+ ".html": "text/html; charset=utf-8",
560
+ ".js": "text/javascript; charset=utf-8",
561
+ ".mjs": "text/javascript; charset=utf-8",
562
+ ".css": "text/css; charset=utf-8",
563
+ ".json": "application/json; charset=utf-8",
564
+ ".txt": "text/plain; charset=utf-8",
565
+ ".svg": "image/svg+xml",
566
+ ".ico": "image/x-icon",
567
+ ".png": "image/png",
568
+ ".webp": "image/webp",
569
+ ".woff": "font/woff",
570
+ ".woff2": "font/woff2"
571
+ };
572
+
521
573
  // src/server/shutdown.ts
522
574
  function installGracefulShutdown(server, options = {}) {
523
575
  const timeoutMs = options.timeoutMs ?? 1e4;
@@ -594,19 +646,49 @@ function startNodeServer(handler, options = {}) {
594
646
  try {
595
647
  const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
596
648
  if (req.method === "GET" || req.method === "HEAD") {
597
- const staticFile = resolveStaticFile(clientDir, url.pathname);
598
- if (staticFile !== null) {
599
- scheduleRevalidation(staticFile, url.pathname, handler, options, clientDir);
600
- const body = readFileSync(staticFile);
601
- res.statusCode = 200;
602
- res.setHeader("content-type", MIME_TYPES[extname(staticFile).toLowerCase()] ?? "application/octet-stream");
603
- for (const [name, value] of Object.entries(options.headers ?? {})) {
604
- if (!res.hasHeader(name)) {
605
- res.setHeader(name, value);
649
+ if (options.storage !== undefined) {
650
+ const entry = await options.storage.read(url.pathname);
651
+ if (entry !== null) {
652
+ scheduleRevalidation({
653
+ pathname: url.pathname,
654
+ mtimeMs: entry.mtimeMs,
655
+ storage: options.storage,
656
+ handler,
657
+ options,
658
+ clientDir
659
+ });
660
+ res.statusCode = 200;
661
+ res.setHeader("content-type", contentTypeForPathname(url.pathname));
662
+ for (const [name, value] of Object.entries(options.headers ?? {})) {
663
+ if (!res.hasHeader(name)) {
664
+ res.setHeader(name, value);
665
+ }
606
666
  }
667
+ res.end(req.method === "HEAD" ? undefined : Buffer.from(entry.body));
668
+ return;
669
+ }
670
+ } else {
671
+ const staticFile = resolveStaticFile(clientDir, url.pathname);
672
+ if (staticFile !== null) {
673
+ scheduleRevalidation({
674
+ pathname: url.pathname,
675
+ mtimeMs: statSync2(staticFile).mtimeMs,
676
+ file: staticFile,
677
+ handler,
678
+ options,
679
+ clientDir
680
+ });
681
+ const body = readFileSync2(staticFile);
682
+ res.statusCode = 200;
683
+ res.setHeader("content-type", MIME_TYPES[extname2(staticFile).toLowerCase()] ?? "application/octet-stream");
684
+ for (const [name, value] of Object.entries(options.headers ?? {})) {
685
+ if (!res.hasHeader(name)) {
686
+ res.setHeader(name, value);
687
+ }
688
+ }
689
+ res.end(req.method === "HEAD" ? undefined : body);
690
+ return;
607
691
  }
608
- res.end(req.method === "HEAD" ? undefined : body);
609
- return;
610
692
  }
611
693
  }
612
694
  const response = await handler(await toWebRequest2(req));
@@ -643,6 +725,10 @@ function startNodeServer(handler, options = {}) {
643
725
  return server;
644
726
  }
645
727
  function resolveStaticFile(clientDir, pathname) {
728
+ const target = staticFileTarget(clientDir, pathname);
729
+ return target !== null && isFile(target) ? target : null;
730
+ }
731
+ function staticFileTarget(clientDir, pathname) {
646
732
  let decoded;
647
733
  try {
648
734
  decoded = decodeURIComponent(pathname);
@@ -657,10 +743,7 @@ function resolveStaticFile(clientDir, pathname) {
657
743
  const manifest = readPrerenderManifest(clientDir);
658
744
  if (manifest.paths.has(normalized)) {
659
745
  const target = normalized === "/" ? "index.html" : `${normalized.slice(1)}/index.html`;
660
- const candidate = safeWithin(clientDir, `./${target}`);
661
- if (candidate !== null && isFile(candidate)) {
662
- return candidate;
663
- }
746
+ return safeWithin(clientDir, `./${target}`);
664
747
  }
665
748
  return null;
666
749
  }
@@ -672,18 +755,18 @@ function safeWithin(clientDir, relative) {
672
755
  return candidate;
673
756
  }
674
757
  function isFile(path) {
675
- return existsSync(path) && statSync(path).isFile();
758
+ return existsSync(path) && statSync2(path).isFile();
676
759
  }
677
760
  var prerenderManifestCache = null;
678
761
  function readPrerenderManifest(clientDir) {
679
762
  const file = join(clientDir, "_moons_prerender.json");
680
763
  const empty = { paths: new Set, revalidate: new Map };
681
764
  try {
682
- const mtimeMs = statSync(file).mtimeMs;
765
+ const mtimeMs = statSync2(file).mtimeMs;
683
766
  if (prerenderManifestCache !== null && prerenderManifestCache.file === file && prerenderManifestCache.mtimeMs === mtimeMs) {
684
767
  return prerenderManifestCache.info;
685
768
  }
686
- const json = JSON.parse(readFileSync(file, "utf8"));
769
+ const json = JSON.parse(readFileSync2(file, "utf8"));
687
770
  const paths = new Set;
688
771
  const revalidate = new Map;
689
772
  if (Array.isArray(json.paths)) {
@@ -713,26 +796,22 @@ function readPrerenderManifest(clientDir) {
713
796
  return empty;
714
797
  }
715
798
  }
716
- function scheduleRevalidation(staticFile, pathname, handler, options, clientDir) {
717
- const normalized = pathname.length > 1 ? pathname.replace(/\/+$/, "") : pathname;
718
- const seconds = readPrerenderManifest(clientDir).revalidate.get(normalized);
799
+ function scheduleRevalidation(input) {
800
+ const normalized = input.pathname.length > 1 ? input.pathname.replace(/\/+$/, "") : input.pathname;
801
+ const seconds = readPrerenderManifest(input.clientDir).revalidate.get(normalized);
719
802
  if (seconds === undefined || seconds < 0) {
720
803
  return;
721
804
  }
722
- let mtimeMs;
723
- try {
724
- mtimeMs = statSync(staticFile).mtimeMs;
725
- } catch {
726
- return;
727
- }
728
- if (!shouldRevalidate({ mtimeMs, revalidateSeconds: seconds })) {
805
+ if (!shouldRevalidate({ mtimeMs: input.mtimeMs, revalidateSeconds: seconds })) {
729
806
  return;
730
807
  }
731
808
  revalidatePrerendered({
732
809
  pathname: normalized,
733
- file: staticFile,
734
- handler,
735
- ...options.canary === undefined ? {} : { canary: options.canary }
810
+ ...input.file === undefined ? {} : { file: input.file },
811
+ ...input.storage === undefined ? {} : { storage: input.storage },
812
+ handler: input.handler,
813
+ ...input.options.canary === undefined ? {} : { canary: input.options.canary },
814
+ env: process.env
736
815
  });
737
816
  }
738
817
  // src/server/test-server.ts
@@ -808,8 +887,8 @@ function createPluginRuntime(options) {
808
887
  }
809
888
  // src/server/prerender.ts
810
889
  import { MoonsError as MoonsError2 } from "@moonsjs/core";
811
- import { mkdirSync, writeFileSync as writeFileSync2 } from "node:fs";
812
- import { dirname, join as join2, resolve as resolve2, sep as sep2 } from "node:path";
890
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
891
+ import { dirname as dirname2, join as join2, resolve as resolve2, sep as sep2 } from "node:path";
813
892
  var PRERENDER_MANIFEST_FILE = "_moons_prerender.json";
814
893
  var NOT_FOUND_SENTINEL = "/_moons/404";
815
894
  var NOT_FOUND_FILE = "404.html";
@@ -869,8 +948,8 @@ async function runPrerender(options) {
869
948
  const html = await response.text();
870
949
  assertNoLeak(html, pathname, route.file, options, env);
871
950
  const file = outputFile(options.clientDir, pathname);
872
- mkdirSync(dirname(file), { recursive: true });
873
- writeFileSync2(file, html);
951
+ mkdirSync2(dirname2(file), { recursive: true });
952
+ writeFileSync3(file, html);
874
953
  entries.push(typeof revalidate === "number" && revalidate >= 0 ? { path: pathname, revalidate } : { path: pathname });
875
954
  written += 1;
876
955
  }
@@ -878,10 +957,10 @@ async function runPrerender(options) {
878
957
  const notFound = await renderStaticNotFound(options, env, log);
879
958
  let wrote404 = false;
880
959
  if (notFound !== null) {
881
- writeFileSync2(join2(options.clientDir, NOT_FOUND_FILE), notFound);
960
+ writeFileSync3(join2(options.clientDir, NOT_FOUND_FILE), notFound);
882
961
  wrote404 = true;
883
962
  }
884
- writeFileSync2(join2(options.clientDir, PRERENDER_MANIFEST_FILE), `${JSON.stringify({ version: 2, entries }, null, 2)}
963
+ writeFileSync3(join2(options.clientDir, PRERENDER_MANIFEST_FILE), `${JSON.stringify({ version: 2, entries }, null, 2)}
885
964
  `);
886
965
  const emitted = emitStaticFiles(options.clientDir, options.staticConfig, entries);
887
966
  const extras = [...wrote404 ? [NOT_FOUND_FILE] : [], ...emitted];
@@ -896,7 +975,7 @@ function emitStaticFiles(clientDir, staticConfig, entries) {
896
975
  const headers = Object.entries(staticConfig.headers ?? {});
897
976
  if (headers.length > 0) {
898
977
  const lines = ["/*", ...headers.map(([name, value]) => ` ${name}: ${value}`)];
899
- writeFileSync2(join2(clientDir, "_headers"), `${lines.join(`
978
+ writeFileSync3(join2(clientDir, "_headers"), `${lines.join(`
900
979
  `)}
901
980
  `);
902
981
  emitted.push("_headers");
@@ -904,7 +983,7 @@ function emitStaticFiles(clientDir, staticConfig, entries) {
904
983
  const redirects = staticConfig.redirects ?? [];
905
984
  if (redirects.length > 0) {
906
985
  const lines = redirects.map((entry) => `${entry.from} ${entry.to} ${entry.status ?? 301}`);
907
- writeFileSync2(join2(clientDir, "_redirects"), `${lines.join(`
986
+ writeFileSync3(join2(clientDir, "_redirects"), `${lines.join(`
908
987
  `)}
909
988
  `);
910
989
  emitted.push("_redirects");
@@ -922,7 +1001,7 @@ function emitStaticFiles(clientDir, staticConfig, entries) {
922
1001
  ""
923
1002
  ].join(`
924
1003
  `);
925
- writeFileSync2(join2(clientDir, "sitemap.xml"), xml);
1004
+ writeFileSync3(join2(clientDir, "sitemap.xml"), xml);
926
1005
  emitted.push("sitemap.xml");
927
1006
  }
928
1007
  const robots = staticConfig.robots;
@@ -934,7 +1013,7 @@ function emitStaticFiles(clientDir, staticConfig, entries) {
934
1013
  if ((robots.sitemap ?? true) && sitemap !== undefined) {
935
1014
  lines.push("", `Sitemap: ${sitemap.site.replace(/\/$/, "")}/sitemap.xml`);
936
1015
  }
937
- writeFileSync2(join2(clientDir, "robots.txt"), `${lines.join(`
1016
+ writeFileSync3(join2(clientDir, "robots.txt"), `${lines.join(`
938
1017
  `)}
939
1018
  `);
940
1019
  emitted.push("robots.txt");
@@ -1085,8 +1164,10 @@ function prerenderError(route, message) {
1085
1164
  export {
1086
1165
  DEFAULT_TEMPLATE2 as DEFAULT_TEMPLATE,
1087
1166
  ROOT_PLACEHOLDER2 as ROOT_PLACEHOLDER,
1167
+ contentTypeForPathname,
1088
1168
  createDevShell2 as createDevShell,
1089
1169
  createFileShell2 as createFileShell,
1170
+ createFileStorage,
1090
1171
  createPluginRuntime,
1091
1172
  createRequestHandler,
1092
1173
  createTestServer,
@@ -1100,4 +1181,4 @@ export {
1100
1181
  toWebRequest2 as toWebRequest
1101
1182
  };
1102
1183
 
1103
- //# debugId=FB2CA2137E39D98464756E2164756E21
1184
+ //# debugId=9A8636F992D1AC9F64756E2164756E21