davaux 0.8.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 (333) hide show
  1. package/BASELINE.md +169 -0
  2. package/CLAUDE.md +518 -0
  3. package/LICENSE +21 -0
  4. package/README.md +36 -0
  5. package/ROADMAP.md +198 -0
  6. package/build.mjs +101 -0
  7. package/client/control.ts +247 -0
  8. package/client/hydrate.ts +37 -0
  9. package/client/index.ts +19 -0
  10. package/client/jsx-runtime.ts +209 -0
  11. package/client/resource.ts +122 -0
  12. package/client/signal.ts +211 -0
  13. package/client/store.ts +110 -0
  14. package/client/useHead.ts +63 -0
  15. package/dist/build/config.d.ts +3 -0
  16. package/dist/build/config.d.ts.map +1 -0
  17. package/dist/build/config.js +38 -0
  18. package/dist/build/config.js.map +7 -0
  19. package/dist/build/index.d.ts +2 -0
  20. package/dist/build/index.d.ts.map +1 -0
  21. package/dist/build/index.js +13 -0
  22. package/dist/build/index.js.map +7 -0
  23. package/dist/build/plugins.d.ts +7 -0
  24. package/dist/build/plugins.d.ts.map +1 -0
  25. package/dist/build/plugins.js +85 -0
  26. package/dist/build/plugins.js.map +7 -0
  27. package/dist/cli.d.ts +2 -0
  28. package/dist/cli.d.ts.map +1 -0
  29. package/dist/cli.js +427 -0
  30. package/dist/cli.js.map +7 -0
  31. package/dist/client/control.d.ts +49 -0
  32. package/dist/client/control.d.ts.map +1 -0
  33. package/dist/client/control.js +154 -0
  34. package/dist/client/control.js.map +7 -0
  35. package/dist/client/hydrate.d.ts +7 -0
  36. package/dist/client/hydrate.d.ts.map +1 -0
  37. package/dist/client/hydrate.js +23 -0
  38. package/dist/client/hydrate.js.map +7 -0
  39. package/dist/client/index.d.ts +12 -0
  40. package/dist/client/index.d.ts.map +1 -0
  41. package/dist/client/index.js +32 -0
  42. package/dist/client/index.js.map +7 -0
  43. package/dist/client/jsx-runtime.d.ts +40 -0
  44. package/dist/client/jsx-runtime.d.ts.map +1 -0
  45. package/dist/client/jsx-runtime.js +139 -0
  46. package/dist/client/jsx-runtime.js.map +7 -0
  47. package/dist/client/resource.d.ts +31 -0
  48. package/dist/client/resource.d.ts.map +1 -0
  49. package/dist/client/resource.js +64 -0
  50. package/dist/client/resource.js.map +7 -0
  51. package/dist/client/signal.d.ts +90 -0
  52. package/dist/client/signal.d.ts.map +1 -0
  53. package/dist/client/signal.js +115 -0
  54. package/dist/client/signal.js.map +7 -0
  55. package/dist/client/store.d.ts +26 -0
  56. package/dist/client/store.d.ts.map +1 -0
  57. package/dist/client/store.js +63 -0
  58. package/dist/client/store.js.map +7 -0
  59. package/dist/client/useHead.d.ts +28 -0
  60. package/dist/client/useHead.d.ts.map +1 -0
  61. package/dist/client/useHead.js +33 -0
  62. package/dist/client/useHead.js.map +7 -0
  63. package/dist/config.d.ts +182 -0
  64. package/dist/config.d.ts.map +1 -0
  65. package/dist/config.js +21 -0
  66. package/dist/config.js.map +7 -0
  67. package/dist/create-multisite.d.ts +2 -0
  68. package/dist/create-multisite.d.ts.map +1 -0
  69. package/dist/create-multisite.js +291 -0
  70. package/dist/create-multisite.js.map +7 -0
  71. package/dist/create.d.ts +2 -0
  72. package/dist/create.d.ts.map +1 -0
  73. package/dist/create.js +179 -0
  74. package/dist/create.js.map +7 -0
  75. package/dist/dev/blueprints.d.ts +11 -0
  76. package/dist/dev/blueprints.d.ts.map +1 -0
  77. package/dist/dev/blueprints.js +65 -0
  78. package/dist/dev/blueprints.js.map +7 -0
  79. package/dist/dev/components.d.ts +19 -0
  80. package/dist/dev/components.d.ts.map +1 -0
  81. package/dist/dev/components.js +87 -0
  82. package/dist/dev/components.js.map +7 -0
  83. package/dist/dev/insert.d.ts +11 -0
  84. package/dist/dev/insert.d.ts.map +1 -0
  85. package/dist/dev/insert.js +160 -0
  86. package/dist/dev/insert.js.map +7 -0
  87. package/dist/dev/remove.d.ts +53 -0
  88. package/dist/dev/remove.d.ts.map +1 -0
  89. package/dist/dev/remove.js +518 -0
  90. package/dist/dev/remove.js.map +7 -0
  91. package/dist/dev/watch.d.ts +26 -0
  92. package/dist/dev/watch.d.ts.map +1 -0
  93. package/dist/dev/watch.js +2905 -0
  94. package/dist/dev/watch.js.map +7 -0
  95. package/dist/errors.d.ts +6 -0
  96. package/dist/errors.d.ts.map +1 -0
  97. package/dist/errors.js +63 -0
  98. package/dist/errors.js.map +7 -0
  99. package/dist/generate.d.ts +2 -0
  100. package/dist/generate.d.ts.map +1 -0
  101. package/dist/generate.js +191 -0
  102. package/dist/generate.js.map +7 -0
  103. package/dist/index.d.ts +9 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +57 -0
  106. package/dist/index.js.map +7 -0
  107. package/dist/island.d.ts +24 -0
  108. package/dist/island.d.ts.map +1 -0
  109. package/dist/island.js +15 -0
  110. package/dist/island.js.map +7 -0
  111. package/dist/jsx-runtime.d.ts +406 -0
  112. package/dist/jsx-runtime.d.ts.map +1 -0
  113. package/dist/jsx-runtime.js +90 -0
  114. package/dist/jsx-runtime.js.map +7 -0
  115. package/dist/link.d.ts +27 -0
  116. package/dist/link.d.ts.map +1 -0
  117. package/dist/link.js +29 -0
  118. package/dist/link.js.map +7 -0
  119. package/dist/oml/fragment.d.ts +16 -0
  120. package/dist/oml/fragment.d.ts.map +1 -0
  121. package/dist/oml/fragment.js +26 -0
  122. package/dist/oml/fragment.js.map +7 -0
  123. package/dist/oml/index.d.ts +11 -0
  124. package/dist/oml/index.d.ts.map +1 -0
  125. package/dist/oml/index.js +21 -0
  126. package/dist/oml/index.js.map +7 -0
  127. package/dist/oml/jsx-runtime.d.ts +34 -0
  128. package/dist/oml/jsx-runtime.d.ts.map +1 -0
  129. package/dist/oml/jsx-runtime.js +59 -0
  130. package/dist/oml/jsx-runtime.js.map +7 -0
  131. package/dist/oml/jsx.d.ts +14 -0
  132. package/dist/oml/jsx.d.ts.map +1 -0
  133. package/dist/oml/jsx.js +96 -0
  134. package/dist/oml/jsx.js.map +7 -0
  135. package/dist/oml/page.d.ts +7 -0
  136. package/dist/oml/page.d.ts.map +1 -0
  137. package/dist/oml/page.js +6 -0
  138. package/dist/oml/page.js.map +7 -0
  139. package/dist/oml/render.d.ts +13 -0
  140. package/dist/oml/render.d.ts.map +1 -0
  141. package/dist/oml/render.js +117 -0
  142. package/dist/oml/render.js.map +7 -0
  143. package/dist/oml/types.d.ts +79 -0
  144. package/dist/oml/types.d.ts.map +1 -0
  145. package/dist/oml/types.js +64 -0
  146. package/dist/oml/types.js.map +7 -0
  147. package/dist/router/handler.d.ts +53 -0
  148. package/dist/router/handler.d.ts.map +1 -0
  149. package/dist/router/handler.js +342 -0
  150. package/dist/router/handler.js.map +7 -0
  151. package/dist/router/matcher.d.ts +21 -0
  152. package/dist/router/matcher.d.ts.map +1 -0
  153. package/dist/router/matcher.js +28 -0
  154. package/dist/router/matcher.js.map +7 -0
  155. package/dist/router/scanner.d.ts +17 -0
  156. package/dist/router/scanner.d.ts.map +1 -0
  157. package/dist/router/scanner.js +197 -0
  158. package/dist/router/scanner.js.map +7 -0
  159. package/dist/server/index.d.ts +23 -0
  160. package/dist/server/index.d.ts.map +1 -0
  161. package/dist/server/index.js +29 -0
  162. package/dist/server/index.js.map +7 -0
  163. package/dist/signal.d.ts +15 -0
  164. package/dist/signal.d.ts.map +1 -0
  165. package/dist/signal.js +29 -0
  166. package/dist/signal.js.map +7 -0
  167. package/dist/ssg.d.ts +45 -0
  168. package/dist/ssg.d.ts.map +1 -0
  169. package/dist/ssg.js +175 -0
  170. package/dist/ssg.js.map +7 -0
  171. package/dist/test/actions.test.d.ts +2 -0
  172. package/dist/test/actions.test.d.ts.map +1 -0
  173. package/dist/test/body-limits.test.d.ts +2 -0
  174. package/dist/test/body-limits.test.d.ts.map +1 -0
  175. package/dist/test/errors.test.d.ts +2 -0
  176. package/dist/test/errors.test.d.ts.map +1 -0
  177. package/dist/test/fixtures/routes/[id].page.d.ts +4 -0
  178. package/dist/test/fixtures/routes/[id].page.d.ts.map +1 -0
  179. package/dist/test/fixtures/routes/_error.d.ts +3 -0
  180. package/dist/test/fixtures/routes/_error.d.ts.map +1 -0
  181. package/dist/test/fixtures/routes/_global.d.ts +3 -0
  182. package/dist/test/fixtures/routes/_global.d.ts.map +1 -0
  183. package/dist/test/fixtures/routes/_layout-template.d.ts +3 -0
  184. package/dist/test/fixtures/routes/_layout-template.d.ts.map +1 -0
  185. package/dist/test/fixtures/routes/_layout.d.ts +3 -0
  186. package/dist/test/fixtures/routes/_layout.d.ts.map +1 -0
  187. package/dist/test/fixtures/routes/_layout_scripts.d.ts +3 -0
  188. package/dist/test/fixtures/routes/_layout_scripts.d.ts.map +1 -0
  189. package/dist/test/fixtures/routes/_middleware.d.ts +3 -0
  190. package/dist/test/fixtures/routes/_middleware.d.ts.map +1 -0
  191. package/dist/test/fixtures/routes/_redirect301_mw.d.ts +3 -0
  192. package/dist/test/fixtures/routes/_redirect301_mw.d.ts.map +1 -0
  193. package/dist/test/fixtures/routes/_redirect_mw.d.ts +3 -0
  194. package/dist/test/fixtures/routes/_redirect_mw.d.ts.map +1 -0
  195. package/dist/test/fixtures/routes/about.page.d.ts +3 -0
  196. package/dist/test/fixtures/routes/about.page.d.ts.map +1 -0
  197. package/dist/test/fixtures/routes/action.page.d.ts +6 -0
  198. package/dist/test/fixtures/routes/action.page.d.ts.map +1 -0
  199. package/dist/test/fixtures/routes/api/form-all.post.d.ts +3 -0
  200. package/dist/test/fixtures/routes/api/form-all.post.d.ts.map +1 -0
  201. package/dist/test/fixtures/routes/api/form-limited.post.d.ts +6 -0
  202. package/dist/test/fixtures/routes/api/form-limited.post.d.ts.map +1 -0
  203. package/dist/test/fixtures/routes/api/response-obj.get.d.ts +3 -0
  204. package/dist/test/fixtures/routes/api/response-obj.get.d.ts.map +1 -0
  205. package/dist/test/fixtures/routes/api/upload.post.d.ts +12 -0
  206. package/dist/test/fixtures/routes/api/upload.post.d.ts.map +1 -0
  207. package/dist/test/fixtures/routes/api/users.get.d.ts +6 -0
  208. package/dist/test/fixtures/routes/api/users.get.d.ts.map +1 -0
  209. package/dist/test/fixtures/routes/api/xml.get.d.ts +3 -0
  210. package/dist/test/fixtures/routes/api/xml.get.d.ts.map +1 -0
  211. package/dist/test/fixtures/routes/auth/_middleware.d.ts +3 -0
  212. package/dist/test/fixtures/routes/auth/_middleware.d.ts.map +1 -0
  213. package/dist/test/fixtures/routes/auth/protected.page.d.ts +3 -0
  214. package/dist/test/fixtures/routes/auth/protected.page.d.ts.map +1 -0
  215. package/dist/test/fixtures/routes/index.page.d.ts +3 -0
  216. package/dist/test/fixtures/routes/index.page.d.ts.map +1 -0
  217. package/dist/test/fixtures/routes/oml.page.d.ts +3 -0
  218. package/dist/test/fixtures/routes/oml.page.d.ts.map +1 -0
  219. package/dist/test/fixtures/routes/redirect.page.d.ts +3 -0
  220. package/dist/test/fixtures/routes/redirect.page.d.ts.map +1 -0
  221. package/dist/test/fixtures/routes/ssg/[slug].page.d.ts +5 -0
  222. package/dist/test/fixtures/routes/ssg/[slug].page.d.ts.map +1 -0
  223. package/dist/test/fixtures/routes/ssg/server.page.d.ts +4 -0
  224. package/dist/test/fixtures/routes/ssg/server.page.d.ts.map +1 -0
  225. package/dist/test/fixtures/routes/state.page.d.ts +3 -0
  226. package/dist/test/fixtures/routes/state.page.d.ts.map +1 -0
  227. package/dist/test/fixtures/routes/throw.page.d.ts +3 -0
  228. package/dist/test/fixtures/routes/throw.page.d.ts.map +1 -0
  229. package/dist/test/fixtures/routes/wiki/[...slug].page.d.ts +3 -0
  230. package/dist/test/fixtures/routes/wiki/[...slug].page.d.ts.map +1 -0
  231. package/dist/test/helpers.d.ts +37 -0
  232. package/dist/test/helpers.d.ts.map +1 -0
  233. package/dist/test/layouts.test.d.ts +2 -0
  234. package/dist/test/layouts.test.d.ts.map +1 -0
  235. package/dist/test/middleware.test.d.ts +2 -0
  236. package/dist/test/middleware.test.d.ts.map +1 -0
  237. package/dist/test/multipart.test.d.ts +2 -0
  238. package/dist/test/multipart.test.d.ts.map +1 -0
  239. package/dist/test/oml-routing.test.d.ts +2 -0
  240. package/dist/test/oml-routing.test.d.ts.map +1 -0
  241. package/dist/test/oml.test.d.ts +2 -0
  242. package/dist/test/oml.test.d.ts.map +1 -0
  243. package/dist/test/redirects.test.d.ts +2 -0
  244. package/dist/test/redirects.test.d.ts.map +1 -0
  245. package/dist/test/routing.test.d.ts +2 -0
  246. package/dist/test/routing.test.d.ts.map +1 -0
  247. package/dist/test/ssg.test.d.ts +2 -0
  248. package/dist/test/ssg.test.d.ts.map +1 -0
  249. package/dist/test/web-response.test.d.ts +2 -0
  250. package/dist/test/web-response.test.d.ts.map +1 -0
  251. package/dist/types.d.ts +314 -0
  252. package/dist/types.d.ts.map +1 -0
  253. package/dist/types.js +292 -0
  254. package/dist/types.js.map +7 -0
  255. package/package.json +103 -0
  256. package/pka.config.json +32 -0
  257. package/src/build/config.ts +42 -0
  258. package/src/build/index.ts +6 -0
  259. package/src/build/plugins.ts +118 -0
  260. package/src/cli.ts +502 -0
  261. package/src/config.ts +197 -0
  262. package/src/create-multisite.ts +310 -0
  263. package/src/create.ts +194 -0
  264. package/src/dev/blueprints.ts +75 -0
  265. package/src/dev/components.ts +108 -0
  266. package/src/dev/insert.ts +221 -0
  267. package/src/dev/remove.ts +677 -0
  268. package/src/dev/watch.ts +3098 -0
  269. package/src/env.d.ts +5 -0
  270. package/src/errors.ts +64 -0
  271. package/src/generate.ts +228 -0
  272. package/src/index.ts +67 -0
  273. package/src/island.ts +47 -0
  274. package/src/jsx-runtime.d.ts +408 -0
  275. package/src/jsx-runtime.d.ts.map +1 -0
  276. package/src/jsx-runtime.ts +536 -0
  277. package/src/link.ts +49 -0
  278. package/src/oml/fragment.ts +54 -0
  279. package/src/oml/index.ts +21 -0
  280. package/src/oml/jsx-runtime.ts +121 -0
  281. package/src/oml/jsx.ts +151 -0
  282. package/src/oml/page.ts +13 -0
  283. package/src/oml/render.ts +181 -0
  284. package/src/oml/types.ts +159 -0
  285. package/src/router/handler.ts +515 -0
  286. package/src/router/matcher.ts +52 -0
  287. package/src/router/scanner.ts +272 -0
  288. package/src/server/index.ts +49 -0
  289. package/src/signal.ts +39 -0
  290. package/src/ssg.ts +253 -0
  291. package/src/test/actions.test.ts +40 -0
  292. package/src/test/body-limits.test.ts +83 -0
  293. package/src/test/errors.test.ts +53 -0
  294. package/src/test/fixtures/routes/[id].page.ts +3 -0
  295. package/src/test/fixtures/routes/_error.ts +6 -0
  296. package/src/test/fixtures/routes/_global.ts +8 -0
  297. package/src/test/fixtures/routes/_layout-template.ts +7 -0
  298. package/src/test/fixtures/routes/_layout.ts +7 -0
  299. package/src/test/fixtures/routes/_layout_scripts.ts +8 -0
  300. package/src/test/fixtures/routes/_middleware.ts +8 -0
  301. package/src/test/fixtures/routes/_redirect301_mw.ts +5 -0
  302. package/src/test/fixtures/routes/_redirect_mw.ts +5 -0
  303. package/src/test/fixtures/routes/about.page.ts +6 -0
  304. package/src/test/fixtures/routes/action.page.ts +11 -0
  305. package/src/test/fixtures/routes/api/form-all.post.ts +5 -0
  306. package/src/test/fixtures/routes/api/form-limited.post.ts +6 -0
  307. package/src/test/fixtures/routes/api/response-obj.get.ts +17 -0
  308. package/src/test/fixtures/routes/api/upload.post.ts +14 -0
  309. package/src/test/fixtures/routes/api/users.get.ts +3 -0
  310. package/src/test/fixtures/routes/api/xml.get.ts +5 -0
  311. package/src/test/fixtures/routes/auth/_middleware.ts +11 -0
  312. package/src/test/fixtures/routes/auth/protected.page.ts +3 -0
  313. package/src/test/fixtures/routes/index.page.ts +3 -0
  314. package/src/test/fixtures/routes/oml.page.ts +7 -0
  315. package/src/test/fixtures/routes/redirect.page.ts +3 -0
  316. package/src/test/fixtures/routes/ssg/[slug].page.ts +8 -0
  317. package/src/test/fixtures/routes/ssg/server.page.ts +5 -0
  318. package/src/test/fixtures/routes/state.page.ts +4 -0
  319. package/src/test/fixtures/routes/throw.page.ts +5 -0
  320. package/src/test/fixtures/routes/wiki/[...slug].page.ts +3 -0
  321. package/src/test/helpers.ts +132 -0
  322. package/src/test/layouts.test.ts +76 -0
  323. package/src/test/middleware.test.ts +69 -0
  324. package/src/test/multipart.test.ts +91 -0
  325. package/src/test/oml-routing.test.ts +59 -0
  326. package/src/test/oml.test.ts +429 -0
  327. package/src/test/redirects.test.ts +32 -0
  328. package/src/test/routing.test.ts +118 -0
  329. package/src/test/ssg.test.ts +273 -0
  330. package/src/test/web-response.test.ts +33 -0
  331. package/src/types.ts +670 -0
  332. package/tsconfig.client.json +17 -0
  333. package/tsconfig.json +20 -0
package/src/env.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ // Ambient type declarations for assets that davaux handles at build time.
2
+ // Reference this file from your project:
3
+ // /// <reference types="davaux/env" />
4
+
5
+ declare module '*.css' {}
package/src/errors.ts ADDED
@@ -0,0 +1,64 @@
1
+ import type { Message } from 'esbuild'
2
+
3
+ export function formatBuildErrors(errors: Message[]): string {
4
+ return errors
5
+ .map((e) => {
6
+ const lines: string[] = [` ${e.text}`]
7
+ if (e.location) {
8
+ lines.push(` at ${e.location.file}:${e.location.line}:${e.location.column}`)
9
+ if (e.location.lineText.trim()) lines.push(` > ${e.location.lineText.trim()}`)
10
+ }
11
+ return lines.join('\n')
12
+ })
13
+ .join('\n\n')
14
+ }
15
+
16
+ export function frameworkWarn(message: string, hint?: string): void {
17
+ console.warn(`[davaux] ${message}`)
18
+ if (hint) console.warn(` hint: ${hint}`)
19
+ }
20
+
21
+ export function frameworkError(message: string, hint?: string): never {
22
+ console.error(`\n[davaux] ${message}`)
23
+ if (hint) console.error(` hint: ${hint}`)
24
+ process.exit(1)
25
+ }
26
+
27
+ export function handleBuildError(label: string, err: unknown): never {
28
+ if (
29
+ err != null &&
30
+ typeof err === 'object' &&
31
+ Array.isArray((err as { errors?: unknown }).errors)
32
+ ) {
33
+ const msgs = (err as { errors: Message[] }).errors
34
+ if (msgs.length > 0) {
35
+ console.error(`\n[davaux] ${label} failed:\n${formatBuildErrors(msgs)}`)
36
+ const cjsPkg = detectCjsPackage(msgs)
37
+ if (cjsPkg) {
38
+ console.error(
39
+ `\n Hint: "${cjsPkg}" uses CommonJS require() and cannot be bundled by esbuild.\n` +
40
+ ` Add it to the external list in davaux.config.ts:\n\n` +
41
+ ` export default defineConfig({\n` +
42
+ ` external: ['${cjsPkg}'],\n` +
43
+ ` })\n`,
44
+ )
45
+ }
46
+ process.exit(1)
47
+ }
48
+ }
49
+ console.error(`\n[davaux] ${label} failed:`, err)
50
+ process.exit(1)
51
+ }
52
+
53
+ // Detects "Dynamic require of X is not supported" errors and extracts the
54
+ // originating package name from the error location, so we can suggest adding
55
+ // it to `external`.
56
+ function detectCjsPackage(errors: Message[]): string | null {
57
+ for (const e of errors) {
58
+ if (!/[Dd]ynamic require/.test(e.text)) continue
59
+ const file = e.location?.file ?? ''
60
+ const m = file.match(/node_modules\/((?:@[^/]+\/)?[^/]+)/)
61
+ if (m) return m[1]
62
+ }
63
+ return null
64
+ }
@@ -0,0 +1,228 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
2
+ import { dirname, join, relative, resolve } from 'node:path'
3
+
4
+ const VALID_TYPES = ['page', 'api', 'layout', 'island', 'middleware'] as const
5
+ type GenerateType = (typeof VALID_TYPES)[number]
6
+
7
+ const VALID_METHODS = ['get', 'post', 'put', 'patch', 'delete'] as const
8
+ type HttpMethod = (typeof VALID_METHODS)[number]
9
+
10
+ export function generate(args: string[], cwd: string): void {
11
+ const [type, pathArg, ...rest] = args
12
+
13
+ if (!type || !VALID_TYPES.includes(type as GenerateType)) {
14
+ if (type) console.error(`[davaux] Unknown generator "${type}"`)
15
+ printUsage()
16
+ process.exit(1)
17
+ }
18
+
19
+ const routesDir = resolve(cwd, 'src', 'routes')
20
+ const islandsDir = resolve(cwd, 'src', 'islands')
21
+
22
+ switch (type as GenerateType) {
23
+ case 'page':
24
+ genPage(pathArg, routesDir, cwd)
25
+ break
26
+ case 'api': {
27
+ const methodArg = getFlag('--method', rest) ?? 'get'
28
+ if (!VALID_METHODS.includes(methodArg as HttpMethod)) {
29
+ console.error(`[davaux] Invalid method "${methodArg}". Valid: ${VALID_METHODS.join(', ')}`)
30
+ process.exit(1)
31
+ }
32
+ genApi(pathArg, routesDir, methodArg as HttpMethod, cwd)
33
+ break
34
+ }
35
+ case 'layout':
36
+ genLayout(pathArg, routesDir, cwd)
37
+ break
38
+ case 'island':
39
+ genIsland(pathArg, islandsDir, cwd)
40
+ break
41
+ case 'middleware':
42
+ genMiddleware(pathArg, routesDir, cwd)
43
+ break
44
+ }
45
+ }
46
+
47
+ // ─── Generators ───────────────────────────────────────────────────────────────
48
+
49
+ function genPage(pathArg: string | undefined, routesDir: string, cwd: string) {
50
+ if (!pathArg) {
51
+ console.error('[davaux] Usage: davaux generate page <path>')
52
+ console.error(' Example: davaux generate page about')
53
+ console.error(' Example: davaux generate page blog/[slug]')
54
+ process.exit(1)
55
+ }
56
+ const filePath = join(routesDir, `${pathArg}.page.tsx`)
57
+ writeGenerated(filePath, cwd, pageTemplate(pathArg))
58
+ }
59
+
60
+ function genApi(pathArg: string | undefined, routesDir: string, method: HttpMethod, cwd: string) {
61
+ if (!pathArg) {
62
+ console.error('[davaux] Usage: davaux generate api <path> [--method get|post|put|patch|delete]')
63
+ process.exit(1)
64
+ }
65
+ const filePath = join(routesDir, `${pathArg}.${method}.ts`)
66
+ writeGenerated(filePath, cwd, apiTemplate(pathArg))
67
+ }
68
+
69
+ function genLayout(pathArg: string | undefined, routesDir: string, cwd: string) {
70
+ const filePath = pathArg
71
+ ? join(routesDir, pathArg, '_layout.tsx')
72
+ : join(routesDir, '_layout.tsx')
73
+ writeGenerated(filePath, cwd, layoutTemplate())
74
+ }
75
+
76
+ function genIsland(nameArg: string | undefined, islandsDir: string, cwd: string) {
77
+ if (!nameArg) {
78
+ console.error('[davaux] Usage: davaux generate island <Name>')
79
+ console.error(' Example: davaux generate island Counter')
80
+ process.exit(1)
81
+ }
82
+ const filePath = join(islandsDir, `${nameArg}.tsx`)
83
+ writeGenerated(filePath, cwd, islandTemplate(nameArg))
84
+ }
85
+
86
+ function genMiddleware(pathArg: string | undefined, routesDir: string, cwd: string) {
87
+ const filePath = pathArg
88
+ ? join(routesDir, pathArg, '_middleware.ts')
89
+ : join(routesDir, '_middleware.ts')
90
+ writeGenerated(filePath, cwd, middlewareTemplate())
91
+ }
92
+
93
+ // ─── Templates ────────────────────────────────────────────────────────────────
94
+
95
+ function pageTemplate(routePath: string): string {
96
+ const title = toTitle(lastSegment(routePath))
97
+ const hasParams = routePath.includes('[')
98
+
99
+ if (hasParams) {
100
+ return `import { definePage, defineStaticPaths, type ExtractParams } from 'davaux'
101
+
102
+ export const getStaticPaths = defineStaticPaths(async () => [
103
+ // Return one entry per URL to pre-render with \`davaux static\`
104
+ { params: { ${firstParam(routePath)}: 'example' } },
105
+ ])
106
+
107
+ export default definePage<ExtractParams<'${routePath}'>>((ctx) => {
108
+ return <h1>${title}: {ctx.params.${firstParam(routePath)}}</h1>
109
+ })
110
+ `
111
+ }
112
+
113
+ return `import { definePage } from 'davaux'
114
+
115
+ export default definePage((ctx) => {
116
+ ctx.head.title = '${title}'
117
+ return <h1>${title}</h1>
118
+ })
119
+ `
120
+ }
121
+
122
+ function apiTemplate(routePath: string): string {
123
+ const hasParams = routePath.includes('[')
124
+
125
+ if (hasParams) {
126
+ return `import { defineHandler, type ExtractParams } from 'davaux'
127
+
128
+ export default defineHandler<unknown, ExtractParams<'${routePath}'>>(async (_ctx) => {
129
+ return { ok: true }
130
+ })
131
+ `
132
+ }
133
+
134
+ return `import { defineHandler } from 'davaux'
135
+
136
+ export default defineHandler(async (_ctx) => {
137
+ return { ok: true }
138
+ })
139
+ `
140
+ }
141
+
142
+ function layoutTemplate(): string {
143
+ return `import { defineLayout } from 'davaux'
144
+
145
+ export default defineLayout(({ children }) => (
146
+ <div>
147
+ {children as unknown as string}
148
+ </div>
149
+ ))
150
+ `
151
+ }
152
+
153
+ function islandTemplate(name: string): string {
154
+ return `import { createSignal } from 'davaux/client'
155
+
156
+ export default function ${name}() {
157
+ const [count, setCount] = createSignal(0)
158
+ return (
159
+ <button type="button" onClick={() => setCount(count() + 1)}>
160
+ {() => count()}
161
+ </button>
162
+ )
163
+ }
164
+ `
165
+ }
166
+
167
+ function middlewareTemplate(): string {
168
+ return `import { defineMiddleware } from 'davaux'
169
+
170
+ export default defineMiddleware(async (_ctx, next) => {
171
+ await next()
172
+ })
173
+ `
174
+ }
175
+
176
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
177
+
178
+ function writeGenerated(filePath: string, cwd: string, content: string) {
179
+ if (existsSync(filePath)) {
180
+ console.error(`[davaux] File already exists: ${relative(cwd, filePath)}`)
181
+ process.exit(1)
182
+ }
183
+ mkdirSync(dirname(filePath), { recursive: true })
184
+ writeFileSync(filePath, content, 'utf8')
185
+ console.log(`[davaux] Created ${relative(cwd, filePath)}`)
186
+ }
187
+
188
+ function lastSegment(routePath: string): string {
189
+ const segments = routePath.split('/')
190
+ return segments[segments.length - 1]
191
+ .replace(/\[.*?\]/g, '')
192
+ .replace(/[-_]/g, ' ')
193
+ .trim()
194
+ }
195
+
196
+ function toTitle(segment: string): string {
197
+ return segment.replace(/\b\w/g, (c) => c.toUpperCase()).trim() || 'Page'
198
+ }
199
+
200
+ function firstParam(routePath: string): string {
201
+ const match = routePath.match(/\[(\w+)\]/)
202
+ return match ? match[1] : 'id'
203
+ }
204
+
205
+ function getFlag(name: string, argv: string[]): string | undefined {
206
+ const idx = argv.indexOf(name)
207
+ return idx !== -1 ? argv[idx + 1] : undefined
208
+ }
209
+
210
+ function printUsage() {
211
+ console.error('Usage: davaux generate <type> [path]')
212
+ console.error('')
213
+ console.error('Types:')
214
+ console.error(' page <path> Page route')
215
+ console.error(' api <path> [--method <method>] API route (default: get)')
216
+ console.error(' layout [path] Layout (root if no path given)')
217
+ console.error(' island <Name> Client island component')
218
+ console.error(' middleware [path] Middleware (root if no path given)')
219
+ console.error('')
220
+ console.error('Examples:')
221
+ console.error(' davaux generate page about')
222
+ console.error(' davaux generate page blog/[slug]')
223
+ console.error(' davaux generate api users')
224
+ console.error(' davaux generate api users --method post')
225
+ console.error(' davaux generate layout admin')
226
+ console.error(' davaux generate island Counter')
227
+ console.error(' davaux generate middleware admin')
228
+ }
package/src/index.ts ADDED
@@ -0,0 +1,67 @@
1
+ export { island } from './island.js'
2
+ export type { JSX } from './jsx-runtime.js'
3
+ export { createLink } from './link.js'
4
+ export type {
5
+ OmlBlueprint,
6
+ OmlComponent,
7
+ OmlElement,
8
+ OmlFragment,
9
+ OmlFragmentOptions,
10
+ OmlNode,
11
+ OmlPageHandler,
12
+ OmlPropSchema,
13
+ OmlProps,
14
+ OmlPropType,
15
+ OmlRaw,
16
+ OmlText,
17
+ } from './oml/index.js'
18
+ export {
19
+ blueprintToFile,
20
+ clearAllFragments,
21
+ defineFragment,
22
+ defineOmlPage,
23
+ parseOml,
24
+ parseOmlBlueprint,
25
+ renderToHtml,
26
+ renderToJsx,
27
+ } from './oml/index.js'
28
+ export { batch, createEffect, createMemo, createSignal, untrack } from './signal.js'
29
+ export type {
30
+ ActionFn,
31
+ ApiHandler,
32
+ CookieOptions,
33
+ ErrorPageHandler,
34
+ ErrorPageProps,
35
+ ExtractParams,
36
+ GetStaticPathsFn,
37
+ IslandFile,
38
+ LayoutFile,
39
+ LayoutHandler,
40
+ LayoutProps,
41
+ MiddlewareFile,
42
+ MiddlewareFn,
43
+ MultipartFile,
44
+ MultipartResult,
45
+ PageHandler,
46
+ RequestContext,
47
+ RouteFile,
48
+ RouteType,
49
+ ScanResult,
50
+ State,
51
+ StaticPath,
52
+ Validator,
53
+ } from './types.js'
54
+ export {
55
+ CookieJar,
56
+ defineAction,
57
+ defineError,
58
+ defineHandler,
59
+ defineLayout,
60
+ defineMiddleware,
61
+ definePage,
62
+ defineStaticPaths,
63
+ PayloadTooLargeError,
64
+ RedirectError,
65
+ redirect,
66
+ ValidationError,
67
+ } from './types.js'
package/src/island.ts ADDED
@@ -0,0 +1,47 @@
1
+ import type { JSX } from './jsx-runtime.js'
2
+
3
+ /** A component intended to run on both server and client. */
4
+ export type IslandComponent<P extends Record<string, unknown> = Record<string, unknown>> = (
5
+ props: P,
6
+ ) => JSX.Element
7
+
8
+ let counter = 0
9
+
10
+ /**
11
+ * Mark a component as a client island. Write the component once — the framework
12
+ * compiles it for both server and client automatically.
13
+ *
14
+ * On the server: renders initial HTML and embeds serialized props in `data-props`.
15
+ * On the client: `hydrate()` picks up `[data-island]` elements and remounts the
16
+ * component with full signal reactivity.
17
+ *
18
+ * @example
19
+ * // src/islands/Counter.tsx
20
+ * import { island } from 'davaux'
21
+ * import { createSignal } from 'davaux/client'
22
+ *
23
+ * function Counter({ initial = 0 }: { initial?: number }) {
24
+ * const [count, setCount] = createSignal(initial)
25
+ * return <button onClick={() => setCount(c => c + 1)}>{() => count()}</button>
26
+ * }
27
+ * export default island(Counter)
28
+ */
29
+ export function island<P extends Record<string, unknown>>(
30
+ Component: IslandComponent<P>,
31
+ islandId?: string,
32
+ ): (props: P) => Promise<string> {
33
+ const id = islandId ?? Component.name ?? `island-${counter++}`
34
+
35
+ const wrapper = async (props: P): Promise<string> => {
36
+ const rendered = await (Component(props) as unknown as Promise<string> | string)
37
+ const serialized = JSON.stringify(props)
38
+ .replace(/&/g, '\\u0026')
39
+ .replace(/</g, '\\u003c')
40
+ .replace(/>/g, '\\u003e')
41
+ .replace(/'/g, '\\u0027')
42
+
43
+ return `<div data-island="${id}" data-props='${serialized}'>${rendered}</div>`
44
+ }
45
+ Object.defineProperty(wrapper, 'name', { value: id, configurable: true })
46
+ return wrapper
47
+ }