@async/db 0.2.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 (398) hide show
  1. package/CHANGELOG.md +167 -0
  2. package/README.md +431 -0
  3. package/SPEC.md +1429 -0
  4. package/db.config.example.mjs +128 -0
  5. package/dist/cli/args.d.ts +8 -0
  6. package/dist/cli/args.js +16 -0
  7. package/dist/cli/commands/create.d.ts +3 -0
  8. package/dist/cli/commands/create.js +13 -0
  9. package/dist/cli/commands/doctor.d.ts +3 -0
  10. package/dist/cli/commands/doctor.js +31 -0
  11. package/dist/cli/commands/generate.d.ts +6 -0
  12. package/dist/cli/commands/generate.js +24 -0
  13. package/dist/cli/commands/operations.d.ts +12 -0
  14. package/dist/cli/commands/operations.js +61 -0
  15. package/dist/cli/commands/schema.d.ts +11 -0
  16. package/dist/cli/commands/schema.js +1086 -0
  17. package/dist/cli/commands/serve.d.ts +9 -0
  18. package/dist/cli/commands/serve.js +18 -0
  19. package/dist/cli/commands/sync.d.ts +3 -0
  20. package/dist/cli/commands/sync.js +11 -0
  21. package/dist/cli/commands/types.d.ts +7 -0
  22. package/dist/cli/commands/types.js +37 -0
  23. package/dist/cli/commands/viewer.d.ts +6 -0
  24. package/dist/cli/commands/viewer.js +29 -0
  25. package/dist/cli/index.d.ts +2 -0
  26. package/dist/cli/index.js +108 -0
  27. package/dist/cli/output.d.ts +25 -0
  28. package/dist/cli/output.js +149 -0
  29. package/dist/cli/schema-prompt.d.ts +20 -0
  30. package/dist/cli/schema-prompt.js +66 -0
  31. package/dist/cli.d.ts +2 -0
  32. package/dist/cli.js +3 -0
  33. package/dist/client-cache.d.ts +105 -0
  34. package/dist/client-cache.js +916 -0
  35. package/dist/client.d.ts +64 -0
  36. package/dist/client.js +405 -0
  37. package/dist/config-public.d.ts +1 -0
  38. package/dist/config-public.js +1 -0
  39. package/dist/config.d.ts +54 -0
  40. package/dist/config.js +2 -0
  41. package/dist/csv.d.ts +1 -0
  42. package/dist/csv.js +1 -0
  43. package/dist/db.d.ts +3 -0
  44. package/dist/db.js +3 -0
  45. package/dist/doctor.d.ts +1 -0
  46. package/dist/doctor.js +1 -0
  47. package/dist/errors.d.ts +1 -0
  48. package/dist/errors.js +1 -0
  49. package/dist/features/config/defaults.d.ts +98 -0
  50. package/dist/features/config/defaults.js +95 -0
  51. package/dist/features/config/load.d.ts +11 -0
  52. package/dist/features/config/load.js +265 -0
  53. package/dist/features/config/public.d.ts +17 -0
  54. package/dist/features/config/public.js +75 -0
  55. package/dist/features/doctor/duplicate-ids.d.ts +18 -0
  56. package/dist/features/doctor/duplicate-ids.js +79 -0
  57. package/dist/features/doctor/field-consistency.d.ts +17 -0
  58. package/dist/features/doctor/field-consistency.js +48 -0
  59. package/dist/features/doctor/index.d.ts +39 -0
  60. package/dist/features/doctor/index.js +177 -0
  61. package/dist/features/doctor/relations.d.ts +22 -0
  62. package/dist/features/doctor/relations.js +90 -0
  63. package/dist/features/doctor/schema-guidance.d.ts +35 -0
  64. package/dist/features/doctor/schema-guidance.js +184 -0
  65. package/dist/features/generate/registry.d.ts +14 -0
  66. package/dist/features/generate/registry.js +37 -0
  67. package/dist/features/http/registry.d.ts +46 -0
  68. package/dist/features/http/registry.js +86 -0
  69. package/dist/features/operations/index.d.ts +49 -0
  70. package/dist/features/operations/index.js +199 -0
  71. package/dist/features/operations/maps.d.ts +1 -0
  72. package/dist/features/operations/maps.js +10 -0
  73. package/dist/features/operations/readiness.d.ts +30 -0
  74. package/dist/features/operations/readiness.js +228 -0
  75. package/dist/features/operations/runtime.d.ts +57 -0
  76. package/dist/features/operations/runtime.js +288 -0
  77. package/dist/features/runtime/collection.d.ts +51 -0
  78. package/dist/features/runtime/collection.js +198 -0
  79. package/dist/features/runtime/db.d.ts +152 -0
  80. package/dist/features/runtime/db.js +824 -0
  81. package/dist/features/runtime/document.d.ts +43 -0
  82. package/dist/features/runtime/document.js +111 -0
  83. package/dist/features/runtime/fanout.d.ts +24 -0
  84. package/dist/features/runtime/fanout.js +77 -0
  85. package/dist/features/runtime/json-pointer.d.ts +5 -0
  86. package/dist/features/runtime/json-pointer.js +49 -0
  87. package/dist/features/runtime/scope-state.d.ts +44 -0
  88. package/dist/features/runtime/scope-state.js +185 -0
  89. package/dist/features/runtime/state.d.ts +1 -0
  90. package/dist/features/runtime/state.js +1 -0
  91. package/dist/features/schema/api.d.ts +107 -0
  92. package/dist/features/schema/api.js +460 -0
  93. package/dist/features/schema/builders.d.ts +86 -0
  94. package/dist/features/schema/builders.js +110 -0
  95. package/dist/features/schema/fields.d.ts +38 -0
  96. package/dist/features/schema/fields.js +296 -0
  97. package/dist/features/schema/generated.d.ts +29 -0
  98. package/dist/features/schema/generated.js +32 -0
  99. package/dist/features/schema/locator.d.ts +16 -0
  100. package/dist/features/schema/locator.js +135 -0
  101. package/dist/features/schema/manifest.d.ts +91 -0
  102. package/dist/features/schema/manifest.js +384 -0
  103. package/dist/features/schema/metadata.d.ts +30 -0
  104. package/dist/features/schema/metadata.js +75 -0
  105. package/dist/features/schema/project.d.ts +46 -0
  106. package/dist/features/schema/project.js +442 -0
  107. package/dist/features/schema/relations.d.ts +38 -0
  108. package/dist/features/schema/relations.js +109 -0
  109. package/dist/features/schema/resolvers.d.ts +36 -0
  110. package/dist/features/schema/resolvers.js +111 -0
  111. package/dist/features/schema/resource.d.ts +75 -0
  112. package/dist/features/schema/resource.js +253 -0
  113. package/dist/features/schema/source-definitions.d.ts +21 -0
  114. package/dist/features/schema/source-definitions.js +29 -0
  115. package/dist/features/schema/sources.d.ts +83 -0
  116. package/dist/features/schema/sources.js +689 -0
  117. package/dist/features/schema/standard-schema.d.ts +57 -0
  118. package/dist/features/schema/standard-schema.js +232 -0
  119. package/dist/features/schema/validation.d.ts +69 -0
  120. package/dist/features/schema/validation.js +434 -0
  121. package/dist/features/storage/events.d.ts +12 -0
  122. package/dist/features/storage/events.js +30 -0
  123. package/dist/features/storage/json.d.ts +112 -0
  124. package/dist/features/storage/json.js +239 -0
  125. package/dist/features/storage/memory.d.ts +30 -0
  126. package/dist/features/storage/memory.js +44 -0
  127. package/dist/features/storage/resource-json.d.ts +31 -0
  128. package/dist/features/storage/resource-json.js +76 -0
  129. package/dist/features/storage/runtime.d.ts +37 -0
  130. package/dist/features/storage/runtime.js +184 -0
  131. package/dist/features/storage/source-metadata.d.ts +20 -0
  132. package/dist/features/storage/source-metadata.js +25 -0
  133. package/dist/features/storage/source.d.ts +37 -0
  134. package/dist/features/storage/source.js +60 -0
  135. package/dist/features/storage/static.d.ts +29 -0
  136. package/dist/features/storage/static.js +42 -0
  137. package/dist/features/sync/defaults.d.ts +21 -0
  138. package/dist/features/sync/defaults.js +21 -0
  139. package/dist/features/sync/index.d.ts +35 -0
  140. package/dist/features/sync/index.js +85 -0
  141. package/dist/features/sync/mirror-state.d.ts +14 -0
  142. package/dist/features/sync/mirror-state.js +4 -0
  143. package/dist/features/sync/runtime-dirs.d.ts +5 -0
  144. package/dist/features/sync/runtime-dirs.js +9 -0
  145. package/dist/features/sync/source-writes.d.ts +15 -0
  146. package/dist/features/sync/source-writes.js +27 -0
  147. package/dist/features/sync/synthetic-seed.d.ts +26 -0
  148. package/dist/features/sync/synthetic-seed.js +83 -0
  149. package/dist/features/viewer/manifest.d.ts +148 -0
  150. package/dist/features/viewer/manifest.js +165 -0
  151. package/dist/fs-utils.d.ts +1 -0
  152. package/dist/fs-utils.js +1 -0
  153. package/dist/generate/hono/app.d.ts +6 -0
  154. package/dist/generate/hono/app.js +51 -0
  155. package/dist/generate/hono/graphql.d.ts +7 -0
  156. package/dist/generate/hono/graphql.js +53 -0
  157. package/dist/generate/hono/index.d.ts +55 -0
  158. package/dist/generate/hono/index.js +140 -0
  159. package/dist/generate/hono/package.d.ts +6 -0
  160. package/dist/generate/hono/package.js +44 -0
  161. package/dist/generate/hono/readme.d.ts +13 -0
  162. package/dist/generate/hono/readme.js +28 -0
  163. package/dist/generate/hono/repository.d.ts +1 -0
  164. package/dist/generate/hono/repository.js +27 -0
  165. package/dist/generate/hono/rest.d.ts +1 -0
  166. package/dist/generate/hono/rest.js +38 -0
  167. package/dist/generate/hono/schema.d.ts +13 -0
  168. package/dist/generate/hono/schema.js +18 -0
  169. package/dist/generate/hono/sqlite.d.ts +20 -0
  170. package/dist/generate/hono/sqlite.js +266 -0
  171. package/dist/generate/hono/validators.d.ts +1 -0
  172. package/dist/generate/hono/validators.js +141 -0
  173. package/dist/generate/hono.d.ts +1 -0
  174. package/dist/generate/hono.js +1 -0
  175. package/dist/graphql/execute.d.ts +14 -0
  176. package/dist/graphql/execute.js +719 -0
  177. package/dist/graphql/http.d.ts +15 -0
  178. package/dist/graphql/http.js +29 -0
  179. package/dist/graphql/index.d.ts +3 -0
  180. package/dist/graphql/index.js +3 -0
  181. package/dist/graphql/parser.d.ts +54 -0
  182. package/dist/graphql/parser.js +433 -0
  183. package/dist/hono.d.ts +77 -0
  184. package/dist/hono.js +1 -0
  185. package/dist/index.d.ts +1065 -0
  186. package/dist/index.js +14 -0
  187. package/dist/integrations/hono.d.ts +136 -0
  188. package/dist/integrations/hono.js +508 -0
  189. package/dist/integrations/kv.d.ts +69 -0
  190. package/dist/integrations/kv.js +69 -0
  191. package/dist/integrations/postgres.d.ts +52 -0
  192. package/dist/integrations/postgres.js +113 -0
  193. package/dist/integrations/sqlite.d.ts +112 -0
  194. package/dist/integrations/sqlite.js +489 -0
  195. package/dist/integrations/vite.d.ts +45 -0
  196. package/dist/integrations/vite.js +111 -0
  197. package/dist/json.d.ts +48 -0
  198. package/dist/json.js +1 -0
  199. package/dist/jsonc.d.ts +1 -0
  200. package/dist/jsonc.js +1 -0
  201. package/dist/kv.d.ts +24 -0
  202. package/dist/kv.js +1 -0
  203. package/dist/mock.d.ts +1 -0
  204. package/dist/mock.js +1 -0
  205. package/dist/names.d.ts +1 -0
  206. package/dist/names.js +1 -0
  207. package/dist/operations.d.ts +3 -0
  208. package/dist/operations.js +3 -0
  209. package/dist/postgres.d.ts +24 -0
  210. package/dist/postgres.js +1 -0
  211. package/dist/redis.d.ts +14 -0
  212. package/dist/redis.js +1 -0
  213. package/dist/rest/formats.d.ts +80 -0
  214. package/dist/rest/formats.js +318 -0
  215. package/dist/rest/handler.d.ts +111 -0
  216. package/dist/rest/handler.js +833 -0
  217. package/dist/rest/shape.d.ts +33 -0
  218. package/dist/rest/shape.js +218 -0
  219. package/dist/schema-builders.d.ts +1 -0
  220. package/dist/schema-builders.js +1 -0
  221. package/dist/schema-manifest.d.ts +1 -0
  222. package/dist/schema-manifest.js +1 -0
  223. package/dist/schema.d.ts +193 -0
  224. package/dist/schema.js +6 -0
  225. package/dist/server.d.ts +116 -0
  226. package/dist/server.js +601 -0
  227. package/dist/shared/csv.d.ts +8 -0
  228. package/dist/shared/csv.js +149 -0
  229. package/dist/shared/errors.d.ts +40 -0
  230. package/dist/shared/errors.js +55 -0
  231. package/dist/shared/fs-utils.d.ts +4 -0
  232. package/dist/shared/fs-utils.js +30 -0
  233. package/dist/shared/jsonc.d.ts +2 -0
  234. package/dist/shared/jsonc.js +99 -0
  235. package/dist/shared/mock.d.ts +40 -0
  236. package/dist/shared/mock.js +83 -0
  237. package/dist/shared/names.d.ts +28 -0
  238. package/dist/shared/names.js +127 -0
  239. package/dist/shared/operations.d.ts +32 -0
  240. package/dist/shared/operations.js +302 -0
  241. package/dist/sqlite.d.ts +24 -0
  242. package/dist/sqlite.js +1 -0
  243. package/dist/state.d.ts +1 -0
  244. package/dist/state.js +1 -0
  245. package/dist/sync.d.ts +1 -0
  246. package/dist/sync.js +1 -0
  247. package/dist/tracing.d.ts +95 -0
  248. package/dist/tracing.js +260 -0
  249. package/dist/types.d.ts +51 -0
  250. package/dist/types.js +285 -0
  251. package/dist/viewer-manifest.d.ts +1 -0
  252. package/dist/viewer-manifest.js +1 -0
  253. package/dist/vite.d.ts +59 -0
  254. package/dist/vite.js +1 -0
  255. package/dist/web/json-viewer.d.ts +5 -0
  256. package/dist/web/json-viewer.js +176 -0
  257. package/dist/web/viewer.d.ts +12 -0
  258. package/dist/web/viewer.js +1015 -0
  259. package/docs/README.md +42 -0
  260. package/docs/architecture.md +112 -0
  261. package/docs/ci-and-release.md +177 -0
  262. package/docs/cms-storage-patterns.md +108 -0
  263. package/docs/concepts.md +141 -0
  264. package/docs/configuration.md +552 -0
  265. package/docs/fixtures-and-schemas.md +527 -0
  266. package/docs/fork-branch-workflows.md +108 -0
  267. package/docs/generated-files.md +174 -0
  268. package/docs/getting-started.md +165 -0
  269. package/docs/integrations.md +206 -0
  270. package/docs/json-production.md +120 -0
  271. package/docs/package-api.md +418 -0
  272. package/docs/prototype-to-production.md +378 -0
  273. package/docs/server-and-viewer.md +466 -0
  274. package/docs/store-graduation.md +120 -0
  275. package/docs/typescript-schema-sources.md +79 -0
  276. package/examples/advanced/README.md +55 -0
  277. package/examples/advanced/db/projects.schema.jsonc +44 -0
  278. package/examples/advanced/db/settings.jsonc +9 -0
  279. package/examples/advanced/db/users.json +23 -0
  280. package/examples/advanced/db/users.schema.mjs +31 -0
  281. package/examples/advanced/db.config.mjs +18 -0
  282. package/examples/advanced/example.json +5 -0
  283. package/examples/advanced/src/generated/db.types.d.ts +64 -0
  284. package/examples/basic/README.md +95 -0
  285. package/examples/basic/db/operations/get-user.jsonc +8 -0
  286. package/examples/basic/db/settings.json +7 -0
  287. package/examples/basic/db/users.schema.jsonc +36 -0
  288. package/examples/basic/db.config.mjs +68 -0
  289. package/examples/basic/example.json +5 -0
  290. package/examples/basic/src/generated/db.types.d.ts +39 -0
  291. package/examples/cms-json-publish/README.md +21 -0
  292. package/examples/cms-json-publish/db/navigation.json +7 -0
  293. package/examples/cms-json-publish/db/pages.json +18 -0
  294. package/examples/cms-json-publish/example.json +5 -0
  295. package/examples/cms-json-publish/src/cms.mjs +104 -0
  296. package/examples/computed-fields/README.md +93 -0
  297. package/examples/computed-fields/db/orders.schema.mjs +62 -0
  298. package/examples/computed-fields/db/posts.schema.mjs +59 -0
  299. package/examples/computed-fields/db/products.schema.mjs +39 -0
  300. package/examples/computed-fields/db/users.schema.mjs +43 -0
  301. package/examples/computed-fields/db.config.mjs +15 -0
  302. package/examples/computed-fields/example.json +5 -0
  303. package/examples/computed-fields/src/generated/db.types.d.ts +81 -0
  304. package/examples/content-collections/README.md +91 -0
  305. package/examples/content-collections/db/authors.json +12 -0
  306. package/examples/content-collections/db/authors.schema.mjs +20 -0
  307. package/examples/content-collections/db/blog/draft-roadmap.mdx +12 -0
  308. package/examples/content-collections/db/blog/index.schema.mjs +61 -0
  309. package/examples/content-collections/db/blog/launch-notes.mdx +15 -0
  310. package/examples/content-collections/db/docs/index.schema.mjs +32 -0
  311. package/examples/content-collections/db/docs/intro.mdx +11 -0
  312. package/examples/content-collections/db/docs/schema-workflow.mdx +10 -0
  313. package/examples/content-collections/db/site.schema.jsonc +21 -0
  314. package/examples/content-collections/db.config.mjs +26 -0
  315. package/examples/content-collections/example.json +5 -0
  316. package/examples/content-collections/src/content-preview.mjs +66 -0
  317. package/examples/content-collections/src/generated/db.types.d.ts +81 -0
  318. package/examples/csv/README.md +52 -0
  319. package/examples/csv/db/customers.csv +4 -0
  320. package/examples/csv/db.config.mjs +13 -0
  321. package/examples/csv/example.json +5 -0
  322. package/examples/data-first/README.md +54 -0
  323. package/examples/data-first/db/posts.json +16 -0
  324. package/examples/data-first/db/settings.json +8 -0
  325. package/examples/data-first/db/users.json +14 -0
  326. package/examples/data-first/db.config.mjs +13 -0
  327. package/examples/data-first/example.json +5 -0
  328. package/examples/diagnostics/README.md +55 -0
  329. package/examples/diagnostics/db/projects.schema.jsonc +27 -0
  330. package/examples/diagnostics/db/users.json +9 -0
  331. package/examples/diagnostics/db/users.schema.jsonc +23 -0
  332. package/examples/diagnostics/db.config.mjs +16 -0
  333. package/examples/diagnostics/example.json +5 -0
  334. package/examples/free-plan-upgrade/README.md +22 -0
  335. package/examples/free-plan-upgrade/db/appSettings.json +4 -0
  336. package/examples/free-plan-upgrade/db/projects.json +7 -0
  337. package/examples/free-plan-upgrade/example.json +5 -0
  338. package/examples/free-plan-upgrade/src/upgrade-tenant-to-paid.mjs +105 -0
  339. package/examples/hono-auth/README.md +74 -0
  340. package/examples/hono-auth/db/pages.schema.jsonc +44 -0
  341. package/examples/hono-auth/db/users.schema.jsonc +42 -0
  342. package/examples/hono-auth/db.config.mjs +17 -0
  343. package/examples/hono-auth/example.json +5 -0
  344. package/examples/hono-auth/package.json +14 -0
  345. package/examples/hono-auth/src/app.mjs +79 -0
  346. package/examples/hono-auth/src/server.mjs +13 -0
  347. package/examples/production-json/README.md +102 -0
  348. package/examples/production-json/db/appSettings.schema.jsonc +41 -0
  349. package/examples/production-json/db/featureFlags.schema.jsonc +84 -0
  350. package/examples/production-json/db/operations/get-control-plane.jsonc +6 -0
  351. package/examples/production-json/db/operations/get-feature-flag.jsonc +9 -0
  352. package/examples/production-json/db/operations/list-feature-flags.jsonc +8 -0
  353. package/examples/production-json/db/operations/read-public-settings.jsonc +8 -0
  354. package/examples/production-json/db.config.mjs +33 -0
  355. package/examples/production-json/example.json +5 -0
  356. package/examples/production-json/src/client-demo.mjs +28 -0
  357. package/examples/production-json/src/generated/db.types.d.ts +60 -0
  358. package/examples/relations/README.md +56 -0
  359. package/examples/relations/db/posts.schema.jsonc +46 -0
  360. package/examples/relations/db/users.schema.jsonc +34 -0
  361. package/examples/relations/db.config.mjs +13 -0
  362. package/examples/relations/example.json +5 -0
  363. package/examples/rest-client/README.md +54 -0
  364. package/examples/rest-client/db/settings.json +5 -0
  365. package/examples/rest-client/db/users.schema.jsonc +42 -0
  366. package/examples/rest-client/db.config.mjs +13 -0
  367. package/examples/rest-client/example.json +5 -0
  368. package/examples/rest-client/src/client-demo.mjs +24 -0
  369. package/examples/schema-first/README.md +55 -0
  370. package/examples/schema-first/db/auditEvents.schema.jsonc +24 -0
  371. package/examples/schema-first/db/settings.schema.jsonc +29 -0
  372. package/examples/schema-first/db/users.schema.jsonc +36 -0
  373. package/examples/schema-first/db.config.mjs +15 -0
  374. package/examples/schema-first/example.json +5 -0
  375. package/examples/schema-first/src/generated/db.types.d.ts +47 -0
  376. package/examples/schema-manifest/README.md +50 -0
  377. package/examples/schema-manifest/db/projects.schema.jsonc +48 -0
  378. package/examples/schema-manifest/db/users.schema.jsonc +35 -0
  379. package/examples/schema-manifest/db.config.mjs +41 -0
  380. package/examples/schema-manifest/example.json +5 -0
  381. package/examples/schema-manifest/src/generated/db.schema.json +130 -0
  382. package/examples/schema-manifest/src/generated/db.types.d.ts +50 -0
  383. package/examples/schema-ui/README.md +103 -0
  384. package/examples/schema-ui/db/pages.schema.jsonc +53 -0
  385. package/examples/schema-ui/db/users.schema.jsonc +30 -0
  386. package/examples/schema-ui/db.config.mjs +55 -0
  387. package/examples/schema-ui/example.json +5 -0
  388. package/examples/schema-ui/src/cms-ssr.mjs +276 -0
  389. package/examples/schema-ui/src/generated/db.schema.json +133 -0
  390. package/examples/schema-ui/src/generated/db.types.d.ts +46 -0
  391. package/examples/schema-ui/src/render-admin.mjs +175 -0
  392. package/examples/schema-ui/src/schema-ui-ssr-handler.mjs +149 -0
  393. package/examples/schema-ui/src/start-schema-ui-server.mjs +140 -0
  394. package/examples/standard-schema/README.md +55 -0
  395. package/examples/standard-schema/db/settings.schema.mjs +22 -0
  396. package/examples/standard-schema/db/users.schema.mjs +72 -0
  397. package/examples/standard-schema/example.json +5 -0
  398. package/package.json +108 -0
@@ -0,0 +1,165 @@
1
+ import { resolveFrom, writeText } from '../../fs-utils.js';
2
+ import { restFormatMetadata } from '../../rest/formats.js';
3
+ import { loadProjectSchema } from '../schema/project.js';
4
+ import { renderSchemaManifest } from '../schema/manifest.js';
5
+ export async function generateViewerManifest(config, options = {}) {
6
+ const project = (options.project ?? await loadProjectSchema(config));
7
+ const manifest = renderViewerManifest(project.resources, config, {
8
+ diagnostics: project.diagnostics,
9
+ generatedAt: options.generatedAt,
10
+ routes: options.routes,
11
+ });
12
+ const content = `${JSON.stringify(manifest, null, 2)}\n`;
13
+ const outFiles = outputFiles(config, options);
14
+ for (const outFile of outFiles) {
15
+ await writeText(outFile, content);
16
+ }
17
+ return {
18
+ manifest,
19
+ content,
20
+ outFiles,
21
+ diagnostics: project.diagnostics,
22
+ };
23
+ }
24
+ export function renderViewerManifest(resources, config = {}, options = {}) {
25
+ const schemaManifest = renderSchemaManifest(resources, config);
26
+ const routes = normalizeViewerRoutes(config, options.routes);
27
+ const resourceList = [...resources];
28
+ const collections = resourceBucketManifest(schemaManifest.collections, resourceList, routes);
29
+ const documents = resourceBucketManifest(schemaManifest.documents, resourceList, routes);
30
+ const restEnabled = config.rest?.enabled !== false;
31
+ return {
32
+ version: 1,
33
+ kind: 'db.viewerManifest',
34
+ generatedAt: options.generatedAt ?? new Date().toISOString(),
35
+ api: {
36
+ viewer: routes.viewerPath,
37
+ manifest: routes.manifestPath,
38
+ manifestJson: routes.manifestJsonPath,
39
+ manifestHtml: routes.manifestHtmlPath,
40
+ manifestMarkdown: routes.manifestMarkdownPath,
41
+ formats: restFormatMetadata(config, routes),
42
+ viewers: viewerLinks(config, routes.viewerPath),
43
+ schema: routes.schemaPath,
44
+ events: routes.eventsPath,
45
+ log: routes.logPath,
46
+ batch: routes.batchPath,
47
+ import: routes.importPath,
48
+ graphql: routes.graphqlPath,
49
+ restBasePath: routes.restBasePath ?? '',
50
+ resources: Object.fromEntries(resourceList.map((resource) => [resource.name, resourceApi(resource, routes)])),
51
+ },
52
+ capabilities: {
53
+ collections: resourceList.some((resource) => resource.kind === 'collection'),
54
+ documents: resourceList.some((resource) => resource.kind === 'document'),
55
+ rest: restEnabled,
56
+ writes: restEnabled,
57
+ restBatch: restEnabled,
58
+ graphql: config.graphql?.enabled !== false,
59
+ csvImport: true,
60
+ liveEvents: true,
61
+ },
62
+ collections,
63
+ documents,
64
+ diagnostics: options.diagnostics ?? [],
65
+ };
66
+ }
67
+ function outputFiles(config, options) {
68
+ const outFile = options.outFile
69
+ ? resolveFrom(config.cwd ?? '.', options.outFile)
70
+ : config.viewerManifestOutFile;
71
+ return outFile ? [outFile] : [];
72
+ }
73
+ function resourceBucketManifest(bucket = {}, resources, routes) {
74
+ return Object.fromEntries(Object.entries(bucket).map(([resourceName, manifest]) => {
75
+ const resource = resources.find((candidate) => candidate.name === resourceName);
76
+ if (!resource) {
77
+ return [resourceName, manifest];
78
+ }
79
+ return [resourceName, {
80
+ ...manifest,
81
+ typeName: resource.typeName,
82
+ routePath: resource.routePath,
83
+ api: resourceApi(resource, routes),
84
+ relations: resource.relations ?? [],
85
+ }];
86
+ }));
87
+ }
88
+ function resourceApi(resource, routes) {
89
+ const route = joinPaths(routes.restBasePath ?? '', resource.routePath);
90
+ if (resource.kind === 'document') {
91
+ return {
92
+ kind: 'document',
93
+ read: route,
94
+ write: route,
95
+ };
96
+ }
97
+ return {
98
+ kind: 'collection',
99
+ list: route,
100
+ record: `${route}/{${resource.idField ?? 'id'}}`,
101
+ };
102
+ }
103
+ function normalizeViewerRoutes(config, routes = {}) {
104
+ const apiBase = normalizeBasePath(routes.apiBase ?? config.server?.apiBase ?? '/__db');
105
+ const restBasePath = routes.restBasePath === null
106
+ ? ''
107
+ : normalizeBasePath(routes.restBasePath ?? '');
108
+ return {
109
+ apiBase,
110
+ viewerPath: routes.viewerPath ?? apiBase,
111
+ manifestPath: routes.manifestPath ?? `${apiBase}/manifest`,
112
+ manifestJsonPath: routes.manifestJsonPath ?? `${apiBase}/manifest.json`,
113
+ manifestHtmlPath: routes.manifestHtmlPath ?? `${apiBase}/manifest.html`,
114
+ manifestMarkdownPath: routes.manifestMarkdownPath ?? `${apiBase}/manifest.md`,
115
+ schemaPath: routes.schemaPath ?? `${apiBase}/schema`,
116
+ eventsPath: routes.eventsPath ?? `${apiBase}/events`,
117
+ logPath: routes.logPath ?? `${apiBase}/log`,
118
+ batchPath: routes.batchPath ?? `${apiBase}/batch`,
119
+ importPath: routes.importPath ?? `${apiBase}/import`,
120
+ graphqlPath: routes.graphqlPath ?? config.graphql?.path ?? '/graphql',
121
+ restBasePath,
122
+ };
123
+ }
124
+ function viewerLinks(config, viewerPath) {
125
+ const configuredLinks = Array.isArray(config.server?.viewerLinks)
126
+ ? config.server.viewerLinks
127
+ : [];
128
+ return [
129
+ {
130
+ label: 'Data Viewer',
131
+ href: viewerPath,
132
+ source: 'built-in',
133
+ },
134
+ ...configuredLinks.map(normalizeViewerLink).filter(Boolean),
135
+ ];
136
+ }
137
+ function normalizeViewerLink(link) {
138
+ if (!isRecord(link)) {
139
+ return null;
140
+ }
141
+ const href = typeof link.href === 'string' ? link.href : link.url;
142
+ if (typeof href !== 'string' || href.trim() === '') {
143
+ return null;
144
+ }
145
+ return {
146
+ label: typeof link.label === 'string' && link.label.trim() ? link.label : 'Custom Viewer',
147
+ href,
148
+ source: 'custom',
149
+ };
150
+ }
151
+ function joinPaths(basePath, routePath) {
152
+ if (!basePath) {
153
+ return routePath;
154
+ }
155
+ const base = `/${String(basePath).replace(/^\/+/, '').replace(/\/+$/, '')}`;
156
+ const route = `/${String(routePath || '/').replace(/^\/+/, '')}`;
157
+ return `${base}${route === '/' ? '' : route}`;
158
+ }
159
+ function normalizeBasePath(value) {
160
+ const pathValue = `/${String(value ?? '').replace(/^\/+/, '').replace(/\/+$/, '')}`;
161
+ return pathValue === '/' ? '' : pathValue;
162
+ }
163
+ function isRecord(value) {
164
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
165
+ }
@@ -0,0 +1 @@
1
+ export { readText, resolveFrom, toPosixPath, writeText } from './shared/fs-utils.js';
@@ -0,0 +1 @@
1
+ export { readText, resolveFrom, toPosixPath, writeText } from './shared/fs-utils.js';
@@ -0,0 +1,6 @@
1
+ type HonoAppRenderOptions = {
2
+ api: string[];
3
+ };
4
+ export declare function renderHonoApp(options: HonoAppRenderOptions): string;
5
+ export declare function renderServerEntry(): string;
6
+ export {};
@@ -0,0 +1,51 @@
1
+ export function renderHonoApp(options) {
2
+ const imports = [
3
+ "import { Hono } from 'hono';",
4
+ "import { openSqliteRepository } from './sqlite.js';",
5
+ ];
6
+ const registrations = [];
7
+ if (options.api.includes('rest')) {
8
+ imports.push("import { registerDbRoutes } from './rest.js';");
9
+ registrations.push('registerDbRoutes(app, repository);');
10
+ }
11
+ if (options.api.includes('graphql')) {
12
+ imports.push("import { registerGraphqlRoutes } from './graphql.js';");
13
+ registrations.push('registerGraphqlRoutes(app, repository);');
14
+ }
15
+ return `${generatedHeader()}
16
+ ${imports.join('\n')}
17
+
18
+ export const repository = openSqliteRepository();
19
+ export const app = new Hono();
20
+
21
+ app.onError((error, c) => {
22
+ const status = typeof (error as any).status === 'number' ? (error as any).status : 500;
23
+ return c.json({
24
+ error: {
25
+ code: (error as any).code || 'SERVER_ERROR',
26
+ message: error.message,
27
+ },
28
+ }, status as any);
29
+ });
30
+
31
+ ${registrations.join('\n')}
32
+ `;
33
+ }
34
+ export function renderServerEntry() {
35
+ return `${generatedHeader()}
36
+ import { serve } from '@hono/node-server';
37
+ import { app } from './app.js';
38
+
39
+ const port = Number(process.env.PORT || 3000);
40
+
41
+ serve({
42
+ fetch: app.fetch,
43
+ port,
44
+ });
45
+
46
+ console.log('db Hono API listening on http://127.0.0.1:' + port);
47
+ `;
48
+ }
49
+ function generatedHeader(comment = '//') {
50
+ return `${comment} This file is generated by db. Edit it freely after generation.\n`;
51
+ }
@@ -0,0 +1,7 @@
1
+ type HonoGraphqlProject = {
2
+ schema: {
3
+ graphql?: string;
4
+ };
5
+ };
6
+ export declare function renderGraphqlRoutes(project: HonoGraphqlProject): string;
7
+ export {};
@@ -0,0 +1,53 @@
1
+ export function renderGraphqlRoutes(project) {
2
+ return `${generatedHeader()}
3
+ import type { Hono } from 'hono';
4
+ import { executeGraphql } from '@async/db';
5
+ import type { DbRepository } from './repository.js';
6
+
7
+ const graphqlSdl = ${JSON.stringify(project.schema.graphql)};
8
+
9
+ export function registerGraphqlRoutes(app: Hono, repository: DbRepository, path = '/graphql') {
10
+ app.get(path, (c) => c.text(graphqlSdl));
11
+ app.post(path, async (c) => executeGraphql(createDbFacade(repository), await c.req.json()).then((result) => c.json(result)));
12
+ }
13
+
14
+ function createDbFacade(repository: DbRepository) {
15
+ return {
16
+ resources: new Map(Object.entries(repository.resources)),
17
+ collection(name: string) {
18
+ return repository.collection(name);
19
+ },
20
+ document(name: string) {
21
+ const document = repository.document(name);
22
+ return {
23
+ all: () => document.all(),
24
+ update: (patch: Record<string, unknown>) => document.patch(patch),
25
+ put: (value: Record<string, unknown>) => document.put(value),
26
+ async set(pointer: string, value: unknown) {
27
+ const current = await document.all();
28
+ setPointer(current, pointer, value);
29
+ await document.put(current);
30
+ return value;
31
+ },
32
+ };
33
+ },
34
+ };
35
+ }
36
+
37
+ function setPointer(document: Record<string, unknown>, pointer: string, value: unknown) {
38
+ const parts = pointer.split('/').slice(1).map((part) => part.replaceAll('~1', '/').replaceAll('~0', '~'));
39
+ let current: Record<string, unknown> = document;
40
+ while (parts.length > 1) {
41
+ const part = parts.shift() as string;
42
+ if (!current[part] || typeof current[part] !== 'object' || Array.isArray(current[part])) {
43
+ current[part] = {};
44
+ }
45
+ current = current[part] as Record<string, unknown>;
46
+ }
47
+ current[parts[0] || ''] = value;
48
+ }
49
+ `;
50
+ }
51
+ function generatedHeader(comment = '//') {
52
+ return `${comment} This file is generated by db. Edit it freely after generation.\n`;
53
+ }
@@ -0,0 +1,55 @@
1
+ type HonoDiagnostic = {
2
+ severity: 'error' | 'warn' | 'info';
3
+ message: string;
4
+ [key: string]: unknown;
5
+ };
6
+ type HonoResource = {
7
+ name: string;
8
+ kind: string;
9
+ idField?: string;
10
+ fields: Record<string, {
11
+ type?: string;
12
+ required?: boolean;
13
+ [key: string]: unknown;
14
+ }>;
15
+ seed?: unknown;
16
+ };
17
+ type HonoProject = {
18
+ resources: HonoResource[];
19
+ diagnostics: HonoDiagnostic[];
20
+ schema: {
21
+ resources: unknown;
22
+ graphql?: string;
23
+ [key: string]: unknown;
24
+ };
25
+ };
26
+ type HonoGenerateConfig = {
27
+ cwd?: string;
28
+ generate?: {
29
+ hono?: Partial<HonoGenerateOptions>;
30
+ [key: string]: unknown;
31
+ };
32
+ [key: string]: unknown;
33
+ };
34
+ type HonoGenerateOptions = {
35
+ outDir: string;
36
+ out?: string;
37
+ api: string[] | string;
38
+ db: string;
39
+ app: string;
40
+ runtime: string;
41
+ seed: false | 'fixtures' | string | boolean;
42
+ allowWarnings: boolean;
43
+ [key: string]: unknown;
44
+ };
45
+ type GeneratedFile = {
46
+ path: string;
47
+ content: string;
48
+ };
49
+ export declare function generateHonoStarter(config: HonoGenerateConfig, options?: Partial<HonoGenerateOptions>): Promise<{
50
+ outDir: string;
51
+ files: string[];
52
+ diagnostics: HonoDiagnostic[];
53
+ }>;
54
+ export declare function renderHonoStarter(project: HonoProject, options?: Partial<HonoGenerateOptions>): GeneratedFile[];
55
+ export {};
@@ -0,0 +1,140 @@
1
+ import path from 'node:path';
2
+ import { dbError } from '../../errors.js';
3
+ import { writeText } from '../../fs-utils.js';
4
+ import { loadProjectSchema } from '../../schema.js';
5
+ import { renderHonoApp, renderServerEntry } from './app.js';
6
+ import { renderGraphqlRoutes } from './graphql.js';
7
+ import { renderPackageJson, renderTsconfig } from './package.js';
8
+ import { renderReadme } from './readme.js';
9
+ import { renderRepositoryTypes } from './repository.js';
10
+ import { renderRestRoutes } from './rest.js';
11
+ import { renderGeneratedSchema, renderSeedModule } from './schema.js';
12
+ import { renderInitialMigration, renderSqliteAdapter } from './sqlite.js';
13
+ import { renderValidators } from './validators.js';
14
+ const DEFAULT_OPTIONS = {
15
+ outDir: './db-api',
16
+ api: ['rest'],
17
+ db: 'sqlite',
18
+ app: 'standalone',
19
+ runtime: 'node-sqlite',
20
+ seed: false,
21
+ allowWarnings: false,
22
+ };
23
+ export async function generateHonoStarter(config, options = {}) {
24
+ const resolved = resolveGenerateOptions(config, options);
25
+ const project = await loadProjectSchema(config);
26
+ assertGeneratable(project, resolved);
27
+ const files = renderHonoStarter(project, resolved);
28
+ for (const file of files) {
29
+ await writeText(path.join(resolved.outDir, file.path), file.content);
30
+ }
31
+ return {
32
+ outDir: resolved.outDir,
33
+ files: files.map((file) => path.join(resolved.outDir, file.path)),
34
+ diagnostics: project.diagnostics,
35
+ };
36
+ }
37
+ export function renderHonoStarter(project, options = {}) {
38
+ const resolved = {
39
+ ...DEFAULT_OPTIONS,
40
+ ...options,
41
+ api: normalizeApi(options.api ?? DEFAULT_OPTIONS.api),
42
+ };
43
+ const files = [
44
+ generatedFile('src/schema.ts', renderGeneratedSchema(project)),
45
+ generatedFile('src/repository.ts', renderRepositoryTypes()),
46
+ generatedFile('src/validators.ts', renderValidators()),
47
+ generatedFile('src/sqlite.ts', renderSqliteAdapter(project, resolved)),
48
+ generatedFile('migrations/0001_initial.sql', renderInitialMigration(project.resources)),
49
+ generatedFile('README.md', renderReadme(project, resolved)),
50
+ ];
51
+ if (resolved.seed === 'fixtures') {
52
+ files.push(generatedFile('src/seed.ts', renderSeedModule()));
53
+ }
54
+ if (resolved.api.includes('rest')) {
55
+ files.push(generatedFile('src/rest.ts', renderRestRoutes()));
56
+ }
57
+ if (resolved.api.includes('graphql')) {
58
+ files.push(generatedFile('src/graphql.ts', renderGraphqlRoutes(project)));
59
+ }
60
+ if (resolved.api.length > 0) {
61
+ files.push(generatedFile('src/app.ts', renderHonoApp(resolved)));
62
+ }
63
+ if (resolved.app === 'standalone') {
64
+ files.push(generatedFile('src/server.ts', renderServerEntry()), generatedFile('package.json', renderPackageJson(resolved)), generatedFile('tsconfig.json', renderTsconfig()));
65
+ }
66
+ return files;
67
+ }
68
+ function resolveGenerateOptions(config, options) {
69
+ const fromConfig = config.generate?.hono ?? {};
70
+ const definedOptions = Object.fromEntries(Object.entries(options).filter(([, value]) => value !== undefined));
71
+ const merged = {
72
+ ...DEFAULT_OPTIONS,
73
+ ...fromConfig,
74
+ ...definedOptions,
75
+ };
76
+ merged.api = normalizeApi(merged.api);
77
+ merged.outDir = path.resolve(config.cwd, merged.outDir ?? merged.out ?? DEFAULT_OPTIONS.outDir);
78
+ merged.db = merged.db ?? 'sqlite';
79
+ merged.app = merged.app ?? 'standalone';
80
+ merged.runtime = merged.runtime ?? 'node-sqlite';
81
+ merged.seed = merged.seed === true ? 'fixtures' : merged.seed;
82
+ if (merged.db !== 'sqlite') {
83
+ throw dbError('GENERATE_UNSUPPORTED_DB', `Unsupported generated database "${merged.db}".`, {
84
+ hint: 'Use --db sqlite for the v1 generator.',
85
+ details: {
86
+ db: merged.db,
87
+ },
88
+ });
89
+ }
90
+ if (!['standalone', 'module'].includes(merged.app)) {
91
+ throw dbError('GENERATE_UNSUPPORTED_APP_SHAPE', `Unsupported generated app shape "${merged.app}".`, {
92
+ hint: 'Use --app standalone or --app module.',
93
+ details: {
94
+ app: merged.app,
95
+ },
96
+ });
97
+ }
98
+ return merged;
99
+ }
100
+ function normalizeApi(value) {
101
+ const raw = Array.isArray(value) ? value : String(value ?? 'rest').split(',');
102
+ const api = raw.map((item) => String(item).trim()).filter(Boolean);
103
+ if (api.length === 1 && api[0] === 'none') {
104
+ return [];
105
+ }
106
+ const unsupported = api.filter((item) => !['rest', 'graphql'].includes(item));
107
+ if (unsupported.length > 0) {
108
+ throw dbError('GENERATE_UNSUPPORTED_API', `Unsupported generated API target "${unsupported[0]}".`, {
109
+ hint: 'Use --api rest, --api graphql, --api rest,graphql, or --api none.',
110
+ details: {
111
+ api,
112
+ },
113
+ });
114
+ }
115
+ return [...new Set(api)];
116
+ }
117
+ function assertGeneratable(project, options) {
118
+ const errors = project.diagnostics.filter((diagnostic) => diagnostic.severity === 'error');
119
+ const warnings = project.diagnostics.filter((diagnostic) => diagnostic.severity === 'warn');
120
+ const blocking = options.allowWarnings ? errors : [...errors, ...warnings];
121
+ if (blocking.length === 0) {
122
+ return;
123
+ }
124
+ const error = dbError('GENERATE_SCHEMA_DIAGNOSTICS', `Cannot generate Hono starter because schema diagnostics are present: ${blocking[0].message}`, {
125
+ hint: options.allowWarnings
126
+ ? 'Fix schema errors before generating production starter code.'
127
+ : 'Fix schema warnings/errors, or pass --allow-warnings to generate while keeping warning diagnostics.',
128
+ details: {
129
+ diagnostics: blocking,
130
+ },
131
+ });
132
+ error.diagnostics = blocking;
133
+ throw error;
134
+ }
135
+ function generatedFile(filePath, content) {
136
+ return {
137
+ path: filePath,
138
+ content: content.endsWith('\n') ? content : `${content}\n`,
139
+ };
140
+ }
@@ -0,0 +1,6 @@
1
+ type PackageRenderOptions = {
2
+ api: string[];
3
+ };
4
+ export declare function renderPackageJson(options: PackageRenderOptions): string;
5
+ export declare function renderTsconfig(): string;
6
+ export {};
@@ -0,0 +1,44 @@
1
+ export function renderPackageJson(options) {
2
+ const dependencies = {
3
+ '@hono/node-server': '^1.13.8',
4
+ hono: '^4.6.0',
5
+ };
6
+ if (options.api.includes('graphql')) {
7
+ dependencies['@async/db'] = '^0.1.0';
8
+ }
9
+ return `${JSON.stringify({
10
+ name: 'db-api',
11
+ version: '0.1.0',
12
+ private: true,
13
+ type: 'module',
14
+ scripts: {
15
+ dev: 'tsx watch src/server.ts',
16
+ start: 'node dist/server.js',
17
+ build: 'tsc -p tsconfig.json',
18
+ },
19
+ dependencies,
20
+ devDependencies: {
21
+ '@types/node': '^22.13.0',
22
+ tsx: '^4.19.0',
23
+ typescript: '^5.7.0',
24
+ },
25
+ engines: {
26
+ node: '>=22.13',
27
+ },
28
+ }, null, 2)}\n`;
29
+ }
30
+ export function renderTsconfig() {
31
+ return `${JSON.stringify({
32
+ compilerOptions: {
33
+ target: 'ES2022',
34
+ module: 'NodeNext',
35
+ moduleResolution: 'NodeNext',
36
+ strict: true,
37
+ esModuleInterop: true,
38
+ outDir: 'dist',
39
+ rootDir: 'src',
40
+ skipLibCheck: true,
41
+ },
42
+ include: ['src/**/*.ts'],
43
+ }, null, 2)}\n`;
44
+ }
@@ -0,0 +1,13 @@
1
+ type HonoReadmeResource = {
2
+ name: string;
3
+ kind: string;
4
+ };
5
+ type HonoReadmeProject = {
6
+ resources: HonoReadmeResource[];
7
+ };
8
+ type HonoReadmeOptions = {
9
+ api: string[];
10
+ seed: unknown;
11
+ };
12
+ export declare function renderReadme(project: HonoReadmeProject, options: HonoReadmeOptions): string;
13
+ export {};
@@ -0,0 +1,28 @@
1
+ export function renderReadme(project, options) {
2
+ const apiText = options.api.length === 0 ? 'SQLite repository only' : options.api.join(' + ');
3
+ return `${generatedHeader()}# db Hono API Starter
4
+
5
+ Generated from db schema resources:
6
+
7
+ ${project.resources.map((resource) => `- ${resource.name} (${resource.kind})`).join('\n')}
8
+
9
+ ## Shape
10
+
11
+ - API: ${apiText}
12
+ - Database: SQLite with node:sqlite
13
+ - Runtime: Node.js >=22.13
14
+ - Seed fixtures: ${options.seed === 'fixtures' ? 'enabled' : 'disabled'}
15
+
16
+ ## Commands
17
+
18
+ \`\`\`bash
19
+ npm install
20
+ npm run dev
21
+ \`\`\`
22
+
23
+ The initial migration is in \`migrations/0001_initial.sql\`. Destructive schema changes should be reviewed manually.
24
+ `;
25
+ }
26
+ function generatedHeader(comment = '//') {
27
+ return `${comment} This file is generated by db. Edit it freely after generation.\n`;
28
+ }
@@ -0,0 +1 @@
1
+ export declare function renderRepositoryTypes(): string;
@@ -0,0 +1,27 @@
1
+ export function renderRepositoryTypes() {
2
+ return `${generatedHeader()}
3
+ export type CollectionRepository = {
4
+ all(): Promise<Record<string, unknown>[]>;
5
+ get(id: string): Promise<Record<string, unknown> | null>;
6
+ create(record: Record<string, unknown>): Promise<Record<string, unknown>>;
7
+ patch(id: string, patch: Record<string, unknown>): Promise<Record<string, unknown> | null>;
8
+ delete(id: string): Promise<boolean>;
9
+ };
10
+
11
+ export type DocumentRepository = {
12
+ all(): Promise<Record<string, unknown>>;
13
+ put(value: Record<string, unknown>): Promise<Record<string, unknown>>;
14
+ patch(value: Record<string, unknown>): Promise<Record<string, unknown>>;
15
+ };
16
+
17
+ export type DbRepository = {
18
+ resources: Record<string, any>;
19
+ collection(name: string): CollectionRepository;
20
+ document(name: string): DocumentRepository;
21
+ close?(): void;
22
+ };
23
+ `;
24
+ }
25
+ function generatedHeader(comment = '//') {
26
+ return `${comment} This file is generated by db. Edit it freely after generation.\n`;
27
+ }
@@ -0,0 +1 @@
1
+ export declare function renderRestRoutes(): string;
@@ -0,0 +1,38 @@
1
+ export function renderRestRoutes() {
2
+ return `${generatedHeader()}
3
+ import type { Hono } from 'hono';
4
+ import type { DbRepository } from './repository.js';
5
+ import { resources } from './schema.js';
6
+
7
+ export function registerDbRoutes(app: Hono, repository: DbRepository) {
8
+ for (const [resourceName, resource] of Object.entries<any>(resources)) {
9
+ if (resource.kind === 'collection') {
10
+ app.get(resource.routePath, async (c) => c.json(await repository.collection(resourceName).all()));
11
+ app.get(resource.routePath + '/:id', async (c) => {
12
+ const record = await repository.collection(resourceName).get(c.req.param('id'));
13
+ return record ? c.json(record) : c.json({ error: 'Not found' }, 404);
14
+ });
15
+ app.post(resource.routePath, async (c) => {
16
+ const record = await repository.collection(resourceName).create(await c.req.json());
17
+ return c.json(record, 201);
18
+ });
19
+ app.patch(resource.routePath + '/:id', async (c) => {
20
+ const record = await repository.collection(resourceName).patch(c.req.param('id'), await c.req.json());
21
+ return record ? c.json(record) : c.json({ error: 'Not found' }, 404);
22
+ });
23
+ app.delete(resource.routePath + '/:id', async (c) => {
24
+ const deleted = await repository.collection(resourceName).delete(c.req.param('id'));
25
+ return deleted ? c.body(null, 204) : c.json({ error: 'Not found' }, 404);
26
+ });
27
+ } else {
28
+ app.get(resource.routePath, async (c) => c.json(await repository.document(resourceName).all()));
29
+ app.put(resource.routePath, async (c) => c.json(await repository.document(resourceName).put(await c.req.json())));
30
+ app.patch(resource.routePath, async (c) => c.json(await repository.document(resourceName).patch(await c.req.json())));
31
+ }
32
+ }
33
+ }
34
+ `;
35
+ }
36
+ function generatedHeader(comment = '//') {
37
+ return `${comment} This file is generated by db. Edit it freely after generation.\n`;
38
+ }
@@ -0,0 +1,13 @@
1
+ type HonoSchemaResource = {
2
+ name: string;
3
+ seed?: unknown;
4
+ };
5
+ type HonoSchemaProject = {
6
+ schema: {
7
+ resources: unknown;
8
+ };
9
+ resources: HonoSchemaResource[];
10
+ };
11
+ export declare function renderGeneratedSchema(project: HonoSchemaProject): string;
12
+ export declare function renderSeedModule(): string;
13
+ export {};