@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,174 @@
1
+ # Generated Files
2
+
3
+ @async/db writes generated output during `sync`, `serve`, package API startup, and some smoke commands. Know which files are runtime state and which files are intentionally committed.
4
+
5
+ ## Default Generated Output
6
+
7
+ Default sync output:
8
+
9
+ ```txt
10
+ .db/schema.generated.json
11
+ .db/types/index.d.ts
12
+ .db/state/*.json
13
+ ```
14
+
15
+ `.db/` is normally uncommitted. It contains generated schema metadata, generated TypeScript types, source metadata, and writable runtime store state.
16
+
17
+ ## Runtime State
18
+
19
+ With the default JSON store:
20
+
21
+ ```txt
22
+ db/users.json source fixture
23
+ .db/state/users.json writable runtime JSON store
24
+ ```
25
+
26
+ REST writes, GraphQL mutations, package API writes, and viewer operations write to runtime state. Changed source fixtures refresh state based on source hashes; unchanged source fixtures preserve runtime edits.
27
+
28
+ ## Generated Ids
29
+
30
+ Collections need ids. If a JSON, JSONC, or CSV collection fixture omits `id`, @async/db adds counter ids in the selected runtime store.
31
+
32
+ Source fixtures stay unchanged by default. For resources bound to the `sourceFile` store, @async/db may write generated ids back to plain `.json` collection fixtures when configured intentionally.
33
+
34
+ ## Generated Types
35
+
36
+ Default generated TypeScript output:
37
+
38
+ ```txt
39
+ .db/types/index.d.ts
40
+ ```
41
+
42
+ Use `outputs.committedTypes` when TypeScript imports should work before anyone runs sync:
43
+
44
+ ```js
45
+ import { defineConfig } from '@async/db/config';
46
+
47
+ export default defineConfig({
48
+ outputs: {
49
+ committedTypes: './src/generated/db.types.d.ts',
50
+ },
51
+ });
52
+ ```
53
+
54
+ Field descriptions become TypeScript JSDoc:
55
+
56
+ ```ts
57
+ export type User = {
58
+ /** Stable user id. */
59
+ id: string;
60
+
61
+ /** Email address used for local sign-in. */
62
+ email: string;
63
+ };
64
+ ```
65
+
66
+ Selected examples intentionally commit generated type output:
67
+
68
+ ```txt
69
+ examples/advanced/src/generated/db.types.d.ts
70
+ examples/basic/src/generated/db.types.d.ts
71
+ examples/computed-fields/src/generated/db.types.d.ts
72
+ examples/content-collections/src/generated/db.types.d.ts
73
+ examples/production-json/src/generated/db.types.d.ts
74
+ examples/schema-first/src/generated/db.types.d.ts
75
+ examples/schema-manifest/src/generated/db.types.d.ts
76
+ examples/schema-ui/src/generated/db.types.d.ts
77
+ ```
78
+
79
+ ## Schema Manifest Output
80
+
81
+ Use `outputs.schemaManifest` when a local admin, CMS, or form-building UI needs runtime schema metadata:
82
+
83
+ ```js
84
+ import { defineConfig } from '@async/db/config';
85
+
86
+ export default defineConfig({
87
+ outputs: {
88
+ schemaManifest: './src/generated/db.schema.json',
89
+ },
90
+ });
91
+ ```
92
+
93
+ `async-db sync` writes the manifest when `outputs.schemaManifest` is set. You can also generate it directly:
94
+
95
+ ```bash
96
+ npm run db -- schema manifest --out ./src/generated/db.schema.json
97
+ ```
98
+
99
+ The manifest includes normalized resource and field metadata such as `type`, `required`, `nullable`, `default`, `values`, nested `fields`, array `items`, relations, and generated UI defaults. The manifest file is metadata output only. Schema field defaults still drive configured runtime behavior such as create-time defaults and safe additive store hydration.
100
+
101
+ The manifests at [examples/schema-manifest/src/generated/db.schema.json](../examples/schema-manifest/src/generated/db.schema.json) and [examples/schema-ui/src/generated/db.schema.json](../examples/schema-ui/src/generated/db.schema.json) are intentionally committed.
102
+
103
+ ## Viewer Manifest Output
104
+
105
+ Use `outputs.viewerManifest` when a custom data viewer needs the same JSON metadata used by the built-in viewer:
106
+
107
+ ```js
108
+ import { defineConfig } from '@async/db/config';
109
+
110
+ export default defineConfig({
111
+ outputs: {
112
+ viewerManifest: './src/generated/db.viewer.json',
113
+ },
114
+ });
115
+ ```
116
+
117
+ `async-db sync` writes the viewer manifest when `outputs.viewerManifest` is set. You can also generate it directly:
118
+
119
+ ```bash
120
+ npm run db -- viewer manifest --out ./src/generated/db.viewer.json
121
+ ```
122
+
123
+ The viewer manifest includes field metadata, UI hints, relation hints, diagnostics, capabilities, configured viewer links, and API links such as `/__db/manifest`, `/__db/manifest.json`, `/__db/manifest.html`, `/__db/manifest.md`, `/__db/batch`, `/graphql`, and scoped REST resource routes under `/__db/rest`. It does not include seed records, source paths, source hashes, runtime state paths, or GraphQL SDL. Fetch actual records from REST or GraphQL.
124
+
125
+ ## Operation Registry And Client Contract
126
+
127
+ Use `outputs.operationRegistry` for the full server-side operation registry and
128
+ `outputs.operationRefs` for the client-safe refs file:
129
+
130
+ ```js
131
+ import { defineConfig } from '@async/db/config';
132
+
133
+ export default defineConfig({
134
+ outputs: {
135
+ operationRegistry: './src/generated/db.operations.json',
136
+ operationRefs: './src/generated/db.operation-refs.json',
137
+ },
138
+ });
139
+ ```
140
+
141
+ Build both files with:
142
+
143
+ ```bash
144
+ npm run db -- operations build
145
+ ```
146
+
147
+ `db.operations.json` contains full templates and should stay server-side.
148
+ `db.operation-refs.json` is the browser-facing surface: it exposes operation
149
+ names and callable refs only, not paths, query templates, variables, request
150
+ bodies, or server registry internals.
151
+
152
+ For CI, use the deterministic contract view:
153
+
154
+ ```bash
155
+ npm run db -- operations contract --check
156
+ ```
157
+
158
+ The check compares the current generated client contract with
159
+ `outputs.operationRefs` by default. It ignores volatile `generatedAt` values and
160
+ fails only when exposed operation names or refs change.
161
+
162
+ ## Cleanup Rules
163
+
164
+ - Do not commit `.db/` unless a task explicitly asks for generated runtime state.
165
+ - Do commit configured `outputs.committedTypes` output when an app needs stable imports in a fresh checkout.
166
+ - Do commit configured `outputs.schemaManifest` output when an app needs stable schema metadata at runtime.
167
+ - Do commit configured `outputs.viewerManifest` output when a custom viewer needs stable metadata and route links at runtime.
168
+ - Do commit configured `outputs.operationRefs` output when app or CI code imports approved registered operation refs.
169
+ - Smoke commands against examples may create `examples/*/.db/`; remove that generated runtime output before finalizing.
170
+
171
+ ## Related Examples
172
+
173
+ - [Basic](../examples/basic/README.md)
174
+ - [Schema Manifest](../examples/schema-manifest/README.md)
@@ -0,0 +1,165 @@
1
+ # Getting Started
2
+
3
+ This guide takes a project from one fixture file to a local API, viewer, generated schema metadata, and generated TypeScript types.
4
+
5
+ ## Install
6
+
7
+ Install @async/db from npm:
8
+
9
+ ```bash
10
+ npm install @async/db
11
+ ```
12
+
13
+ Add package scripts for the CLI commands you want to run often:
14
+
15
+ ```json
16
+ {
17
+ "scripts": {
18
+ "db": "async-db",
19
+ "db:sync": "async-db sync",
20
+ "db:serve": "async-db serve",
21
+ "db:types": "async-db types"
22
+ }
23
+ }
24
+ ```
25
+
26
+ If you need an unreleased fix, pin a reviewed GitHub commit or release tag instead of the moving default branch:
27
+
28
+ ```json
29
+ {
30
+ "devDependencies": {
31
+ "@async/db": "github:async-framework/async-db#<reviewed-commit-sha-or-tag>"
32
+ }
33
+ }
34
+ ```
35
+
36
+ The scripts use the local `node_modules/.bin/async-db` binary, so each project controls its own @async/db version.
37
+
38
+ ## Create A Fixture
39
+
40
+ @async/db uses `./db` by default:
41
+
42
+ ```bash
43
+ mkdir -p db
44
+ cat > db/users.json <<'JSON'
45
+ [
46
+ {
47
+ "id": "u_1",
48
+ "name": "Ada Lovelace",
49
+ "email": "ada@example.com"
50
+ }
51
+ ]
52
+ JSON
53
+ ```
54
+
55
+ ## Sync
56
+
57
+ ```bash
58
+ npm run db:sync
59
+ ```
60
+
61
+ Sync reads fixtures and writes generated runtime output:
62
+
63
+ ```txt
64
+ .db/schema.generated.json
65
+ .db/types/index.d.ts
66
+ .db/state/users.json
67
+ ```
68
+
69
+ By default, app writes update the generated JSON store under `.db/state`. Source fixtures stay unchanged.
70
+
71
+ ## Serve
72
+
73
+ In terminal 1:
74
+
75
+ ```bash
76
+ npm run db:serve
77
+ ```
78
+
79
+ Open the viewer:
80
+
81
+ ```txt
82
+ http://127.0.0.1:7331/__db
83
+ ```
84
+
85
+ In terminal 2, call the REST API:
86
+
87
+ ```bash
88
+ curl http://127.0.0.1:7331/db/users.json
89
+ ```
90
+
91
+ You can also read one record through the fixture-shaped URL:
92
+
93
+ ```bash
94
+ curl 'http://127.0.0.1:7331/db/users.json?id=u_1'
95
+ ```
96
+
97
+ Create another record:
98
+
99
+ ```bash
100
+ curl -X POST http://127.0.0.1:7331/db/users \
101
+ -H 'content-type: application/json' \
102
+ -d '{"id":"u_2","name":"Grace Hopper","email":"grace@example.com"}'
103
+ ```
104
+
105
+ The new record is written to `.db/state/users.json`, not `db/users.json`.
106
+
107
+ ## Add A Schema
108
+
109
+ Add schema when the contract matters: required fields, defaults, descriptions, enums, uniqueness, relations, or stricter validation.
110
+
111
+ Create `db/users.schema.json`:
112
+
113
+ ```json
114
+ {
115
+ "kind": "collection",
116
+ "idField": "id",
117
+ "fields": {
118
+ "id": { "type": "string", "required": true },
119
+ "name": { "type": "string", "required": true },
120
+ "email": {
121
+ "type": "string",
122
+ "required": true,
123
+ "unique": true,
124
+ "description": "Email address used for local sign-in."
125
+ },
126
+ "role": {
127
+ "type": "enum",
128
+ "values": ["admin", "user"],
129
+ "default": "user"
130
+ }
131
+ }
132
+ }
133
+ ```
134
+
135
+ Validate:
136
+
137
+ ```bash
138
+ npm run db -- schema validate
139
+ ```
140
+
141
+ When `db/users.schema.json` and `db/users.json` both exist, the schema defines the contract and the data file provides seed records.
142
+
143
+ ## Run A Repo Example
144
+
145
+ From this repository root:
146
+
147
+ ```bash
148
+ npm run db -- sync --cwd ./examples/basic
149
+ npm run db -- serve --cwd ./examples/basic
150
+ ```
151
+
152
+ Open:
153
+
154
+ ```txt
155
+ http://127.0.0.1:7331/__db
156
+ ```
157
+
158
+ The example README has the exact files and requests for that workflow: [examples/basic](../examples/basic/README.md).
159
+
160
+ ## Next Steps
161
+
162
+ - Use [Concepts](./concepts.md) to understand data-first, schema-first, mixed resources, runtime stores, and source writebacks.
163
+ - Use [Fixtures And Schemas](./fixtures-and-schemas.md) to author richer fixtures and schemas.
164
+ - Use [Server And Viewer](./server-and-viewer.md) for REST, GraphQL, viewer, and watch behavior.
165
+ - Use [Generated Files](./generated-files.md) before committing generated output.
@@ -0,0 +1,206 @@
1
+ # Integrations
2
+
3
+ @async/db keeps integrations optional. The core package remains dependency-light; apps opt into Vite, Hono, SQLite, or generated starter code when they need those paths.
4
+
5
+ ## Vite Dev Server Plugin
6
+
7
+ Vite apps can mount @async/db into the existing dev server instead of running `async-db serve` on a second port:
8
+
9
+ ```js
10
+ import { defineConfig } from 'vite';
11
+ import { dbPlugin } from '@async/db/vite';
12
+
13
+ export default defineConfig({
14
+ plugins: [
15
+ dbPlugin(),
16
+ ],
17
+ });
18
+ ```
19
+
20
+ The plugin is dev-only (`apply: 'serve'`). It does not run during `vite build`, and it does not add a mandatory Vite dependency to @async/db.
21
+
22
+ By default, app data routes use `/db`, while dev-tool routes stay scoped under `/__db`:
23
+
24
+ ```txt
25
+ GET /db/users.json
26
+ GET /__db
27
+ GET /__db/schema
28
+ POST /__db/batch
29
+ POST /__db/graphql
30
+ GET /__db/rest/users
31
+ GET /__db/rest/users/u_1
32
+ ```
33
+
34
+ Use the virtual browser client from app code:
35
+
36
+ ```ts
37
+ import db from 'virtual:db/client';
38
+
39
+ const users = await db.rest.get('/users');
40
+ const selected = await db.rest.get('/users?select=id,name');
41
+ ```
42
+
43
+ Plugin options include `cwd`, `dbDir`, `outputs`, legacy `stateDir`, `apiBase`, `dataPath`, `restBasePath`, `graphqlPath`, `rootRoutes`, `clientVirtualModule`, `clientImport`, and `clientCache`.
44
+ The plugin uses `apiBase` first, then `server.apiBase`, then `/__db` for scoped dev routes.
45
+ Use `server.dataPath: false` to disable the `/db` app-facing data route alias.
46
+
47
+ Set `clientCache: true` to opt the virtual browser client into the default
48
+ memory cache during Vite dev. Object form supports serializable cache policy
49
+ options:
50
+
51
+ ```ts
52
+ dbPlugin({
53
+ clientCache: {
54
+ enabled: true,
55
+ readPolicy: 'cache-and-network',
56
+ writePolicy: 'merge-and-invalidate',
57
+ eventPolicy: 'refetch',
58
+ },
59
+ });
60
+ ```
61
+
62
+ Use `createDbClient()` directly when you need an explicit browser storage
63
+ adapter such as `createIndexedDbCacheStorage(...)`.
64
+
65
+ Add `trace` to the plugin options to override `db.config.mjs` for Vite dev
66
+ requests:
67
+
68
+ ```ts
69
+ dbPlugin({
70
+ trace: {
71
+ enabled: true,
72
+ slowMs: 100,
73
+ },
74
+ });
75
+ ```
76
+
77
+ Set `rootRoutes: true` only when you intentionally want Vite dev to also answer unscoped routes like `/users`. Standalone `async-db serve` keeps those root REST routes by default.
78
+
79
+ The plugin watches fixture sources, not generated runtime output. @async/db also skips rewriting generated and state files when their content is unchanged, so normal `sync` or `openDb()` calls should not trigger Vite reloads by changing mtimes alone.
80
+
81
+ If an app commits generated files under frontend source, Vite may still reload when those files genuinely change. Ignore only generated files that the browser does not need to hot reload.
82
+
83
+ ```ts
84
+ export default defineConfig({
85
+ server: {
86
+ watch: {
87
+ ignored: [
88
+ '../.db/**',
89
+ // Only include committed generated files here when browser code
90
+ // does not import them at runtime.
91
+ 'src/generated/db.schema.json',
92
+ 'src/generated/db.types.d.ts',
93
+ ],
94
+ },
95
+ },
96
+ });
97
+ ```
98
+
99
+ ## Hono Route Registration
100
+
101
+ Apps that own a Hono instance can register @async/db REST routes and wrap them with lifecycle hooks.
102
+
103
+ ```ts
104
+ import { registerDbRoutes } from '@async/db/hono';
105
+
106
+ registerDbRoutes(app, db, {
107
+ prefix: '/api',
108
+ operations: true,
109
+ trace: true,
110
+ resources: ['pages', 'charts'],
111
+ lifecycleHooks: {
112
+ beforeRequest({ c }) {
113
+ const session = readSession(c.req.header('authorization'));
114
+ if (!session) return c.json({ error: 'Unauthorized' }, 401);
115
+ c.set('session', session);
116
+ },
117
+ beforeWrite({ c, body }) {
118
+ if (c.get('session')?.role !== 'admin') {
119
+ return c.json({ error: 'Forbidden' }, 403);
120
+ }
121
+ if (body) body.updatedAt = new Date().toISOString();
122
+ },
123
+ },
124
+ hooks: {
125
+ beforeCreate({ body }) {
126
+ body.createdAt ??= body.updatedAt;
127
+ },
128
+ },
129
+ });
130
+ ```
131
+
132
+ Resource hook order is deterministic:
133
+
134
+ 1. `beforeRequest`
135
+ 2. `beforeWrite` for `create`, `patch`, `put`, or `delete`
136
+ 3. matching global method hook
137
+ 4. matching resource method hook
138
+ 5. @async/db operation
139
+
140
+ Any hook can return a Hono response to short-circuit the request. Write hooks can mutate `body` before @async/db validates and writes it.
141
+ Registered operation routes run `lifecycleHooks.beforeRequest` before operation
142
+ execution with `method: 'operation'` and the operation `ref`. They do not run
143
+ resource write or resource method hooks.
144
+ When tracing is enabled, hook phases and short-circuit responses are included in
145
+ the request trace event without recording request or response bodies.
146
+
147
+ Registered operations mount at `POST {prefix}/operations/:ref` when
148
+ `db.config.operations.enabled` is true. Set `operations: false` for a REST-only
149
+ mount, `operations: true` to explicitly use global config, or pass a local
150
+ registry/resolver when a Hono app owns a custom build step:
151
+
152
+ ```ts
153
+ registerDbRoutes(app, db, {
154
+ prefix: '/api/db',
155
+ operations: {
156
+ registry: generatedOperations.operations,
157
+ acceptRefs: 'ref',
158
+ },
159
+ });
160
+ ```
161
+
162
+ See [examples/hono-auth](../examples/hono-auth/README.md) for a runnable Hono app with bearer-token auth.
163
+
164
+ For guidance on moving local `/db/*` prototype routes to `/api/db/*` or
165
+ `/api/*` production namespaces, registered operation refs, and locked-down
166
+ route exposure, see the
167
+ [Prototype To Production REST Guide](./prototype-to-production.md).
168
+
169
+ ## Hono And SQLite Starter Generation
170
+
171
+ When fixtures and schemas have settled enough to graduate toward a real database API, generate a Hono starter:
172
+
173
+ ```bash
174
+ async-db generate hono
175
+ async-db generate hono --api rest,graphql --out ./server
176
+ async-db generate hono --api none --app module
177
+ ```
178
+
179
+ The default output is `./db-api` with REST routes, a portable repository interface, a `node:sqlite` adapter, validators, and an initial SQL migration.
180
+
181
+ Generated standalone apps are TypeScript-first and target Node.js `>=22.13` because SQLite output uses `node:sqlite`.
182
+
183
+ The main package stays dependency-light. Generated apps declare their own `hono`, `@hono/node-server`, `typescript`, and `tsx` dependencies.
184
+
185
+ Generation fails on schema errors and, by default, on schema warnings so production starter code only uses declared schema fields. Pass `--allow-warnings` only when you intentionally want to generate with warning diagnostics.
186
+
187
+ ## Optional Runtime Hono/SQLite
188
+
189
+ Apps can also use optional runtime exports directly:
190
+
191
+ ```ts
192
+ import { Hono } from 'hono';
193
+ import { createDbHonoApp } from '@async/db/hono';
194
+
195
+ const app = new Hono();
196
+ app.route('/api', await createDbHonoApp({
197
+ dbDir: './db',
198
+ storage: {
199
+ kind: 'sqlite',
200
+ file: './data/app.sqlite',
201
+ },
202
+ api: ['rest'],
203
+ }));
204
+ ```
205
+
206
+ These integrations are opt-in. They should not make `hono`, `@hono/node-server`, or SQLite libraries mandatory dependencies of the core package.
@@ -0,0 +1,120 @@
1
+ # Production JSON Database
2
+
3
+ `@async/db/json` is the first-party file database surface for @async/db. It is for resources that should stay simple, reviewable, and file-backed while the app talks to the same @async/db API layer it would use for SQLite, Postgres, or a custom store.
4
+
5
+ The product split is:
6
+
7
+ - `@async/db` owns the app-facing data layer: schemas, generated types, clients, REST/GraphQL metadata, registered operations, and store switching.
8
+ - `@async/db/json` owns the simple JSON file database surface: JSON store capability metadata and safe JSON state-file helpers.
9
+
10
+ JSON controls the app. Databases record the app.
11
+
12
+ ## Good Production Fits
13
+
14
+ Use the JSON store for small low-write resources that are naturally files:
15
+
16
+ - app settings
17
+ - feature flags and rollout rules
18
+ - navigation, labels, and UI configuration
19
+ - CMS/content records, docs metadata, and templates
20
+ - prompt templates and model/provider defaults
21
+ - plan, pricing, and entitlement definitions
22
+ - policy rules and permission maps
23
+ - seed data, demo data, fixtures, mocks, and test baselines
24
+
25
+ These are control-plane resources. They are valuable in production when they stay easy to review, snapshot, diff, and promote between environments.
26
+
27
+ See [examples/production-json](../examples/production-json/README.md) for a runnable feature flags and app settings example that keeps JSON as the store while browser traffic uses registered operation refs.
28
+
29
+ ## Hard Limits
30
+
31
+ Do not use the JSON store as the primary production store for:
32
+
33
+ - chat messages, activity feeds, analytics events, or logs
34
+ - payments, ledgers, balances, inventory counters, or booking availability
35
+ - high-write user data or large searchable datasets
36
+ - data written by multiple app instances at the same time
37
+ - multi-region writes or cross-process transactional workflows
38
+ - compliance-heavy records that require database-level audit, retention, or access controls
39
+
40
+ The default JSON store writes complete resource files under `.db/state`. Writes are atomic at the file/resource level and queued in-process, but that is not the same as a database transaction, cross-process lock, query planner, or replicated storage system.
41
+
42
+ Treat 1,000 collection records as a review point. `async-db doctor` already warns when a JSON-backed collection has more than 1,000 seed records without index metadata. For fast-changing or query-heavy collections, graduate the resource before users depend on it.
43
+
44
+ If a JSON state file is corrupt or only partially recoverable, `@async/db/json` reports `JSON_STATE_INVALID` with the file path and parser message. Restore that file from a known-good snapshot, delete it only when rehydrating from seed data is safe, or fix the JSON syntax before restarting the app.
45
+
46
+ ## Production API Boundary
47
+
48
+ Do not expose local `async-db serve` as an unauthenticated public database API.
49
+
50
+ For production-facing traffic:
51
+
52
+ 1. Move app routes to `/api/db/*` or `/api/*`.
53
+ 2. Register stable operations for browser-facing reads and writes.
54
+ 3. Generate client-safe operation refs.
55
+ 4. Use `server.expose.rest: 'registered-only'` when raw REST should be blocked.
56
+ 5. Add app-owned auth, authorization, rate limits, and monitoring around the mounted API.
57
+
58
+ The browser should call the data contract, not the JSON files. With the built-in operation system, that means calling generated operation refs:
59
+
60
+ ```ts
61
+ const flags = await db.query(operationRefs.operations.ListFeatureFlags.ref);
62
+ ```
63
+
64
+ The operation template can read JSON today and later point at a SQLite, Postgres, Redis, or custom-backed resource while the client call stays the same. App-owned servers can also wrap the operation route with auth, rate limits, policy checks, and flag evaluation before returning a client-safe result.
65
+
66
+ ## Public JSON Helpers
67
+
68
+ Use `@async/db/json` when app or tooling code needs to inspect the built-in JSON database surface directly:
69
+
70
+ ```ts
71
+ import {
72
+ jsonStoreCapabilities,
73
+ jsonStatePathForResource,
74
+ readJsonState,
75
+ writeJsonState,
76
+ } from '@async/db/json';
77
+
78
+ if (jsonStoreCapabilities.production === 'small-local') {
79
+ const file = jsonStatePathForResource({ stateDir: './.db' }, 'settings');
80
+ const settings = await readJsonState(file, {});
81
+ await writeJsonState(file, settings);
82
+ }
83
+ ```
84
+
85
+ Most app code should still use `openDb()`, `createDbClient()`, and registered operations. The JSON helpers are for tooling, diagnostics, migrations, exports, and advanced local workflows.
86
+
87
+ ## Mixed Stores
88
+
89
+ Keep JSON for control-plane resources and graduate data-plane resources independently:
90
+
91
+ ```js
92
+ export default {
93
+ stores: {
94
+ default: 'json',
95
+ appDb: postgresStore({ client }),
96
+ },
97
+ resources: {
98
+ featureFlags: { store: 'json' },
99
+ settings: { store: 'json' },
100
+ activityEvents: { store: 'appDb' },
101
+ orders: { store: 'appDb' },
102
+ },
103
+ };
104
+ ```
105
+
106
+ The app-facing contract stays in @async/db. Frontend code calls the same generated types, REST resources, or registered operation refs while each resource chooses the storage boundary that fits its write rate and operational risk.
107
+
108
+ For the full resource-by-resource migration path, see [Resource Graduation And Mixed Stores](./store-graduation.md).
109
+
110
+ ## Readiness Checklist
111
+
112
+ - Run `async-db doctor --production` before treating JSON-backed resources as production data. Use `async-db check --strict --production` when warnings should fail CI.
113
+ - Use explicit schemas for production JSON resources.
114
+ - Prefer `schema.unknownFields: 'error'` when drift should fail.
115
+ - Keep JSON-backed writes low-volume and single-writer.
116
+ - Snapshot or back up `.db/state` before deployments and migrations.
117
+ - Practice recovery for `JSON_STATE_INVALID` by restoring a known-good state snapshot.
118
+ - Keep browser traffic behind registered operations when exposing production APIs.
119
+ - Return evaluated feature flags or policy decisions to the browser, not sensitive rule internals.
120
+ - Move a resource to SQLite, Postgres, or a custom store when write rate, size, query needs, or concurrency exceed file-backed JSON limits.