@pyreon/zero 0.5.0 → 0.11.0

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 (110) hide show
  1. package/lib/cache.js.map +1 -1
  2. package/lib/client.js.map +1 -1
  3. package/lib/config.js.map +1 -1
  4. package/lib/font.js.map +1 -1
  5. package/lib/fs-router-BkbIWqek.js.map +1 -1
  6. package/lib/fs-router-n4VA4lxu.js.map +1 -1
  7. package/lib/image-plugin.js.map +1 -1
  8. package/lib/image.js +1 -1
  9. package/lib/image.js.map +1 -1
  10. package/lib/index.js +1 -1
  11. package/lib/index.js.map +1 -1
  12. package/lib/link.js +1 -1
  13. package/lib/link.js.map +1 -1
  14. package/lib/script.js +1 -1
  15. package/lib/script.js.map +1 -1
  16. package/lib/seo.js.map +1 -1
  17. package/lib/theme.js +1 -1
  18. package/lib/theme.js.map +1 -1
  19. package/package.json +14 -13
  20. package/src/actions.ts +20 -28
  21. package/src/adapters/bun.ts +7 -7
  22. package/src/adapters/index.ts +12 -14
  23. package/src/adapters/node.ts +8 -11
  24. package/src/adapters/static.ts +3 -3
  25. package/src/api-routes.ts +23 -50
  26. package/src/app.ts +9 -13
  27. package/src/cache.ts +16 -29
  28. package/src/client.ts +8 -8
  29. package/src/compression.ts +21 -28
  30. package/src/config.ts +6 -7
  31. package/src/cors.ts +20 -28
  32. package/src/entry-server.ts +15 -19
  33. package/src/error-overlay.ts +10 -13
  34. package/src/font.ts +44 -55
  35. package/src/fs-router.ts +44 -63
  36. package/src/image-plugin.ts +53 -79
  37. package/src/image.tsx +39 -41
  38. package/src/index.ts +36 -36
  39. package/src/isr.ts +8 -8
  40. package/src/link.tsx +27 -30
  41. package/src/rate-limit.ts +15 -15
  42. package/src/script.tsx +21 -22
  43. package/src/seo.ts +47 -57
  44. package/src/sharp.d.ts +2 -6
  45. package/src/testing.ts +8 -12
  46. package/src/theme.tsx +18 -20
  47. package/src/types.ts +6 -6
  48. package/src/utils/use-intersection-observer.ts +2 -2
  49. package/src/utils/with-headers.ts +1 -4
  50. package/src/vite-plugin.ts +21 -28
  51. package/lib/types/actions.d.ts +0 -57
  52. package/lib/types/actions.d.ts.map +0 -1
  53. package/lib/types/adapters/bun.d.ts +0 -6
  54. package/lib/types/adapters/bun.d.ts.map +0 -1
  55. package/lib/types/adapters/index.d.ts +0 -10
  56. package/lib/types/adapters/index.d.ts.map +0 -1
  57. package/lib/types/adapters/node.d.ts +0 -6
  58. package/lib/types/adapters/node.d.ts.map +0 -1
  59. package/lib/types/adapters/static.d.ts +0 -7
  60. package/lib/types/adapters/static.d.ts.map +0 -1
  61. package/lib/types/api-routes.d.ts +0 -66
  62. package/lib/types/api-routes.d.ts.map +0 -1
  63. package/lib/types/app.d.ts +0 -24
  64. package/lib/types/app.d.ts.map +0 -1
  65. package/lib/types/cache.d.ts +0 -54
  66. package/lib/types/cache.d.ts.map +0 -1
  67. package/lib/types/client.d.ts +0 -19
  68. package/lib/types/client.d.ts.map +0 -1
  69. package/lib/types/compression.d.ts +0 -33
  70. package/lib/types/compression.d.ts.map +0 -1
  71. package/lib/types/config.d.ts +0 -18
  72. package/lib/types/config.d.ts.map +0 -1
  73. package/lib/types/cors.d.ts +0 -32
  74. package/lib/types/cors.d.ts.map +0 -1
  75. package/lib/types/entry-server.d.ts +0 -34
  76. package/lib/types/entry-server.d.ts.map +0 -1
  77. package/lib/types/error-overlay.d.ts +0 -6
  78. package/lib/types/error-overlay.d.ts.map +0 -1
  79. package/lib/types/font.d.ts +0 -119
  80. package/lib/types/font.d.ts.map +0 -1
  81. package/lib/types/fs-router.d.ts +0 -38
  82. package/lib/types/fs-router.d.ts.map +0 -1
  83. package/lib/types/image-plugin.d.ts +0 -79
  84. package/lib/types/image-plugin.d.ts.map +0 -1
  85. package/lib/types/image.d.ts +0 -51
  86. package/lib/types/image.d.ts.map +0 -1
  87. package/lib/types/index.d.ts +0 -37
  88. package/lib/types/index.d.ts.map +0 -1
  89. package/lib/types/isr.d.ts +0 -9
  90. package/lib/types/isr.d.ts.map +0 -1
  91. package/lib/types/link.d.ts +0 -116
  92. package/lib/types/link.d.ts.map +0 -1
  93. package/lib/types/rate-limit.d.ts +0 -34
  94. package/lib/types/rate-limit.d.ts.map +0 -1
  95. package/lib/types/script.d.ts +0 -35
  96. package/lib/types/script.d.ts.map +0 -1
  97. package/lib/types/seo.d.ts +0 -88
  98. package/lib/types/seo.d.ts.map +0 -1
  99. package/lib/types/testing.d.ts +0 -85
  100. package/lib/types/testing.d.ts.map +0 -1
  101. package/lib/types/theme.d.ts +0 -39
  102. package/lib/types/theme.d.ts.map +0 -1
  103. package/lib/types/types.d.ts +0 -109
  104. package/lib/types/types.d.ts.map +0 -1
  105. package/lib/types/utils/use-intersection-observer.d.ts +0 -10
  106. package/lib/types/utils/use-intersection-observer.d.ts.map +0 -1
  107. package/lib/types/utils/with-headers.d.ts +0 -6
  108. package/lib/types/utils/with-headers.d.ts.map +0 -1
  109. package/lib/types/vite-plugin.d.ts +0 -17
  110. package/lib/types/vite-plugin.d.ts.map +0 -1
package/src/testing.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { Middleware, MiddlewareContext } from '@pyreon/server'
2
- import type { ApiHandler, ApiRouteEntry } from './api-routes'
3
- import { createApiMiddleware } from './api-routes'
1
+ import type { Middleware, MiddlewareContext } from "@pyreon/server"
2
+ import type { ApiHandler, ApiRouteEntry } from "./api-routes"
3
+ import { createApiMiddleware } from "./api-routes"
4
4
 
5
5
  // ─── Test helpers for Zero applications ─────────────────────────────────────
6
6
 
@@ -21,14 +21,14 @@ export function createTestContext(
21
21
  body?: unknown
22
22
  } = {},
23
23
  ): MiddlewareContext {
24
- const { method = 'GET', headers = {}, body } = options
24
+ const { method = "GET", headers = {}, body } = options
25
25
  const url = new URL(`http://localhost${path}`)
26
26
 
27
27
  const requestHeaders: Record<string, string> = { ...headers }
28
28
  let requestBody: string | undefined
29
29
 
30
30
  if (body !== undefined) {
31
- requestHeaders['Content-Type'] = 'application/json'
31
+ requestHeaders["Content-Type"] = "application/json"
32
32
  requestBody = JSON.stringify(body)
33
33
  }
34
34
 
@@ -107,7 +107,7 @@ export function createTestApiServer(routes: ApiRouteEntry[]) {
107
107
  const ctx = createTestContext(path, options)
108
108
  const result = await middleware(ctx)
109
109
  if (!result) {
110
- return new Response('Not Found', { status: 404 })
110
+ return new Response("Not Found", { status: 404 })
111
111
  }
112
112
  return result
113
113
  },
@@ -127,11 +127,7 @@ export function createTestApiServer(routes: ApiRouteEntry[]) {
127
127
  * expect(handler.calls[0].params).toEqual({ id: "123" })
128
128
  */
129
129
  export function createMockHandler(
130
- responseConfig: {
131
- status?: number
132
- body?: unknown
133
- headers?: Record<string, string>
134
- } = {},
130
+ responseConfig: { status?: number; body?: unknown; headers?: Record<string, string> } = {},
135
131
  ): ApiHandler & {
136
132
  calls: Array<{ path: string; params: Record<string, string> }>
137
133
  } {
@@ -142,7 +138,7 @@ export function createMockHandler(
142
138
  calls.push({ path: ctx.path, params: ctx.params })
143
139
  return new Response(JSON.stringify(body), {
144
140
  status,
145
- headers: { 'Content-Type': 'application/json', ...headers },
141
+ headers: { "Content-Type": "application/json", ...headers },
146
142
  })
147
143
  }
148
144
 
package/src/theme.tsx CHANGED
@@ -1,6 +1,6 @@
1
- import type { VNodeChild } from '@pyreon/core'
2
- import { onMount, onUnmount } from '@pyreon/core'
3
- import { effect, signal } from '@pyreon/reactivity'
1
+ import type { VNodeChild } from "@pyreon/core"
2
+ import { onMount, onUnmount } from "@pyreon/core"
3
+ import { effect, signal } from "@pyreon/reactivity"
4
4
 
5
5
  // ─── Theme system ───────────────────────────────────────────────────────────
6
6
  //
@@ -10,21 +10,19 @@ import { effect, signal } from '@pyreon/reactivity'
10
10
  // - No flash of wrong theme (inline script in HTML)
11
11
  // - Reactive theme signal for components
12
12
 
13
- export type Theme = 'light' | 'dark' | 'system'
13
+ export type Theme = "light" | "dark" | "system"
14
14
 
15
- const STORAGE_KEY = 'zero-theme'
15
+ const STORAGE_KEY = "zero-theme"
16
16
 
17
17
  /** Reactive theme signal. */
18
- export const theme = signal<Theme>('system')
18
+ export const theme = signal<Theme>("system")
19
19
 
20
20
  /** Computed resolved theme (what's actually applied). */
21
- export function resolvedTheme(): 'light' | 'dark' {
21
+ export function resolvedTheme(): "light" | "dark" {
22
22
  const t = theme()
23
- if (t === 'system') {
24
- if (typeof window === 'undefined') return 'dark'
25
- return window.matchMedia('(prefers-color-scheme: dark)').matches
26
- ? 'dark'
27
- : 'light'
23
+ if (t === "system") {
24
+ if (typeof window === "undefined") return "dark"
25
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"
28
26
  }
29
27
  return t
30
28
  }
@@ -32,13 +30,13 @@ export function resolvedTheme(): 'light' | 'dark' {
32
30
  /** Toggle between light and dark. */
33
31
  export function toggleTheme() {
34
32
  const current = resolvedTheme()
35
- setTheme(current === 'dark' ? 'light' : 'dark')
33
+ setTheme(current === "dark" ? "light" : "dark")
36
34
  }
37
35
 
38
36
  /** Set theme explicitly. */
39
37
  export function setTheme(t: Theme) {
40
38
  theme.set(t)
41
- if (typeof document !== 'undefined') {
39
+ if (typeof document !== "undefined") {
42
40
  document.documentElement.dataset.theme = resolvedTheme()
43
41
  try {
44
42
  localStorage.setItem(STORAGE_KEY, t)
@@ -57,7 +55,7 @@ export function initTheme() {
57
55
  // Read persisted preference
58
56
  try {
59
57
  const stored = localStorage.getItem(STORAGE_KEY) as Theme | null
60
- if (stored === 'light' || stored === 'dark' || stored === 'system') {
58
+ if (stored === "light" || stored === "dark" || stored === "system") {
61
59
  theme.set(stored)
62
60
  }
63
61
  } catch {
@@ -68,14 +66,14 @@ export function initTheme() {
68
66
  document.documentElement.dataset.theme = resolvedTheme()
69
67
 
70
68
  // Watch for system preference changes
71
- const mq = window.matchMedia('(prefers-color-scheme: dark)')
69
+ const mq = window.matchMedia("(prefers-color-scheme: dark)")
72
70
  function onChange() {
73
- if (theme() === 'system') {
71
+ if (theme() === "system") {
74
72
  document.documentElement.dataset.theme = resolvedTheme()
75
73
  }
76
74
  }
77
- mq.addEventListener('change', onChange)
78
- onUnmount(() => mq.removeEventListener('change', onChange))
75
+ mq.addEventListener("change", onChange)
76
+ onUnmount(() => mq.removeEventListener("change", onChange))
79
77
 
80
78
  // Re-apply when theme signal changes
81
79
  const dispose = effect(() => {
@@ -107,7 +105,7 @@ export function ThemeToggle(props: { class?: string; style?: string }): VNodeChi
107
105
  type="button"
108
106
  >
109
107
  {() =>
110
- resolvedTheme() === 'dark' ? (
108
+ resolvedTheme() === "dark" ? (
111
109
  <svg
112
110
  width="18"
113
111
  height="18"
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { ComponentFn } from '@pyreon/core'
2
- import type { NavigationGuard } from '@pyreon/router'
3
- import type { Middleware } from '@pyreon/server'
1
+ import type { ComponentFn } from "@pyreon/core"
2
+ import type { NavigationGuard } from "@pyreon/router"
3
+ import type { Middleware } from "@pyreon/server"
4
4
 
5
5
  // ─── Route module conventions ────────────────────────────────────────────────
6
6
 
@@ -43,7 +43,7 @@ export interface RouteMeta {
43
43
 
44
44
  // ─── Rendering modes ─────────────────────────────────────────────────────────
45
45
 
46
- export type RenderMode = 'ssr' | 'ssg' | 'spa' | 'isr'
46
+ export type RenderMode = "ssr" | "ssg" | "spa" | "isr"
47
47
 
48
48
  export interface ISRConfig {
49
49
  /** Revalidation interval in seconds. */
@@ -62,7 +62,7 @@ export interface ZeroConfig {
62
62
  /** SSR options. */
63
63
  ssr?: {
64
64
  /** Streaming mode. Default: "string" */
65
- mode?: 'string' | 'stream'
65
+ mode?: "string" | "stream"
66
66
  }
67
67
 
68
68
  /** SSG options — only used when mode is "ssg". */
@@ -75,7 +75,7 @@ export interface ZeroConfig {
75
75
  isr?: ISRConfig
76
76
 
77
77
  /** Deploy adapter. Default: "node" */
78
- adapter?: 'node' | 'bun' | 'static'
78
+ adapter?: "node" | "bun" | "static"
79
79
 
80
80
  /** Base URL path. Default: "/" */
81
81
  base?: string
@@ -1,4 +1,4 @@
1
- import { onMount, onUnmount } from '@pyreon/core'
1
+ import { onMount, onUnmount } from "@pyreon/core"
2
2
 
3
3
  /**
4
4
  * Observes an element and calls `onIntersect` once it enters the viewport.
@@ -11,7 +11,7 @@ import { onMount, onUnmount } from '@pyreon/core'
11
11
  export function useIntersectionObserver(
12
12
  getElement: () => HTMLElement | undefined,
13
13
  onIntersect: () => void,
14
- rootMargin = '200px',
14
+ rootMargin = "200px",
15
15
  ) {
16
16
  onMount(() => {
17
17
  const el = getElement()
@@ -2,10 +2,7 @@
2
2
  * Clone a Response with modified headers.
3
3
  * Avoids repeating the `new Response(body, { status, statusText, headers })` pattern.
4
4
  */
5
- export function withHeaders(
6
- response: Response,
7
- modify: (headers: Headers) => void,
8
- ): Response {
5
+ export function withHeaders(response: Response, modify: (headers: Headers) => void): Response {
9
6
  const headers = new Headers(response.headers)
10
7
  modify(headers)
11
8
  return new Response(response.body, {
@@ -1,21 +1,17 @@
1
- import type { Plugin } from 'vite'
2
- import { generateApiRouteModule } from './api-routes'
3
- import { resolveConfig } from './config'
4
- import { renderErrorOverlay } from './error-overlay'
5
- import {
6
- generateMiddlewareModule,
7
- generateRouteModule,
8
- scanRouteFiles,
9
- } from './fs-router'
10
- import type { ZeroConfig } from './types'
11
-
12
- const VIRTUAL_ROUTES_ID = 'virtual:zero/routes'
1
+ import type { Plugin } from "vite"
2
+ import { generateApiRouteModule } from "./api-routes"
3
+ import { resolveConfig } from "./config"
4
+ import { renderErrorOverlay } from "./error-overlay"
5
+ import { generateMiddlewareModule, generateRouteModule, scanRouteFiles } from "./fs-router"
6
+ import type { ZeroConfig } from "./types"
7
+
8
+ const VIRTUAL_ROUTES_ID = "virtual:zero/routes"
13
9
  const RESOLVED_VIRTUAL_ROUTES_ID = `\0${VIRTUAL_ROUTES_ID}`
14
10
 
15
- const VIRTUAL_MIDDLEWARE_ID = 'virtual:zero/route-middleware'
11
+ const VIRTUAL_MIDDLEWARE_ID = "virtual:zero/route-middleware"
16
12
  const RESOLVED_VIRTUAL_MIDDLEWARE_ID = `\0${VIRTUAL_MIDDLEWARE_ID}`
17
13
 
18
- const VIRTUAL_API_ROUTES_ID = 'virtual:zero/api-routes'
14
+ const VIRTUAL_API_ROUTES_ID = "virtual:zero/api-routes"
19
15
  const RESOLVED_VIRTUAL_API_ROUTES_ID = `\0${VIRTUAL_API_ROUTES_ID}`
20
16
 
21
17
  /**
@@ -37,8 +33,8 @@ export function zeroPlugin(userConfig: ZeroConfig = {}): Plugin {
37
33
  let root: string
38
34
 
39
35
  const plugin: Plugin & { _zeroConfig: ZeroConfig } = {
40
- name: 'pyreon-zero',
41
- enforce: 'pre',
36
+ name: "pyreon-zero",
37
+ enforce: "pre",
42
38
  _zeroConfig: userConfig,
43
39
 
44
40
  configResolved(resolvedConfig) {
@@ -86,8 +82,8 @@ export function zeroPlugin(userConfig: ZeroConfig = {}): Plugin {
86
82
  // This runs as a late middleware (return function) so it wraps
87
83
  // Vite's own SSR handling and catches rendering failures.
88
84
  server.middlewares.use((req, res, next) => {
89
- const accept = req.headers.accept ?? ''
90
- if (!accept.includes('text/html')) return next()
85
+ const accept = req.headers.accept ?? ""
86
+ if (!accept.includes("text/html")) return next()
91
87
 
92
88
  // Monkey-patch res.end to catch errors from SSR rendering
93
89
  const originalEnd = res.end.bind(res)
@@ -100,12 +96,12 @@ export function zeroPlugin(userConfig: ZeroConfig = {}): Plugin {
100
96
  server.ssrFixStacktrace(error)
101
97
  const html = renderErrorOverlay(error)
102
98
  res.statusCode = 500
103
- res.setHeader('Content-Type', 'text/html; charset=utf-8')
104
- res.setHeader('Content-Length', Buffer.byteLength(html))
99
+ res.setHeader("Content-Type", "text/html; charset=utf-8")
100
+ res.setHeader("Content-Length", Buffer.byteLength(html))
105
101
  originalEnd(html)
106
102
  }
107
103
 
108
- res.on('error', handleError)
104
+ res.on("error", handleError)
109
105
 
110
106
  // Wrap next() in try/catch to handle synchronous errors
111
107
  try {
@@ -119,11 +115,8 @@ export function zeroPlugin(userConfig: ZeroConfig = {}): Plugin {
119
115
  server.watcher.add(`${routesDir}/**/*.{tsx,jsx,ts,js}`)
120
116
 
121
117
  // Invalidate virtual modules when route files change
122
- server.watcher.on('all', (event, path) => {
123
- if (
124
- path.startsWith(routesDir) &&
125
- (event === 'add' || event === 'unlink')
126
- ) {
118
+ server.watcher.on("all", (event, path) => {
119
+ if (path.startsWith(routesDir) && (event === "add" || event === "unlink")) {
127
120
  for (const resolvedId of [
128
121
  RESOLVED_VIRTUAL_ROUTES_ID,
129
122
  RESOLVED_VIRTUAL_MIDDLEWARE_ID,
@@ -132,7 +125,7 @@ export function zeroPlugin(userConfig: ZeroConfig = {}): Plugin {
132
125
  const mod = server.moduleGraph.getModuleById(resolvedId)
133
126
  if (mod) server.moduleGraph.invalidateModule(mod)
134
127
  }
135
- server.ws.send({ type: 'full-reload' })
128
+ server.ws.send({ type: "full-reload" })
136
129
  }
137
130
  })
138
131
  },
@@ -140,7 +133,7 @@ export function zeroPlugin(userConfig: ZeroConfig = {}): Plugin {
140
133
  config() {
141
134
  return {
142
135
  resolve: {
143
- conditions: ['bun'],
136
+ conditions: ["bun"],
144
137
  },
145
138
  server: {
146
139
  port: config.port,
@@ -1,57 +0,0 @@
1
- import type { MiddlewareContext } from '@pyreon/server';
2
- /** Context passed to server action handlers. */
3
- export interface ActionContext {
4
- /** The original request. */
5
- request: Request;
6
- /** Parsed form data (for form submissions). */
7
- formData: FormData | null;
8
- /** Parsed JSON body (for JSON submissions). */
9
- json: unknown;
10
- /** Request headers. */
11
- headers: Headers;
12
- }
13
- /** A server action handler function. */
14
- export type ActionHandler<T = unknown> = (ctx: ActionContext) => T | Promise<T>;
15
- /** A registered action with its ID and handler. */
16
- interface RegisteredAction {
17
- id: string;
18
- handler: ActionHandler;
19
- }
20
- /** Client-side callable action returned by defineAction. */
21
- export interface Action<T = unknown> {
22
- /** Call the action with JSON data. */
23
- (data?: unknown): Promise<T>;
24
- /** The action's unique ID. */
25
- actionId: string;
26
- }
27
- /**
28
- * Define a server action. Returns a callable function that:
29
- * - On the **client**: sends a POST request to `/_zero/actions/<id>`
30
- * - On the **server** (SSR): executes the handler directly (no fetch)
31
- *
32
- * @example
33
- * // In a route file or module:
34
- * export const createPost = defineAction(async (ctx) => {
35
- * const data = ctx.json as { title: string; body: string }
36
- * // ... save to database
37
- * return { success: true, id: 123 }
38
- * })
39
- *
40
- * // In a component:
41
- * const result = await createPost({ title: 'Hello', body: '...' })
42
- */
43
- export declare function defineAction<T = unknown>(handler: ActionHandler<T>): Action<T>;
44
- /** Get all registered actions. Useful for testing. */
45
- export declare function getRegisteredActions(): Map<string, RegisteredAction>;
46
- /**
47
- * Reset the action registry. Useful for testing.
48
- * @internal
49
- */
50
- export declare function _resetActions(): void;
51
- /**
52
- * Create a middleware that handles action requests at `/_zero/actions/*`.
53
- * Mount this before the SSR handler in the server entry.
54
- */
55
- export declare function createActionMiddleware(): (ctx: MiddlewareContext) => Response | undefined | Promise<Response | undefined>;
56
- export {};
57
- //# sourceMappingURL=actions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAIvD,gDAAgD;AAChD,MAAM,WAAW,aAAa;IAC5B,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,+CAA+C;IAC/C,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IACzB,+CAA+C;IAC/C,IAAI,EAAE,OAAO,CAAA;IACb,uBAAuB;IACvB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wCAAwC;AACxC,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,GAAG,EAAE,aAAa,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AAE/E,mDAAmD;AACnD,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,aAAa,CAAA;CACvB;AAED,4DAA4D;AAC5D,MAAM,WAAW,MAAM,CAAC,CAAC,GAAG,OAAO;IACjC,sCAAsC;IACtC,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC5B,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAA;CACjB;AAOD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,OAAO,EACtC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GACxB,MAAM,CAAC,CAAC,CAAC,CAsCX;AAED,sDAAsD;AACtD,wBAAgB,oBAAoB,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAEpE;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAGpC;AAID;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,CACxC,GAAG,EAAE,iBAAiB,KACnB,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAiBxD"}
@@ -1,6 +0,0 @@
1
- import type { Adapter } from '../types';
2
- /**
3
- * Bun adapter — generates a standalone Bun.serve() entry.
4
- */
5
- export declare function bunAdapter(): Adapter;
6
- //# sourceMappingURL=bun.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bun.d.ts","sourceRoot":"","sources":["../../../src/adapters/bun.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAuB,MAAM,UAAU,CAAA;AAE5D;;GAEG;AACH,wBAAgB,UAAU,IAAI,OAAO,CA2DpC"}
@@ -1,10 +0,0 @@
1
- export { bunAdapter } from './bun';
2
- export { nodeAdapter } from './node';
3
- export { staticAdapter } from './static';
4
- import type { Adapter, ZeroConfig } from '../types';
5
- /**
6
- * Resolve the adapter from config.
7
- * Returns a built-in adapter or throws if unknown.
8
- */
9
- export declare function resolveAdapter(config: ZeroConfig): Adapter;
10
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAKnD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAe1D"}
@@ -1,6 +0,0 @@
1
- import type { Adapter } from '../types';
2
- /**
3
- * Node.js adapter — generates a standalone server entry using node:http.
4
- */
5
- export declare function nodeAdapter(): Adapter;
6
- //# sourceMappingURL=node.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/adapters/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAuB,MAAM,UAAU,CAAA;AAE5D;;GAEG;AACH,wBAAgB,WAAW,IAAI,OAAO,CA2GrC"}
@@ -1,7 +0,0 @@
1
- import type { Adapter } from '../types';
2
- /**
3
- * Static adapter — just copies the client build output.
4
- * Used with SSG mode where all pages are pre-rendered at build time.
5
- */
6
- export declare function staticAdapter(): Adapter;
7
- //# sourceMappingURL=static.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../../src/adapters/static.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAuB,MAAM,UAAU,CAAA;AAE5D;;;GAGG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAUvC"}
@@ -1,66 +0,0 @@
1
- import type { Middleware } from '@pyreon/server';
2
- /** HTTP methods supported by API routes. */
3
- export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
4
- /** Context passed to API route handlers. */
5
- export interface ApiContext {
6
- /** The incoming request. */
7
- request: Request;
8
- /** Parsed URL. */
9
- url: URL;
10
- /** URL path. */
11
- path: string;
12
- /** Dynamic route parameters (e.g., { id: "123" }). */
13
- params: Record<string, string>;
14
- /** Request headers. */
15
- headers: Headers;
16
- }
17
- /** An API route handler function. */
18
- export type ApiHandler = (ctx: ApiContext) => Response | Promise<Response>;
19
- /** An API route module — exports named HTTP method handlers. */
20
- export interface ApiRouteModule {
21
- GET?: ApiHandler;
22
- POST?: ApiHandler;
23
- PUT?: ApiHandler;
24
- PATCH?: ApiHandler;
25
- DELETE?: ApiHandler;
26
- HEAD?: ApiHandler;
27
- OPTIONS?: ApiHandler;
28
- }
29
- /** A registered API route entry. */
30
- export interface ApiRouteEntry {
31
- /** URL pattern (e.g., "/api/posts/:id"). */
32
- pattern: string;
33
- /** The route module with method handlers. */
34
- module: ApiRouteModule;
35
- }
36
- /**
37
- * Match a URL path against an API route pattern.
38
- * Returns extracted params or null if no match.
39
- */
40
- export declare function matchApiRoute(pattern: string, path: string): Record<string, string> | null;
41
- /**
42
- * Create a middleware that dispatches API route requests.
43
- * API routes are matched by URL pattern and HTTP method.
44
- */
45
- export declare function createApiMiddleware(routes: ApiRouteEntry[]): Middleware;
46
- /**
47
- * Detect whether a route file is an API route.
48
- * API routes are `.ts` or `.js` files inside an `api/` directory.
49
- */
50
- export declare function isApiRoute(filePath: string): boolean;
51
- /**
52
- * Convert an API route file path to a URL pattern.
53
- *
54
- * Examples:
55
- * "api/posts.ts" → "/api/posts"
56
- * "api/posts/index.ts" → "/api/posts"
57
- * "api/posts/[id].ts" → "/api/posts/:id"
58
- * "api/[...path].ts" → "/api/:path*"
59
- */
60
- export declare function apiFilePathToPattern(filePath: string): string;
61
- /**
62
- * Generate a virtual module that exports API route entries.
63
- * Each entry maps a URL pattern to a module with HTTP method handlers.
64
- */
65
- export declare function generateApiRouteModule(files: string[], routesDir: string): string;
66
- //# sourceMappingURL=api-routes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-routes.d.ts","sourceRoot":"","sources":["../../src/api-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,gBAAgB,CAAA;AAInE,4CAA4C;AAC5C,MAAM,MAAM,UAAU,GAClB,KAAK,GACL,MAAM,GACN,KAAK,GACL,OAAO,GACP,QAAQ,GACR,MAAM,GACN,SAAS,CAAA;AAEb,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,kBAAkB;IAClB,GAAG,EAAE,GAAG,CAAA;IACR,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,uBAAuB;IACvB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,qCAAqC;AACrC,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;AAE1E,gEAAgE;AAChE,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,UAAU,CAAA;IAChB,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,GAAG,CAAC,EAAE,UAAU,CAAA;IAChB,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,OAAO,CAAC,EAAE,UAAU,CAAA;CACrB;AAED,oCAAoC;AACpC,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAA;IACf,6CAA6C;IAC7C,MAAM,EAAE,cAAc,CAAA;CACvB;AAID;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CA8B/B;AAcD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,UAAU,CA8BvE;AAID;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkC7D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EAAE,EACf,SAAS,EAAE,MAAM,GAChB,MAAM,CA4BR"}
@@ -1,24 +0,0 @@
1
- import type { ComponentFn } from '@pyreon/core';
2
- import type { RouteRecord } from '@pyreon/router';
3
- export interface CreateAppOptions {
4
- /** Route definitions (from file-based routing or manual). */
5
- routes: RouteRecord[];
6
- /** Router mode. Default: "history" for SSR, "hash" for SPA. */
7
- routerMode?: 'hash' | 'history';
8
- /** Initial URL for SSR. */
9
- url?: string;
10
- /** Root layout component wrapping all routes. */
11
- layout?: ComponentFn;
12
- /** Global error component. */
13
- errorComponent?: ComponentFn;
14
- }
15
- /**
16
- * Create a full Zero app — assembles router, head provider, and root layout.
17
- *
18
- * Used internally by entry-server and entry-client.
19
- */
20
- export declare function createApp(options: CreateAppOptions): {
21
- App: () => import("@pyreon/core").VNode;
22
- router: import("@pyreon/router").Router;
23
- };
24
- //# sourceMappingURL=app.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAS,MAAM,cAAc,CAAA;AAGtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAKjD,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,MAAM,EAAE,WAAW,EAAE,CAAA;IAErB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAE/B,2BAA2B;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ,iDAAiD;IACjD,MAAM,CAAC,EAAE,WAAW,CAAA;IAEpB,8BAA8B;IAC9B,cAAc,CAAC,EAAE,WAAW,CAAA;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB;;;EAuBlD"}
@@ -1,54 +0,0 @@
1
- import type { Middleware } from '@pyreon/server';
2
- export interface CacheConfig {
3
- /** Cache duration for immutable hashed assets (seconds). Default: 31536000 (1 year) */
4
- immutable?: number;
5
- /** Cache duration for static assets like images/fonts (seconds). Default: 86400 (1 day) */
6
- static?: number;
7
- /** Cache duration for pages (seconds). Default: 0 (no cache) */
8
- pages?: number;
9
- /** Stale-while-revalidate window for pages (seconds). Default: 60 */
10
- staleWhileRevalidate?: number;
11
- /** Custom rules by URL pattern. */
12
- rules?: CacheRule[];
13
- }
14
- export interface CacheRule {
15
- /** URL pattern to match (glob-style). e.g. "/api/*" */
16
- match: string;
17
- /** Cache-Control header value. */
18
- control: string;
19
- }
20
- /** @internal Exported for testing */
21
- export declare function matchGlob(pattern: string, path: string): boolean;
22
- /**
23
- * Cache control middleware for Zero.
24
- * Sets Cache-Control headers on the response based on asset type.
25
- *
26
- * @example
27
- * import { cacheMiddleware } from "@pyreon/zero/cache"
28
- *
29
- * export default createHandler({
30
- * routes,
31
- * middleware: [
32
- * cacheMiddleware({
33
- * pages: 60,
34
- * staleWhileRevalidate: 300,
35
- * rules: [
36
- * { match: "/api/*", control: "no-store" },
37
- * ],
38
- * }),
39
- * ],
40
- * })
41
- */
42
- export declare function cacheMiddleware(config?: CacheConfig): Middleware;
43
- /**
44
- * Security headers middleware.
45
- * Adds common security headers to all responses.
46
- */
47
- export declare function securityHeaders(): Middleware;
48
- /**
49
- * Compression detection middleware.
50
- * Sets Vary: Accept-Encoding header so caches can serve compressed variants.
51
- * Actual compression is handled by the runtime (Bun/Node) or reverse proxy.
52
- */
53
- export declare function varyEncoding(): Middleware;
54
- //# sourceMappingURL=cache.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,gBAAgB,CAAA;AAanE,MAAM,WAAW,WAAW;IAC1B,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qEAAqE;IACrE,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,mCAAmC;IACnC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAA;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;IACb,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAA;CAChB;AAOD,qCAAqC;AACrC,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAKhE;AAwBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,MAAM,GAAE,WAAgB,GAAG,UAAU,CA0BpE;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,UAAU,CAW5C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,UAAU,CAUzC"}
@@ -1,19 +0,0 @@
1
- import type { ComponentFn } from '@pyreon/core';
2
- import type { RouteRecord } from '@pyreon/router';
3
- export interface StartClientOptions {
4
- /** Route definitions. */
5
- routes: RouteRecord[];
6
- /** Root layout component. */
7
- layout?: ComponentFn;
8
- }
9
- /**
10
- * Start the client-side app — hydrates SSR content or mounts fresh for SPA.
11
- *
12
- * @example
13
- * import { routes } from "virtual:zero/routes"
14
- * import { startClient } from "@pyreon/zero/client"
15
- *
16
- * startClient({ routes })
17
- */
18
- export declare function startClient(options: StartClientOptions): () => void;
19
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAMjD,MAAM,WAAW,kBAAkB;IACjC,yBAAyB;IACzB,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,cAkBtD"}
@@ -1,33 +0,0 @@
1
- import type { Middleware } from '@pyreon/server';
2
- export interface CompressionConfig {
3
- /** Minimum response size in bytes to compress. Default: `1024` (1KB) */
4
- threshold?: number;
5
- /** Encoding preference order. Default: `["gzip", "deflate"]` */
6
- encodings?: ('gzip' | 'deflate')[];
7
- }
8
- /**
9
- * Compression middleware — compresses responses using gzip or deflate
10
- * based on the client's Accept-Encoding header.
11
- *
12
- * Only compresses text-based content types (HTML, JSON, JS, CSS, XML, SVG).
13
- * Skips responses below the size threshold and already-encoded responses.
14
- *
15
- * @example
16
- * import { compressionMiddleware } from "@pyreon/zero/compression"
17
- *
18
- * compressionMiddleware() // gzip with 1KB threshold
19
- * compressionMiddleware({ threshold: 512, encodings: ["gzip"] })
20
- */
21
- export declare function compressionMiddleware(config?: CompressionConfig): Middleware;
22
- /**
23
- * Compress a Response body if it meets the criteria.
24
- * Use this to post-process responses after the handler runs.
25
- *
26
- * @example
27
- * const response = await handler(request)
28
- * const compressed = await compressResponse(response, 'gzip', 1024)
29
- */
30
- export declare function compressResponse(response: Response, encoding: 'gzip' | 'deflate', threshold: number): Promise<Response>;
31
- /** Check if a content type is compressible. Exported for testing. */
32
- export declare function isCompressible(contentType: string): boolean;
33
- //# sourceMappingURL=compression.d.ts.map