@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,466 @@
1
+ # Server And Viewer
2
+
3
+ `async-db serve` starts a local development server. It syncs on startup, watches fixture sources, serves REST and GraphQL endpoints, and exposes the built-in data viewer.
4
+
5
+ ## Local Trust Boundary
6
+
7
+ The server binds to `127.0.0.1` by default. It is intended for local development and tests, not public hosting.
8
+
9
+ Important write surfaces:
10
+
11
+ - REST writes update runtime state.
12
+ - GraphQL mutations update runtime state.
13
+ - Viewer CSV import writes CSV files into the configured `dbDir`.
14
+ - Resources bound to the `sourceFile` store may write supported changes back to source fixtures.
15
+
16
+ Config and schema JavaScript are trusted project code. Do not treat `.schema.mjs`, `.schema.js`, or config hooks as untrusted data.
17
+
18
+ ## Request Tracing
19
+
20
+ Enable request tracing when a local page appears stuck or slow and you need to
21
+ see where a DB request spent time:
22
+
23
+ ```js
24
+ import { defineConfig } from '@async/db/config';
25
+
26
+ export default defineConfig({
27
+ server: {
28
+ trace: true,
29
+ },
30
+ });
31
+ ```
32
+
33
+ Tracing adds an `x-async-db-request-id` response header, emits
34
+ `request-trace` events through `GET /__db/log`, and prints concise console
35
+ lines unless disabled. Traces include method, pathname, query keys, route
36
+ family, resource, operation, id when known, status, handled state, duration,
37
+ slow status, safe error code/message, and phase timings for clear boundaries
38
+ such as route matching, mock behavior, REST handling, Hono hooks, collection or
39
+ document reads/writes, response shaping, registered operations, batch items, and
40
+ fork dispatch.
41
+
42
+ Trace data intentionally omits request bodies, response bodies, cookie headers,
43
+ authorization headers, and query values. Query strings are represented as keys
44
+ only, for example `["select", "expand"]`.
45
+
46
+ ## Viewer
47
+
48
+ Open the built-in viewer after starting the server:
49
+
50
+ ```txt
51
+ http://127.0.0.1:7331/__db
52
+ ```
53
+
54
+ The default viewer and dev-tool route base is `/__db`. Change it with
55
+ `server.apiBase` when an app needs a different reserved path; schema, batch,
56
+ import, events, log, and fork routes move with that base.
57
+
58
+ Opening `http://127.0.0.1:7331/` in a browser shows a small index with links to the data viewer, schema, GraphQL endpoint, and resource routes. API-style requests to `/` keep returning JSON discovery data by default.
59
+
60
+ The viewer includes:
61
+
62
+ - resource and data browsing
63
+ - drag-and-drop CSV import into the configured fixture folder
64
+ - REST specs with copyable examples
65
+ - a REST request runner
66
+ - GraphQL SDL and operation references
67
+ - schema and field inspection
68
+ - source diagnostics when one fixture file is broken
69
+
70
+ ## Custom Viewer Manifest
71
+
72
+ The built-in viewer reads the same JSON manifest that custom viewer UIs can use:
73
+
74
+ ```txt
75
+ GET /__db/manifest
76
+ GET /__db/manifest.json
77
+ GET /__db/manifest.html
78
+ GET /__db/manifest.md
79
+ ```
80
+
81
+ `/manifest.json` returns JSON. `/manifest.html` returns the built-in formatted JSON viewer with dark mode by default, dark/light/system theme controls, copy, and pretty/raw formatting controls. `/manifest.md` returns Markdown with the manifest JSON in a fenced code block for AI clients. `/manifest` chooses from registered response formats using the request `Accept` header. If `server.apiBase` changes, the routes move with it, for example `GET /_db/manifest`.
82
+
83
+ The manifest includes:
84
+
85
+ - API links for the viewer, manifest, manifest JSON/HTML/Markdown routes, schema, events, batch, import, GraphQL, and each REST resource
86
+ - built-in and configured custom viewer links
87
+ - resource and field metadata, including generated UI hints and relation hints
88
+ - viewer capabilities such as writes, batching, CSV import, GraphQL, and live events
89
+ - diagnostics suitable for display in a custom UI
90
+
91
+ The manifest does not include seed records, source paths, source hashes, runtime state paths, or GraphQL SDL. Custom viewers should fetch `manifest.json` for UI metadata and route links, then fetch actual records from REST or GraphQL. `api.formats` lists the registered response formats, media types, and manifest paths for custom viewers and tools.
92
+
93
+ Add custom viewer links when a project ships its own data UI:
94
+
95
+ Override the built-in Markdown renderer when a project needs a different shape:
96
+
97
+ ```js
98
+ import { defineConfig } from '@async/db/config';
99
+ import { stringify as stringifyYaml } from 'yaml';
100
+
101
+ export default defineConfig({
102
+ server: {
103
+ viewerLinks: [
104
+ { label: 'App Data Viewer', href: 'http://127.0.0.1:5173/db' },
105
+ ],
106
+ },
107
+ });
108
+ ```
109
+
110
+ You can also write the same shape to a committed artifact:
111
+
112
+ ```js
113
+ import { defineConfig } from '@async/db/config';
114
+
115
+ export default defineConfig({
116
+ outputs: {
117
+ viewerManifest: './src/generated/db.viewer.json',
118
+ },
119
+ });
120
+ ```
121
+
122
+ ```bash
123
+ async-db viewer manifest --out ./src/generated/db.viewer.json
124
+ ```
125
+
126
+ ## REST Routes
127
+
128
+ REST routes are enabled by default. Set `rest.enabled: false` to turn off
129
+ generated resource routes and REST batching while keeping dev-tool routes such
130
+ as the viewer, schema, manifest, import, events, and GraphQL available.
131
+
132
+ The app-facing REST route base defaults to `/db`, matching the fixture folder.
133
+ For a fixture at `db/users.json`, fetch the synced runtime resource with:
134
+
135
+ ```js
136
+ const users = await fetch('/db/users.json').then((response) => response.json());
137
+ ```
138
+
139
+ Scoped REST remains available under the tool route base, such as
140
+ `GET /__db/rest/users.json`. Standalone `async-db serve` also keeps root REST
141
+ routes such as `GET /users` for local convenience. Set `server.dataPath: false`
142
+ to disable only the `/db` alias.
143
+
144
+ When a prototype route needs to become an app-owned API route, see the
145
+ [Prototype To Production REST Guide](./prototype-to-production.md) for
146
+ `/api/db/*`, `/api/*`, registered operation refs, and route lockdown.
147
+
148
+ ### Fixture-Like `.json` Routes
149
+
150
+ Use `.json` routes when you want the URL to resemble the source fixture path:
151
+ `db/users.json` becomes `GET /db/users.json`. The server still reads the
152
+ synced runtime resource, not the source fixture file directly, so local writes
153
+ continue going to the selected runtime store.
154
+
155
+ Collections can use `.json` for list and record reads:
156
+
157
+ ```txt
158
+ GET /db/users.json
159
+ GET /db/users/u_1.json
160
+ ```
161
+
162
+ Singleton documents can use the same fixture-like read shape:
163
+
164
+ ```txt
165
+ GET /db/settings.json
166
+ ```
167
+
168
+ Use `?id=` only with the explicit collection `.json` route:
169
+
170
+ ```txt
171
+ GET /db/users.json?id=u_1
172
+ ```
173
+
174
+ Extensionless REST routes keep normal REST semantics and return a structured
175
+ error for `?id=`. Use `GET /db/users/u_1.json` or `GET /db/users/u_1` there.
176
+ Query options such as `select`, `expand`, `offset`, and `limit` apply before
177
+ the response format renders. Sibling `.html` and `.md` routes use the same
178
+ shaped data for browser or Markdown views.
179
+
180
+ Collections:
181
+
182
+ ```txt
183
+ GET /db/users.json
184
+ GET /db/users/:id.json
185
+ POST /db/users
186
+ PATCH /db/users/:id
187
+ DELETE /db/users/:id
188
+ ```
189
+
190
+ Singleton documents:
191
+
192
+ ```txt
193
+ GET /db/settings.json
194
+ PUT /db/settings
195
+ PATCH /db/settings
196
+ ```
197
+
198
+ REST examples:
199
+
200
+ ```bash
201
+ curl http://127.0.0.1:7331/db/users.json
202
+ curl 'http://127.0.0.1:7331/db/users.json?select=id,name&offset=0&limit=20'
203
+ curl 'http://127.0.0.1:7331/db/users.json?id=u_1&select=id,name'
204
+ curl http://127.0.0.1:7331/db/users/u_1.json
205
+ curl http://127.0.0.1:7331/db/settings.json
206
+ ```
207
+
208
+ ```bash
209
+ curl -X POST http://127.0.0.1:7331/db/users \
210
+ -H 'content-type: application/json' \
211
+ -d '{"id":"u_2","name":"Grace Hopper","email":"grace@example.com"}'
212
+ ```
213
+
214
+ ```bash
215
+ curl -X PATCH http://127.0.0.1:7331/db/users/u_2 \
216
+ -H 'content-type: application/json' \
217
+ -d '{"name":"Rear Admiral Grace Hopper"}'
218
+ ```
219
+
220
+ ```bash
221
+ curl -X DELETE http://127.0.0.1:7331/db/users/u_2
222
+ ```
223
+
224
+ Schema-backed computed fields are resolved only when selected. For example,
225
+ `GET /db/users/u_1.json?select=id,fullName` calls the trusted resolver registered
226
+ by `field.computed(...)`; default reads continue returning only stored fixture
227
+ fields.
228
+
229
+ ## REST Formats
230
+
231
+ Resource `GET` routes return JSON by default. The explicit `.json` extension uses the same shaped data:
232
+
233
+ ```txt
234
+ GET /db/users
235
+ GET /db/users.json
236
+ GET /db/users.html
237
+ GET /db/users.md
238
+ GET /db/users/u_1
239
+ GET /db/users/u_1.json
240
+ GET /db/users/u_1.html
241
+ GET /db/users/u_1.md
242
+ ```
243
+
244
+ `.json`, `.html`, and `.md` are built in. Config entries with the same extension override the built-in resource renderer, and object entries can also override manifest rendering. Extensionless resource and manifest routes negotiate registered media types from `Accept`; unsupported `Accept` values fall back to the configured default format. Format renderers receive data after normal REST shaping, so `select`, `expand`, `offset`, and `limit` apply before rendering.
245
+
246
+ ```js
247
+ import { defineConfig } from '@async/db/config';
248
+
249
+ export default defineConfig({
250
+ rest: {
251
+ formats: {
252
+ default: 'json',
253
+ md({ resourceName, data }) {
254
+ return {
255
+ body: `# ${resourceName}\n\n\`\`\`json\n${JSON.stringify(data, null, 2)}\n\`\`\`\n`,
256
+ contentType: 'text/markdown; charset=utf-8',
257
+ };
258
+ },
259
+ yaml: {
260
+ mediaTypes: ['application/yaml', 'text/yaml'],
261
+ contentType: 'application/yaml; charset=utf-8',
262
+ render({ data }) {
263
+ return stringifyYaml(data);
264
+ },
265
+ renderManifest({ data }) {
266
+ return stringifyYaml(data);
267
+ },
268
+ },
269
+ },
270
+ },
271
+ });
272
+ ```
273
+
274
+ Function shorthand is resource-only for compatibility. Use object syntax when a format needs media-type negotiation or manifest support, such as `GET /__db/manifest.yaml`. @async/db does not execute `.jsx` routes directly; JSX is a source/runtime choice for your renderer, while `.html` is the response format.
275
+
276
+ ## Relationship Expansion
277
+
278
+ Schema-backed scalar fields can declare relation metadata while fixtures keep plain ids:
279
+
280
+ ```json
281
+ {
282
+ "authorId": {
283
+ "type": "string",
284
+ "required": true,
285
+ "relation": {
286
+ "name": "author",
287
+ "to": "users",
288
+ "toField": "id",
289
+ "cardinality": "one"
290
+ }
291
+ }
292
+ }
293
+ ```
294
+
295
+ Then REST can expand that to-one relation:
296
+
297
+ ```bash
298
+ curl 'http://127.0.0.1:7331/db/posts/p_1.json?expand=author&select=id,title,author.name'
299
+ ```
300
+
301
+ `select` supports top-level fields and one nested expanded relation field. Relation expansion is depth 1 in this MVP. Reverse to-many expansion is intentionally deferred.
302
+
303
+ ## REST Batching
304
+
305
+ REST batching is supported through:
306
+
307
+ ```txt
308
+ POST /__db/batch
309
+ ```
310
+
311
+ If `server.apiBase` is changed, the batch endpoint follows that base, for
312
+ example `POST /_db/batch`.
313
+
314
+ ```json
315
+ [
316
+ {
317
+ "method": "GET",
318
+ "path": "/db/users.json"
319
+ },
320
+ {
321
+ "method": "PATCH",
322
+ "path": "/db/settings",
323
+ "body": {
324
+ "theme": "dark"
325
+ }
326
+ }
327
+ ]
328
+ ```
329
+
330
+ REST batches execute sequentially and are intentionally non-transactional. If an earlier write succeeds and a later batch item fails, the earlier write stays committed.
331
+
332
+ Errors are shaped for humans and automation:
333
+
334
+ ```json
335
+ {
336
+ "error": {
337
+ "code": "REST_BATCH_INVALID_PATH",
338
+ "message": "REST batch path must start with \"/\": users",
339
+ "hint": "Use absolute local paths such as \"/users\", \"/settings\", or \"/__db/schema\".",
340
+ "details": {
341
+ "path": "users"
342
+ }
343
+ }
344
+ }
345
+ ```
346
+
347
+ ## Registered REST Operations
348
+
349
+ Registered queries are optional REST or GraphQL request templates with callable
350
+ refs and optional names. They let production-style apps allowlist specific
351
+ reads and writes while local fixture CRUD can stay open by default. The
352
+ underlying config and CLI still use the `operations` name.
353
+
354
+ ```txt
355
+ GET /users/{id}.json?select=id,name
356
+ ```
357
+
358
+ ```json
359
+ {
360
+ "name": "GetUser",
361
+ "method": "GET",
362
+ "path": "/users/{id}.json",
363
+ "query": {
364
+ "select": "id,name"
365
+ }
366
+ }
367
+ ```
368
+
369
+ GraphQL templates use the same registry and ref execution route:
370
+
371
+ ```json
372
+ {
373
+ "name": "GetUser",
374
+ "query": "query GetUser($id: ID!) { user(id: $id) { id name } }",
375
+ "operationName": "GetUser",
376
+ "variables": {
377
+ "id": "{id}"
378
+ }
379
+ }
380
+ ```
381
+
382
+ Build the registry and optional client-safe refs:
383
+
384
+ ```bash
385
+ async-db operations build --out ./src/generated/db.operations.json --refs-out ./src/generated/db.operation-refs.json
386
+ ```
387
+
388
+ At runtime, registered operation execution is always a POST to the dev-tool base:
389
+
390
+ ```bash
391
+ curl -X POST http://127.0.0.1:7331/__db/operations/users.get \
392
+ -H 'content-type: application/json' \
393
+ -d '{"variables":{"id":"u_1"}}'
394
+ ```
395
+
396
+ Readable names work as app-facing operation refs. Refs are allowlist identifiers, not
397
+ secrets. Generated refs default to `hashOperation(template)`, and apps can set
398
+ their own `ref` in operation sources when they want readable or app-owned ids.
399
+ Keep the full registry server-side. Client refs contain names and callable refs
400
+ but not full request templates, variables, or request bodies. Use
401
+ `async-db operations contract --check` in CI when committed refs need approval
402
+ before the browser-facing operation contract changes. `operations.acceptRefs`
403
+ controls whether the server accepts refs, names, or both. Use `operations.resolveRef` or
404
+ `operations.validateRef` for custom server-side registry lookup or policy.
405
+
406
+ To block raw REST while allowing registered operations:
407
+
408
+ ```js
409
+ import { defineConfig } from '@async/db/config';
410
+
411
+ export default defineConfig({
412
+ outputs: {
413
+ operationRegistry: './src/generated/db.operations.json',
414
+ },
415
+ operations: {
416
+ enabled: true,
417
+ acceptRefs: 'ref',
418
+ },
419
+ server: {
420
+ expose: {
421
+ rest: 'registered-only',
422
+ graphql: false,
423
+ viewer: 'dev',
424
+ schema: 'dev',
425
+ manifest: 'dev',
426
+ },
427
+ },
428
+ });
429
+ ```
430
+
431
+ `registered-only` blocks raw REST resource and batch routes. Registered REST
432
+ operation execution still uses normal REST shaping, including `select`,
433
+ formats, schema validation, and computed resolver projection. Registered
434
+ GraphQL operations execute through the same GraphQL executor as direct GraphQL
435
+ requests, and still require `graphql.enabled !== false`.
436
+
437
+ ## GraphQL Boundary
438
+
439
+ GraphQL is available at `/graphql` for apps that prefer it. It supports aliases, variables, `operationName`, `__typename`, named and inline fragments, `@include`/`@skip`, HTTP batching, and minimal `__schema`/`__type` introspection for local tooling.
440
+
441
+ Set `graphql.enabled: false` when an app wants REST, schema, manifest, viewer, import, and events without a GraphQL endpoint. Root discovery reports the GraphQL link as unavailable, and direct GraphQL requests return a structured `GRAPHQL_DISABLED` error.
442
+
443
+ GraphQL HTTP batches execute sequentially and are intentionally non-transactional. If an earlier mutation succeeds and a later batch item fails, the earlier mutation stays committed.
444
+
445
+ REST remains the documented happy path because REST plus the viewer is the intended default workflow.
446
+
447
+ GraphQL selections use the same read projection/fanout path as REST for computed
448
+ fields. Registered GraphQL operations are fixed query templates; they are not a
449
+ direct database query language and do not expose backend SQL or Redis commands.
450
+
451
+ Use `server.expose.graphql`, `server.expose.viewer`, `server.expose.schema`, and
452
+ `server.expose.manifest` to keep non-REST surfaces `open`, `dev`, or disabled in
453
+ production-like servers.
454
+
455
+ Unsupported in v1:
456
+
457
+ - subscriptions
458
+ - full GraphQL spec introspection
459
+ - general-purpose GraphQL validation beyond @async/db's local subset
460
+ - relation traversal from schema relation metadata; GraphQL projects stored fields in v1
461
+
462
+ ## Watch Behavior
463
+
464
+ `serve` watches fixture sources, ignores `.db/`, reloads valid resources when files change, and surfaces file-specific diagnostics in the viewer without breaking unrelated resources.
465
+
466
+ If an app commits generated files under frontend source folders, Vite may still reload when those files genuinely change. Only ignore generated files that the browser does not need to hot reload.
@@ -0,0 +1,120 @@
1
+ # Resource Graduation And Mixed Stores
2
+
3
+ `@async/db` lets each resource choose the store that matches its operational risk while the app keeps one data layer. The usual production shape is:
4
+
5
+ - JSON for control-plane resources such as settings, feature flags, templates, policy rules, and seed data.
6
+ - SQLite, Postgres, or a custom store for data-plane resources such as orders, activity, user-owned records, and high-write collections.
7
+ - Registered operations as the public API boundary so client code does not care which store backs a resource.
8
+
9
+ ## When To Graduate A Resource
10
+
11
+ Move one resource out of JSON when it starts needing database behavior:
12
+
13
+ - writes happen often enough that whole-file rewrites are wasteful
14
+ - more than one process or app instance can write it
15
+ - users need filtered, indexed, or paginated queries over a growing dataset
16
+ - records need transactional guarantees, audit controls, or operational retention
17
+ - the data is business-critical enough that database backup and restore should own it
18
+
19
+ Do not graduate the whole app by default. Keep file-suitable resources in JSON and move only the resource that outgrew it.
20
+
21
+ ## Postgres Example
22
+
23
+ Keep control-plane resources on JSON and put app data in Postgres:
24
+
25
+ ```js
26
+ import { defineConfig } from '@async/db/config';
27
+ import { postgresStore } from '@async/db/postgres';
28
+ import { pool } from './src/server/postgres-client.js';
29
+
30
+ export default defineConfig({
31
+ stores: {
32
+ default: 'json',
33
+ appDb: postgresStore({
34
+ client: pool,
35
+ namespace: 'production',
36
+ }),
37
+ },
38
+ resources: {
39
+ appSettings: { store: 'json' },
40
+ featureFlags: { store: 'json' },
41
+ promptTemplates: { store: 'json' },
42
+ orders: { store: 'appDb' },
43
+ activityEvents: { store: 'appDb' },
44
+ },
45
+ operations: {
46
+ enabled: true,
47
+ acceptRefs: 'ref',
48
+ sourceDir: './db/operations',
49
+ },
50
+ server: {
51
+ expose: {
52
+ rest: 'registered-only',
53
+ graphql: false,
54
+ viewer: 'dev',
55
+ schema: 'dev',
56
+ manifest: 'dev',
57
+ },
58
+ },
59
+ });
60
+ ```
61
+
62
+ The built-in Postgres store persists each resource value in JSONB envelopes. That is enough for a resource graduation path behind the `@async/db` API. If a mature resource needs relational tables, custom SQL, or Postgres-native indexes per field, move that resource behind an app-owned custom store or generated API while preserving the same operation refs.
63
+
64
+ ## SQLite Example
65
+
66
+ For single-node production apps, desktop apps, internal tools, and small deployments, SQLite can be the first graduation step:
67
+
68
+ ```js
69
+ import { defineConfig } from '@async/db/config';
70
+ import { sqliteStore } from '@async/db/sqlite';
71
+
72
+ export default defineConfig({
73
+ stores: {
74
+ default: 'json',
75
+ appDb: sqliteStore({
76
+ file: './.db/app.sqlite',
77
+ }),
78
+ },
79
+ resources: {
80
+ appSettings: { store: 'json' },
81
+ featureFlags: { store: 'json' },
82
+ orders: { store: 'appDb' },
83
+ },
84
+ });
85
+ ```
86
+
87
+ SQLite keeps the deployment simple, but it still changes the operational boundary: backup the SQLite file, avoid multi-writer network filesystems, and move to Postgres when many app instances need concurrent writes.
88
+
89
+ ## What The App Keeps
90
+
91
+ When a resource graduates, preserve these contracts:
92
+
93
+ - resource name, such as `orders`
94
+ - schema fields and generated TypeScript names where possible
95
+ - registered operation name and ref
96
+ - client call shape, such as `db.query(operationRefs.operations.ListOrders.ref)`
97
+ - app-owned auth and policy checks around the operation route
98
+
99
+ The store config changes, but app code keeps calling the same data layer:
100
+
101
+ ```ts
102
+ await db.query(operationRefs.operations.GetControlPlane.ref);
103
+ await db.query(operationRefs.operations.ListOrders.ref, { accountId });
104
+ ```
105
+
106
+ `GetControlPlane` can read JSON-backed `appSettings` and `featureFlags`; `ListOrders` can read a database-backed `orders` resource. Both calls still go through `@async/db` registered operations.
107
+
108
+ ## Graduation Steps
109
+
110
+ 1. Add or tighten the explicit schema for the resource while it is still JSON-backed.
111
+ 2. Add a registered operation for the browser-facing read or write path.
112
+ 3. Generate and commit the client-safe operation contract if the app ships refs.
113
+ 4. Add the target store to `db.config.mjs`.
114
+ 5. Set only the graduating resource to that store with `resources.<name>.store`.
115
+ 6. Run `async-db sync` so the target store hydrates from the existing seed or fixture.
116
+ 7. Move existing production state with an app-owned migration or export/import script.
117
+ 8. Keep JSON resources in JSON unless they have their own reason to graduate.
118
+ 9. Run `async-db doctor --production`, operation contract checks, and app integration tests before deploying.
119
+
120
+ See [examples/production-json](../examples/production-json/README.md) for the feature flags/settings side of this pattern.
@@ -0,0 +1,79 @@
1
+ # TypeScript Schema Sources
2
+
3
+ @async/db executes schema modules with normal Node.js ESM loading. It supports JavaScript schema files at runtime and lets TypeScript projects compile schema authoring files into those runtime files.
4
+
5
+ @async/db does not execute `.ts` schema files directly in this pass. Add a build step when you author schemas in TypeScript.
6
+
7
+ ## Supported Authoring Paths
8
+
9
+ ### JavaScript ESM
10
+
11
+ Use `.schema.js` when the nearest `package.json` has `"type": "module"`:
12
+
13
+ ```json
14
+ {
15
+ "type": "module"
16
+ }
17
+ ```
18
+
19
+ ```js
20
+ // db/users.schema.js
21
+ import { collection, field } from '@async/db/schema';
22
+
23
+ export default collection({
24
+ idField: 'id',
25
+ fields: {
26
+ id: field.string({ required: true }),
27
+ email: field.string({ required: true, unique: true }),
28
+ },
29
+ });
30
+ ```
31
+
32
+ This works for `db.schema.js`, `db/*.schema.js`, and `db/**/index.schema.js`.
33
+
34
+ ### TypeScript Authoring
35
+
36
+ Author TypeScript in a separate source folder and compile it into supported runtime schema files:
37
+
38
+ ```ts
39
+ // db/schema-src/users.schema.ts
40
+ import { collection, field } from '@async/db/schema';
41
+
42
+ export default collection({
43
+ idField: 'id',
44
+ fields: {
45
+ id: field.string({ required: true }),
46
+ email: field.string({ required: true, unique: true }),
47
+ },
48
+ });
49
+ ```
50
+
51
+ Compile to `.schema.js`:
52
+
53
+ ```json
54
+ {
55
+ "scripts": {
56
+ "db:schema:build": "tsc -p tsconfig.db-schema.json",
57
+ "db:sync": "npm run db:schema:build && async-db sync"
58
+ }
59
+ }
60
+ ```
61
+
62
+ When the project root `package.json` is not already `"type": "module"`, @async/db creates `db/package.json` with `"type": "module"` before loading `.schema.js` files from the fixture folder. Set `schema.autoModulePackageJson: false` when you want to manage that file yourself.
63
+
64
+ ```json
65
+ {
66
+ "extends": "./tsconfig.json",
67
+ "compilerOptions": {
68
+ "rootDir": "db/schema-src",
69
+ "outDir": "db",
70
+ "module": "NodeNext",
71
+ "moduleResolution": "NodeNext",
72
+ "target": "ES2022",
73
+ "declaration": false,
74
+ "sourceMap": false,
75
+ "strict": true
76
+ },
77
+ "include": ["db/schema-src/**/*.schema.ts"]
78
+ }
79
+ ```