@junejs/server 0.1.3 → 0.2.1

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.
Files changed (131) hide show
  1. package/assets/icon-latin.LICENSE.txt +92 -0
  2. package/assets/icon-latin.ttf +0 -0
  3. package/dist/adapter-D0UnYBuN.d.ts +64 -0
  4. package/dist/adapter.d.ts +2 -56
  5. package/dist/adapter.js +107 -6
  6. package/dist/agent-compile.d.ts +38 -0
  7. package/dist/agent-compile.js +145 -0
  8. package/dist/agent-discover.d.ts +4 -4
  9. package/dist/agent-discover.js +30 -44
  10. package/dist/agent-durable.d.ts +94 -19
  11. package/dist/agent-durable.js +647 -32
  12. package/dist/agent-native.d.ts +44 -13
  13. package/dist/agent-native.js +264 -27
  14. package/dist/app.d.ts +5 -5
  15. package/dist/app.js +42 -10
  16. package/dist/assets.d.ts +23 -0
  17. package/dist/assets.js +123 -0
  18. package/dist/blob.d.ts +4 -5
  19. package/dist/build.d.ts +8 -30
  20. package/dist/build.js +143 -298
  21. package/dist/client-bundle.d.ts +8 -9
  22. package/dist/client-bundle.js +1 -1
  23. package/dist/config-freeze-r5p-vTWv.d.ts +17 -0
  24. package/dist/config-freeze.d.ts +2 -0
  25. package/dist/config-freeze.js +54 -0
  26. package/dist/config-loader.d.ts +3 -4
  27. package/dist/connection-auth.d.ts +38 -0
  28. package/dist/connection-auth.js +31 -0
  29. package/dist/content-freeze-CyiW2fRK.d.ts +4 -0
  30. package/dist/content-freeze.d.ts +2 -0
  31. package/dist/content-freeze.js +83 -0
  32. package/dist/content.d.ts +22 -9
  33. package/dist/content.js +43 -3
  34. package/dist/core-version.d.ts +4 -0
  35. package/dist/core-version.js +12 -0
  36. package/dist/css-modules-ambient.d.ts +2 -1
  37. package/dist/css-modules.d.ts +10 -11
  38. package/dist/css.d.ts +9 -10
  39. package/dist/d1-migrate.d.ts +6 -7
  40. package/dist/d1-migrate.js +3 -2
  41. package/dist/db.d.ts +2 -2
  42. package/dist/deploy.d.ts +3 -4
  43. package/dist/deploy.js +3 -2
  44. package/dist/dev-reload.d.ts +3 -4
  45. package/dist/dev.d.ts +8 -5
  46. package/dist/dev.js +40 -9
  47. package/dist/favicon.d.ts +37 -0
  48. package/dist/favicon.js +248 -0
  49. package/dist/host.d.ts +6 -5
  50. package/dist/host.js +2 -1
  51. package/dist/icon-letter.d.ts +3 -0
  52. package/dist/icon-letter.js +8 -0
  53. package/dist/index.d.ts +11 -5
  54. package/dist/index.js +9 -3
  55. package/dist/instrumentation.d.ts +2 -3
  56. package/dist/instrumentation.js +2 -1
  57. package/dist/island-registry.d.ts +6 -7
  58. package/dist/isolate-local.d.ts +5 -0
  59. package/dist/isolate-local.js +12 -0
  60. package/dist/kv.d.ts +3 -4
  61. package/dist/llms-links.d.ts +9 -0
  62. package/dist/llms-links.js +65 -0
  63. package/dist/manifest-CwTT1zVs.d.ts +11 -0
  64. package/dist/manifest.d.ts +2 -0
  65. package/dist/manifest.js +113 -0
  66. package/dist/negotiate.d.ts +4 -3
  67. package/dist/negotiate.js +24 -14
  68. package/dist/{pipeline-CCp9idQ4.d.ts → pipeline-BHUjBO0G.d.ts} +13 -1
  69. package/dist/pipeline.d.ts +2 -2
  70. package/dist/pipeline.js +286 -35
  71. package/dist/resources.d.ts +5 -6
  72. package/dist/route-rank.d.ts +6 -7
  73. package/dist/route-scan-BMbBzPIB.d.ts +20 -0
  74. package/dist/route-scan.d.ts +2 -0
  75. package/dist/route-scan.js +100 -0
  76. package/dist/router.d.ts +12 -13
  77. package/dist/router.js +51 -38
  78. package/dist/rsc-build.d.ts +6 -7
  79. package/dist/rsc-bundle.d.ts +6 -7
  80. package/dist/rsc-manifest.d.ts +5 -6
  81. package/dist/rsc-runtime/flight-render-routes.d.ts +3 -4
  82. package/dist/rsc-runtime/flight-render.d.ts +2 -3
  83. package/dist/rsc-runtime/flight-to-html.d.ts +2 -3
  84. package/dist/rsc-runtime/flight-to-html.js +3 -2
  85. package/dist/rsc-runtime/rsc-worker.js +11 -8
  86. package/dist/rsc-runtime/rsdw-shims.d.ts +2 -1
  87. package/dist/segment.d.ts +4 -5
  88. package/dist/sqlite-driver.d.ts +11 -11
  89. package/dist/sqlite-driver.js +17 -4
  90. package/dist/static-files.d.ts +4 -5
  91. package/dist/tsconfig-jsx.d.ts +4 -4
  92. package/dist/tsconfig-jsx.js +1 -1
  93. package/dist/turn-events.d.ts +4 -0
  94. package/dist/turn-events.js +46 -0
  95. package/dist/web-manifest.d.ts +5 -0
  96. package/dist/web-manifest.js +42 -0
  97. package/dist/worker-2qbQjj2c.d.ts +64 -0
  98. package/dist/worker.d.ts +2 -57
  99. package/dist/worker.js +69 -27
  100. package/package.json +28 -9
  101. package/src/adapter.ts +149 -4
  102. package/src/agent-compile.ts +271 -0
  103. package/src/agent-discover.ts +77 -63
  104. package/src/agent-durable.ts +998 -30
  105. package/src/agent-native.ts +370 -35
  106. package/src/app.ts +75 -6
  107. package/src/assets.ts +200 -0
  108. package/src/build.ts +241 -449
  109. package/src/config-freeze.ts +109 -0
  110. package/src/connection-auth.ts +101 -0
  111. package/src/content-freeze.ts +151 -0
  112. package/src/content.ts +55 -4
  113. package/src/core-version.ts +34 -0
  114. package/src/dev.ts +41 -8
  115. package/src/favicon.ts +325 -0
  116. package/src/host.ts +4 -3
  117. package/src/icon-letter.ts +14 -0
  118. package/src/index.ts +22 -0
  119. package/src/isolate-local.ts +33 -0
  120. package/src/llms-links.ts +96 -0
  121. package/src/manifest.ts +130 -0
  122. package/src/negotiate.ts +39 -15
  123. package/src/pipeline.ts +494 -44
  124. package/src/route-scan.ts +161 -0
  125. package/src/router.ts +66 -54
  126. package/src/rsc-runtime/rsc-worker.tsx +5 -4
  127. package/src/sqlite-driver.ts +36 -6
  128. package/src/tsconfig-jsx.ts +2 -2
  129. package/src/turn-events.ts +43 -0
  130. package/src/web-manifest.ts +38 -0
  131. package/src/worker.ts +131 -35
package/dist/dev.js CHANGED
@@ -9,17 +9,42 @@ import { watch } from "node:fs";
9
9
  import { dirname } from "node:path";
10
10
  import { createServer } from "node:net";
11
11
  //#region src/dev.ts
12
- async function findFreePort(start, tries = 20) {
12
+ function devUrl(hostname, port) {
13
+ if ([
14
+ "127.0.0.1",
15
+ "0.0.0.0",
16
+ "::",
17
+ "localhost"
18
+ ].includes(hostname)) return `http://localhost:${port}`;
19
+ return `http://${hostname.includes(":") ? `[${hostname}]` : hostname}:${port}`;
20
+ }
21
+ function devAllowedHosts(configured, hostname) {
22
+ const hosts = /* @__PURE__ */ new Set([
23
+ "localhost",
24
+ ".localhost",
25
+ ...configured ?? []
26
+ ]);
27
+ if (!/^[\d.]+$|:/.test(hostname)) hosts.add(hostname.toLowerCase());
28
+ return [...hosts];
29
+ }
30
+ async function findFreePort(start, hostname, tries = 20) {
13
31
  for (let p = start; p < start + tries; p++) if (await new Promise((resolve) => {
14
32
  const probe = createServer();
15
33
  probe.once("error", () => resolve(false));
16
- probe.listen(p, () => probe.close(() => resolve(true)));
34
+ probe.listen(p, hostname, () => probe.close(() => resolve(true)));
17
35
  })) return p;
18
36
  throw new Error(`june dev: no free port between ${start} and ${start + tries - 1}`);
19
37
  }
20
- async function startDevServer({ appDir, port = 3e3, host: host$1 = host }) {
38
+ async function startDevServer({ appDir, port = 3e3, hostname = "127.0.0.1", host: host$1 = host }) {
21
39
  await installAsyncContext();
22
- const config = await loadJuneConfig(appDir);
40
+ const loaded = await loadJuneConfig(appDir);
41
+ const config = {
42
+ ...loaded,
43
+ agent: {
44
+ ...loaded.agent,
45
+ allowedHosts: devAllowedHosts(loaded.agent?.allowedHosts, hostname)
46
+ }
47
+ };
23
48
  const m = await migrateApp(dirname(appDir), config);
24
49
  if (m?.applied.length) console.log(`[june] migrated: ${m.applied.join(", ")}`);
25
50
  if (m?.blocked) console.warn(`[june] ${blockedMessage(m.blocked)}`);
@@ -28,11 +53,12 @@ async function startDevServer({ appDir, port = 3e3, host: host$1 = host }) {
28
53
  config
29
54
  });
30
55
  await app.warmup();
31
- const freePort = await findFreePort(port);
56
+ const freePort = await findFreePort(port, hostname);
32
57
  if (freePort !== port) console.log(`[june] port ${port} is taken → using ${freePort}`);
33
58
  port = freePort;
34
59
  const handle = host$1.serve(withLiveReload((req) => app.fetch(req)), {
35
60
  port,
61
+ hostname,
36
62
  earlyHints: () => app.earlyHints()
37
63
  });
38
64
  if (findGlobalCss(appDir)) {
@@ -44,12 +70,17 @@ async function startDevServer({ appDir, port = 3e3, host: host$1 = host }) {
44
70
  });
45
71
  processCssCached(appDir).catch(() => {});
46
72
  }
47
- const url = `http://localhost:${handle.port}`;
48
- console.log(`june dev → ${url} (host: ${host$1.name})`);
73
+ const url = devUrl(hostname, handle.port);
74
+ const lan = hostname === "127.0.0.1" ? "" : ` · listening on ${hostname}`;
75
+ console.log(`june dev → ${url} (host: ${host$1.name})${lan}`);
49
76
  return {
50
77
  ...handle,
51
- url
78
+ url,
79
+ async stop(force) {
80
+ handle.stop(force);
81
+ await app.close();
82
+ }
52
83
  };
53
84
  }
54
85
  //#endregion
55
- export { startDevServer };
86
+ export { devAllowedHosts, devUrl, startDevServer };
@@ -0,0 +1,37 @@
1
+ import { DocumentConfig } from "@junejs/core/document";
2
+ //#region src/favicon.d.ts
3
+ type Site = DocumentConfig["site"];
4
+ export declare const ICON_BG = "#1d1d1f";
5
+ export declare const ICON_FG = "#fbfbf8";
6
+ export declare const GENERATED_ICONS: readonly ["apple-touch-icon.png", "icon.png", "favicon.ico", "icon-192.png", "icon-512.png"];
7
+ export type GeneratedIconFile = (typeof GENERATED_ICONS)[number];
8
+ export declare function publicFileCheck(publicDir: string): (file: string) => boolean;
9
+ export declare function resolveIcons(site: Site, inPublic: (file: string) => boolean): {
10
+ generate: boolean;
11
+ icons: NonNullable<DocumentConfig["icons"]>;
12
+ };
13
+ export declare function hanFamily(lang: string | undefined): string;
14
+ export declare function iconFamily(ch: string, lang: string | undefined): string | null | undefined;
15
+ export type FontFetcher = (family: string, text: string) => Promise<Uint8Array | null>;
16
+ export declare function googleFontFetcher(cacheDir: string, opts?: {
17
+ fetch?: typeof fetch;
18
+ timeoutMs?: number;
19
+ }): FontFetcher;
20
+ export declare const INK_H = 28;
21
+ export declare const INK_W = 40;
22
+ export declare function pngToIco(png: Uint8Array, size: number): Uint8Array<ArrayBuffer>;
23
+ export type GeneratedIcons = {
24
+ "apple-touch-icon.png": Uint8Array<ArrayBuffer>;
25
+ "icon.png": Uint8Array<ArrayBuffer>;
26
+ "favicon.ico": Uint8Array<ArrayBuffer>;
27
+ "icon-192.png": Uint8Array<ArrayBuffer>;
28
+ "icon-512.png": Uint8Array<ArrayBuffer>;
29
+ letter: string;
30
+ family: string | null;
31
+ };
32
+ export declare function renderIcons(opts: {
33
+ site: Site;
34
+ fetchFont: FontFetcher;
35
+ warn?: (msg: string) => void;
36
+ }): Promise<GeneratedIcons>;
37
+ //#endregion
@@ -0,0 +1,248 @@
1
+ import { iconLetter } from "./icon-letter.js";
2
+ import { existsSync, lstatSync } from "node:fs";
3
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import { createHash } from "node:crypto";
6
+ import { createRequire } from "node:module";
7
+ //#region src/favicon.ts
8
+ const ICON_BG = "#1d1d1f";
9
+ const ICON_FG = "#fbfbf8";
10
+ const GENERATED_ICONS = [
11
+ "apple-touch-icon.png",
12
+ "icon.png",
13
+ "favicon.ico",
14
+ "icon-192.png",
15
+ "icon-512.png"
16
+ ];
17
+ const PRIMARY_ICON_FILES = [
18
+ "favicon.svg",
19
+ "icon.svg",
20
+ "favicon.png",
21
+ "icon.png",
22
+ "favicon.ico"
23
+ ];
24
+ const CUSTOM_ICON_FILES = [...PRIMARY_ICON_FILES, "apple-touch-icon.png"];
25
+ const MANIFEST_FILES = [
26
+ "manifest.webmanifest",
27
+ "manifest.json",
28
+ "site.webmanifest"
29
+ ];
30
+ function publicFileCheck(publicDir) {
31
+ let real = false;
32
+ try {
33
+ real = lstatSync(publicDir).isDirectory();
34
+ } catch {}
35
+ return (file) => real && existsSync(join(publicDir, file));
36
+ }
37
+ function resolveIcons(site, inPublic) {
38
+ const ownManifest = MANIFEST_FILES.find(inPublic);
39
+ if (!(Boolean(site.icon) || CUSTOM_ICON_FILES.some(inPublic))) return {
40
+ generate: true,
41
+ icons: {
42
+ png: "/icon.png",
43
+ appleTouch: "/apple-touch-icon.png",
44
+ manifest: ownManifest ? `/${ownManifest}` : "/manifest.webmanifest",
45
+ generated: !ownManifest
46
+ }
47
+ };
48
+ const primary = PRIMARY_ICON_FILES.find(inPublic);
49
+ return {
50
+ generate: false,
51
+ icons: {
52
+ primary: primary ? `/${primary}` : void 0,
53
+ png: inPublic("icon.png") ? "/icon.png" : void 0,
54
+ appleTouch: inPublic("apple-touch-icon.png") ? "/apple-touch-icon.png" : void 0,
55
+ manifest: ownManifest ? `/${ownManifest}` : void 0
56
+ }
57
+ };
58
+ }
59
+ const is = (re) => (ch) => re.test(ch);
60
+ const isBundled = is(/^[\p{Script=Latin}\p{Script=Greek}\p{Script=Cyrillic}0-9•]/u);
61
+ const isEmoji = is(/^\p{Extended_Pictographic}/u);
62
+ const isKana = is(/^[\p{Script=Hiragana}\p{Script=Katakana}]/u);
63
+ const isHangul = is(/^\p{Script=Hangul}/u);
64
+ const isHan = is(/^\p{Script=Han}/u);
65
+ const NOTO_SCRIPT_RES = [
66
+ "Arabic",
67
+ "Armenian",
68
+ "Bengali",
69
+ "Devanagari",
70
+ "Ethiopic",
71
+ "Georgian",
72
+ "Gujarati",
73
+ "Gurmukhi",
74
+ "Hebrew",
75
+ "Kannada",
76
+ "Khmer",
77
+ "Lao",
78
+ "Malayalam",
79
+ "Myanmar",
80
+ "Sinhala",
81
+ "Tamil",
82
+ "Telugu",
83
+ "Thai"
84
+ ].map((s) => [s, new RegExp(`^\\p{Script=${s}}`, "u")]);
85
+ function hanFamily(lang) {
86
+ let loc;
87
+ try {
88
+ loc = new Intl.Locale(lang || "und").maximize();
89
+ } catch {
90
+ return "Noto Sans SC";
91
+ }
92
+ if (loc.script === "Jpan") return "Noto Sans JP";
93
+ if (loc.script === "Kore") return "Noto Sans KR";
94
+ if (loc.script === "Hant") return loc.region === "HK" || loc.region === "MO" ? "Noto Sans HK" : "Noto Sans TC";
95
+ return "Noto Sans SC";
96
+ }
97
+ function iconFamily(ch, lang) {
98
+ if (!ch) return void 0;
99
+ if (isBundled(ch)) return null;
100
+ if (isEmoji(ch)) return "Noto Emoji";
101
+ if (isKana(ch)) return "Noto Sans JP";
102
+ if (isHangul(ch)) return "Noto Sans KR";
103
+ if (isHan(ch)) return hanFamily(lang);
104
+ const script = NOTO_SCRIPT_RES.find(([, re]) => re.test(ch))?.[0];
105
+ return script ? `Noto Sans ${script}` : void 0;
106
+ }
107
+ const LEGACY_UA = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1";
108
+ function googleFontFetcher(cacheDir, opts = {}) {
109
+ const doFetch = opts.fetch ?? fetch;
110
+ const timeoutMs = opts.timeoutMs ?? 3e3;
111
+ return async (family, text) => {
112
+ const cssUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(family)}:wght@600&text=${encodeURIComponent(text)}`;
113
+ const file = join(cacheDir, createHash("sha256").update(cssUrl).digest("hex").slice(0, 32) + ".ttf");
114
+ try {
115
+ return new Uint8Array(await readFile(file));
116
+ } catch {}
117
+ try {
118
+ const signal = AbortSignal.timeout(timeoutMs);
119
+ const cssRes = await doFetch(cssUrl, {
120
+ headers: { "User-Agent": LEGACY_UA },
121
+ signal
122
+ });
123
+ if (!cssRes.ok) return null;
124
+ const url = (await cssRes.text()).match(/src: url\((.+?)\)/)?.[1];
125
+ if (!url) return null;
126
+ const fontRes = await doFetch(url, { signal });
127
+ if (!fontRes.ok) return null;
128
+ const bytes = new Uint8Array(await fontRes.arrayBuffer());
129
+ await mkdir(cacheDir, { recursive: true });
130
+ await writeFile(file, bytes);
131
+ return bytes;
132
+ } catch {
133
+ return null;
134
+ }
135
+ };
136
+ }
137
+ let resvgReady;
138
+ function loadResvg() {
139
+ return resvgReady ??= (async () => {
140
+ const mod = await import("@resvg/resvg-wasm");
141
+ const wasmPath = createRequire(import.meta.url).resolve("@resvg/resvg-wasm/index_bg.wasm");
142
+ await mod.initWasm(await readFile(wasmPath));
143
+ return mod;
144
+ })();
145
+ }
146
+ let bundledFont;
147
+ const loadBundledFont = () => bundledFont ??= readFile(new URL("../assets/icon-latin.ttf", import.meta.url)).then((b) => new Uint8Array(b));
148
+ const BUNDLED_FAMILY = "Inter";
149
+ const escapeXml = (s) => s.replace(/[<>&"']/g, (c) => `&#${c.charCodeAt(0)};`);
150
+ const PROBE = 1e3;
151
+ const INK_H = 28;
152
+ const INK_W = 40;
153
+ function inkBox(resvg, ch, family, font) {
154
+ const probe = `<svg xmlns="http://www.w3.org/2000/svg" width="${PROBE}" height="${PROBE}"><text x="${PROBE / 2}" y="${PROBE * .7}" font-family="${family}" font-size="${PROBE * .6}">${escapeXml(ch)}</text></svg>`;
155
+ const r = new resvg.Resvg(probe, { font: {
156
+ fontBuffers: [font],
157
+ loadSystemFonts: false,
158
+ defaultFontFamily: family
159
+ } });
160
+ const bbox = r.getBBox();
161
+ const box = bbox && bbox.width > 0 && bbox.height > 0 ? {
162
+ x: bbox.x,
163
+ y: bbox.y,
164
+ width: bbox.width,
165
+ height: bbox.height
166
+ } : null;
167
+ bbox?.free();
168
+ r.free();
169
+ return box;
170
+ }
171
+ const NOTDEF_PROBE = "";
172
+ function place(resvg, ch, family, font) {
173
+ const bbox = inkBox(resvg, ch, family, font);
174
+ if (!bbox) return null;
175
+ const notdef = inkBox(resvg, NOTDEF_PROBE, family, font);
176
+ if (notdef && notdef.x === bbox.x && notdef.y === bbox.y && notdef.width === bbox.width && notdef.height === bbox.height) return null;
177
+ const scale = Math.min(28 / bbox.height, 40 / bbox.width);
178
+ const cx = bbox.x + bbox.width / 2 - PROBE / 2;
179
+ const cy = bbox.y + bbox.height / 2 - PROBE * .7;
180
+ return {
181
+ family,
182
+ font,
183
+ size: PROBE * .6 * scale,
184
+ x: 32 - cx * scale,
185
+ y: 32 - cy * scale
186
+ };
187
+ }
188
+ function iconSvg(ch, p, rounded) {
189
+ const glyph = p ? `<text x="${p.x.toFixed(2)}" y="${p.y.toFixed(2)}" font-family="${p.family}" font-size="${p.size.toFixed(2)}" fill="${ICON_FG}">${escapeXml(ch)}</text>` : "";
190
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64"><rect width="64" height="64"${rounded ? ` rx="12"` : ""} fill="${ICON_BG}"/>${glyph}</svg>`;
191
+ }
192
+ function pngToIco(png, size) {
193
+ const out = new Uint8Array(22 + png.length);
194
+ const v = new DataView(out.buffer);
195
+ v.setUint16(2, 1, true);
196
+ v.setUint16(4, 1, true);
197
+ out[6] = size >= 256 ? 0 : size;
198
+ out[7] = size >= 256 ? 0 : size;
199
+ v.setUint16(10, 1, true);
200
+ v.setUint16(12, 32, true);
201
+ v.setUint32(14, png.length, true);
202
+ v.setUint32(18, 22, true);
203
+ out.set(png, 22);
204
+ return out;
205
+ }
206
+ async function renderIcons(opts) {
207
+ const resvg = await loadResvg();
208
+ const ch = iconLetter(opts.site.name);
209
+ const family = iconFamily(ch, opts.site.lang);
210
+ let placement = null;
211
+ if (family === null) placement = place(resvg, ch, BUNDLED_FAMILY, await loadBundledFont());
212
+ else if (family !== void 0) {
213
+ const font = await opts.fetchFont(family, ch);
214
+ if (font) placement = place(resvg, ch, family, font);
215
+ }
216
+ if (ch && !placement) opts.warn?.(`[june] default icon: no font for "${ch}"${family ? ` (${family} unavailable — offline?)` : ""}; drew the square without it. Set site.icon or add public/icon.png to use your own.`);
217
+ const fonts = placement ? [placement.font] : [];
218
+ const render = (size, rounded) => {
219
+ const r = new resvg.Resvg(iconSvg(ch, placement, rounded), {
220
+ fitTo: {
221
+ mode: "width",
222
+ value: size
223
+ },
224
+ font: {
225
+ fontBuffers: fonts,
226
+ loadSystemFonts: false,
227
+ defaultFontFamily: placement?.family ?? BUNDLED_FAMILY
228
+ }
229
+ });
230
+ const image = r.render();
231
+ const png = image.asPng();
232
+ image.free();
233
+ r.free();
234
+ return png;
235
+ };
236
+ const icon32 = render(32, true);
237
+ return {
238
+ "apple-touch-icon.png": render(180, false),
239
+ "icon.png": icon32,
240
+ "favicon.ico": pngToIco(icon32, 32),
241
+ "icon-192.png": render(192, false),
242
+ "icon-512.png": render(512, false),
243
+ letter: ch,
244
+ family: placement?.family ?? null
245
+ };
246
+ }
247
+ //#endregion
248
+ export { GENERATED_ICONS, ICON_BG, ICON_FG, INK_H, INK_W, googleFontFetcher, hanFamily, iconFamily, pngToIco, publicFileCheck, renderIcons, resolveIcons };
package/dist/host.d.ts CHANGED
@@ -1,18 +1,19 @@
1
1
  import { JuneDb, RunResult } from "@junejs/core/resources";
2
2
  //#region src/host.d.ts
3
- type ServeHandle = {
3
+ export type ServeHandle = {
4
4
  port: number;
5
5
  stop(force?: boolean): void;
6
6
  };
7
- type SpawnedModule = {
7
+ export type SpawnedModule = {
8
8
  stdout: ReadableStream<Uint8Array>;
9
9
  stderrText(): Promise<string>;
10
10
  exited: Promise<number>;
11
11
  };
12
- interface JuneHost {
12
+ export interface JuneHost {
13
13
  readonly name: "bun" | "node";
14
14
  serve(handler: (req: Request) => Promise<Response>, opts: {
15
15
  port: number;
16
+ hostname?: string;
16
17
  earlyHints?: () => string[];
17
18
  }): ServeHandle;
18
19
  spawnModule(entry: string, args: string[], opts: {
@@ -20,6 +21,6 @@ interface JuneHost {
20
21
  }): SpawnedModule;
21
22
  openDb(path: string): Promise<JuneDb>;
22
23
  }
23
- declare const host: JuneHost;
24
+ export declare const host: JuneHost;
24
25
  //#endregion
25
- export { type JuneDb, JuneHost, type RunResult, ServeHandle, SpawnedModule, host };
26
+ export type { JuneDb, RunResult };
package/dist/host.js CHANGED
@@ -9,6 +9,7 @@ function bunHost() {
9
9
  serve(handler, opts) {
10
10
  const server = Bun.serve({
11
11
  port: opts.port,
12
+ hostname: opts.hostname,
12
13
  fetch: handler,
13
14
  idleTimeout: 0
14
15
  });
@@ -64,7 +65,7 @@ function nodeHost() {
64
65
  res.end("Internal Server Error");
65
66
  }
66
67
  });
67
- server.listen(opts.port);
68
+ server.listen(opts.port, opts.hostname);
68
69
  return {
69
70
  get port() {
70
71
  const addr = server.address();
@@ -0,0 +1,3 @@
1
+ //#region src/icon-letter.d.ts
2
+ export declare function iconLetter(name: string | undefined): string;
3
+ //#endregion
@@ -0,0 +1,8 @@
1
+ //#region src/icon-letter.ts
2
+ function iconLetter(name) {
3
+ const trimmed = (name ?? "").trim();
4
+ if (!trimmed) return "";
5
+ return (new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(trimmed)[Symbol.iterator]().next().value?.segment ?? "").toUpperCase();
6
+ }
7
+ //#endregion
8
+ export { iconLetter };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,16 @@
1
- import { AdapterCapabilities, AdapterEmitContext, AdapterEntry, JuneAdapter, ResourcePlan, deno, staticSite, vercel, workers } from "./adapter.js";
1
+ import { a as ResourcePlan, d as workers, i as JuneAdapter, l as staticSite, n as AdapterEmitContext, o as deno, r as AdapterEntry, t as AdapterCapabilities, u as vercel } from "./adapter-D0UnYBuN.js";
2
+ import { AGENT_MODULE_FILE, AgentDirScan, emitAgentModule, findAgentDir, generateAgentModule, scanAgentDir } from "./agent-compile.js";
2
3
  import { CreateAppOptions, JuneApp, createApp } from "./app.js";
3
4
  import { R2Bucket, localBlob, r2 } from "./blob.js";
4
- import { a as Pipeline, d as createPipeline, n as LayoutComponent, o as PipelineConfig, s as Resolved, u as RouteResolver } from "./pipeline-CCp9idQ4.js";
5
- import { WorkerManifest, createWorker } from "./worker.js";
6
- import { BuildResult, buildManifest, freezeConfig, generateContent, juneBuild, scanRoutes } from "./build.js";
5
+ import { o as scanRoutes } from "./route-scan-BMbBzPIB.js";
6
+ import { t as generateContent } from "./content-freeze-CyiW2fRK.js";
7
+ import { a as Pipeline, d as createPipeline, n as LayoutComponent, o as PipelineConfig, s as Resolved, u as RouteResolver } from "./pipeline-BHUjBO0G.js";
8
+ import { n as WorkerManifest, r as createWorker } from "./worker-2qbQjj2c.js";
9
+ import { t as freezeConfig } from "./config-freeze-r5p-vTWv.js";
10
+ import { n as buildManifest } from "./manifest-CwTT1zVs.js";
11
+ import { BuildResult, juneBuild } from "./build.js";
7
12
  import { loadJuneConfig } from "./config-loader.js";
13
+ import { AccountTokenStore, BetterAuthLike, ConnectionAuth, LinkedAccountAuthOptions, betterAuthAccessToken, betterAuthAccountTokenStore, linkedAccountAuth } from "./connection-auth.js";
8
14
  import { ContentEntry, collection, entry } from "./content.js";
9
15
  import { a as blockedMessage, c as migrateApp, l as readMigrations, n as MigrateResult, o as classify, r as Migration, s as migrate, u as typesApp } from "./migrate-BbWt-PuB.js";
10
16
  import { D1Exec, migrateD1, resolveD1Database, wranglerD1 } from "./d1-migrate.js";
@@ -24,4 +30,4 @@ import { Negotiated, negotiate } from "./negotiate.js";
24
30
  import { blob, currentServices, db, kv } from "@junejs/db";
25
31
  import { ServicesConfig, defineServices } from "@junejs/core/config";
26
32
  import { I18nConfig, LOCALE_COOKIE, LocaleConfig, LocaleMatch, dirForLang, localeDir, localeHref, matchPinnedLocale, negotiateLocale, parseAcceptLanguage, resolveRequestLocale } from "@junejs/core/i18n";
27
- export { type AdapterCapabilities, type AdapterEmitContext, type AdapterEntry, type BuildResult, type ContentEntry, type CreateAppOptions, type D1Database, type D1Exec, type DeployResult, type DevServer, type DevServerOptions, type I18nConfig, type JuneAdapter, type JuneApp, type JuneDb, type JuneHost, LOCALE_COOKIE, type LayoutComponent, type LocaleConfig, type LocaleMatch, type MatchOptions, type MigrateResult, type Migration, type Negotiated, type Pipeline, type PipelineConfig, type R2Bucket, type Resolved, type ResourceFlags, type ResourcePlan, type RouteMatch, type RouteResolver, type RouteTreeMatch, type RunResult, type SegmentMatch, type ServeHandle, type ServicesConfig, type SpawnedModule, type WorkerEnv, type WorkerManifest, bindWorkerResources, blob, blockedMessage, buildManifest, classify, collection, createApp, createPipeline, createWorker, currentServices, d1, db, defineServices, deno, dirForLang, entry, freezeConfig, generateContent, host, installAsyncContext, juneBuild, juneDeploy, kv, listRoutes, loadJuneConfig, localBlob, localeDir, localeHref, matchPinnedLocale, matchRoute, matchRouteTree, memoizeResources, memoryKv, migrate, migrateApp, migrateD1, mysql, negotiate, negotiateLocale, parseAcceptLanguage, postgres, r2, readMigrations, redisKv, resolveD1Database, resolveNotFound, resolveRequestLocale, scanRoutes, sqlite, startDevServer, staticSite, turso, typesApp, vercel, workers, wranglerD1 };
33
+ export { AGENT_MODULE_FILE, type AccountTokenStore, type AdapterCapabilities, type AdapterEmitContext, type AdapterEntry, type AgentDirScan, type BetterAuthLike, type BuildResult, type ConnectionAuth, type ContentEntry, type CreateAppOptions, type D1Database, type D1Exec, type DeployResult, type DevServer, type DevServerOptions, type I18nConfig, type JuneAdapter, type JuneApp, type JuneDb, type JuneHost, LOCALE_COOKIE, type LayoutComponent, type LinkedAccountAuthOptions, type LocaleConfig, type LocaleMatch, type MatchOptions, type MigrateResult, type Migration, type Negotiated, type Pipeline, type PipelineConfig, type R2Bucket, type Resolved, type ResourceFlags, type ResourcePlan, type RouteMatch, type RouteResolver, type RouteTreeMatch, type RunResult, type SegmentMatch, type ServeHandle, type ServicesConfig, type SpawnedModule, type WorkerEnv, type WorkerManifest, betterAuthAccessToken, betterAuthAccountTokenStore, bindWorkerResources, blob, blockedMessage, buildManifest, classify, collection, createApp, createPipeline, createWorker, currentServices, d1, db, defineServices, deno, dirForLang, emitAgentModule, entry, findAgentDir, freezeConfig, generateAgentModule, generateContent, host, installAsyncContext, juneBuild, juneDeploy, kv, linkedAccountAuth, listRoutes, loadJuneConfig, localBlob, localeDir, localeHref, matchPinnedLocale, matchRoute, matchRouteTree, memoizeResources, memoryKv, migrate, migrateApp, migrateD1, mysql, negotiate, negotiateLocale, parseAcceptLanguage, postgres, r2, readMigrations, redisKv, resolveD1Database, resolveNotFound, resolveRequestLocale, scanAgentDir, scanRoutes, sqlite, startDevServer, staticSite, turso, typesApp, vercel, workers, wranglerD1 };
package/dist/index.js CHANGED
@@ -1,15 +1,21 @@
1
1
  import { deno, staticSite, vercel, workers } from "./adapter.js";
2
+ import { AGENT_MODULE_FILE, emitAgentModule, findAgentDir, generateAgentModule, scanAgentDir } from "./agent-compile.js";
2
3
  import { listRoutes, matchRoute, matchRouteTree, resolveNotFound } from "./router.js";
4
+ import { scanRoutes } from "./route-scan.js";
3
5
  import { negotiate } from "./negotiate.js";
4
6
  import { createPipeline } from "./pipeline.js";
5
7
  import { d1 } from "./d1.js";
6
8
  import { bindWorkerResources, memoizeResources } from "./resources.js";
7
- import { createApp } from "./app.js";
8
9
  import { localBlob, r2 } from "./blob.js";
10
+ import { createApp } from "./app.js";
9
11
  import { loadJuneConfig } from "./config-loader.js";
12
+ import { freezeConfig } from "./config-freeze.js";
10
13
  import { collection, entry } from "./content.js";
14
+ import { generateContent } from "./content-freeze.js";
11
15
  import { createWorker } from "./worker.js";
12
- import { buildManifest, freezeConfig, generateContent, juneBuild, scanRoutes } from "./build.js";
16
+ import { buildManifest } from "./manifest.js";
17
+ import { juneBuild } from "./build.js";
18
+ import { betterAuthAccessToken, betterAuthAccountTokenStore, linkedAccountAuth } from "./connection-auth.js";
13
19
  import { blockedMessage, classify, migrate, migrateApp, readMigrations, typesApp } from "./migrate.js";
14
20
  import { migrateD1, resolveD1Database, wranglerD1 } from "./d1-migrate.js";
15
21
  import { postgres } from "./postgres-driver.js";
@@ -24,4 +30,4 @@ import { memoryKv, redisKv } from "./kv.js";
24
30
  import { blob, currentServices, db, kv } from "@junejs/db";
25
31
  import { defineServices } from "@junejs/core/config";
26
32
  import { LOCALE_COOKIE, dirForLang, localeDir, localeHref, matchPinnedLocale, negotiateLocale, parseAcceptLanguage, resolveRequestLocale } from "@junejs/core/i18n";
27
- export { LOCALE_COOKIE, bindWorkerResources, blob, blockedMessage, buildManifest, classify, collection, createApp, createPipeline, createWorker, currentServices, d1, db, defineServices, deno, dirForLang, entry, freezeConfig, generateContent, host, installAsyncContext, juneBuild, juneDeploy, kv, listRoutes, loadJuneConfig, localBlob, localeDir, localeHref, matchPinnedLocale, matchRoute, matchRouteTree, memoizeResources, memoryKv, migrate, migrateApp, migrateD1, mysql, negotiate, negotiateLocale, parseAcceptLanguage, postgres, r2, readMigrations, redisKv, resolveD1Database, resolveNotFound, resolveRequestLocale, scanRoutes, sqlite, startDevServer, staticSite, turso, typesApp, vercel, workers, wranglerD1 };
33
+ export { AGENT_MODULE_FILE, LOCALE_COOKIE, betterAuthAccessToken, betterAuthAccountTokenStore, bindWorkerResources, blob, blockedMessage, buildManifest, classify, collection, createApp, createPipeline, createWorker, currentServices, d1, db, defineServices, deno, dirForLang, emitAgentModule, entry, findAgentDir, freezeConfig, generateAgentModule, generateContent, host, installAsyncContext, juneBuild, juneDeploy, kv, linkedAccountAuth, listRoutes, loadJuneConfig, localBlob, localeDir, localeHref, matchPinnedLocale, matchRoute, matchRouteTree, memoizeResources, memoryKv, migrate, migrateApp, migrateD1, mysql, negotiate, negotiateLocale, parseAcceptLanguage, postgres, r2, readMigrations, redisKv, resolveD1Database, resolveNotFound, resolveRequestLocale, scanAgentDir, scanRoutes, sqlite, startDevServer, staticSite, turso, typesApp, vercel, workers, wranglerD1 };
@@ -1,4 +1,3 @@
1
1
  //#region src/instrumentation.d.ts
2
- declare function installAsyncContext(): Promise<boolean>;
3
- //#endregion
4
- export { installAsyncContext };
2
+ export declare function installAsyncContext(): Promise<boolean>;
3
+ //#endregion
@@ -4,7 +4,8 @@ let installed = false;
4
4
  async function installAsyncContext() {
5
5
  if (installed) return true;
6
6
  try {
7
- installTraceContext(new (await (import("node:async_hooks"))).AsyncLocalStorage());
7
+ const mod = await import("node:async_hooks");
8
+ installTraceContext(new mod.AsyncLocalStorage());
8
9
  installed = true;
9
10
  return true;
10
11
  } catch {
@@ -1,8 +1,7 @@
1
1
  //#region src/island-registry.d.ts
2
- declare const ISLAND_REGISTRY_FILE = "_islands.gen.ts";
3
- declare function walk(dir: string): string[];
4
- declare function firstStatementIsDirective(src: string, directive: string): boolean;
5
- declare function exportNames(src: string): string[];
6
- declare function generateIslandRegistry(appDir: string): Promise<number>;
7
- //#endregion
8
- export { ISLAND_REGISTRY_FILE, exportNames, firstStatementIsDirective, generateIslandRegistry, walk };
2
+ export declare const ISLAND_REGISTRY_FILE = "_islands.gen.ts";
3
+ export declare function walk(dir: string): string[];
4
+ export declare function firstStatementIsDirective(src: string, directive: string): boolean;
5
+ export declare function exportNames(src: string): string[];
6
+ export declare function generateIslandRegistry(appDir: string): Promise<number>;
7
+ //#endregion
@@ -0,0 +1,5 @@
1
+ //#region src/isolate-local.d.ts
2
+ export type IsolateLocal = <T>(key: string | symbol, make: () => T) => T;
3
+ export declare function makeIsolateLocalFallback(): IsolateLocal;
4
+ export declare const isolateLocal: IsolateLocal;
5
+ //#endregion
@@ -0,0 +1,12 @@
1
+ import * as juneDb from "@junejs/db";
2
+ //#region src/isolate-local.ts
3
+ function makeIsolateLocalFallback() {
4
+ const values = /* @__PURE__ */ new Map();
5
+ return (key, make) => {
6
+ if (!values.has(key)) values.set(key, make());
7
+ return values.get(key);
8
+ };
9
+ }
10
+ const isolateLocal = juneDb.isolateLocal ?? makeIsolateLocalFallback();
11
+ //#endregion
12
+ export { isolateLocal, makeIsolateLocalFallback };
package/dist/kv.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { KvFactory } from "@junejs/core/resources";
2
2
  //#region src/kv.d.ts
3
- declare function memoryKv(): KvFactory;
4
- declare function redisKv(opts: {
3
+ export declare function memoryKv(): KvFactory;
4
+ export declare function redisKv(opts: {
5
5
  url: string;
6
6
  }): KvFactory;
7
- //#endregion
8
- export { memoryKv, redisKv };
7
+ //#endregion
@@ -0,0 +1,9 @@
1
+ import { u as RouteResolver } from "./pipeline-BHUjBO0G.js";
2
+ import { LlmsLink, SitemapPage } from "@junejs/core/discovery";
3
+ //#region src/llms-links.d.ts
4
+ export declare function collectLlmsLinks(origin: string, routes: string[], resolve: RouteResolver): Promise<LlmsLink[]>;
5
+ export declare function collectSitemapPages(routes: string[], resolve: RouteResolver, opts?: {
6
+ i18n?: boolean;
7
+ staticPaths?: boolean;
8
+ }): Promise<SitemapPage[]>;
9
+ //#endregion
@@ -0,0 +1,65 @@
1
+ //#region src/llms-links.ts
2
+ const DEFAULT_SECTION = "Pages";
3
+ const mdPath = (path) => path === "/" ? "/index.md" : `${path.replace(/\/+$/, "")}.md`;
4
+ async function collectLlmsLinks(origin, routes, resolve) {
5
+ const links = [];
6
+ const seen = /* @__PURE__ */ new Set();
7
+ for (const route of routes) {
8
+ const resolved = await resolve(route);
9
+ if (!resolved || !("def" in resolved)) continue;
10
+ const { def } = resolved;
11
+ if (def.llms === false) continue;
12
+ const dynamic = route.includes("[");
13
+ const declared = typeof def.llms === "function" ? await def.llms() : def.llms;
14
+ const entries = declared ? Array.isArray(declared) ? declared : [declared] : dynamic ? [] : [{}];
15
+ const meta = typeof def.metadata === "object" ? def.metadata : void 0;
16
+ for (const entry of entries) {
17
+ const path = entry.path ?? (dynamic ? void 0 : route);
18
+ if (!path) continue;
19
+ const url = origin + (def.md === false ? path : mdPath(path));
20
+ if (seen.has(url)) continue;
21
+ seen.add(url);
22
+ const own = path === route;
23
+ links.push({
24
+ title: entry.title ?? (own ? meta?.title : void 0) ?? path,
25
+ url,
26
+ description: entry.description ?? (own ? meta?.description : void 0),
27
+ section: entry.section ?? DEFAULT_SECTION,
28
+ optional: entry.optional === true
29
+ });
30
+ }
31
+ }
32
+ return links;
33
+ }
34
+ async function collectSitemapPages(routes, resolve, opts = {}) {
35
+ const pages = /* @__PURE__ */ new Map();
36
+ const add = (path, lastModified) => {
37
+ const key = path === "/" ? "/" : path.replace(/\/+$/, "");
38
+ const prev = pages.get(key);
39
+ if (!prev) pages.set(key, lastModified ? {
40
+ path: key,
41
+ lastModified
42
+ } : { path: key });
43
+ else if (lastModified && !prev.lastModified) prev.lastModified = lastModified;
44
+ };
45
+ for (const route of routes) {
46
+ const resolved = await resolve(route);
47
+ if (!resolved || !("def" in resolved)) continue;
48
+ const { def } = resolved;
49
+ const dynamic = route.includes("[");
50
+ const declared = def.llms ? typeof def.llms === "function" ? await def.llms() : def.llms : void 0;
51
+ const entries = declared ? Array.isArray(declared) ? declared : [declared] : [];
52
+ if (!dynamic) {
53
+ add(route, entries.find((e) => (e.path ?? route) === route)?.lastModified);
54
+ continue;
55
+ }
56
+ for (const e of entries) if (e.path) add(e.path, e.lastModified);
57
+ if (opts.staticPaths && !opts.i18n && def.staticPaths) {
58
+ const sp = typeof def.staticPaths === "function" ? await def.staticPaths() : def.staticPaths;
59
+ for (const p of sp) add(p);
60
+ }
61
+ }
62
+ return [...pages.values()];
63
+ }
64
+ //#endregion
65
+ export { collectLlmsLinks, collectSitemapPages };
@@ -0,0 +1,11 @@
1
+ import { n as LayoutComponent } from "./pipeline-BHUjBO0G.js";
2
+ import { n as WorkerManifest } from "./worker-2qbQjj2c.js";
3
+ //#region src/manifest.d.ts
4
+ type ImportedLayout = {
5
+ component: LayoutComponent;
6
+ boundary: boolean;
7
+ };
8
+ declare function importLayout(file: string): Promise<ImportedLayout | null>;
9
+ declare function buildManifest(appRoot: string): Promise<WorkerManifest>;
10
+ //#endregion
11
+ export { buildManifest as n, importLayout as r, ImportedLayout as t };
@@ -0,0 +1,2 @@
1
+ import { n as buildManifest, r as importLayout, t as ImportedLayout } from "./manifest-CwTT1zVs.js";
2
+ export { ImportedLayout, buildManifest, importLayout };