@junejs/server 1.0.0-dev.29 → 1.0.0-dev.36

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 (75) hide show
  1. package/dist/agent-compile.d.ts +8 -9
  2. package/dist/agent-discover.d.ts +3 -4
  3. package/dist/agent-durable.d.ts +20 -19
  4. package/dist/agent-durable.js +41 -6
  5. package/dist/agent-native.d.ts +10 -11
  6. package/dist/agent-native.js +6 -2
  7. package/dist/app.d.ts +4 -5
  8. package/dist/app.js +2 -1
  9. package/dist/blob.d.ts +4 -5
  10. package/dist/build.d.ts +6 -6
  11. package/dist/build.js +34 -7
  12. package/dist/client-bundle.d.ts +8 -9
  13. package/dist/{config-freeze-DwI-Rmvq.d.ts → config-freeze-ZWC_Qd4h.d.ts} +1 -1
  14. package/dist/config-freeze.d.ts +1 -1
  15. package/dist/config-loader.d.ts +3 -4
  16. package/dist/connection-auth.d.ts +8 -9
  17. package/dist/content.d.ts +9 -10
  18. package/dist/core-version.d.ts +3 -4
  19. package/dist/css-modules-ambient.d.ts +2 -1
  20. package/dist/css-modules.d.ts +10 -11
  21. package/dist/css.d.ts +9 -10
  22. package/dist/d1-migrate.d.ts +6 -7
  23. package/dist/d1-migrate.js +3 -2
  24. package/dist/db.d.ts +2 -2
  25. package/dist/deploy.d.ts +3 -4
  26. package/dist/deploy.js +3 -2
  27. package/dist/dev-reload.d.ts +3 -4
  28. package/dist/dev.d.ts +4 -5
  29. package/dist/favicon.d.ts +16 -17
  30. package/dist/host.d.ts +5 -5
  31. package/dist/icon-letter.d.ts +2 -3
  32. package/dist/index.d.ts +4 -4
  33. package/dist/instrumentation.d.ts +2 -3
  34. package/dist/instrumentation.js +2 -1
  35. package/dist/island-registry.d.ts +6 -7
  36. package/dist/isolate-local.d.ts +4 -5
  37. package/dist/kv.d.ts +3 -4
  38. package/dist/llms-links.d.ts +8 -5
  39. package/dist/llms-links.js +31 -1
  40. package/dist/{manifest-gcNWqWoI.d.ts → manifest-DSNX4I-G.d.ts} +2 -2
  41. package/dist/manifest.d.ts +1 -1
  42. package/dist/negotiate.d.ts +4 -3
  43. package/dist/negotiate.js +24 -14
  44. package/dist/{pipeline-cCR6MGNK.d.ts → pipeline-BHUjBO0G.d.ts} +5 -1
  45. package/dist/pipeline.d.ts +2 -2
  46. package/dist/pipeline.js +260 -41
  47. package/dist/resources.d.ts +5 -6
  48. package/dist/router.d.ts +12 -13
  49. package/dist/rsc-build.d.ts +6 -7
  50. package/dist/rsc-bundle.d.ts +6 -7
  51. package/dist/rsc-manifest.d.ts +5 -6
  52. package/dist/rsc-runtime/flight-render-routes.d.ts +3 -4
  53. package/dist/rsc-runtime/flight-render.d.ts +2 -3
  54. package/dist/rsc-runtime/flight-to-html.d.ts +2 -3
  55. package/dist/rsc-runtime/flight-to-html.js +3 -2
  56. package/dist/rsc-runtime/rsdw-shims.d.ts +2 -1
  57. package/dist/segment.d.ts +4 -5
  58. package/dist/sqlite-driver.d.ts +10 -11
  59. package/dist/static-files.d.ts +4 -5
  60. package/dist/tsconfig-jsx.d.ts +4 -5
  61. package/dist/turn-events.d.ts +2 -3
  62. package/dist/web-manifest.d.ts +3 -4
  63. package/dist/web-manifest.js +2 -6
  64. package/dist/{worker-BkFHGtxp.d.ts → worker-Dv4l6Ybs.d.ts} +4 -2
  65. package/dist/worker.d.ts +1 -1
  66. package/dist/worker.js +35 -18
  67. package/package.json +5 -5
  68. package/src/agent-durable.ts +39 -10
  69. package/src/agent-native.ts +5 -1
  70. package/src/build.ts +63 -5
  71. package/src/llms-links.ts +46 -1
  72. package/src/negotiate.ts +39 -15
  73. package/src/pipeline.ts +433 -45
  74. package/src/web-manifest.ts +2 -6
  75. package/src/worker.ts +55 -17
@@ -2,17 +2,13 @@
2
2
  // Home Screen" name, icons, and colours, built from the same config the
3
3
  // document renders with. Worker-safe (no node:*): the pipeline serves it like
4
4
  // the SVG favicon, so dev, the worker, and the static build all agree.
5
+ import { siteShortName } from "@junejs/core/config";
5
6
  import { resolveThemeColor, type DocumentConfig } from "@junejs/core/document";
6
7
 
7
8
  // The home-screen label: site.shortName, else the site name's leading segment
8
9
  // ("June — build agents into real apps" → "June"). Launchers truncate past
9
10
  // ~12 characters, and a tagline is never the label anyone wants.
10
- export function shortName(site: DocumentConfig["site"]): string | undefined {
11
- if (site.shortName) return site.shortName;
12
- const name = site.name?.trim();
13
- if (!name) return undefined;
14
- return name.split(/\s+[—–|-]\s+|:\s+/)[0]!.trim() || name;
15
- }
11
+ export const shortName = (site: DocumentConfig["site"]): string | undefined => siteShortName(site);
16
12
 
17
13
  export function webManifest(config: DocumentConfig): string {
18
14
  const base = config.basePath ?? "";
package/src/worker.ts CHANGED
@@ -21,6 +21,7 @@ import type { Channel, ChannelFactory } from "@junejs/core/agent-config";
21
21
 
22
22
  import { createPipeline, type ExtraHandler, type LayoutComponent, type LoadingComponent, type Resolved, type ResolvedResource, type ResourceHandler } from "./pipeline";
23
23
  import { durableAgentSurface, durableChannelSurface, type DurableObjectNamespace } from "./agent-durable";
24
+ import { acceptTarget } from "./negotiate";
24
25
  import { contentTypeFor, RESERVED_PREFIX, safeRelativePath } from "./static-files";
25
26
 
26
27
  // The slice of workerd's ExecutionContext the worker threads through: webhook
@@ -125,8 +126,11 @@ function compilePattern(pattern: string): { regex: RegExp; names: string[] } {
125
126
  return { regex: new RegExp(allOptional ? `^(?:${source}|/)$` : `^${source}$`), names };
126
127
  }
127
128
 
129
+ // opts.staticBuild: set only by the static() build's in-process prerender worker
130
+ // (see PipelineConfig.staticBuild) — never by a deployed entry.
128
131
  export function createWorker(
129
132
  manifest: WorkerManifest,
133
+ opts: { staticBuild?: boolean } = {},
130
134
  ): { fetch(request: Request, env?: unknown, ctx?: WorkerExecutionContext): Promise<Response> } {
131
135
  const dynamic: Compiled[] = (manifest.dynamicRoutes ?? []).map((d) => ({
132
136
  ...compilePattern(d.pattern),
@@ -212,6 +216,7 @@ export function createWorker(
212
216
  agentSurface,
213
217
  i18n: manifest.i18n,
214
218
  routeList: () => routeList,
219
+ staticBuild: opts.staticBuild,
215
220
  earlyHints: manifest.earlyHints,
216
221
  htmlCacheControl: manifest.htmlCacheControl,
217
222
  notFoundComponent: manifest.notFound,
@@ -282,7 +287,9 @@ export function createWorker(
282
287
  // --- the deployed worker's outermost layer (run_worker_first) ---------------
283
288
  // Prerendered pages are served as static ASSETS, which bypass the pipeline —
284
289
  // so the agent-ready signals the asset layer can't produce get added HERE:
285
- // 1. `Accept: text/markdown` on a page → the prerendered `.md` asset.
290
+ // 1. a negotiated projection on a page (Accept: text/markdown / application/
291
+ // json → the prerendered .md / .json asset; else, and for the client
292
+ // router's fragment, the pipeline — never the page's HTML asset).
286
293
  // 2. a `Link` header on every HTML response (RFC 8288/9727 discovery).
287
294
  // 3. `x-markdown-tokens` on markdown responses.
288
295
  // Static assets are served by the ASSETS binding (no re-render); only genuinely
@@ -293,6 +300,15 @@ type FetchPipeline = { fetch(request: Request, env?: unknown, ctx?: WorkerExecut
293
300
 
294
301
  const estimateTokens = (s: string) => String(Math.ceil(s.length / 4));
295
302
 
303
+ // Add Accept to a response's Vary, keeping whatever the asset layer already set.
304
+ function varyAccept(headers: Headers): void {
305
+ const vary = headers.get("vary");
306
+ if (!vary) headers.set("vary", "accept");
307
+ else if (vary.trim() !== "*" && !vary.split(",").some((v) => v.trim().toLowerCase() === "accept")) {
308
+ headers.set("vary", `${vary}, accept`);
309
+ }
310
+ }
311
+
296
312
  export function withAssets(
297
313
  pipeline: FetchPipeline,
298
314
  opts: { link?: string | null } = {},
@@ -302,23 +318,40 @@ export function withAssets(
302
318
  const assets = env?.ASSETS;
303
319
  const url = new URL(request.url);
304
320
  const isPagePath = !/\.[a-z0-9]+$/i.test(url.pathname); // no file extension
305
- const accept = request.headers.get("accept") ?? "";
321
+ // The pipeline's own Accept decision (q-values included). A page path that
322
+ // negotiates a projection other than the HTML view must get THAT projection
323
+ // or the pipeline's answer for it — never the prerendered HTML asset.
324
+ const target = isPagePath ? acceptTarget(request.headers.get("accept") ?? "") : null;
306
325
 
307
- // 1. Markdown content negotiation on a page path → prerendered .md asset.
308
- if (assets && request.method === "GET" && isPagePath && /text\/markdown/.test(accept)) {
309
- const base = url.pathname === "/" ? "/index" : url.pathname.replace(/\/+$/, "");
310
- const mdUrl = new URL(url);
311
- mdUrl.pathname = `${base}.md`;
312
- const a = await assets.fetch(new Request(mdUrl.toString(), { headers: request.headers }));
313
- if (a.ok) {
314
- const body = await a.text();
315
- const headers = new Headers(a.headers);
316
- headers.set("content-type", "text/markdown; charset=utf-8");
317
- headers.set("x-markdown-tokens", estimateTokens(body));
318
- if (opts.link) headers.set("link", opts.link);
319
- return new Response(body, { status: 200, headers });
326
+ // 1. Negotiated projections on a page path.
327
+ if (target && (request.method === "GET" || request.method === "HEAD")) {
328
+ // md / json → the prerendered <path>.md / <path>.json asset when the build
329
+ // emitted one (.md unless md = false; .json only for a json() route). Only
330
+ // the flat file — never <path>/index.*, a distinct /path/index route's twin
331
+ // (locale homes' <locale>/index.* are a static()-target artifact; this
332
+ // workers()-only layer never has them).
333
+ if (assets && request.method === "GET" && (target === "md" || target === "json")) {
334
+ const base = url.pathname === "/" ? "/index" : url.pathname.replace(/\/+$/, "");
335
+ const assetUrl = new URL(url);
336
+ assetUrl.pathname = `${base}.${target}`;
337
+ const a = await assets.fetch(new Request(assetUrl.toString(), { headers: request.headers }));
338
+ if (a.ok) {
339
+ const headers = new Headers(a.headers);
340
+ if (opts.link) headers.set("link", opts.link);
341
+ varyAccept(headers);
342
+ if (target === "json") return new Response(a.body, { status: 200, headers });
343
+ const body = await a.text();
344
+ headers.set("content-type", "text/markdown; charset=utf-8");
345
+ headers.set("x-markdown-tokens", estimateTokens(body));
346
+ return new Response(body, { status: 200, headers });
347
+ }
320
348
  }
321
- // no prerendered .md → fall through; a dynamic route renders it below.
349
+ // No such asset (or a fragment, or HEAD) → the pipeline (step 3). It renders
350
+ // a dynamic route's projection, derives .json from the loader data, 404s a
351
+ // disabled projection, and renders the client router's soft-nav fragment —
352
+ // the HTML asset is a full DOCUMENT, which the router would morph into its
353
+ // [data-june-root] as if it were the root's inner HTML.
354
+ return pipeline.fetch(request, env, ctx);
322
355
  }
323
356
 
324
357
  // 2. Static assets (prerendered HTML/.md/.json, /client.js, hashed CSS)
@@ -335,10 +368,15 @@ export function withAssets(
335
368
  // URL changes when the bytes do, so the browser may cache forever and
336
369
  // never revalidate (no 304 round-trip, no stale window).
337
370
  const immutable = /\.[a-f0-9]{8,}\.(css|js)$/.test(url.pathname);
338
- if (addLink || immutable) {
371
+ // A page path answers HTML here but Markdown under Accept: text/markdown
372
+ // (step 1) — the same URL, so caches must key on Accept or they hand an
373
+ // agent the HTML (or a browser the Markdown).
374
+ const negotiated = isPagePath && ct.includes("text/html");
375
+ if (addLink || immutable || negotiated) {
339
376
  const headers = new Headers(a.headers);
340
377
  if (addLink) headers.set("link", opts.link!);
341
378
  if (immutable) headers.set("cache-control", "public, max-age=31536000, immutable");
379
+ if (negotiated) varyAccept(headers);
342
380
  return new Response(a.body, { status: a.status, headers });
343
381
  }
344
382
  return a;