alabjs 0.1.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 (277) hide show
  1. package/dist/adapters/cloudflare.d.ts +31 -0
  2. package/dist/adapters/cloudflare.d.ts.map +1 -0
  3. package/dist/adapters/cloudflare.js +30 -0
  4. package/dist/adapters/cloudflare.js.map +1 -0
  5. package/dist/adapters/deno.d.ts +22 -0
  6. package/dist/adapters/deno.d.ts.map +1 -0
  7. package/dist/adapters/deno.js +21 -0
  8. package/dist/adapters/deno.js.map +1 -0
  9. package/dist/adapters/web.d.ts +47 -0
  10. package/dist/adapters/web.d.ts.map +1 -0
  11. package/dist/adapters/web.js +212 -0
  12. package/dist/adapters/web.js.map +1 -0
  13. package/dist/cli.d.ts +11 -0
  14. package/dist/cli.d.ts.map +1 -0
  15. package/dist/cli.js +61 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/client/hooks.d.ts +119 -0
  18. package/dist/client/hooks.d.ts.map +1 -0
  19. package/dist/client/hooks.js +220 -0
  20. package/dist/client/hooks.js.map +1 -0
  21. package/dist/client/hooks.test.d.ts +2 -0
  22. package/dist/client/hooks.test.d.ts.map +1 -0
  23. package/dist/client/hooks.test.js +45 -0
  24. package/dist/client/hooks.test.js.map +1 -0
  25. package/dist/client/index.d.ts +6 -0
  26. package/dist/client/index.d.ts.map +1 -0
  27. package/dist/client/index.js +4 -0
  28. package/dist/client/index.js.map +1 -0
  29. package/dist/client/offline.d.ts +52 -0
  30. package/dist/client/offline.d.ts.map +1 -0
  31. package/dist/client/offline.js +90 -0
  32. package/dist/client/offline.js.map +1 -0
  33. package/dist/client/provider.d.ts +12 -0
  34. package/dist/client/provider.d.ts.map +1 -0
  35. package/dist/client/provider.js +10 -0
  36. package/dist/client/provider.js.map +1 -0
  37. package/dist/commands/build.d.ts +18 -0
  38. package/dist/commands/build.d.ts.map +1 -0
  39. package/dist/commands/build.js +173 -0
  40. package/dist/commands/build.js.map +1 -0
  41. package/dist/commands/dev.d.ts +8 -0
  42. package/dist/commands/dev.d.ts.map +1 -0
  43. package/dist/commands/dev.js +447 -0
  44. package/dist/commands/dev.js.map +1 -0
  45. package/dist/commands/info.d.ts +6 -0
  46. package/dist/commands/info.d.ts.map +1 -0
  47. package/dist/commands/info.js +92 -0
  48. package/dist/commands/info.js.map +1 -0
  49. package/dist/commands/ssg.d.ts +8 -0
  50. package/dist/commands/ssg.d.ts.map +1 -0
  51. package/dist/commands/ssg.js +124 -0
  52. package/dist/commands/ssg.js.map +1 -0
  53. package/dist/commands/start.d.ts +7 -0
  54. package/dist/commands/start.d.ts.map +1 -0
  55. package/dist/commands/start.js +26 -0
  56. package/dist/commands/start.js.map +1 -0
  57. package/dist/commands/test.d.ts +24 -0
  58. package/dist/commands/test.d.ts.map +1 -0
  59. package/dist/commands/test.js +87 -0
  60. package/dist/commands/test.js.map +1 -0
  61. package/dist/components/ErrorBoundary.d.ts +38 -0
  62. package/dist/components/ErrorBoundary.d.ts.map +1 -0
  63. package/dist/components/ErrorBoundary.js +46 -0
  64. package/dist/components/ErrorBoundary.js.map +1 -0
  65. package/dist/components/Font.d.ts +57 -0
  66. package/dist/components/Font.d.ts.map +1 -0
  67. package/dist/components/Font.js +33 -0
  68. package/dist/components/Font.js.map +1 -0
  69. package/dist/components/Image.d.ts +74 -0
  70. package/dist/components/Image.d.ts.map +1 -0
  71. package/dist/components/Image.js +85 -0
  72. package/dist/components/Image.js.map +1 -0
  73. package/dist/components/Link.d.ts +23 -0
  74. package/dist/components/Link.d.ts.map +1 -0
  75. package/dist/components/Link.js +48 -0
  76. package/dist/components/Link.js.map +1 -0
  77. package/dist/components/Script.d.ts +37 -0
  78. package/dist/components/Script.d.ts.map +1 -0
  79. package/dist/components/Script.js +70 -0
  80. package/dist/components/Script.js.map +1 -0
  81. package/dist/components/index.d.ts +10 -0
  82. package/dist/components/index.d.ts.map +1 -0
  83. package/dist/components/index.js +6 -0
  84. package/dist/components/index.js.map +1 -0
  85. package/dist/i18n/i18n.test.d.ts +2 -0
  86. package/dist/i18n/i18n.test.d.ts.map +1 -0
  87. package/dist/i18n/i18n.test.js +132 -0
  88. package/dist/i18n/i18n.test.js.map +1 -0
  89. package/dist/i18n/index.d.ts +135 -0
  90. package/dist/i18n/index.d.ts.map +1 -0
  91. package/dist/i18n/index.js +189 -0
  92. package/dist/i18n/index.js.map +1 -0
  93. package/dist/index.d.ts +4 -0
  94. package/dist/index.d.ts.map +1 -0
  95. package/dist/index.js +3 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/router/code-router.d.ts +204 -0
  98. package/dist/router/code-router.d.ts.map +1 -0
  99. package/dist/router/code-router.js +258 -0
  100. package/dist/router/code-router.js.map +1 -0
  101. package/dist/router/code-router.test.d.ts +2 -0
  102. package/dist/router/code-router.test.d.ts.map +1 -0
  103. package/dist/router/code-router.test.js +128 -0
  104. package/dist/router/code-router.test.js.map +1 -0
  105. package/dist/router/index.d.ts +4 -0
  106. package/dist/router/index.d.ts.map +1 -0
  107. package/dist/router/index.js +2 -0
  108. package/dist/router/index.js.map +1 -0
  109. package/dist/router/manifest.d.ts +12 -0
  110. package/dist/router/manifest.d.ts.map +1 -0
  111. package/dist/router/manifest.js +2 -0
  112. package/dist/router/manifest.js.map +1 -0
  113. package/dist/server/app.d.ts +13 -0
  114. package/dist/server/app.d.ts.map +1 -0
  115. package/dist/server/app.js +407 -0
  116. package/dist/server/app.js.map +1 -0
  117. package/dist/server/cache.d.ts +99 -0
  118. package/dist/server/cache.d.ts.map +1 -0
  119. package/dist/server/cache.js +161 -0
  120. package/dist/server/cache.js.map +1 -0
  121. package/dist/server/cache.test.d.ts +2 -0
  122. package/dist/server/cache.test.d.ts.map +1 -0
  123. package/dist/server/cache.test.js +150 -0
  124. package/dist/server/cache.test.js.map +1 -0
  125. package/dist/server/csrf.d.ts +28 -0
  126. package/dist/server/csrf.d.ts.map +1 -0
  127. package/dist/server/csrf.js +66 -0
  128. package/dist/server/csrf.js.map +1 -0
  129. package/dist/server/csrf.test.d.ts +2 -0
  130. package/dist/server/csrf.test.d.ts.map +1 -0
  131. package/dist/server/csrf.test.js +154 -0
  132. package/dist/server/csrf.test.js.map +1 -0
  133. package/dist/server/image.d.ts +18 -0
  134. package/dist/server/image.d.ts.map +1 -0
  135. package/dist/server/image.js +97 -0
  136. package/dist/server/image.js.map +1 -0
  137. package/dist/server/index.d.ts +57 -0
  138. package/dist/server/index.d.ts.map +1 -0
  139. package/dist/server/index.js +58 -0
  140. package/dist/server/index.js.map +1 -0
  141. package/dist/server/middleware.d.ts +53 -0
  142. package/dist/server/middleware.d.ts.map +1 -0
  143. package/dist/server/middleware.js +80 -0
  144. package/dist/server/middleware.js.map +1 -0
  145. package/dist/server/middleware.test.d.ts +2 -0
  146. package/dist/server/middleware.test.d.ts.map +1 -0
  147. package/dist/server/middleware.test.js +125 -0
  148. package/dist/server/middleware.test.js.map +1 -0
  149. package/dist/server/revalidate.d.ts +49 -0
  150. package/dist/server/revalidate.d.ts.map +1 -0
  151. package/dist/server/revalidate.js +62 -0
  152. package/dist/server/revalidate.js.map +1 -0
  153. package/dist/server/revalidate.test.d.ts +2 -0
  154. package/dist/server/revalidate.test.d.ts.map +1 -0
  155. package/dist/server/revalidate.test.js +93 -0
  156. package/dist/server/revalidate.test.js.map +1 -0
  157. package/dist/server/server-fn.test.d.ts +2 -0
  158. package/dist/server/server-fn.test.d.ts.map +1 -0
  159. package/dist/server/server-fn.test.js +105 -0
  160. package/dist/server/server-fn.test.js.map +1 -0
  161. package/dist/server/sitemap.d.ts +9 -0
  162. package/dist/server/sitemap.d.ts.map +1 -0
  163. package/dist/server/sitemap.js +26 -0
  164. package/dist/server/sitemap.js.map +1 -0
  165. package/dist/server/sitemap.test.d.ts +2 -0
  166. package/dist/server/sitemap.test.d.ts.map +1 -0
  167. package/dist/server/sitemap.test.js +61 -0
  168. package/dist/server/sitemap.test.js.map +1 -0
  169. package/dist/server/sse.d.ts +59 -0
  170. package/dist/server/sse.d.ts.map +1 -0
  171. package/dist/server/sse.js +91 -0
  172. package/dist/server/sse.js.map +1 -0
  173. package/dist/server/sse.test.d.ts +2 -0
  174. package/dist/server/sse.test.d.ts.map +1 -0
  175. package/dist/server/sse.test.js +68 -0
  176. package/dist/server/sse.test.js.map +1 -0
  177. package/dist/signals/index.d.ts +101 -0
  178. package/dist/signals/index.d.ts.map +1 -0
  179. package/dist/signals/index.js +149 -0
  180. package/dist/signals/index.js.map +1 -0
  181. package/dist/signals/signals.test.d.ts +2 -0
  182. package/dist/signals/signals.test.d.ts.map +1 -0
  183. package/dist/signals/signals.test.js +146 -0
  184. package/dist/signals/signals.test.js.map +1 -0
  185. package/dist/ssr/html.d.ts +27 -0
  186. package/dist/ssr/html.d.ts.map +1 -0
  187. package/dist/ssr/html.js +107 -0
  188. package/dist/ssr/html.js.map +1 -0
  189. package/dist/ssr/html.test.d.ts +2 -0
  190. package/dist/ssr/html.test.d.ts.map +1 -0
  191. package/dist/ssr/html.test.js +178 -0
  192. package/dist/ssr/html.test.js.map +1 -0
  193. package/dist/ssr/render.d.ts +46 -0
  194. package/dist/ssr/render.d.ts.map +1 -0
  195. package/dist/ssr/render.js +87 -0
  196. package/dist/ssr/render.js.map +1 -0
  197. package/dist/ssr/router-dev.d.ts +60 -0
  198. package/dist/ssr/router-dev.d.ts.map +1 -0
  199. package/dist/ssr/router-dev.js +205 -0
  200. package/dist/ssr/router-dev.js.map +1 -0
  201. package/dist/ssr/router-dev.test.d.ts +2 -0
  202. package/dist/ssr/router-dev.test.d.ts.map +1 -0
  203. package/dist/ssr/router-dev.test.js +189 -0
  204. package/dist/ssr/router-dev.test.js.map +1 -0
  205. package/dist/test/index.d.ts +93 -0
  206. package/dist/test/index.d.ts.map +1 -0
  207. package/dist/test/index.js +146 -0
  208. package/dist/test/index.js.map +1 -0
  209. package/dist/types/index.d.ts +117 -0
  210. package/dist/types/index.d.ts.map +1 -0
  211. package/dist/types/index.js +2 -0
  212. package/dist/types/index.js.map +1 -0
  213. package/dist/types/napi.d.ts +15 -0
  214. package/dist/types/napi.d.ts.map +1 -0
  215. package/dist/types/napi.js +2 -0
  216. package/dist/types/napi.js.map +1 -0
  217. package/package.json +107 -0
  218. package/src/adapters/cloudflare.ts +30 -0
  219. package/src/adapters/deno.ts +21 -0
  220. package/src/adapters/web.ts +259 -0
  221. package/src/cli.ts +68 -0
  222. package/src/client/hooks.test.ts +54 -0
  223. package/src/client/hooks.ts +329 -0
  224. package/src/client/index.ts +5 -0
  225. package/src/client/offline-sw.ts +191 -0
  226. package/src/client/offline.ts +114 -0
  227. package/src/client/provider.tsx +14 -0
  228. package/src/commands/build.ts +201 -0
  229. package/src/commands/dev.ts +509 -0
  230. package/src/commands/info.ts +111 -0
  231. package/src/commands/ssg.ts +177 -0
  232. package/src/commands/start.ts +32 -0
  233. package/src/commands/test.ts +102 -0
  234. package/src/components/ErrorBoundary.tsx +73 -0
  235. package/src/components/Font.tsx +100 -0
  236. package/src/components/Image.tsx +141 -0
  237. package/src/components/Link.tsx +64 -0
  238. package/src/components/Script.tsx +97 -0
  239. package/src/components/index.ts +9 -0
  240. package/src/i18n/i18n.test.tsx +169 -0
  241. package/src/i18n/index.tsx +256 -0
  242. package/src/index.ts +10 -0
  243. package/src/router/code-router.test.ts +146 -0
  244. package/src/router/code-router.tsx +459 -0
  245. package/src/router/index.ts +18 -0
  246. package/src/router/manifest.ts +13 -0
  247. package/src/server/app.ts +466 -0
  248. package/src/server/cache.test.ts +192 -0
  249. package/src/server/cache.ts +195 -0
  250. package/src/server/csrf.test.ts +199 -0
  251. package/src/server/csrf.ts +80 -0
  252. package/src/server/image.ts +112 -0
  253. package/src/server/index.ts +144 -0
  254. package/src/server/middleware.test.ts +151 -0
  255. package/src/server/middleware.ts +95 -0
  256. package/src/server/revalidate.test.ts +106 -0
  257. package/src/server/revalidate.ts +75 -0
  258. package/src/server/server-fn.test.ts +127 -0
  259. package/src/server/sitemap.test.ts +68 -0
  260. package/src/server/sitemap.ts +30 -0
  261. package/src/server/sse.test.ts +81 -0
  262. package/src/server/sse.ts +110 -0
  263. package/src/signals/index.ts +177 -0
  264. package/src/signals/signals.test.ts +164 -0
  265. package/src/ssr/html.test.ts +200 -0
  266. package/src/ssr/html.ts +140 -0
  267. package/src/ssr/render.ts +144 -0
  268. package/src/ssr/router-dev.test.ts +230 -0
  269. package/src/ssr/router-dev.ts +229 -0
  270. package/src/test/index.ts +206 -0
  271. package/src/types/compiler.d.ts +25 -0
  272. package/src/types/index.ts +147 -0
  273. package/src/types/napi.ts +20 -0
  274. package/src/types/plugins.d.ts +3 -0
  275. package/tsconfig.json +11 -0
  276. package/tsconfig.tsbuildinfo +1 -0
  277. package/vitest.config.ts +32 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Alab adapter for Cloudflare Workers.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * // src/worker.ts (entry point for `wrangler deploy`)
7
+ * import { createCloudflareHandler } from "alabjs/adapters/cloudflare";
8
+ * import manifest from "../.alabjs/manifest.json" assert { type: "json" };
9
+ * import * as pages from "../.alabjs/pages";
10
+ *
11
+ * export default createCloudflareHandler(manifest, pages);
12
+ * ```
13
+ *
14
+ * **wrangler.toml**
15
+ * ```toml
16
+ * name = "my-alab-app"
17
+ * main = "src/worker.ts"
18
+ * compatibility_date = "2024-01-01"
19
+ *
20
+ * [site]
21
+ * bucket = ".alabjs/dist/client"
22
+ * ```
23
+ *
24
+ * **Notes:**
25
+ * - Image optimisation (`/_alabjs/image`) is not available on Workers;
26
+ * requests are redirected to the original source URL.
27
+ * - Static assets are served by Cloudflare's edge via the `[site]` binding.
28
+ */
29
+ export { createFetchHandler as createCloudflareHandler } from "./web.js";
30
+ export type { PageModule } from "./web.js";
31
+ //# sourceMappingURL=cloudflare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../src/adapters/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,kBAAkB,IAAI,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACzE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Alab adapter for Cloudflare Workers.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * // src/worker.ts (entry point for `wrangler deploy`)
7
+ * import { createCloudflareHandler } from "alabjs/adapters/cloudflare";
8
+ * import manifest from "../.alabjs/manifest.json" assert { type: "json" };
9
+ * import * as pages from "../.alabjs/pages";
10
+ *
11
+ * export default createCloudflareHandler(manifest, pages);
12
+ * ```
13
+ *
14
+ * **wrangler.toml**
15
+ * ```toml
16
+ * name = "my-alab-app"
17
+ * main = "src/worker.ts"
18
+ * compatibility_date = "2024-01-01"
19
+ *
20
+ * [site]
21
+ * bucket = ".alabjs/dist/client"
22
+ * ```
23
+ *
24
+ * **Notes:**
25
+ * - Image optimisation (`/_alabjs/image`) is not available on Workers;
26
+ * requests are redirected to the original source URL.
27
+ * - Static assets are served by Cloudflare's edge via the `[site]` binding.
28
+ */
29
+ export { createFetchHandler as createCloudflareHandler } from "./web.js";
30
+ //# sourceMappingURL=cloudflare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../src/adapters/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,kBAAkB,IAAI,uBAAuB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Alab adapter for Deno Deploy.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * // main.ts (entry point for `deployctl deploy`)
7
+ * import { createDenoHandler } from "alabjs/adapters/deno";
8
+ * import manifest from "./.alabjs/manifest.json" with { type: "json" };
9
+ * import * as pages from "./.alabjs/pages";
10
+ *
11
+ * const handler = createDenoHandler(manifest, pages);
12
+ * Deno.serve(handler.fetch.bind(handler));
13
+ * ```
14
+ *
15
+ * **Notes:**
16
+ * - Image optimisation (`/_alabjs/image`) is not available on Deno Deploy;
17
+ * requests are redirected to the original source URL.
18
+ * - Uses the same Web Fetch API handler as the Cloudflare adapter.
19
+ */
20
+ export { createFetchHandler as createDenoHandler } from "./web.js";
21
+ export type { PageModule } from "./web.js";
22
+ //# sourceMappingURL=deno.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deno.d.ts","sourceRoot":"","sources":["../../src/adapters/deno.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,kBAAkB,IAAI,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACnE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Alab adapter for Deno Deploy.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * // main.ts (entry point for `deployctl deploy`)
7
+ * import { createDenoHandler } from "alabjs/adapters/deno";
8
+ * import manifest from "./.alabjs/manifest.json" with { type: "json" };
9
+ * import * as pages from "./.alabjs/pages";
10
+ *
11
+ * const handler = createDenoHandler(manifest, pages);
12
+ * Deno.serve(handler.fetch.bind(handler));
13
+ * ```
14
+ *
15
+ * **Notes:**
16
+ * - Image optimisation (`/_alabjs/image`) is not available on Deno Deploy;
17
+ * requests are redirected to the original source URL.
18
+ * - Uses the same Web Fetch API handler as the Cloudflare adapter.
19
+ */
20
+ export { createFetchHandler as createDenoHandler } from "./web.js";
21
+ //# sourceMappingURL=deno.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deno.js","sourceRoot":"","sources":["../../src/adapters/deno.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,kBAAkB,IAAI,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Alab Web Fetch adapter — shared by Cloudflare Workers and Deno Deploy.
3
+ *
4
+ * Both runtimes expose the standard Web Fetch API (`Request` / `Response`).
5
+ * The adapter accepts a pre-built route manifest and a map of pre-bundled
6
+ * page modules, then returns a `(request: Request) => Promise<Response>`
7
+ * handler that the platform wires up itself.
8
+ *
9
+ * Image optimization (`/_alabjs/image`) is not available on these runtimes
10
+ * because the Rust napi binary cannot run there. The handler redirects
11
+ * image requests to the original source URL so images still load correctly
12
+ * in production — you can also point these to Cloudflare Images or a CDN.
13
+ */
14
+ import type { RouteManifest } from "../router/manifest.js";
15
+ import type { PageMetadata } from "../types/index.js";
16
+ export type PageModule = {
17
+ default: (props: {
18
+ params: Record<string, string>;
19
+ searchParams: Record<string, string>;
20
+ }) => unknown;
21
+ metadata?: PageMetadata | undefined;
22
+ generateMetadata?: (params: Record<string, string>) => PageMetadata | Promise<PageMetadata>;
23
+ ssr?: boolean | undefined;
24
+ };
25
+ /** API route module — exports HTTP method handlers. */
26
+ export type ApiModule = Record<string, (req: Request) => Promise<Response> | Response>;
27
+ /**
28
+ * Create a Web Fetch API handler from the Alab route manifest and a map of
29
+ * pre-bundled page modules.
30
+ *
31
+ * @param manifest - Route manifest (from `alab build` or `.alabjs/manifest.json`)
32
+ * @param pageModules - Map of route file path → imported page module
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * // cloudflare worker entry (src/worker.ts):
37
+ * import { createFetchHandler } from "alabjs/adapters/web";
38
+ * import manifest from "../.alabjs/manifest.json";
39
+ * import * as pages from "../.alabjs/pages"; // bundled by wrangler
40
+ *
41
+ * export default createFetchHandler(manifest, pages);
42
+ * ```
43
+ */
44
+ export declare function createFetchHandler(manifest: RouteManifest, pageModules: Record<string, PageModule>, apiModules?: Record<string, ApiModule>): {
45
+ fetch(request: Request): Promise<Response>;
46
+ };
47
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/adapters/web.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAS,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,CAAC,KAAK,EAAE;QACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACtC,KAAK,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACpC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5F,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC3B,CAAC;AAEF,uDAAuD;AACvD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC;AAEvF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,aAAa,EACvB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EACvC,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAM,GACzC;IAAE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAAE,CAkKhD"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Alab Web Fetch adapter — shared by Cloudflare Workers and Deno Deploy.
3
+ *
4
+ * Both runtimes expose the standard Web Fetch API (`Request` / `Response`).
5
+ * The adapter accepts a pre-built route manifest and a map of pre-bundled
6
+ * page modules, then returns a `(request: Request) => Promise<Response>`
7
+ * handler that the platform wires up itself.
8
+ *
9
+ * Image optimization (`/_alabjs/image`) is not available on these runtimes
10
+ * because the Rust napi binary cannot run there. The handler redirects
11
+ * image requests to the original source URL so images still load correctly
12
+ * in production — you can also point these to Cloudflare Images or a CDN.
13
+ */
14
+ import { createElement } from "react";
15
+ import { renderToReadableStream } from "react-dom/server";
16
+ import { htmlShellBefore, htmlShellAfter } from "../ssr/html.js";
17
+ import { generateSitemap } from "../server/sitemap.js";
18
+ /**
19
+ * Create a Web Fetch API handler from the Alab route manifest and a map of
20
+ * pre-bundled page modules.
21
+ *
22
+ * @param manifest - Route manifest (from `alab build` or `.alabjs/manifest.json`)
23
+ * @param pageModules - Map of route file path → imported page module
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * // cloudflare worker entry (src/worker.ts):
28
+ * import { createFetchHandler } from "alabjs/adapters/web";
29
+ * import manifest from "../.alabjs/manifest.json";
30
+ * import * as pages from "../.alabjs/pages"; // bundled by wrangler
31
+ *
32
+ * export default createFetchHandler(manifest, pages);
33
+ * ```
34
+ */
35
+ export function createFetchHandler(manifest, pageModules, apiModules = {}) {
36
+ return {
37
+ async fetch(request) {
38
+ const url = new URL(request.url);
39
+ const pathname = url.pathname;
40
+ // Security headers applied to every response.
41
+ const secHeaders = {
42
+ "x-content-type-options": "nosniff",
43
+ "x-frame-options": "SAMEORIGIN",
44
+ "referrer-policy": "strict-origin-when-cross-origin",
45
+ };
46
+ // ── Auto sitemap ──────────────────────────────────────────────────────
47
+ if (pathname === "/sitemap.xml") {
48
+ const xml = generateSitemap(manifest.routes, url.origin);
49
+ return new Response(xml, {
50
+ headers: {
51
+ ...secHeaders,
52
+ "content-type": "application/xml; charset=utf-8",
53
+ "cache-control": "public, max-age=3600",
54
+ },
55
+ });
56
+ }
57
+ // ── Image optimisation — redirect to raw src ──────────────────────────
58
+ // The Rust napi binary cannot run on Cloudflare Workers or Deno Deploy.
59
+ // Redirect to the original source URL so images still load. Replace
60
+ // this with Cloudflare Images / a CDN transform URL in production.
61
+ if (pathname.startsWith("/_alabjs/image")) {
62
+ const src = url.searchParams.get("src") ?? "";
63
+ if (src)
64
+ return Response.redirect(new URL(src, url.origin).href, 302);
65
+ return new Response("[alabjs] Image src missing", { status: 400, headers: secHeaders });
66
+ }
67
+ // ── API routes ────────────────────────────────────────────────────────
68
+ const matchedApi = matchRoute(manifest.routes.filter(r => r.kind === "api"), pathname);
69
+ if (matchedApi) {
70
+ const apiMod = apiModules[matchedApi.route.file];
71
+ if (!apiMod) {
72
+ return new Response(`[alabjs] API module not found: ${matchedApi.route.file}`, {
73
+ status: 500, headers: secHeaders,
74
+ });
75
+ }
76
+ const method = request.method.toUpperCase();
77
+ const handler = apiMod[method];
78
+ if (typeof handler !== "function") {
79
+ const allowed = Object.keys(apiMod).filter(k => /^(GET|POST|PUT|PATCH|DELETE|HEAD)$/.test(k)).join(", ");
80
+ return new Response("Method Not Allowed", { status: 405, headers: { ...secHeaders, allow: allowed } });
81
+ }
82
+ return handler(request);
83
+ }
84
+ // ── Page routing ──────────────────────────────────────────────────────
85
+ const matched = matchRoute(manifest.routes, pathname);
86
+ if (!matched) {
87
+ // Check for not-found page module
88
+ const nfMod = pageModules["app/not-found.tsx"];
89
+ if (nfMod?.default) {
90
+ const shellBefore = htmlShellBefore({
91
+ metadata: { title: "404 — Not Found" },
92
+ paramsJson: "{}",
93
+ searchParamsJson: "{}",
94
+ routeFile: "app/not-found.tsx",
95
+ ssr: true,
96
+ });
97
+ const shellAfter = htmlShellAfter({});
98
+ const enc = new TextEncoder();
99
+ const nfStream = await renderToReadableStream(createElement(nfMod.default, { params: {}, searchParams: {} }), { onError(err) { console.error("[alabjs] not-found SSR error:", err); } });
100
+ await nfStream.allReady;
101
+ const readable = new ReadableStream({
102
+ async start(ctrl) {
103
+ ctrl.enqueue(enc.encode(shellBefore));
104
+ const reader = nfStream.getReader();
105
+ for (;;) {
106
+ const { done, value } = await reader.read();
107
+ if (done)
108
+ break;
109
+ ctrl.enqueue(value);
110
+ }
111
+ ctrl.enqueue(enc.encode(shellAfter));
112
+ ctrl.close();
113
+ },
114
+ });
115
+ return new Response(readable, { status: 404, headers: { ...secHeaders, "content-type": "text/html; charset=utf-8" } });
116
+ }
117
+ return new Response("Not Found", { status: 404, headers: secHeaders });
118
+ }
119
+ const { route, params } = matched;
120
+ const mod = pageModules[route.file];
121
+ if (!mod?.default) {
122
+ return new Response(`[alabjs] Page module not found: ${route.file}`, {
123
+ status: 500,
124
+ headers: secHeaders,
125
+ });
126
+ }
127
+ const Page = mod.default;
128
+ const metadata = typeof mod.generateMetadata === "function"
129
+ ? await mod.generateMetadata(params)
130
+ : (mod.metadata ?? {});
131
+ const ssrEnabled = mod.ssr === true;
132
+ const searchParams = {};
133
+ for (const [k, v] of url.searchParams.entries()) {
134
+ searchParams[k] = v;
135
+ }
136
+ const shellBefore = htmlShellBefore({
137
+ metadata,
138
+ paramsJson: JSON.stringify(params),
139
+ searchParamsJson: JSON.stringify(searchParams),
140
+ routeFile: route.file,
141
+ ssr: ssrEnabled,
142
+ });
143
+ const shellAfter = htmlShellAfter({});
144
+ if (ssrEnabled) {
145
+ const enc = new TextEncoder();
146
+ let didError = false;
147
+ const reactStream = await renderToReadableStream(createElement(Page, { params, searchParams }), {
148
+ onError(err) {
149
+ didError = true;
150
+ console.error("[alabjs] SSR error:", err);
151
+ },
152
+ });
153
+ // Wait for all Suspense boundaries to resolve (no streaming on Workers).
154
+ await reactStream.allReady;
155
+ const readable = new ReadableStream({
156
+ async start(ctrl) {
157
+ ctrl.enqueue(enc.encode(shellBefore));
158
+ const reader = reactStream.getReader();
159
+ for (;;) {
160
+ const { done, value } = await reader.read();
161
+ if (done)
162
+ break;
163
+ ctrl.enqueue(value);
164
+ }
165
+ ctrl.enqueue(enc.encode(shellAfter));
166
+ ctrl.close();
167
+ },
168
+ });
169
+ return new Response(readable, {
170
+ status: didError ? 500 : 200,
171
+ headers: { ...secHeaders, "content-type": "text/html; charset=utf-8" },
172
+ });
173
+ }
174
+ // CSR — return the HTML shell only; React hydrates on the client.
175
+ return new Response(`${shellBefore}${shellAfter}`, {
176
+ headers: { ...secHeaders, "content-type": "text/html; charset=utf-8" },
177
+ });
178
+ },
179
+ };
180
+ }
181
+ // ─── Internal helpers ──────────────────────────────────────────────────────────
182
+ function matchRoute(routes, pathname) {
183
+ // Sort: fewer params = higher priority (static routes beat dynamic ones).
184
+ const sorted = [...routes].sort((a, b) => a.params.length - b.params.length);
185
+ for (const route of sorted) {
186
+ if (route.kind !== "page" && route.kind !== "api")
187
+ continue;
188
+ const paramNames = [];
189
+ const regexStr = route.path
190
+ .split("/")
191
+ .map((seg) => {
192
+ const m = /^\[(.+)\]$/.exec(seg);
193
+ if (m) {
194
+ paramNames.push(m[1]);
195
+ return "([^/]+)";
196
+ }
197
+ return seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
198
+ })
199
+ .join("/");
200
+ const regex = route.path === "/" ? /^\/$/ : new RegExp(`^${regexStr}\\/?$`);
201
+ const match = regex.exec(pathname);
202
+ if (match) {
203
+ const params = {};
204
+ paramNames.forEach((name, i) => {
205
+ params[name] = decodeURIComponent(match[i + 1] ?? "");
206
+ });
207
+ return { route, params };
208
+ }
209
+ }
210
+ return null;
211
+ }
212
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/adapters/web.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Alab CLI
4
+ *
5
+ * alab dev — start the development server (Vite + Rust compiler)
6
+ * alab build — production build (Rust compile + Vite bundle)
7
+ * alab start — start the production HTTP server
8
+ * alab info — print the route manifest and compiler info
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG"}
package/dist/cli.js ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Alab CLI
4
+ *
5
+ * alab dev — start the development server (Vite + Rust compiler)
6
+ * alab build — production build (Rust compile + Vite bundle)
7
+ * alab start — start the production HTTP server
8
+ * alab info — print the route manifest and compiler info
9
+ */
10
+ import { parseArgs } from "node:util";
11
+ const { positionals, values } = parseArgs({
12
+ allowPositionals: true,
13
+ options: {
14
+ port: { type: "string", short: "p", default: "3000" },
15
+ host: { type: "string", default: "localhost" },
16
+ "skip-typecheck": { type: "boolean", default: false },
17
+ mode: { type: "string" },
18
+ analyze: { type: "boolean", default: false },
19
+ watch: { type: "boolean", default: false },
20
+ ui: { type: "boolean", default: false },
21
+ },
22
+ });
23
+ const [command = "dev"] = positionals;
24
+ const cwd = process.cwd();
25
+ switch (command) {
26
+ case "dev":
27
+ await import("./commands/dev.js").then((m) => m.dev({ cwd }));
28
+ break;
29
+ case "build": {
30
+ const buildMode = values["mode"];
31
+ await import("./commands/build.js").then((m) => m.build({
32
+ cwd,
33
+ skipTypecheck: values["skip-typecheck"],
34
+ mode: buildMode === "spa" ? "spa" : "ssr",
35
+ analyze: values["analyze"],
36
+ }));
37
+ break;
38
+ }
39
+ case "start":
40
+ await import("./commands/start.js").then((m) => m.start({ cwd }));
41
+ break;
42
+ case "info":
43
+ await import("./commands/info.js").then((m) => m.info({ cwd }));
44
+ break;
45
+ case "ssg":
46
+ await import("./commands/ssg.js").then((m) => m.ssg({ cwd }));
47
+ break;
48
+ case "test":
49
+ await import("./commands/test.js").then((m) => m.test({
50
+ cwd,
51
+ watch: values["watch"],
52
+ ui: values["ui"],
53
+ files: positionals.slice(1),
54
+ }));
55
+ break;
56
+ default:
57
+ console.error(`Unknown command: ${command}`);
58
+ console.error("Usage: alab <dev|build|start|info|ssg|test>");
59
+ process.exit(1);
60
+ }
61
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import type { ServerFn, InferServerOutput, RouteParams, InferServerPath } from "../types/index.js";
2
+ /** Clear the server-side promise cache between SSR renders. Called by alab's dev server. */
3
+ export declare function _clearALabSSRCache(): void;
4
+ /**
5
+ * Fetch server data with full type inference from a `ServerFn`.
6
+ *
7
+ * Use `import type` to reference the server function — type-only imports
8
+ * are erased at compile time and never cross the server/client boundary.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * // app/posts/[id]/page.tsx
13
+ * import type { getPost } from "./page.server"; // ← import type, safe
14
+ * import { useServerData } from "alabjs/client";
15
+ *
16
+ * export default function PostPage({ params }: { params: { id: string } }) {
17
+ * // Return type is inferred from getPost — no manual type annotation needed
18
+ * const post = useServerData<typeof getPost>("getPost", params);
19
+ * post.title; // ✅ typed
20
+ * post.foo; // ✅ TS error — doesn't exist on the return type
21
+ * }
22
+ * ```
23
+ */
24
+ export declare function useServerData<T extends ServerFn<any, any, any>>(fnName: string, params?: RouteParams<InferServerPath<T>>): InferServerOutput<T>;
25
+ export interface UseMutationOptions<Output, Input> {
26
+ /**
27
+ * Compute an optimistic value from the input immediately — before the server
28
+ * responds. The component sees this value via `optimisticData` while the
29
+ * request is in flight.
30
+ *
31
+ * On server error, `optimisticData` is cleared and `onError` is called with
32
+ * a `rollback` callback you can use to undo any local side effects.
33
+ */
34
+ optimistic?: (input: Input) => Partial<Output>;
35
+ /** Called when the mutation succeeds with the server response. */
36
+ onSuccess?: (data: Output) => void;
37
+ /**
38
+ * Called when the mutation fails.
39
+ * `rollback()` clears the optimistic value and resets state to idle.
40
+ */
41
+ onError?: (err: Error, rollback: () => void) => void;
42
+ }
43
+ /**
44
+ * Trigger a server function mutation from the client, with full async state
45
+ * and optional optimistic updates.
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * import type { updateTodo } from "./page.server";
50
+ * import { useMutation } from "alabjs/client";
51
+ *
52
+ * // Basic
53
+ * const { mutate, data, isPending, error, zodError, reset } =
54
+ * useMutation<typeof updateTodo>("updateTodo");
55
+ *
56
+ * // With optimistic update
57
+ * const { mutate, optimisticData } = useMutation<typeof updateTodo>("updateTodo", {
58
+ * optimistic: (input) => ({ ...currentTodo, ...input }),
59
+ * onError: (err, rollback) => rollback(),
60
+ * });
61
+ * ```
62
+ */
63
+ export declare function useMutation<T extends ServerFn<any, any, any>>(fnName: string, options?: UseMutationOptions<InferServerOutput<T>, T extends ServerFn<infer I, any, any> ? I : never>): {
64
+ mutate: (input: T extends ServerFn<infer I, any, any> ? I : never) => void;
65
+ data: InferServerOutput<T> | undefined;
66
+ /** Present when `optimistic` option is set and the request is in flight. */
67
+ optimisticData: Partial<InferServerOutput<T>> | undefined;
68
+ isPending: boolean;
69
+ error: Error | undefined;
70
+ /** Zod validation errors returned by `defineServerFn` schema checks (HTTP 422). */
71
+ zodError: unknown;
72
+ isSuccess: boolean;
73
+ isError: boolean;
74
+ isInvalid: boolean;
75
+ reset: () => void;
76
+ };
77
+ /** Possible connection states matching the browser EventSource readyState values. */
78
+ export type SSEReadyState = "connecting" | "open" | "closed";
79
+ export interface UseSSEOptions {
80
+ /** Named event to subscribe to. Defaults to `"message"`. */
81
+ event?: string;
82
+ /** Whether to connect immediately. Set `false` to defer. @default true */
83
+ enabled?: boolean;
84
+ /** Called once when the EventSource opens. */
85
+ onOpen?: () => void;
86
+ /** Called when the EventSource closes or errors. */
87
+ onError?: (err: Event) => void;
88
+ }
89
+ export interface UseSSEResult<T> {
90
+ /** Most recently received event data (parsed JSON). `undefined` until first event. */
91
+ data: T | undefined;
92
+ /** The `lastEventId` string from the most recent event. */
93
+ lastEventId: string;
94
+ readyState: SSEReadyState;
95
+ /** Close the EventSource and stop listening. */
96
+ close: () => void;
97
+ }
98
+ /**
99
+ * Subscribe to a server-sent event stream from a `defineSSEHandler` route.
100
+ *
101
+ * The EventSource is created when the component mounts and closed on unmount.
102
+ * Data is parsed as JSON automatically.
103
+ *
104
+ * @example
105
+ * ```tsx
106
+ * import { useSSE } from "alabjs/client";
107
+ *
108
+ * export default function PricesPage() {
109
+ * const { data, readyState } = useSSE<{ ticker: string; price: number }>(
110
+ * "/api/prices?ticker=BTC",
111
+ * { event: "price" },
112
+ * );
113
+ *
114
+ * return <div>{readyState === "open" ? data?.price ?? "—" : "connecting…"}</div>;
115
+ * }
116
+ * ```
117
+ */
118
+ export declare function useSSE<T = unknown>(url: string, options?: UseSSEOptions): UseSSEResult<T>;
119
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/client/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAUnG,4FAA4F;AAC5F,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAC7D,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,GACvC,iBAAiB,CAAC,CAAC,CAAC,CAuBtB;AAiCD,MAAM,WAAW,kBAAkB,CAAC,MAAM,EAAE,KAAK;IAC/C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,kEAAkE;IAClE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACtD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAC3D,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;6CAG/D,CAAC,4BAkBI,IAAI;UAgDzB,uBAAS,SAAS;IACtC,4EAA4E;;;WAGtD,KAAK,GAAG,SAAS;IACvC,mFAAmF;;;;;;EAOtF;AAID,qFAAqF;AACrF,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,oDAAoD;IACpD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,sFAAsF;IACtF,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IACpB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,aAAa,CAAC;IAC1B,gDAAgD;IAChD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,MAAM,CAAC,CAAC,GAAG,OAAO,EAChC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,aAAkB,GAC1B,YAAY,CAAC,CAAC,CAAC,CA4DjB"}