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,189 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { mkdtempSync, writeFileSync, mkdirSync, rmSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { scanDevRoutes, matchDevRoute, findLayoutFiles, findErrorFile, findLoadingFile, scanDevApiRoutes, matchDevApiRoute, } from "./router-dev.js";
6
+ let appDir;
7
+ beforeEach(() => {
8
+ appDir = mkdtempSync(join(tmpdir(), "alab-test-"));
9
+ });
10
+ afterEach(() => {
11
+ rmSync(appDir, { recursive: true, force: true });
12
+ });
13
+ function createFile(relPath, content = "export default function Page() { return null; }") {
14
+ const full = join(appDir, relPath);
15
+ mkdirSync(join(full, ".."), { recursive: true });
16
+ writeFileSync(full, content, "utf8");
17
+ }
18
+ // ─── scanDevRoutes ────────────────────────────────────────────────────────────
19
+ describe("scanDevRoutes", () => {
20
+ it("finds page.tsx at root", () => {
21
+ createFile("page.tsx");
22
+ const routes = scanDevRoutes(appDir);
23
+ expect(routes).toHaveLength(1);
24
+ expect(routes[0].pattern.test("/")).toBe(true);
25
+ });
26
+ it("finds nested page.tsx", () => {
27
+ createFile("about/page.tsx");
28
+ const routes = scanDevRoutes(appDir);
29
+ expect(routes).toHaveLength(1);
30
+ expect(routes[0].pattern.test("/about")).toBe(true);
31
+ });
32
+ it("finds dynamic route [id]", () => {
33
+ createFile("users/[id]/page.tsx");
34
+ const routes = scanDevRoutes(appDir);
35
+ expect(routes).toHaveLength(1);
36
+ expect(routes[0].pattern.test("/users/42")).toBe(true);
37
+ expect(routes[0].paramNames).toEqual(["id"]);
38
+ });
39
+ it("sorts static routes before dynamic ones", () => {
40
+ createFile("users/new/page.tsx");
41
+ createFile("users/[id]/page.tsx");
42
+ const routes = scanDevRoutes(appDir);
43
+ expect(routes).toHaveLength(2);
44
+ // Static route (0 params) should come first
45
+ expect(routes[0].paramNames).toHaveLength(0);
46
+ expect(routes[1].paramNames).toHaveLength(1);
47
+ });
48
+ it("finds page.ts files too", () => {
49
+ createFile("page.ts");
50
+ const routes = scanDevRoutes(appDir);
51
+ expect(routes).toHaveLength(1);
52
+ });
53
+ it("returns empty for empty directory", () => {
54
+ const routes = scanDevRoutes(appDir);
55
+ expect(routes).toHaveLength(0);
56
+ });
57
+ });
58
+ // ─── matchDevRoute ────────────────────────────────────────────────────────────
59
+ describe("matchDevRoute", () => {
60
+ it("matches a static route", () => {
61
+ createFile("about/page.tsx");
62
+ const routes = scanDevRoutes(appDir);
63
+ const match = matchDevRoute(routes, "/about");
64
+ expect(match).not.toBe(null);
65
+ expect(match.params).toEqual({});
66
+ });
67
+ it("matches root route", () => {
68
+ createFile("page.tsx");
69
+ const routes = scanDevRoutes(appDir);
70
+ const match = matchDevRoute(routes, "/");
71
+ expect(match).not.toBe(null);
72
+ });
73
+ it("extracts dynamic params", () => {
74
+ createFile("users/[id]/page.tsx");
75
+ const routes = scanDevRoutes(appDir);
76
+ const match = matchDevRoute(routes, "/users/42");
77
+ expect(match).not.toBe(null);
78
+ expect(match.params).toEqual({ id: "42" });
79
+ });
80
+ it("returns null for unmatched path", () => {
81
+ createFile("about/page.tsx");
82
+ const routes = scanDevRoutes(appDir);
83
+ const match = matchDevRoute(routes, "/nonexistent");
84
+ expect(match).toBe(null);
85
+ });
86
+ it("decodes URI components in params", () => {
87
+ createFile("posts/[slug]/page.tsx");
88
+ const routes = scanDevRoutes(appDir);
89
+ const match = matchDevRoute(routes, "/posts/hello%20world");
90
+ expect(match).not.toBe(null);
91
+ expect(match.params["slug"]).toBe("hello world");
92
+ });
93
+ it("matches with optional trailing slash", () => {
94
+ createFile("about/page.tsx");
95
+ const routes = scanDevRoutes(appDir);
96
+ const match = matchDevRoute(routes, "/about/");
97
+ expect(match).not.toBe(null);
98
+ });
99
+ });
100
+ // ─── findLayoutFiles ──────────────────────────────────────────────────────────
101
+ describe("findLayoutFiles", () => {
102
+ it("finds root layout", () => {
103
+ createFile("layout.tsx");
104
+ createFile("page.tsx");
105
+ const layouts = findLayoutFiles(join(appDir, "page.tsx"), appDir);
106
+ expect(layouts).toHaveLength(1);
107
+ expect(layouts[0]).toContain("layout.tsx");
108
+ });
109
+ it("finds nested layouts ordered outermost first", () => {
110
+ createFile("layout.tsx");
111
+ createFile("dashboard/layout.tsx");
112
+ createFile("dashboard/settings/page.tsx");
113
+ const layouts = findLayoutFiles(join(appDir, "dashboard/settings/page.tsx"), appDir);
114
+ expect(layouts).toHaveLength(2);
115
+ // Root layout should come first
116
+ expect(layouts[0]).toContain(join(appDir, "layout.tsx"));
117
+ expect(layouts[1]).toContain(join(appDir, "dashboard/layout.tsx"));
118
+ });
119
+ it("returns empty when no layouts exist", () => {
120
+ createFile("about/page.tsx");
121
+ const layouts = findLayoutFiles(join(appDir, "about/page.tsx"), appDir);
122
+ expect(layouts).toHaveLength(0);
123
+ });
124
+ });
125
+ // ─── findErrorFile ────────────────────────────────────────────────────────────
126
+ describe("findErrorFile", () => {
127
+ it("finds nearest error.tsx", () => {
128
+ createFile("error.tsx");
129
+ createFile("dashboard/page.tsx");
130
+ const errorFile = findErrorFile(join(appDir, "dashboard/page.tsx"), appDir);
131
+ expect(errorFile).not.toBe(null);
132
+ expect(errorFile).toContain("error.tsx");
133
+ });
134
+ it("returns null when no error file exists", () => {
135
+ createFile("page.tsx");
136
+ const errorFile = findErrorFile(join(appDir, "page.tsx"), appDir);
137
+ expect(errorFile).toBe(null);
138
+ });
139
+ it("prefers the innermost error.tsx", () => {
140
+ createFile("error.tsx");
141
+ createFile("dashboard/error.tsx");
142
+ createFile("dashboard/settings/page.tsx");
143
+ const errorFile = findErrorFile(join(appDir, "dashboard/settings/page.tsx"), appDir);
144
+ expect(errorFile).toContain(join("dashboard", "error.tsx"));
145
+ });
146
+ });
147
+ // ─── findLoadingFile ──────────────────────────────────────────────────────────
148
+ describe("findLoadingFile", () => {
149
+ it("finds nearest loading.tsx", () => {
150
+ createFile("loading.tsx");
151
+ createFile("page.tsx");
152
+ const loadingFile = findLoadingFile(join(appDir, "page.tsx"), appDir);
153
+ expect(loadingFile).not.toBe(null);
154
+ expect(loadingFile).toContain("loading.tsx");
155
+ });
156
+ it("returns null when no loading file exists", () => {
157
+ createFile("page.tsx");
158
+ const loadingFile = findLoadingFile(join(appDir, "page.tsx"), appDir);
159
+ expect(loadingFile).toBe(null);
160
+ });
161
+ });
162
+ // ─── API routes ───────────────────────────────────────────────────────────────
163
+ describe("scanDevApiRoutes", () => {
164
+ it("finds route.ts files", () => {
165
+ createFile("api/health/route.ts");
166
+ const routes = scanDevApiRoutes(appDir);
167
+ expect(routes).toHaveLength(1);
168
+ });
169
+ it("returns empty when no route files", () => {
170
+ createFile("page.tsx");
171
+ const routes = scanDevApiRoutes(appDir);
172
+ expect(routes).toHaveLength(0);
173
+ });
174
+ });
175
+ describe("matchDevApiRoute", () => {
176
+ it("matches static API route", () => {
177
+ createFile("api/health/route.ts");
178
+ const routes = scanDevApiRoutes(appDir);
179
+ const match = matchDevApiRoute(routes, "/api/health");
180
+ expect(match).not.toBe(null);
181
+ });
182
+ it("returns null for unmatched API path", () => {
183
+ createFile("api/health/route.ts");
184
+ const routes = scanDevApiRoutes(appDir);
185
+ const match = matchDevApiRoute(routes, "/api/nonexistent");
186
+ expect(match).toBe(null);
187
+ });
188
+ });
189
+ //# sourceMappingURL=router-dev.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router-dev.test.js","sourceRoot":"","sources":["../../src/ssr/router-dev.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Alab test utilities — zero setup required.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { renderPage, mockServerFn } from "alabjs/test";
7
+ * import { getUser } from "./app/users/[id]/page.server.js";
8
+ *
9
+ * mockServerFn(getUser, { id: "1", name: "Alice" });
10
+ * const { html, status } = await renderPage("/users/1");
11
+ * expect(html).toContain("Alice");
12
+ * ```
13
+ */
14
+ import { type ComponentType } from "react";
15
+ import type { ServerFn } from "../types/index.js";
16
+ /**
17
+ * Mock a `defineServerFn` function for the duration of a test.
18
+ *
19
+ * The mock is applied globally for the current test process. Use
20
+ * `clearMocks()` in `afterEach` if you need isolation between tests,
21
+ * or rely on Vitest's built-in mock isolation.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * import { getUser } from "./page.server.js";
26
+ * mockServerFn(getUser, { id: "1", name: "Alice", email: "alice@example.com" });
27
+ * ```
28
+ */
29
+ export declare function mockServerFn<T extends ServerFn<any, any, any>>(fn: T, returnValue: T extends ServerFn<any, infer O, any> ? O : never): void;
30
+ /**
31
+ * Mock a server function with a custom handler (for dynamic responses).
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * mockServerFnWith(getUser, async ({ params }) => {
36
+ * if (params.id === "1") return { name: "Alice" };
37
+ * throw new Error("Not found");
38
+ * });
39
+ * ```
40
+ */
41
+ export declare function mockServerFnWith<T extends ServerFn<any, any, any>>(fn: T, handler: T extends ServerFn<infer I, infer O, any> ? (ctx: {
42
+ params: Record<string, string>;
43
+ }, input: I) => Promise<O> : never): void;
44
+ /** Remove all server function mocks. Call in `afterEach` for test isolation. */
45
+ export declare function clearMocks(): void;
46
+ /** @internal Used by Alab's dev server to resolve mocked functions in tests. */
47
+ export declare function _getMock(fnName: string): unknown | undefined;
48
+ export interface RenderPageResult {
49
+ /** Full HTML string including the Alab shell. */
50
+ html: string;
51
+ /** HTTP status code (200, 404, 500, etc.). */
52
+ status: number;
53
+ /** Whether the render threw an error. */
54
+ error: Error | null;
55
+ }
56
+ export interface RenderPageOptions {
57
+ /**
58
+ * Params to inject — useful when the route path has dynamic segments.
59
+ * @example `{ id: "42" }` for `/users/[id]`
60
+ */
61
+ params?: Record<string, string>;
62
+ /** Search params to inject. */
63
+ searchParams?: Record<string, string>;
64
+ /**
65
+ * Request headers forwarded to middleware and server functions.
66
+ */
67
+ headers?: Record<string, string>;
68
+ }
69
+ /**
70
+ * Render a page component to an HTML string for integration testing.
71
+ *
72
+ * Automatically applies any `mockServerFn` mocks registered before this call.
73
+ * Does not start an HTTP server — renders entirely in-process.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * const { html, status } = await renderPage("/users/1", { params: { id: "1" } });
78
+ * expect(status).toBe(200);
79
+ * expect(html).toContain('<h1>Alice</h1>');
80
+ * ```
81
+ */
82
+ export declare function renderPage(path: string, options?: RenderPageOptions): Promise<RenderPageResult>;
83
+ /**
84
+ * Render a specific component to HTML (lower-level than `renderPage`).
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * import UserPage from "./app/users/[id]/page.js";
89
+ * const { html } = await renderComponent(UserPage, { params: { id: "1" }, searchParams: {} });
90
+ * ```
91
+ */
92
+ export declare function renderComponent<P extends Record<string, unknown>>(Component: ComponentType<P>, props: P): Promise<RenderPageResult>;
93
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAOlD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAC5D,EAAE,EAAE,CAAC,EACL,WAAW,EAAE,CAAC,SAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,GAC7D,IAAI,CAEN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAChE,EAAE,EAAE,CAAC,EACL,OAAO,EAAE,CAAC,SAAS,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,GAC9C,CAAC,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACjE,KAAK,GACR,IAAI,CAEN;AAED,gFAAgF;AAChF,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAE5D;AAID,MAAM,WAAW,gBAAgB;IAC/B,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAwC3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,EAC3B,KAAK,EAAE,CAAC,GACP,OAAO,CAAC,gBAAgB,CAAC,CAW3B"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Alab test utilities — zero setup required.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { renderPage, mockServerFn } from "alabjs/test";
7
+ * import { getUser } from "./app/users/[id]/page.server.js";
8
+ *
9
+ * mockServerFn(getUser, { id: "1", name: "Alice" });
10
+ * const { html, status } = await renderPage("/users/1");
11
+ * expect(html).toContain("Alice");
12
+ * ```
13
+ */
14
+ import { createElement } from "react";
15
+ import { renderToString } from "react-dom/server";
16
+ // ─── mockServerFn ─────────────────────────────────────────────────────────────
17
+ /** Registry of mocked server functions — keyed by function name. */
18
+ const _mocks = new Map();
19
+ /**
20
+ * Mock a `defineServerFn` function for the duration of a test.
21
+ *
22
+ * The mock is applied globally for the current test process. Use
23
+ * `clearMocks()` in `afterEach` if you need isolation between tests,
24
+ * or rely on Vitest's built-in mock isolation.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { getUser } from "./page.server.js";
29
+ * mockServerFn(getUser, { id: "1", name: "Alice", email: "alice@example.com" });
30
+ * ```
31
+ */
32
+ export function mockServerFn(fn, returnValue) {
33
+ _mocks.set(fn.name, returnValue);
34
+ }
35
+ /**
36
+ * Mock a server function with a custom handler (for dynamic responses).
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * mockServerFnWith(getUser, async ({ params }) => {
41
+ * if (params.id === "1") return { name: "Alice" };
42
+ * throw new Error("Not found");
43
+ * });
44
+ * ```
45
+ */
46
+ export function mockServerFnWith(fn, handler) {
47
+ _mocks.set(fn.name, handler);
48
+ }
49
+ /** Remove all server function mocks. Call in `afterEach` for test isolation. */
50
+ export function clearMocks() {
51
+ _mocks.clear();
52
+ }
53
+ /** @internal Used by Alab's dev server to resolve mocked functions in tests. */
54
+ export function _getMock(fnName) {
55
+ return _mocks.get(fnName);
56
+ }
57
+ /**
58
+ * Render a page component to an HTML string for integration testing.
59
+ *
60
+ * Automatically applies any `mockServerFn` mocks registered before this call.
61
+ * Does not start an HTTP server — renders entirely in-process.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const { html, status } = await renderPage("/users/1", { params: { id: "1" } });
66
+ * expect(status).toBe(200);
67
+ * expect(html).toContain('<h1>Alice</h1>');
68
+ * ```
69
+ */
70
+ export async function renderPage(path, options = {}) {
71
+ const { params = {}, searchParams = {} } = options;
72
+ // Dynamically resolve the page module from the file-system.
73
+ // In test environments, Vitest handles module resolution via the Vite plugin.
74
+ const appDir = new URL("../../app", import.meta.url).pathname;
75
+ // Convert URL path to a candidate file path.
76
+ // e.g. "/users/1" → try "app/users/[id]/page.tsx" based on path segments.
77
+ const segments = path.split("/").filter(Boolean);
78
+ const candidates = buildCandidatePaths(appDir, segments, params);
79
+ let PageComponent = null;
80
+ for (const candidate of candidates) {
81
+ try {
82
+ const mod = await import(candidate);
83
+ if (typeof mod.default === "function") {
84
+ PageComponent = mod.default;
85
+ break;
86
+ }
87
+ }
88
+ catch {
89
+ // Try next candidate.
90
+ }
91
+ }
92
+ if (!PageComponent) {
93
+ return { html: "", status: 404, error: new Error(`[alabjs/test] No page found for path: ${path}`) };
94
+ }
95
+ try {
96
+ const html = renderToString(createElement(PageComponent, { params, searchParams }));
97
+ return { html, status: 200, error: null };
98
+ }
99
+ catch (err) {
100
+ return {
101
+ html: "",
102
+ status: 500,
103
+ error: err instanceof Error ? err : new Error(String(err)),
104
+ };
105
+ }
106
+ }
107
+ /**
108
+ * Render a specific component to HTML (lower-level than `renderPage`).
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * import UserPage from "./app/users/[id]/page.js";
113
+ * const { html } = await renderComponent(UserPage, { params: { id: "1" }, searchParams: {} });
114
+ * ```
115
+ */
116
+ export async function renderComponent(Component, props) {
117
+ try {
118
+ const html = renderToString(createElement(Component, props));
119
+ return { html, status: 200, error: null };
120
+ }
121
+ catch (err) {
122
+ return {
123
+ html: "",
124
+ status: 500,
125
+ error: err instanceof Error ? err : new Error(String(err)),
126
+ };
127
+ }
128
+ }
129
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
130
+ function buildCandidatePaths(appDir, segments, params) {
131
+ const paramValues = Object.values(params);
132
+ const candidates = [];
133
+ // Try resolving dynamic segments in reverse (known params replace segments).
134
+ const resolvedSegments = segments.map((seg) => {
135
+ // If this segment matches a known param value, try both [param] and the value.
136
+ const matchingParam = paramValues.find((v) => v === seg);
137
+ return matchingParam ? `[${Object.keys(params).find((k) => params[k] === matchingParam) ?? seg}]` : seg;
138
+ });
139
+ const extensions = [".tsx", ".ts", ".jsx", ".js"];
140
+ for (const ext of extensions) {
141
+ candidates.push(`${appDir}/${resolvedSegments.join("/")}/page${ext}`);
142
+ candidates.push(`${appDir}/${segments.join("/")}/page${ext}`);
143
+ }
144
+ return candidates;
145
+ }
146
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import type { ReactElement } from "react";
2
+ /**
3
+ * Extracts dynamic segment names from a route path string.
4
+ *
5
+ * @example
6
+ * ExtractParams<"/users/[id]/posts/[slug]"> → "id" | "slug"
7
+ */
8
+ type ExtractParams<Path extends string> = Path extends `${string}[${infer Param}]${infer Rest}` ? Param | ExtractParams<Rest> : never;
9
+ /**
10
+ * A typed record of URL path parameters for a given route path.
11
+ *
12
+ * @example
13
+ * RouteParams<"/users/[id]"> → { id: string }
14
+ */
15
+ export type RouteParams<Path extends string = string> = [
16
+ ExtractParams<Path>
17
+ ] extends [never] ? Record<string, string> : {
18
+ readonly [K in ExtractParams<Path>]: string;
19
+ };
20
+ /**
21
+ * The context object passed to every server function.
22
+ * All fields are readonly — the context is immutable inside a handler.
23
+ */
24
+ export interface ServerFnContext<Path extends string = string> {
25
+ /** Typed URL path parameters derived from the route pattern. */
26
+ readonly params: RouteParams<Path>;
27
+ /** Parsed query string parameters. */
28
+ readonly query: Readonly<Record<string, string | readonly string[]>>;
29
+ /** Raw request headers (lowercase keys). */
30
+ readonly headers: Readonly<Record<string, string | readonly string[]>>;
31
+ /** HTTP method — always uppercase. */
32
+ readonly method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD";
33
+ /** Full request URL including protocol and host. */
34
+ readonly url: string;
35
+ }
36
+ declare const SERVER_FN_BRAND: unique symbol;
37
+ /**
38
+ * The type of a server function defined with `defineServerFn()`.
39
+ *
40
+ * **Type-level boundary enforcement:**
41
+ * - Runtime import (`import { fn } from "./page.server"`) in a client file
42
+ * → Rust compiler BUILD ERROR
43
+ * - Type-only import (`import type { fn } from "./page.server"`) in a client file
44
+ * → ✅ Allowed — erased at compile time, used only for inference
45
+ *
46
+ * Use `InferServerOutput<T>` and `InferServerInput<T>` to extract the types
47
+ * from a server function for use in `useServerData`.
48
+ */
49
+ export type ServerFn<Input = undefined, Output = unknown, Path extends string = string> = {
50
+ /** @internal Nominal brand — prevents plain functions from being used as ServerFn */
51
+ readonly [SERVER_FN_BRAND]: true;
52
+ (ctx: ServerFnContext<Path>, input: Input): Promise<Output>;
53
+ };
54
+ /** Extract the resolved output type of a ServerFn. */
55
+ export type InferServerOutput<T extends ServerFn<any, any, any>> = T extends ServerFn<any, infer O, any> ? Awaited<O> : never;
56
+ /** Extract the input type of a ServerFn. */
57
+ export type InferServerInput<T extends ServerFn<any, any, any>> = T extends ServerFn<infer I, any, any> ? I : never;
58
+ /** Extract the route path type of a ServerFn. */
59
+ export type InferServerPath<T extends ServerFn<any, any, any>> = T extends ServerFn<any, any, infer P> ? P : never;
60
+ /**
61
+ * A typed React page component for a given route path.
62
+ *
63
+ * @example
64
+ * // app/users/[id]/page.tsx
65
+ * const UserPage: ALabPage<"/users/[id]"> = ({ params }) => {
66
+ * params.id; // string ✅
67
+ * params.foo; // TS error ✅
68
+ * };
69
+ */
70
+ export type AlabPage<Path extends string = string> = (props: {
71
+ readonly params: RouteParams<Path>;
72
+ readonly searchParams: Readonly<Record<string, string | readonly string[]>>;
73
+ }) => ReactElement | null;
74
+ export interface OpenGraphMetadata {
75
+ readonly title?: string;
76
+ readonly description?: string;
77
+ readonly image?: string;
78
+ readonly url?: string;
79
+ readonly type?: "website" | "article" | "profile";
80
+ readonly siteName?: string;
81
+ }
82
+ export interface TwitterMetadata {
83
+ readonly card?: "summary" | "summary_large_image" | "app" | "player";
84
+ readonly title?: string;
85
+ readonly description?: string;
86
+ readonly image?: string;
87
+ readonly creator?: string;
88
+ }
89
+ /**
90
+ * Export `metadata` from any page to populate `<head>` on SSR.
91
+ *
92
+ * @example
93
+ * export const metadata: PageMetadata = {
94
+ * title: "About us",
95
+ * description: "Learn more about our team.",
96
+ * };
97
+ */
98
+ export interface PageMetadata {
99
+ readonly title?: string;
100
+ readonly description?: string;
101
+ readonly canonical?: string;
102
+ readonly robots?: string;
103
+ readonly og?: OpenGraphMetadata;
104
+ readonly twitter?: TwitterMetadata;
105
+ readonly themeColor?: string;
106
+ /** Additional arbitrary <meta> tags. */
107
+ readonly extra?: ReadonlyArray<Readonly<Record<string, string>>>;
108
+ }
109
+ /**
110
+ * Functional metadata for dynamic pages.
111
+ */
112
+ export type GenerateMetadata<Path extends string = string> = (props: {
113
+ readonly params: RouteParams<Path>;
114
+ readonly searchParams: Readonly<Record<string, string | readonly string[]>>;
115
+ }) => Promise<PageMetadata> | PageMetadata;
116
+ export {};
117
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Minimal interface for the @alabjs/compiler napi binding.
3
+ * Loaded dynamically at runtime — no static import needed.
4
+ */
5
+ export interface AlabNapi {
6
+ compileSource(source: string, filename: string, minify: boolean): string;
7
+ checkBoundary(source: string, filename: string): string;
8
+ buildRoutes(appDir: string): string;
9
+ optimizeImage(input: Buffer, quality?: number | null, width?: number | null, height?: number | null, format?: string | null): Promise<Buffer>;
10
+ /** Returns JSON `Array<{ name: string; endpoint: string }>` */
11
+ extractServerFns(source: string, filename: string): string;
12
+ /** Returns an ES module stub replacing the real handler in client bundles. */
13
+ serverFnStub(name: string, endpoint: string): string;
14
+ }
15
+ //# sourceMappingURL=napi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"napi.d.ts","sourceRoot":"","sources":["../../src/types/napi.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;IACzE,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IACxD,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACpC,aAAa,CACX,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,EACvB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,+DAA+D;IAC/D,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3D,8EAA8E;IAC9E,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;CACtD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=napi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"napi.js","sourceRoot":"","sources":["../../src/types/napi.ts"],"names":[],"mappings":""}