@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,18 @@
1
+ export function renderGeneratedSchema(project) {
2
+ return [
3
+ generatedHeader(),
4
+ `export const resources = ${JSON.stringify(project.schema.resources, null, 2)} as const;`,
5
+ '',
6
+ `export const seedData = ${JSON.stringify(Object.fromEntries(project.resources.map((resource) => [resource.name, resource.seed])), null, 2)} as const;`,
7
+ '',
8
+ 'export type ResourceName = keyof typeof resources;',
9
+ ].join('\n');
10
+ }
11
+ export function renderSeedModule() {
12
+ return `${generatedHeader()}
13
+ export { seedData } from './schema.js';
14
+ `;
15
+ }
16
+ function generatedHeader(comment = '//') {
17
+ return `${comment} This file is generated by db. Edit it freely after generation.\n`;
18
+ }
@@ -0,0 +1,20 @@
1
+ type HonoField = {
2
+ type?: string;
3
+ required?: boolean;
4
+ [key: string]: unknown;
5
+ };
6
+ type HonoResource = {
7
+ name: string;
8
+ kind: string;
9
+ idField?: string;
10
+ fields: Record<string, HonoField>;
11
+ };
12
+ type HonoSqliteProject = {
13
+ resources: HonoResource[];
14
+ };
15
+ type HonoSqliteOptions = {
16
+ seed?: unknown;
17
+ };
18
+ export declare function renderSqliteAdapter(project: HonoSqliteProject, options: HonoSqliteOptions): string;
19
+ export declare function renderInitialMigration(resources: HonoResource[]): string;
20
+ export {};
@@ -0,0 +1,266 @@
1
+ export function renderSqliteAdapter(project, options) {
2
+ const seedImport = options.seed === 'fixtures' ? "import { seedData } from './schema.js';\n" : '';
3
+ const seedCall = options.seed === 'fixtures' ? '\n seedFixtures(db);\n' : '';
4
+ const seedFunction = options.seed === 'fixtures' ? `
5
+ function seedFixtures(db: DatabaseSync) {
6
+ for (const [resourceName, seed] of Object.entries<any>(seedData)) {
7
+ const resource = (resources as Record<string, any>)[resourceName];
8
+ if (!resource) {
9
+ continue;
10
+ }
11
+ if (resource.kind === 'collection') {
12
+ const count = db.prepare('SELECT COUNT(*) as count FROM ' + quoteIdentifier(resourceName)).get() as { count: number };
13
+ if (count.count > 0) {
14
+ continue;
15
+ }
16
+ const collection = collectionRepository(db, resourceName);
17
+ for (const record of seed) {
18
+ collection.create(record);
19
+ }
20
+ } else {
21
+ const existing = db.prepare('SELECT name FROM _db_documents WHERE name = ?').get(resourceName);
22
+ if (!existing) {
23
+ documentRepository(db, resourceName).put(seed);
24
+ }
25
+ }
26
+ }
27
+ }
28
+ ` : '';
29
+ return `${generatedHeader()}
30
+ import { mkdirSync } from 'node:fs';
31
+ import path from 'node:path';
32
+ import { DatabaseSync } from 'node:sqlite';
33
+ import { resources } from './schema.js';
34
+ ${seedImport}import type { CollectionRepository, DocumentRepository, DbRepository } from './repository.js';
35
+ import { applyDefaults, stripUnknownFields, validateRecord } from './validators.js';
36
+
37
+ export function openSqliteRepository(file = process.env.DATABASE_FILE || './data/app.sqlite'): DbRepository {
38
+ if (file !== ':memory:') {
39
+ mkdirSync(path.dirname(file), { recursive: true });
40
+ }
41
+ const db = new DatabaseSync(file);
42
+ migrate(db);${seedCall}
43
+ return {
44
+ resources,
45
+ collection(name: string) {
46
+ return collectionRepository(db, name);
47
+ },
48
+ document(name: string) {
49
+ return documentRepository(db, name);
50
+ },
51
+ close() {
52
+ db.close();
53
+ },
54
+ };
55
+ }
56
+
57
+ export function migrate(db: DatabaseSync) {
58
+ ${renderMigrationExecLines(project.resources)}
59
+ }
60
+
61
+ function collectionRepository(db: DatabaseSync, resourceName: string): CollectionRepository {
62
+ const resource = requireResource(resourceName, 'collection');
63
+ const table = quoteIdentifier(resource.name);
64
+ const fields = Object.keys(resource.fields);
65
+ const idField = resource.idField || 'id';
66
+
67
+ return {
68
+ async all() {
69
+ return (db.prepare('SELECT * FROM ' + table).all() as Record<string, unknown>[]).map((row) => deserializeRow(resourceName, row));
70
+ },
71
+ async get(id) {
72
+ const row = db.prepare('SELECT * FROM ' + table + ' WHERE ' + quoteIdentifier(idField) + ' = ?').get(String(id)) as Record<string, unknown> | undefined;
73
+ return row ? deserializeRow(resourceName, row) : null;
74
+ },
75
+ async create(record) {
76
+ const next = applyDefaults(resourceName, stripUnknownFields(resourceName, { ...record }));
77
+ if (next[idField] === undefined || next[idField] === null || next[idField] === '') {
78
+ next[idField] = nextId(db, table, idField);
79
+ }
80
+ validateRecord(resourceName, next);
81
+ const serialized = serializeRow(resourceName, next);
82
+ const columns = fields.map(quoteIdentifier).join(', ');
83
+ const placeholders = fields.map(() => '?').join(', ');
84
+ db.prepare('INSERT INTO ' + table + ' (' + columns + ') VALUES (' + placeholders + ')').run(...fields.map((field) => serialized[field] ?? null));
85
+ return next;
86
+ },
87
+ async patch(id, patch) {
88
+ const existing = await this.get(id);
89
+ if (!existing) {
90
+ return null;
91
+ }
92
+ const next = stripUnknownFields(resourceName, { ...existing, ...patch, [idField]: existing[idField] });
93
+ validateRecord(resourceName, next);
94
+ const serialized = serializeRow(resourceName, next);
95
+ const updateFields = fields.filter((field) => field !== idField);
96
+ const assignments = updateFields.map((field) => quoteIdentifier(field) + ' = ?').join(', ');
97
+ db.prepare('UPDATE ' + table + ' SET ' + assignments + ' WHERE ' + quoteIdentifier(idField) + ' = ?').run(...updateFields.map((field) => serialized[field] ?? null), String(id));
98
+ return next;
99
+ },
100
+ async delete(id) {
101
+ const result = db.prepare('DELETE FROM ' + table + ' WHERE ' + quoteIdentifier(idField) + ' = ?').run(String(id));
102
+ return result.changes > 0;
103
+ },
104
+ };
105
+ }
106
+
107
+ function documentRepository(db: DatabaseSync, resourceName: string): DocumentRepository {
108
+ const resource = requireResource(resourceName, 'document');
109
+ return {
110
+ async all() {
111
+ const row = db.prepare('SELECT value FROM _db_documents WHERE name = ?').get(resource.name) as { value: string } | undefined;
112
+ return row ? JSON.parse(row.value) : {};
113
+ },
114
+ async put(value) {
115
+ const next = stripUnknownFields(resourceName, value);
116
+ validateRecord(resourceName, next);
117
+ db.prepare('INSERT INTO _db_documents (name, value) VALUES (?, ?) ON CONFLICT(name) DO UPDATE SET value = excluded.value').run(resource.name, JSON.stringify(next));
118
+ return next;
119
+ },
120
+ async patch(value) {
121
+ const existing = await this.all();
122
+ return this.put({ ...existing, ...value });
123
+ },
124
+ };
125
+ }
126
+
127
+ function serializeRow(resourceName: string, record: Record<string, unknown>) {
128
+ const resource = requireResource(resourceName, 'collection');
129
+ const row: Record<string, unknown> = {};
130
+ for (const [fieldName, field] of Object.entries<any>(resource.fields)) {
131
+ const value = record[fieldName];
132
+ if (value === undefined) {
133
+ row[fieldName] = null;
134
+ } else if (field.type === 'boolean') {
135
+ row[fieldName] = value ? 1 : 0;
136
+ } else if (field.type === 'object' || field.type === 'array' || field.type === 'unknown') {
137
+ row[fieldName] = JSON.stringify(value);
138
+ } else {
139
+ row[fieldName] = value;
140
+ }
141
+ }
142
+ return row;
143
+ }
144
+
145
+ function deserializeRow(resourceName: string, row: Record<string, unknown>) {
146
+ const resource = requireResource(resourceName, 'collection');
147
+ const record: Record<string, unknown> = {};
148
+ for (const [fieldName, field] of Object.entries<any>(resource.fields)) {
149
+ const value = row[fieldName];
150
+ if (value === null || value === undefined) {
151
+ continue;
152
+ }
153
+ if (field.type === 'boolean') {
154
+ record[fieldName] = Boolean(value);
155
+ } else if (field.type === 'object' || field.type === 'array' || field.type === 'unknown') {
156
+ record[fieldName] = typeof value === 'string' ? JSON.parse(value) : value;
157
+ } else {
158
+ record[fieldName] = value;
159
+ }
160
+ }
161
+ return record;
162
+ }
163
+
164
+ function nextId(db: DatabaseSync, table: string, idField: string) {
165
+ const rows = db.prepare('SELECT ' + quoteIdentifier(idField) + ' as id FROM ' + table).all() as Array<{ id: string }>;
166
+ const ids = rows.map((row) => String(row.id)).filter(Boolean);
167
+ const numeric = ids.map((id) => Number(id)).filter((id) => Number.isInteger(id) && id > 0);
168
+ let next = numeric.length > 0 ? Math.max(...numeric) + 1 : ids.length + 1;
169
+ while (ids.includes(String(next))) {
170
+ next += 1;
171
+ }
172
+ return String(next);
173
+ }
174
+
175
+ function requireResource(resourceName: string, kind: 'collection' | 'document') {
176
+ const resource = resolveResource(resourceName);
177
+ if (!resource || resource.kind !== kind) {
178
+ throw new Error('Unknown ' + kind + ' resource "' + resourceName + '". Tried: ' + resourceNameCandidates(resourceName).join(', ') + '.');
179
+ }
180
+ return resource;
181
+ }
182
+
183
+ function resolveResource(resourceName: string) {
184
+ for (const candidate of resourceNameCandidates(resourceName)) {
185
+ const resource = (resources as Record<string, any>)[candidate];
186
+ if (resource) {
187
+ return resource;
188
+ }
189
+ }
190
+ return null;
191
+ }
192
+
193
+ function resourceNameCandidates(value: string) {
194
+ const exact = String(value);
195
+ return [...new Set([exact, camelCase(exact), kebabCase(exact)])];
196
+ }
197
+
198
+ function camelCase(value: string) {
199
+ return words(value).map((word, index) => (
200
+ index === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1)
201
+ )).join('');
202
+ }
203
+
204
+ function kebabCase(value: string) {
205
+ return words(value).join('-');
206
+ }
207
+
208
+ function words(value: string) {
209
+ return String(value)
210
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
211
+ .split(/[^A-Za-z0-9]+/)
212
+ .filter(Boolean)
213
+ .map((part) => part.toLowerCase());
214
+ }
215
+
216
+ function quoteIdentifier(value: string) {
217
+ return '"' + String(value).replaceAll('"', '""') + '"';
218
+ }
219
+ ${seedFunction}`;
220
+ }
221
+ export function renderInitialMigration(resources) {
222
+ return `${generatedHeader('--')}${resources.map((resource) => (resource.kind === 'collection'
223
+ ? createTableSql(resource)
224
+ : null)).filter(Boolean).join('\n\n')}
225
+
226
+ CREATE TABLE IF NOT EXISTS "_db_documents" (
227
+ "name" TEXT PRIMARY KEY,
228
+ "value" TEXT NOT NULL
229
+ ) STRICT;
230
+ `;
231
+ }
232
+ function renderMigrationExecLines(resources) {
233
+ const sql = renderInitialMigration(resources).split('\n').filter((line) => !line.startsWith('--')).join('\n');
234
+ return ` db.exec(${JSON.stringify(sql)});`;
235
+ }
236
+ function createTableSql(resource) {
237
+ const columns = Object.entries(resource.fields).map(([fieldName, field]) => {
238
+ const type = sqliteTypeForField(field);
239
+ const primary = fieldName === resource.idField ? ' PRIMARY KEY' : '';
240
+ const required = field.required && fieldName !== resource.idField ? ' NOT NULL' : '';
241
+ return ` ${quoteIdentifier(fieldName)} ${type}${primary}${required}`;
242
+ });
243
+ return `CREATE TABLE IF NOT EXISTS ${quoteIdentifier(resource.name)} (\n${columns.join(',\n')}\n) STRICT;`;
244
+ }
245
+ function sqliteTypeForField(field) {
246
+ switch (field.type) {
247
+ case 'number':
248
+ return 'REAL';
249
+ case 'boolean':
250
+ return 'INTEGER';
251
+ case 'object':
252
+ case 'array':
253
+ case 'unknown':
254
+ return 'TEXT';
255
+ case 'string':
256
+ case 'enum':
257
+ default:
258
+ return 'TEXT';
259
+ }
260
+ }
261
+ function generatedHeader(comment = '//') {
262
+ return `${comment} This file is generated by db. Edit it freely after generation.\n`;
263
+ }
264
+ function quoteIdentifier(value) {
265
+ return `"${String(value).replaceAll('"', '""')}"`;
266
+ }
@@ -0,0 +1 @@
1
+ export declare function renderValidators(): string;
@@ -0,0 +1,141 @@
1
+ export function renderValidators() {
2
+ return `${generatedHeader()}
3
+ import { resources } from './schema.js';
4
+
5
+ export function applyDefaults(resourceName: string, value: Record<string, unknown>) {
6
+ const resource = requireResource(resourceName);
7
+ const next = { ...value };
8
+ for (const [fieldName, field] of Object.entries<any>(resource.fields || {})) {
9
+ if (next[fieldName] === undefined && 'default' in field) {
10
+ next[fieldName] = structuredClone(field.default);
11
+ }
12
+ }
13
+ return next;
14
+ }
15
+
16
+ export function stripUnknownFields(resourceName: string, value: Record<string, unknown>) {
17
+ const resource = requireResource(resourceName);
18
+ const next: Record<string, unknown> = {};
19
+ for (const fieldName of Object.keys(resource.fields || {})) {
20
+ if (value[fieldName] !== undefined) {
21
+ next[fieldName] = value[fieldName];
22
+ }
23
+ }
24
+ return next;
25
+ }
26
+
27
+ export function validateRecord(resourceName: string, value: Record<string, unknown>) {
28
+ const resource = requireResource(resourceName);
29
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
30
+ throw validationError(resourceName, 'Record must be a JSON object.');
31
+ }
32
+
33
+ for (const [fieldName, field] of Object.entries<any>(resource.fields || {})) {
34
+ const fieldValue = value[fieldName];
35
+ if (field.required && (fieldValue === undefined || (fieldValue === null && !field.nullable))) {
36
+ throw validationError(resourceName, 'Missing required field "' + fieldName + '".');
37
+ }
38
+ if (fieldValue !== undefined) {
39
+ validateValue(resourceName, fieldName, field, fieldValue);
40
+ }
41
+ }
42
+ }
43
+
44
+ function validateValue(resourceName: string, fieldPath: string, field: any, value: unknown) {
45
+ if (value === null && field.type !== 'unknown' && !field.nullable) {
46
+ throw validationError(resourceName, 'Field "' + fieldPath + '" cannot be null.');
47
+ }
48
+
49
+ if (value === null) {
50
+ return;
51
+ }
52
+
53
+ if (field.type === 'unknown') {
54
+ return;
55
+ }
56
+ if ((field.type === 'string' || field.type === 'datetime') && typeof value !== 'string') {
57
+ throw validationError(resourceName, 'Field "' + fieldPath + '" must be a string.');
58
+ }
59
+ if (field.type === 'number' && (typeof value !== 'number' || !Number.isFinite(value))) {
60
+ throw validationError(resourceName, 'Field "' + fieldPath + '" must be a finite number.');
61
+ }
62
+ if (field.type === 'boolean' && typeof value !== 'boolean') {
63
+ throw validationError(resourceName, 'Field "' + fieldPath + '" must be a boolean.');
64
+ }
65
+ if (field.type === 'enum' && !field.values?.includes(value)) {
66
+ throw validationError(resourceName, 'Field "' + fieldPath + '" must be one of: ' + (field.values || []).join(', ') + '.');
67
+ }
68
+ if (field.type === 'array') {
69
+ if (!Array.isArray(value)) {
70
+ throw validationError(resourceName, 'Field "' + fieldPath + '" must be an array.');
71
+ }
72
+ value.forEach((item, index) => validateValue(resourceName, fieldPath + '[' + index + ']', field.items || { type: 'unknown' }, item));
73
+ }
74
+ if (field.type === 'object') {
75
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
76
+ throw validationError(resourceName, 'Field "' + fieldPath + '" must be an object.');
77
+ }
78
+ for (const [childName, childField] of Object.entries<any>(field.fields || {})) {
79
+ const childValue = (value as Record<string, unknown>)[childName];
80
+ if (childField.required && (childValue === undefined || (childValue === null && !childField.nullable))) {
81
+ throw validationError(resourceName, 'Missing required field "' + fieldPath + '.' + childName + '".');
82
+ }
83
+ if (childValue !== undefined) {
84
+ validateValue(resourceName, fieldPath + '.' + childName, childField, childValue);
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ function requireResource(resourceName: string) {
91
+ const resource = resolveResource(resourceName);
92
+ if (!resource) {
93
+ throw validationError(resourceName, 'Unknown resource "' + resourceName + '". Tried: ' + resourceNameCandidates(resourceName).join(', ') + '.');
94
+ }
95
+ return resource;
96
+ }
97
+
98
+ function resolveResource(resourceName: string) {
99
+ for (const candidate of resourceNameCandidates(resourceName)) {
100
+ const resource = (resources as Record<string, any>)[candidate];
101
+ if (resource) {
102
+ return resource;
103
+ }
104
+ }
105
+ return null;
106
+ }
107
+
108
+ function resourceNameCandidates(value: string) {
109
+ const exact = String(value);
110
+ return [...new Set([exact, camelCase(exact), kebabCase(exact)])];
111
+ }
112
+
113
+ function camelCase(value: string) {
114
+ return words(value).map((word, index) => (
115
+ index === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1)
116
+ )).join('');
117
+ }
118
+
119
+ function kebabCase(value: string) {
120
+ return words(value).join('-');
121
+ }
122
+
123
+ function words(value: string) {
124
+ return String(value)
125
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
126
+ .split(/[^A-Za-z0-9]+/)
127
+ .filter(Boolean)
128
+ .map((part) => part.toLowerCase());
129
+ }
130
+
131
+ function validationError(resourceName: string, message: string) {
132
+ const error = new Error(resourceName + ': ' + message) as Error & { status?: number; code?: string };
133
+ error.status = 400;
134
+ error.code = 'VALIDATION_FAILED';
135
+ return error;
136
+ }
137
+ `;
138
+ }
139
+ function generatedHeader(comment = '//') {
140
+ return `${comment} This file is generated by db. Edit it freely after generation.\n`;
141
+ }
@@ -0,0 +1 @@
1
+ export { generateHonoStarter, renderHonoStarter } from './hono/index.js';
@@ -0,0 +1 @@
1
+ export { generateHonoStarter, renderHonoStarter } from './hono/index.js';
@@ -0,0 +1,14 @@
1
+ type GraphqlVariables = Record<string, unknown>;
2
+ type GraphqlRequest = string | {
3
+ query?: string;
4
+ variables?: GraphqlVariables;
5
+ operationName?: string | null;
6
+ };
7
+ type GraphqlResult = {
8
+ data: unknown;
9
+ errors?: unknown[];
10
+ };
11
+ type GraphqlDb = Record<string, any>;
12
+ export declare function executeGraphql(db: GraphqlDb, request: GraphqlRequest | GraphqlRequest[]): Promise<GraphqlResult | GraphqlResult[]>;
13
+ export declare function executeGraphqlBatch(db: GraphqlDb, requests: GraphqlRequest[]): Promise<GraphqlResult[]>;
14
+ export {};