@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,105 @@
1
+ import assert from 'node:assert/strict';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { openDb } from '@async/db';
4
+
5
+ const paidStoreData = new Map();
6
+
7
+ export async function openUpgradeDemoDb() {
8
+ return openDb({
9
+ cwd: new URL('../', import.meta.url).pathname,
10
+ stores: {
11
+ default: 'json',
12
+ paidPostgres: {
13
+ read(resource, fallback) {
14
+ return paidStoreData.has(resource.name) ? paidStoreData.get(resource.name) : fallback;
15
+ },
16
+ write(resource, value) {
17
+ paidStoreData.set(resource.name, value);
18
+ },
19
+ },
20
+ },
21
+ });
22
+ }
23
+
24
+ export async function upgradeTenantToPaid({ db, tenantId }) {
25
+ const tenant = await db.forks.ensure(tenantId, {
26
+ from: 'main',
27
+ metadata: {
28
+ purpose: 'tenant',
29
+ plan: 'free',
30
+ },
31
+ });
32
+
33
+ const backup = await tenant.snapshots.create({
34
+ label: 'before-paid-upgrade',
35
+ resources: ['projects'],
36
+ });
37
+
38
+ await tenant.migrations.start('projects-to-paid-postgres', {
39
+ resources: ['projects'],
40
+ mode: 'read-only',
41
+ });
42
+
43
+ await tenant.resources.migrate('projects', {
44
+ from: 'json',
45
+ to: 'paidPostgres',
46
+ });
47
+
48
+ await tenant.migrations.verify('projects-to-paid-postgres', {
49
+ resources: ['projects'],
50
+ checks: ['count', 'checksum'],
51
+ });
52
+
53
+ await tenant.routing.set({
54
+ projects: 'paidPostgres',
55
+ });
56
+
57
+ await tenant.migrations.finish('projects-to-paid-postgres');
58
+
59
+ return {
60
+ tenant,
61
+ backup,
62
+ };
63
+ }
64
+
65
+ async function main() {
66
+ const db = await openUpgradeDemoDb();
67
+ const { tenant, backup } = await upgradeTenantToPaid({
68
+ db,
69
+ tenantId: 'tenant_acme',
70
+ });
71
+
72
+ assert.equal(backup.resources.includes('projects'), true);
73
+ assert.deepEqual(await tenant.collection('projects').all(), [
74
+ {
75
+ id: 'p_1',
76
+ name: 'Launch checklist',
77
+ status: 'active',
78
+ },
79
+ ]);
80
+
81
+ await tenant.collection('projects').create({
82
+ id: 'p_2',
83
+ name: 'Paid workspace project',
84
+ status: 'active',
85
+ });
86
+
87
+ assert.deepEqual(paidStoreData.get('projects'), [
88
+ {
89
+ id: 'p_1',
90
+ name: 'Launch checklist',
91
+ status: 'active',
92
+ },
93
+ {
94
+ id: 'p_2',
95
+ name: 'Paid workspace project',
96
+ status: 'active',
97
+ },
98
+ ]);
99
+
100
+ await db.close();
101
+ }
102
+
103
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
104
+ await main();
105
+ }
@@ -0,0 +1,74 @@
1
+ # Hono Auth Example
2
+
3
+ ## What This Teaches
4
+
5
+ Use this when your app already has a Hono server and you want db to own the CRUD routes while your app owns auth, permissions, and write normalization.
6
+
7
+ ## Files To Inspect
8
+
9
+ - [src/app.mjs](./src/app.mjs): registers db REST routes with `beforeRequest`, `beforeWrite`, and a pages-specific create hook.
10
+ - [src/server.mjs](./src/server.mjs): starts the Hono app locally.
11
+ - [db/pages.schema.jsonc](./db/pages.schema.jsonc): schema-backed page collection with timestamps set by hooks.
12
+ - [db/users.schema.jsonc](./db/users.schema.jsonc): demo users used by the bearer-token sessions.
13
+
14
+ ## Run It
15
+
16
+ From this example directory:
17
+
18
+ ```bash
19
+ npm install
20
+ npm run sync
21
+ npm run dev
22
+ ```
23
+
24
+ ## Requests To Try
25
+
26
+ Leave `npm run dev` running and run these from another terminal.
27
+
28
+ Missing tokens are rejected:
29
+
30
+ ```bash
31
+ curl -i 'http://127.0.0.1:8787/api/pages'
32
+ ```
33
+
34
+ Reader tokens can read:
35
+
36
+ ```bash
37
+ curl -H 'Authorization: Bearer user-token' 'http://127.0.0.1:8787/api/pages'
38
+ ```
39
+
40
+ Reader tokens cannot write:
41
+
42
+ ```bash
43
+ curl -i -X PATCH 'http://127.0.0.1:8787/api/pages/home' \
44
+ -H 'Authorization: Bearer user-token' \
45
+ -H 'content-type: application/json' \
46
+ -d '{"title":"Draft"}'
47
+ ```
48
+
49
+ Admin tokens can write. The shared write hook trims strings and sets `updatedAt`:
50
+
51
+ ```bash
52
+ curl -X PATCH 'http://127.0.0.1:8787/api/pages/home' \
53
+ -H 'Authorization: Bearer admin-token' \
54
+ -H 'content-type: application/json' \
55
+ -d '{"title":" Homepage "}'
56
+ ```
57
+
58
+ ## Token Map
59
+
60
+ - `Bearer admin-token`: read and write.
61
+ - `Bearer user-token`: read only.
62
+
63
+ This is intentionally tiny demo auth. In a real app, `beforeRequest` would read your session or token source, and `beforeWrite` would call your permission policy.
64
+
65
+ ## Features To Notice
66
+
67
+ - [Hono route registration](../../docs/integrations.md#hono-route-registration)
68
+ - [Lifecycle hooks](../../docs/integrations.md#hono-route-registration)
69
+ - [Schema-backed fixtures](../../docs/fixtures-and-schemas.md#schema-files)
70
+
71
+ ## More Docs
72
+
73
+ - [Integrations](../../docs/integrations.md)
74
+ - [Server And Viewer](../../docs/server-and-viewer.md)
@@ -0,0 +1,44 @@
1
+ {
2
+ "kind": "collection",
3
+ "idField": "id",
4
+ "fields": {
5
+ "id": {
6
+ "type": "string",
7
+ "required": true,
8
+ "description": "Stable page id used in routes and links."
9
+ },
10
+ "title": {
11
+ "type": "string",
12
+ "required": true,
13
+ "description": "Human-readable page title."
14
+ },
15
+ "visibility": {
16
+ "type": "enum",
17
+ "values": ["public", "private"],
18
+ "default": "private",
19
+ "description": "Whether the page can be shown publicly."
20
+ },
21
+ "body": {
22
+ "type": "string",
23
+ "description": "Short markdown-like page body for the demo."
24
+ },
25
+ "createdAt": {
26
+ "type": "datetime",
27
+ "description": "Timestamp assigned by the pages create hook."
28
+ },
29
+ "updatedAt": {
30
+ "type": "datetime",
31
+ "description": "Timestamp assigned by the shared write hook."
32
+ }
33
+ },
34
+ "seed": [
35
+ {
36
+ "id": "home",
37
+ "title": "Home",
38
+ "visibility": "public",
39
+ "body": "Welcome to the db Hono auth example.",
40
+ "createdAt": "2026-05-14T00:00:00.000Z",
41
+ "updatedAt": "2026-05-14T00:00:00.000Z"
42
+ }
43
+ ]
44
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "kind": "collection",
3
+ "idField": "id",
4
+ "fields": {
5
+ "id": {
6
+ "type": "string",
7
+ "required": true,
8
+ "description": "Stable user id."
9
+ },
10
+ "name": {
11
+ "type": "string",
12
+ "required": true,
13
+ "description": "Display name shown in the app."
14
+ },
15
+ "email": {
16
+ "type": "string",
17
+ "required": true,
18
+ "unique": true,
19
+ "description": "Email address used for local sign-in."
20
+ },
21
+ "role": {
22
+ "type": "enum",
23
+ "values": ["admin", "user"],
24
+ "default": "user",
25
+ "description": "Local authorization role."
26
+ }
27
+ },
28
+ "seed": [
29
+ {
30
+ "id": "u_admin",
31
+ "name": "Admin Example",
32
+ "email": "admin@example.com",
33
+ "role": "admin"
34
+ },
35
+ {
36
+ "id": "u_user",
37
+ "name": "Reader Example",
38
+ "email": "reader@example.com",
39
+ "role": "user"
40
+ }
41
+ ]
42
+ }
@@ -0,0 +1,17 @@
1
+ // @ts-check
2
+ import { defineConfig } from '@async/db/config';
3
+
4
+ export default defineConfig({
5
+ dbDir: './db',
6
+ outputs: {
7
+ stateDir: './.db',
8
+ types: './.db/types/index.d.ts',
9
+ },
10
+ types: {
11
+ enabled: true,
12
+ emitComments: true,
13
+ },
14
+ schema: {
15
+ unknownFields: 'warn',
16
+ },
17
+ });
@@ -0,0 +1,5 @@
1
+ {
2
+ "title": "Hono Auth",
3
+ "description": "A small Hono app that uses registerDbRoutes lifecycle hooks for bearer-token auth, write permissions, and payload normalization.",
4
+ "tags": ["hono", "auth", "rest"]
5
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "db-hono-auth-example",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "node ./src/server.mjs",
7
+ "sync": "async-db sync --cwd ."
8
+ },
9
+ "dependencies": {
10
+ "@hono/node-server": "^1.13.8",
11
+ "hono": "^4.6.0",
12
+ "@async/db": "file:../.."
13
+ }
14
+ }
@@ -0,0 +1,79 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { openDb } from '@async/db';
4
+ import { registerDbRoutes } from '@async/db/hono';
5
+
6
+ const exampleRoot = fileURLToPath(new URL('..', import.meta.url));
7
+
8
+ export const demoAuthorizationHeaders = {
9
+ admin: 'Bearer admin-token',
10
+ user: 'Bearer user-token',
11
+ };
12
+
13
+ const demoSessions = new Map([
14
+ [authorizationToken(demoAuthorizationHeaders.admin), { userId: 'u_admin', role: 'admin' }],
15
+ [authorizationToken(demoAuthorizationHeaders.user), { userId: 'u_user', role: 'user' }],
16
+ ]);
17
+
18
+ export async function createApp(options = {}) {
19
+ const { Hono } = await import('hono');
20
+ const app = new Hono();
21
+ const db = options.db ?? await openDb({
22
+ cwd: options.cwd ?? path.resolve(exampleRoot),
23
+ });
24
+
25
+ registerDbRoutes(app, db, {
26
+ prefix: '/api',
27
+ resources: ['pages', 'users'],
28
+ lifecycleHooks: {
29
+ beforeRequest(ctx) {
30
+ const session = sessionFromAuthorizationHeader(ctx.c.req.header('authorization'));
31
+ if (!session) {
32
+ return ctx.c.json({ error: 'Unauthorized' }, 401);
33
+ }
34
+ ctx.c.set('session', session);
35
+ },
36
+ beforeWrite(ctx) {
37
+ const session = ctx.c.get('session');
38
+ if (session?.role !== 'admin') {
39
+ return ctx.c.json({ error: 'Forbidden' }, 403);
40
+ }
41
+ normalizeWriteBody(ctx.body);
42
+ },
43
+ },
44
+ resourceOptions: {
45
+ pages: {
46
+ hooks: {
47
+ beforeCreate(ctx) {
48
+ ctx.body.createdAt ??= ctx.body.updatedAt;
49
+ },
50
+ },
51
+ },
52
+ },
53
+ });
54
+
55
+ return app;
56
+ }
57
+
58
+ export function sessionFromAuthorizationHeader(header) {
59
+ return demoSessions.get(authorizationToken(header)) ?? null;
60
+ }
61
+
62
+ function authorizationToken(header) {
63
+ const match = /^Bearer\s+(.+)$/i.exec(String(header ?? ''));
64
+ return match?.[1] ?? null;
65
+ }
66
+
67
+ function normalizeWriteBody(body) {
68
+ if (!body || typeof body !== 'object' || Array.isArray(body)) {
69
+ return;
70
+ }
71
+
72
+ for (const [key, value] of Object.entries(body)) {
73
+ if (typeof value === 'string') {
74
+ body[key] = value.trim();
75
+ }
76
+ }
77
+
78
+ body.updatedAt = new Date().toISOString();
79
+ }
@@ -0,0 +1,13 @@
1
+ import { serve } from '@hono/node-server';
2
+ import { createApp } from './app.mjs';
3
+
4
+ const port = Number(process.env.PORT ?? 8787);
5
+ const app = await createApp();
6
+
7
+ serve({
8
+ fetch: app.fetch,
9
+ hostname: '127.0.0.1',
10
+ port,
11
+ });
12
+
13
+ console.log(`db Hono auth example: http://127.0.0.1:${port}`);
@@ -0,0 +1,102 @@
1
+ # Production JSON Example
2
+
3
+ ## What This Teaches
4
+
5
+ Use this when an app has small production control-plane data that should stay in reviewed JSON while browser traffic goes through registered operations. It models feature flags and public app settings as file-backed JSON resources, then exposes only operation refs to client code.
6
+
7
+ ## Files To Inspect
8
+
9
+ - [db/featureFlags.schema.jsonc](./db/featureFlags.schema.jsonc): low-write feature flag records with explicit schema.
10
+ - [db/appSettings.schema.jsonc](./db/appSettings.schema.jsonc): singleton production settings document.
11
+ - [db/operations](./db/operations): registered operation templates for browser-facing reads.
12
+ - [db.config.mjs](./db.config.mjs): enables operation-only REST exposure and ref-only operation calls.
13
+ - [src/client-demo.mjs](./src/client-demo.mjs): tiny client script that calls generated operation refs.
14
+ - [src/generated/db.types.d.ts](./src/generated/db.types.d.ts): committed generated types.
15
+
16
+ ## Run It
17
+
18
+ From the repository root, use the repo-internal CLI path:
19
+
20
+ ```bash
21
+ npm run db -- sync --cwd ./examples/production-json
22
+ npm run db -- operations build --cwd ./examples/production-json
23
+ npm run db -- serve --cwd ./examples/production-json
24
+ ```
25
+
26
+ In another terminal:
27
+
28
+ ```bash
29
+ ASYNC_DB_URL=http://127.0.0.1:7331 node ./examples/production-json/src/client-demo.mjs
30
+ ```
31
+
32
+ ## Expected Result
33
+
34
+ `sync` writes generated schema, types, and runtime state under `examples/production-json/.db/`, plus the committed type copy in `src/generated/`.
35
+
36
+ `operations build` writes client-safe operation refs under `examples/production-json/src/generated/`. The server reads templates from `db/operations`, while the demo script reads generated refs and calls `GetControlPlane` and `GetFeatureFlag` through `client.query()`.
37
+
38
+ To review the browser-facing operation contract without volatile timestamps:
39
+
40
+ ```bash
41
+ npm run db -- operations contract --cwd ./examples/production-json
42
+ npm run db -- operations contract --cwd ./examples/production-json --check
43
+ ```
44
+
45
+ ## Operation Requests To Try
46
+
47
+ Build operations, then use the generated ref from `examples/production-json/src/generated/db.operation-refs.json`:
48
+
49
+ ```bash
50
+ curl -X POST http://127.0.0.1:7331/__db/operations/REF \
51
+ -H 'content-type: application/json' \
52
+ -d '{"variables":{"id":"flag_billing_v2"}}'
53
+ ```
54
+
55
+ Raw REST routes are intentionally not the production-facing API in this example. `server.expose.rest: 'registered-only'` keeps app traffic on the registered operation boundary while the JSON files remain the first-party store.
56
+
57
+ ## Why This Shape?
58
+
59
+ Feature flags and app settings are control-plane resources: small, low-write, easy to review, and useful to snapshot. That makes them a realistic production fit for `@async/db/json`.
60
+
61
+ The app should still evaluate sensitive targeting, auth, rate limits, and policy in app-owned code. The JSON store keeps the reviewed flag definitions; registered operations keep browser calls stable if a resource later graduates to SQLite, Postgres, Redis, or a custom store.
62
+
63
+ ## Graduating One Resource
64
+
65
+ Keep `appSettings` and `featureFlags` on JSON when they remain small and low-write. If a new `orders` resource outgrows JSON, add a database store and move only that resource:
66
+
67
+ ```js
68
+ import { defineConfig } from '@async/db/config';
69
+ import { postgresStore } from '@async/db/postgres';
70
+ import { pool } from './src/server/postgres-client.js';
71
+
72
+ export default defineConfig({
73
+ stores: {
74
+ default: 'json',
75
+ appDb: postgresStore({ client: pool }),
76
+ },
77
+ resources: {
78
+ appSettings: { store: 'json' },
79
+ featureFlags: { store: 'json' },
80
+ orders: { store: 'appDb' },
81
+ },
82
+ operations: {
83
+ enabled: true,
84
+ acceptRefs: 'ref',
85
+ sourceDir: './db/operations',
86
+ },
87
+ });
88
+ ```
89
+
90
+ Operation templates that read `appSettings`, `featureFlags`, or `orders` stay behind the same `client.query(ref, variables)` call shape. The resource store changes; the browser contract does not.
91
+
92
+ ## Features To Notice
93
+
94
+ - [Production JSON Database](../../docs/json-production.md)
95
+ - [Resource Graduation And Mixed Stores](../../docs/store-graduation.md)
96
+ - [Registered REST operations](../../docs/server-and-viewer.md#registered-rest-operations)
97
+ - [Operation-only exposure](../../docs/configuration.md#server-exposure)
98
+ - [Generated operation refs](../../docs/generated-files.md#operation-registry-output)
99
+
100
+ ## Cleanup
101
+
102
+ Generated `.db/` output is ignored by git and can be removed whenever you want a fresh mirror. Generated operation ref files under `src/generated/` are safe to regenerate after operation template changes.
@@ -0,0 +1,41 @@
1
+ {
2
+ "kind": "document",
3
+ "description": "Small production settings that are safe to keep as reviewed JSON.",
4
+ "fields": {
5
+ "appName": {
6
+ "type": "string",
7
+ "required": true,
8
+ "description": "Public product name shown by the app shell."
9
+ },
10
+ "environment": {
11
+ "type": "enum",
12
+ "values": ["development", "staging", "production"],
13
+ "required": true,
14
+ "description": "Deployment lane this settings file belongs to."
15
+ },
16
+ "maintenanceMode": {
17
+ "type": "boolean",
18
+ "required": true,
19
+ "default": false,
20
+ "description": "Whether the public app should show maintenance UI."
21
+ },
22
+ "defaultLocale": {
23
+ "type": "string",
24
+ "required": true,
25
+ "default": "en-US",
26
+ "description": "Fallback locale for unauthenticated visitors."
27
+ },
28
+ "supportEmail": {
29
+ "type": "string",
30
+ "required": true,
31
+ "description": "Public support contact shown in product chrome."
32
+ }
33
+ },
34
+ "seed": {
35
+ "appName": "Launch Console",
36
+ "environment": "production",
37
+ "maintenanceMode": false,
38
+ "defaultLocale": "en-US",
39
+ "supportEmail": "support@example.test"
40
+ }
41
+ }
@@ -0,0 +1,84 @@
1
+ {
2
+ "kind": "collection",
3
+ "description": "Low-write production feature flags that control app behavior.",
4
+ "idField": "id",
5
+ "fields": {
6
+ "id": {
7
+ "type": "string",
8
+ "required": true,
9
+ "description": "Stable flag id used by operations and review notes."
10
+ },
11
+ "key": {
12
+ "type": "string",
13
+ "required": true,
14
+ "unique": true,
15
+ "description": "Stable application flag key."
16
+ },
17
+ "enabled": {
18
+ "type": "boolean",
19
+ "required": true,
20
+ "default": false,
21
+ "description": "Global default before app-owned targeting runs."
22
+ },
23
+ "audience": {
24
+ "type": "enum",
25
+ "values": ["everyone", "staff", "beta", "enterprise"],
26
+ "required": true,
27
+ "default": "staff",
28
+ "description": "Coarse audience label consumed by the app policy layer."
29
+ },
30
+ "rolloutPercent": {
31
+ "type": "number",
32
+ "required": true,
33
+ "default": 0,
34
+ "description": "Default rollout percentage for app-owned evaluation."
35
+ },
36
+ "description": {
37
+ "type": "string",
38
+ "required": true,
39
+ "description": "Human review note explaining the flag."
40
+ },
41
+ "owner": {
42
+ "type": "string",
43
+ "required": true,
44
+ "description": "Team or person responsible for changing this flag."
45
+ },
46
+ "updatedAt": {
47
+ "type": "string",
48
+ "required": true,
49
+ "description": "ISO timestamp for the last reviewed flag change."
50
+ }
51
+ },
52
+ "seed": [
53
+ {
54
+ "id": "flag_billing_v2",
55
+ "key": "billing.v2",
56
+ "enabled": true,
57
+ "audience": "beta",
58
+ "rolloutPercent": 25,
59
+ "description": "Expose the new billing flow to beta accounts.",
60
+ "owner": "growth",
61
+ "updatedAt": "2026-05-01T12:00:00Z"
62
+ },
63
+ {
64
+ "id": "flag_enterprise_dashboard",
65
+ "key": "dashboard.enterprise",
66
+ "enabled": true,
67
+ "audience": "enterprise",
68
+ "rolloutPercent": 100,
69
+ "description": "Show enterprise reporting navigation.",
70
+ "owner": "platform",
71
+ "updatedAt": "2026-05-03T09:30:00Z"
72
+ },
73
+ {
74
+ "id": "flag_editor_command_palette",
75
+ "key": "editor.commandPalette",
76
+ "enabled": false,
77
+ "audience": "staff",
78
+ "rolloutPercent": 0,
79
+ "description": "Internal preview of command palette shortcuts.",
80
+ "owner": "product",
81
+ "updatedAt": "2026-05-05T16:45:00Z"
82
+ }
83
+ ]
84
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "GetControlPlane",
3
+ "kind": "graphql",
4
+ "operationName": "GetControlPlane",
5
+ "query": "query GetControlPlane { appSettings { appName environment maintenanceMode defaultLocale supportEmail } featureFlags { id key enabled audience rolloutPercent description owner updatedAt } }"
6
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "GetFeatureFlag",
3
+ "method": "GET",
4
+ "path": "/feature-flags.json",
5
+ "query": {
6
+ "id": "{id}",
7
+ "select": "id,key,enabled,audience,rolloutPercent,description,owner,updatedAt"
8
+ }
9
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "ListFeatureFlags",
3
+ "method": "GET",
4
+ "path": "/feature-flags.json",
5
+ "query": {
6
+ "select": "id,key,enabled,audience,rolloutPercent,description,owner,updatedAt"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "ReadPublicSettings",
3
+ "method": "GET",
4
+ "path": "/app-settings.json",
5
+ "query": {
6
+ "select": "appName,environment,maintenanceMode,defaultLocale,supportEmail"
7
+ }
8
+ }