bunderstack 0.17.0-beta.2 → 0.17.0-beta.4

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 (336) hide show
  1. package/CHANGELOG.md +233 -0
  2. package/README.md +11 -1
  3. package/dist/access.d.ts +116 -0
  4. package/dist/access.d.ts.map +1 -0
  5. package/dist/access.js +325 -0
  6. package/dist/access.js.map +1 -0
  7. package/dist/api/builder.d.ts +145 -0
  8. package/dist/api/builder.d.ts.map +1 -0
  9. package/dist/api/builder.js +28 -0
  10. package/dist/api/builder.js.map +1 -0
  11. package/dist/api/context.d.ts +34 -0
  12. package/dist/api/context.d.ts.map +1 -0
  13. package/dist/api/context.js +32 -0
  14. package/dist/api/context.js.map +1 -0
  15. package/dist/api/crud-router.d.ts +290 -0
  16. package/dist/api/crud-router.d.ts.map +1 -0
  17. package/dist/api/crud-router.js +249 -0
  18. package/dist/api/crud-router.js.map +1 -0
  19. package/dist/api/openapi.d.ts +6 -0
  20. package/dist/api/openapi.d.ts.map +1 -0
  21. package/dist/api/openapi.js +146 -0
  22. package/dist/api/openapi.js.map +1 -0
  23. package/dist/api/realtime-router.d.ts +76 -0
  24. package/dist/api/realtime-router.d.ts.map +1 -0
  25. package/dist/api/realtime-router.js +41 -0
  26. package/dist/api/realtime-router.js.map +1 -0
  27. package/dist/api/registry.d.ts +30 -0
  28. package/dist/api/registry.d.ts.map +1 -0
  29. package/dist/api/registry.js +239 -0
  30. package/dist/api/registry.js.map +1 -0
  31. package/dist/api/router.d.ts +9 -0
  32. package/dist/api/router.d.ts.map +1 -0
  33. package/dist/api/router.js +19 -0
  34. package/dist/api/router.js.map +1 -0
  35. package/dist/api/storage-router.d.ts +279 -0
  36. package/dist/api/storage-router.d.ts.map +1 -0
  37. package/dist/api/storage-router.js +155 -0
  38. package/dist/api/storage-router.js.map +1 -0
  39. package/dist/api/types.d.ts +55 -0
  40. package/dist/api/types.d.ts.map +1 -0
  41. package/dist/api/types.js +2 -0
  42. package/dist/api/types.js.map +1 -0
  43. package/dist/auth.d.ts +31 -0
  44. package/dist/auth.d.ts.map +1 -0
  45. package/dist/auth.js +102 -0
  46. package/dist/auth.js.map +1 -0
  47. package/dist/blueprint-generator.d.ts +18 -0
  48. package/dist/blueprint-generator.d.ts.map +1 -0
  49. package/dist/blueprint-generator.js +125 -0
  50. package/dist/blueprint-generator.js.map +1 -0
  51. package/dist/blueprint.d.ts +46 -0
  52. package/dist/blueprint.d.ts.map +1 -0
  53. package/dist/blueprint.js +162 -0
  54. package/dist/blueprint.js.map +1 -0
  55. package/dist/cli.d.ts +8 -0
  56. package/dist/cli.d.ts.map +1 -0
  57. package/dist/cli.js +68 -0
  58. package/dist/cli.js.map +1 -0
  59. package/dist/config.d.ts +108 -0
  60. package/dist/config.d.ts.map +1 -0
  61. package/dist/config.js +90 -0
  62. package/dist/config.js.map +1 -0
  63. package/dist/cron.d.ts +4 -0
  64. package/dist/cron.d.ts.map +1 -0
  65. package/dist/cron.js +3 -0
  66. package/dist/cron.js.map +1 -0
  67. package/dist/crud-operations.d.ts +43 -0
  68. package/dist/crud-operations.d.ts.map +1 -0
  69. package/dist/crud-operations.js +238 -0
  70. package/dist/crud-operations.js.map +1 -0
  71. package/dist/database/adapter.d.ts +20 -0
  72. package/dist/database/adapter.d.ts.map +1 -0
  73. package/dist/database/adapter.js +2 -0
  74. package/dist/database/adapter.js.map +1 -0
  75. package/dist/database/bun-sql.d.ts +3 -0
  76. package/dist/database/bun-sql.d.ts.map +1 -0
  77. package/dist/database/bun-sql.js +21 -0
  78. package/dist/database/bun-sql.js.map +1 -0
  79. package/dist/database/libsql.d.ts +3 -0
  80. package/dist/database/libsql.d.ts.map +1 -0
  81. package/dist/database/libsql.js +22 -0
  82. package/dist/database/libsql.js.map +1 -0
  83. package/dist/database/pglite.d.ts +3 -0
  84. package/dist/database/pglite.d.ts.map +1 -0
  85. package/dist/database/pglite.js +27 -0
  86. package/dist/database/pglite.js.map +1 -0
  87. package/dist/database/postgres-js.d.ts +3 -0
  88. package/dist/database/postgres-js.d.ts.map +1 -0
  89. package/dist/database/postgres-js.js +21 -0
  90. package/dist/database/postgres-js.js.map +1 -0
  91. package/dist/db.d.ts +18 -0
  92. package/dist/db.d.ts.map +1 -0
  93. package/dist/db.js +26 -0
  94. package/dist/db.js.map +1 -0
  95. package/dist/dialect.d.ts +17 -0
  96. package/dist/dialect.d.ts.map +1 -0
  97. package/dist/dialect.js +22 -0
  98. package/dist/dialect.js.map +1 -0
  99. package/dist/email/smtp.d.ts +14 -0
  100. package/dist/email/smtp.d.ts.map +1 -0
  101. package/dist/email/smtp.js +27 -0
  102. package/dist/email/smtp.js.map +1 -0
  103. package/dist/email.d.ts +39 -0
  104. package/dist/email.d.ts.map +1 -0
  105. package/dist/email.js +97 -0
  106. package/dist/email.js.map +1 -0
  107. package/dist/env.d.ts +47 -0
  108. package/dist/env.d.ts.map +1 -0
  109. package/dist/env.js +99 -0
  110. package/dist/env.js.map +1 -0
  111. package/dist/errors.d.ts +125 -0
  112. package/dist/errors.d.ts.map +1 -0
  113. package/dist/errors.js +92 -0
  114. package/dist/errors.js.map +1 -0
  115. package/dist/handler.d.ts +9 -0
  116. package/dist/handler.d.ts.map +1 -0
  117. package/dist/handler.js +22 -0
  118. package/dist/handler.js.map +1 -0
  119. package/dist/idempotency.d.ts +17 -0
  120. package/dist/idempotency.d.ts.map +1 -0
  121. package/dist/idempotency.js +65 -0
  122. package/dist/idempotency.js.map +1 -0
  123. package/dist/index.d.ts +134 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +480 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/internal-tables-pg.d.ts +481 -0
  128. package/dist/internal-tables-pg.d.ts.map +1 -0
  129. package/{src/internal-tables-pg.ts → dist/internal-tables-pg.js} +10 -34
  130. package/dist/internal-tables-pg.js.map +1 -0
  131. package/dist/internal-tables.d.ts +2509 -0
  132. package/dist/internal-tables.d.ts.map +1 -0
  133. package/dist/internal-tables.js +108 -0
  134. package/dist/internal-tables.js.map +1 -0
  135. package/dist/jobs/cron.d.ts +15 -0
  136. package/dist/jobs/cron.d.ts.map +1 -0
  137. package/dist/jobs/cron.js +74 -0
  138. package/dist/jobs/cron.js.map +1 -0
  139. package/dist/jobs/define.d.ts +133 -0
  140. package/dist/jobs/define.d.ts.map +1 -0
  141. package/dist/jobs/define.js +74 -0
  142. package/dist/jobs/define.js.map +1 -0
  143. package/dist/jobs/index.d.ts +11 -0
  144. package/dist/jobs/index.d.ts.map +1 -0
  145. package/dist/jobs/index.js +8 -0
  146. package/dist/jobs/index.js.map +1 -0
  147. package/dist/jobs/queue.d.ts +6 -0
  148. package/dist/jobs/queue.d.ts.map +1 -0
  149. package/dist/jobs/queue.js +55 -0
  150. package/dist/jobs/queue.js.map +1 -0
  151. package/dist/jobs/runtime.d.ts +13 -0
  152. package/dist/jobs/runtime.d.ts.map +1 -0
  153. package/dist/jobs/runtime.js +46 -0
  154. package/dist/jobs/runtime.js.map +1 -0
  155. package/dist/jobs/slots.d.ts +25 -0
  156. package/dist/jobs/slots.d.ts.map +1 -0
  157. package/dist/jobs/slots.js +41 -0
  158. package/dist/jobs/slots.js.map +1 -0
  159. package/dist/jobs/worker.d.ts +12 -0
  160. package/dist/jobs/worker.d.ts.map +1 -0
  161. package/dist/jobs/worker.js +311 -0
  162. package/dist/jobs/worker.js.map +1 -0
  163. package/dist/lifecycle.d.ts +10 -0
  164. package/dist/lifecycle.d.ts.map +1 -0
  165. package/dist/lifecycle.js +37 -0
  166. package/dist/lifecycle.js.map +1 -0
  167. package/dist/list-query.d.ts +62 -0
  168. package/dist/list-query.d.ts.map +1 -0
  169. package/dist/list-query.js +194 -0
  170. package/dist/list-query.js.map +1 -0
  171. package/dist/manifest.d.ts +59 -0
  172. package/dist/manifest.d.ts.map +1 -0
  173. package/dist/manifest.js +167 -0
  174. package/dist/manifest.js.map +1 -0
  175. package/dist/provision-internals.d.ts +24 -0
  176. package/dist/provision-internals.d.ts.map +1 -0
  177. package/dist/provision-internals.js +7 -0
  178. package/dist/provision-internals.js.map +1 -0
  179. package/dist/provision.d.ts +23 -0
  180. package/dist/provision.d.ts.map +1 -0
  181. package/dist/provision.js +96 -0
  182. package/dist/provision.js.map +1 -0
  183. package/dist/rate-limit.d.ts +7 -0
  184. package/dist/rate-limit.d.ts.map +1 -0
  185. package/dist/rate-limit.js +49 -0
  186. package/dist/rate-limit.js.map +1 -0
  187. package/dist/realtime/facade.d.ts +18 -0
  188. package/dist/realtime/facade.d.ts.map +1 -0
  189. package/dist/realtime/facade.js +36 -0
  190. package/dist/realtime/facade.js.map +1 -0
  191. package/dist/realtime/filter.d.ts +13 -0
  192. package/dist/realtime/filter.d.ts.map +1 -0
  193. package/dist/realtime/filter.js +48 -0
  194. package/dist/realtime/filter.js.map +1 -0
  195. package/dist/realtime/heartbeat.d.ts +14 -0
  196. package/dist/realtime/heartbeat.d.ts.map +1 -0
  197. package/dist/realtime/heartbeat.js +64 -0
  198. package/dist/realtime/heartbeat.js.map +1 -0
  199. package/dist/realtime/publisher.d.ts +21 -0
  200. package/dist/realtime/publisher.d.ts.map +1 -0
  201. package/dist/realtime/publisher.js +17 -0
  202. package/dist/realtime/publisher.js.map +1 -0
  203. package/dist/schema-export-pg.d.ts +2 -0
  204. package/dist/schema-export-pg.d.ts.map +1 -0
  205. package/dist/schema-export-pg.js +4 -0
  206. package/dist/schema-export-pg.js.map +1 -0
  207. package/dist/schema-export.d.ts +2 -0
  208. package/dist/schema-export.d.ts.map +1 -0
  209. package/dist/schema-export.js +2 -0
  210. package/dist/schema-export.js.map +1 -0
  211. package/dist/scope.d.ts +4 -0
  212. package/dist/scope.d.ts.map +1 -0
  213. package/dist/scope.js +13 -0
  214. package/dist/scope.js.map +1 -0
  215. package/dist/standard-schema.d.ts +13 -0
  216. package/dist/standard-schema.d.ts.map +1 -0
  217. package/dist/standard-schema.js +34 -0
  218. package/dist/standard-schema.js.map +1 -0
  219. package/dist/storage/buckets.d.ts +80 -0
  220. package/dist/storage/buckets.d.ts.map +1 -0
  221. package/dist/storage/buckets.js +178 -0
  222. package/dist/storage/buckets.js.map +1 -0
  223. package/dist/storage/delete.d.ts +11 -0
  224. package/dist/storage/delete.d.ts.map +1 -0
  225. package/dist/storage/delete.js +18 -0
  226. package/dist/storage/delete.js.map +1 -0
  227. package/dist/storage/file-meta.d.ts +37 -0
  228. package/dist/storage/file-meta.d.ts.map +1 -0
  229. package/dist/storage/file-meta.js +166 -0
  230. package/dist/storage/file-meta.js.map +1 -0
  231. package/dist/storage/index.d.ts +28 -0
  232. package/dist/storage/index.d.ts.map +1 -0
  233. package/dist/storage/index.js +5 -0
  234. package/dist/storage/index.js.map +1 -0
  235. package/dist/storage/local.d.ts +15 -0
  236. package/dist/storage/local.d.ts.map +1 -0
  237. package/dist/storage/local.js +56 -0
  238. package/dist/storage/local.js.map +1 -0
  239. package/dist/storage/operations.d.ts +54 -0
  240. package/dist/storage/operations.d.ts.map +1 -0
  241. package/dist/storage/operations.js +250 -0
  242. package/dist/storage/operations.js.map +1 -0
  243. package/dist/storage/registry.d.ts +10 -0
  244. package/dist/storage/registry.d.ts.map +1 -0
  245. package/dist/storage/registry.js +23 -0
  246. package/dist/storage/registry.js.map +1 -0
  247. package/dist/storage/s3.d.ts +28 -0
  248. package/dist/storage/s3.d.ts.map +1 -0
  249. package/dist/storage/s3.js +71 -0
  250. package/dist/storage/s3.js.map +1 -0
  251. package/dist/storage/sweep.d.ts +9 -0
  252. package/dist/storage/sweep.d.ts.map +1 -0
  253. package/dist/storage/sweep.js +17 -0
  254. package/dist/storage/sweep.js.map +1 -0
  255. package/dist/storage/thumbnails.d.ts +11 -0
  256. package/dist/storage/thumbnails.d.ts.map +1 -0
  257. package/dist/storage/thumbnails.js +60 -0
  258. package/dist/storage/thumbnails.js.map +1 -0
  259. package/dist/testing.d.ts +27 -0
  260. package/dist/testing.d.ts.map +1 -0
  261. package/dist/testing.js +11 -0
  262. package/dist/testing.js.map +1 -0
  263. package/dist/typeid-pg.d.ts +19 -0
  264. package/dist/typeid-pg.d.ts.map +1 -0
  265. package/{src/typeid-pg.ts → dist/typeid-pg.js} +10 -13
  266. package/dist/typeid-pg.js.map +1 -0
  267. package/dist/typeid.d.ts +45 -0
  268. package/dist/typeid.d.ts.map +1 -0
  269. package/dist/typeid.js +100 -0
  270. package/dist/typeid.js.map +1 -0
  271. package/package.json +77 -28
  272. package/src/access.ts +0 -532
  273. package/src/api/builder.ts +0 -52
  274. package/src/api/context.ts +0 -83
  275. package/src/api/crud-router.ts +0 -386
  276. package/src/api/openapi.ts +0 -184
  277. package/src/api/realtime-router.ts +0 -75
  278. package/src/api/registry.ts +0 -338
  279. package/src/api/router.ts +0 -34
  280. package/src/api/storage-router.ts +0 -224
  281. package/src/api/types.ts +0 -105
  282. package/src/auth.ts +0 -117
  283. package/src/blueprint-generator.ts +0 -203
  284. package/src/blueprint.ts +0 -264
  285. package/src/cli.ts +0 -90
  286. package/src/config.ts +0 -215
  287. package/src/cron.ts +0 -3
  288. package/src/crud-operations.ts +0 -478
  289. package/src/database/adapter.ts +0 -26
  290. package/src/database/bun-sql.ts +0 -23
  291. package/src/database/libsql.ts +0 -28
  292. package/src/database/pglite.ts +0 -33
  293. package/src/database/postgres-js.ts +0 -33
  294. package/src/db.ts +0 -61
  295. package/src/dialect.ts +0 -38
  296. package/src/email/smtp.ts +0 -45
  297. package/src/email.ts +0 -154
  298. package/src/env.ts +0 -180
  299. package/src/errors.ts +0 -123
  300. package/src/handler.ts +0 -30
  301. package/src/idempotency.ts +0 -97
  302. package/src/index.ts +0 -834
  303. package/src/internal-tables.ts +0 -149
  304. package/src/jobs/cron.ts +0 -87
  305. package/src/jobs/define.ts +0 -283
  306. package/src/jobs/index.ts +0 -37
  307. package/src/jobs/queue.ts +0 -67
  308. package/src/jobs/runtime.ts +0 -58
  309. package/src/jobs/slots.ts +0 -52
  310. package/src/jobs/worker.ts +0 -369
  311. package/src/lifecycle.ts +0 -49
  312. package/src/list-query.ts +0 -333
  313. package/src/manifest.ts +0 -297
  314. package/src/provision-internals.ts +0 -29
  315. package/src/provision.ts +0 -128
  316. package/src/rate-limit.ts +0 -71
  317. package/src/realtime/facade.ts +0 -74
  318. package/src/realtime/filter.ts +0 -81
  319. package/src/realtime/heartbeat.ts +0 -80
  320. package/src/realtime/publisher.ts +0 -46
  321. package/src/schema-export-pg.ts +0 -7
  322. package/src/schema-export.ts +0 -5
  323. package/src/scope.ts +0 -17
  324. package/src/standard-schema.ts +0 -59
  325. package/src/storage/buckets.ts +0 -308
  326. package/src/storage/delete.ts +0 -26
  327. package/src/storage/file-meta.ts +0 -222
  328. package/src/storage/index.ts +0 -39
  329. package/src/storage/local.ts +0 -69
  330. package/src/storage/operations.ts +0 -398
  331. package/src/storage/registry.ts +0 -40
  332. package/src/storage/s3.ts +0 -99
  333. package/src/storage/sweep.ts +0 -25
  334. package/src/storage/thumbnails.ts +0 -65
  335. package/src/testing.ts +0 -31
  336. package/src/typeid.ts +0 -116
package/CHANGELOG.md ADDED
@@ -0,0 +1,233 @@
1
+ # Changelog
2
+
3
+ All notable changes to `bunderstack` will be documented in this file.
4
+
5
+ ## [0.17.0-beta.4] - 2026-08-12
6
+
7
+ ### Added
8
+
9
+ - **`auth` accepts a builder** — `auth: ({ db, env }) => BetterAuthConfig`, alongside the existing plain-object form. `db` is the app's own connection, typed from `schema` alone, so better-auth database hooks can live in their own file without importing the app they help type — the same reason `api`, `jobs`, and `routes` take builders. Applications no longer need a second drizzle instance just to give auth hooks a database. Exported `AuthConfigContext`, `AuthConfigInput`, `AuthConfigFactory`, and `resolveAuthConfig`.
10
+
11
+ ## [0.17.0-beta.3] - 2026-08-12
12
+
13
+ ### Breaking
14
+
15
+ - **The package publishes built `dist`, not raw `src`.** Every entry point now
16
+ resolves to `dist/<entry>.js` with `dist/<entry>.d.ts` beside it, and the
17
+ tarball no longer contains TypeScript sources. Consumers therefore typecheck
18
+ our *declarations*, which `skipLibCheck` can suppress — previously our sources
19
+ were compiled under the app's own flags, where `exactOptionalPropertyTypes`
20
+ alone produced 168 errors inside `node_modules` and
21
+ `noPropertyAccessFromIndexSignature` another 79. A strict app now sees zero
22
+ (`bun run verify:consumer` packs, installs, and proves it).
23
+ - **`createAuth` returns better-auth's plain `Auth`** instead of the
24
+ plugin-parameterised instance type. The value is unchanged; only the declared
25
+ type is narrower, because the inferred one did not survive declaration emit.
26
+ Plugin endpoints are still reachable through runtime checks.
27
+ - **Relative imports inside the published JS and declarations carry `.js`
28
+ extensions**, so the build no longer depends on bundler-style resolution.
29
+
30
+ ### Fixed
31
+
32
+ - **Generated CRUD types survive publishing.** Declaration emit inlined
33
+ drizzle-valibot's internal generics (`TRefinements`, `TType`) into the
34
+ published `.d.ts`, where they are unbound — a `notNull` column silently became
35
+ optional for consumers. `select`, `update`, and `list` schemas now state their
36
+ types explicitly, which also makes the emitted API dramatically smaller.
37
+ - `lookupIdempotency` no longer takes an unused config parameter, and
38
+ `Bun.Image` is typed locally so image transforms compile against any
39
+ `bun-types` version and report a clear error on an older Bun.
40
+
41
+ ### Added
42
+
43
+ - `bun run build` (and `prepare`/`prepack`) build every package;
44
+ `scripts/build-package.ts` fails the build if an emitted import resolves to
45
+ nothing.
46
+ - `bun run verify:consumer` — packs the tarballs, installs them into a scratch
47
+ app with the strictest common flags and `skipLibCheck: false`, then typechecks
48
+ and smoke-runs it.
49
+ - `noUnusedParameters` and `noImplicitReturns` are on in every package.
50
+ - The tarball now includes `CHANGELOG.md`, and the README links to the migration
51
+ guides with absolute URLs so they are reachable from an installed package.
52
+
53
+ ## [0.17.0-beta.2] - 2026-08-12
54
+
55
+ Migration guide: [docs/MIGRATION-0.17.md](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.17.md).
56
+
57
+ ### Breaking
58
+
59
+ - **Generated `list` takes a typed, nested `filters` object.** Filter, sort, and
60
+ paging parameters are now declared by a per-table schema derived from the
61
+ table's columns and its `access` allowlists, and query strings are coerced to
62
+ those types by oRPC's `SmartCoercionHandlerPlugin`. `?filters[authorId]=u1`
63
+ replaces `?authorId=u1`, `?filters[id][]=a&filters[id][]=b` replaces the
64
+ comma-separated `?id=a,b`, and a bare query param is now a 400 instead of a
65
+ silent filter. On the client, `filters` autocompletes to real columns and
66
+ rejects wrong value types at compile time.
67
+ - **Error codes are oRPC's own codes.** `VALIDATION_ERROR` → `BAD_REQUEST`,
68
+ `RATE_LIMITED` → `TOO_MANY_REQUESTS`. `BUNDERSTACK_ERROR_STATUS_MAP` is
69
+ removed along with the handlers' `errorStatusMap` override.
70
+ - **Realtime events and subscriptions name tables by schema key**, not SQL table
71
+ name, so one name works for procedures, subscriptions, and events. Only
72
+ affects apps whose schema key differs from the table name.
73
+ - **`ScopedCollectionOptions.filter` → `filters`** in `bunderstack-sync`, and
74
+ `table.list(input)` forwards its input to the procedure unchanged.
75
+ - **`filterableColumns` / `sortableColumns` no longer reject** column names like
76
+ `limit` or `sort`; nesting removed the collision that made the rule necessary.
77
+
78
+ ### Fixed
79
+
80
+ - **Client errors answer 4xx instead of 500.** Because the custom status map had
81
+ no entry for oRPC's own codes, every schema failure and every rate-limit
82
+ rejection answered HTTP 500 with a 4xx code in the body — on both REST and
83
+ RPC. Validation responses now also carry `details` naming the failing field.
84
+ - **REST list parameters work.** `?offset=` and `?count=` failed validation
85
+ because only `limit` was coerced from its query string; numeric, boolean, and
86
+ date filters had no way through at all.
87
+ - **`operations.list` no longer reads the raw request URL.** The validated input
88
+ is the only source, so a query param can no longer bypass the procedure schema
89
+ and reach the WHERE clause.
90
+ - **Realtime updates reach sync collections** for tables whose schema key is not
91
+ the SQL name; they previously degraded to refetch-only.
92
+ - **Packages compile under a consumer's `noUnusedLocals`.** Type-probe files are
93
+ excluded from the tarball, unused imports are gone, and every package builds
94
+ with the flag on so this cannot rot again (`scripts/packaging-contract.test.ts`).
95
+
96
+ ### Added
97
+
98
+ - **`ApiContext` is exported**, so shared middleware can be declared as
99
+ `os.$context<ApiContext<typeof schema>>()` instead of over a hand-written
100
+ minimal context.
101
+ - `@orpc/json-schema` as a direct dependency (query/body coercion plugin).
102
+
103
+ ## [0.17.0-beta.0] - 2026-08-11
104
+
105
+ The oRPC-first redesign: one procedure graph for CRUD, storage, realtime, and
106
+ custom procedures, served as RPC at `/api/rpc/*` and REST/OpenAPI at `/api/*`.
107
+
108
+ ### Breaking
109
+
110
+ - **tRPC is replaced by oRPC.** `trpc:` → `api:`, `.query()`/`.mutation()` →
111
+ `.handler()`, `ctx` → `context`. `@trpc/server` is no longer a dependency.
112
+ - **Validation is Standard Schema** (valibot in the box; zod and arktype work,
113
+ with valibot the only vendor the bundled OpenAPI generator can convert).
114
+ - **Realtime runs on oRPC Publisher** as an event-iterator procedure at
115
+ `/api/realtime`, with heartbeats and `Last-Event-ID` resume; the previous
116
+ in-house broker is gone.
117
+ - **Storage and CRUD are procedures**, not bespoke Hono handlers.
118
+ - **`bunderstack-query` exposes oRPC's TanStack Query utilities.**
119
+ `queryOptions(input, opts)` → `queryOptions({ input, ...opts })`,
120
+ `keys.all` → `key()`; `listQuery`/`getQuery` are gone.
121
+
122
+ ## [0.16.0] - 2026-08-07
123
+
124
+ ### Breaking
125
+
126
+ - **Cron collapsed into the jobs table.** A cron occurrence is now an ordinary queue job with `type = 'cron:<name>'`, `runAt = <slot>`, and `dedupeKey = String(slot)`, reusing the existing `unique(type, dedupeKey)` constraint for exactly-once slot ownership. The `_bunderstack_cron_runs` table is dropped — **run `drizzle-kit generate` and apply the migration**.
127
+ - **Removed `app.startCronScheduler()`.** Cron runs through the same tick everywhere, so the development/production split no longer exists.
128
+ - **Removed the signed cron endpoints** `POST /api/_bunderstack/cron/:name` and `POST /api/_bunderstack/maintenance/:name`, along with `signScheduleRequest` / `verifyScheduleRequest` and the `BUNDERSTACK_CRON_SECRET` environment variable. Platforms no longer dispatch individual cron slots.
129
+ - **`bunderstack/cron` export changed.** It no longer re-exports the signing helpers; it now exports `parseCron`, `cronMatches`, `slotsDue`, `floorSlot`, `CRON_PREFIX`, and `SLOT_MS`.
130
+ - **`JobsRuntimeFacade.tick()` returns `TickResult`** (`{ claimed, ran, failed }`) instead of `void`.
131
+ - **Queue job names may not begin with `cron:`** — the prefix is reserved and rejected at startup.
132
+ - **`concurrency` is rejected on cron definitions** at startup; cron slots are already unique.
133
+ - **Removed the `envSource` config option**, replaced by `processEnv` (see below).
134
+
135
+ ### Added
136
+
137
+ - **`BUNDERSTACK_ROLE`** (`all` | `web` | `worker`, default `all`) makes process topology a deployment concern. The background loop starts automatically when the role includes the worker; no application code calls `startWorker()`. Override with `background: { autoStart: false }`.
138
+ - **`app.backgroundRunning`** reports whether this process runs the background loop.
139
+ - **Cron definitions gained `retries`, `backoff`, `timeout`, and `onFailed`**, matching queue jobs. Previously a throwing cron handler was never retried.
140
+ - **Cron definitions gained `catchUp`** (`'latest'` default, or `'all'`) and `catchUpWindow` (default 1 hour) controlling how missed slots are handled after downtime.
141
+ - **`routes` config option** — a builder callback `(ctx) => Hono` mounting custom Hono routes at root, ahead of bunderstack's own. The context carries `db`, `env`, `storage`, `email`, `jobs`, `realtime`, `auth`, plus lazy `getSession(request)` / `getUser(request)`. Exported as `BunderstackRouteContext`.
142
+ - **`processEnv` config option** — a single stand-in for `process.env`, feeding both env validation and platform overrides. Replaces `envSource` and unifies what were three separate injection points.
143
+ - **`typecheck` script** on the package.
144
+
145
+ ### Fixed
146
+
147
+ - **Terminal job updates are fenced on the held lease.** A worker whose lease expired could previously mark a row `succeeded` after another worker re-claimed and re-ran it, and could fire `onFailed` twice.
148
+ - **Retry backoff is jittered** (±20%), so jobs failed by a shared outage no longer retry in lockstep.
149
+ - **Custom routes are rate limited.** Routes mounted via `routes` sit inside the rate-limited app; the previous external-wrapper workaround left them uncovered.
150
+ - **`bunderstack/cron` no longer imports a deleted module.** The entry point was broken at runtime.
151
+ - **Succeeded-row reaping moved off the per-tick path** to at most hourly. Retention is unchanged at 24h.
152
+ - `tableEntryForName` is defined once in `access.ts` instead of copied into four modules, so CRUD, realtime, and route validation cannot disagree on which tables are enabled.
153
+
154
+ ## [0.15.2] - 2026-08-05
155
+
156
+ ### Fixed
157
+
158
+ - S3 uploads carry the correct content type.
159
+ - Documented the nested `node_modules` resolution issue for consumers.
160
+
161
+ ## [0.15.1] - 2026-08-04
162
+
163
+ ### Fixed
164
+
165
+ - Blueprint generator tests use a cross-platform temp directory; the CLI is
166
+ marked executable.
167
+
168
+ ## [0.15.0] - 2026-08-04
169
+
170
+ ### Added
171
+
172
+ - **Deployment blueprints** (`bunderstack blueprint`) — static deploy metadata a
173
+ hosting platform can read without executing application code.
174
+
175
+ ## [0.13.0] - 2026-08-01
176
+
177
+ ### Added
178
+
179
+ - **`StorageFacade.upload()`** for server-generated files.
180
+ - Nested file paths in the storage `GET`/`DELETE` routes.
181
+
182
+ ## [0.12.0] - 2026-07-31
183
+
184
+ ### Added
185
+
186
+ - **`storage` in the procedure context**, alongside `db`, `env`, and the rest.
187
+
188
+ ### Fixed
189
+
190
+ - Presign fallback uses the configured default bucket.
191
+
192
+ ## [0.11.0] - 2026-07-30
193
+
194
+ ### Added
195
+
196
+ - **`BunderstackJobContext`** exported as a type alias for typing job handlers.
197
+
198
+ ## [0.10.0] - 2026-07-28
199
+
200
+ ### Added
201
+
202
+ - **Static Deployment Metadata**: Preserve cron schedule literals in the public jobs type so hosting platforms can infer deployment requirements without executing application code.
203
+
204
+ ### Fixed
205
+
206
+ - **Browser Timer Compatibility**: Accept numeric timer handles in the local cron scheduler.
207
+
208
+ ## [0.9.1] - 2026-07-26
209
+
210
+ ### Fixed
211
+
212
+ - **npm Publish Workspace Resolution**: Automatically sanitize `workspace:*` dependency protocols to exact version specifiers (`^0.9.1`) during `npm publish` in CI/CD pipeline.
213
+
214
+ ## [0.9.0] - 2026-07-26
215
+
216
+ ### Added
217
+
218
+ - **Realtime Transport Metadata**: Added `realtime.transport` (`'disabled' | 'memory' | 'redis'`) to `RealtimeFacade` and `app.realtime`.
219
+ - **Manifest Transport Inspection**: Added `realtimeTransport` field to `BunderstackManifest` and `buildManifest()` for platform introspection (Bunderhost).
220
+ - **Standalone Worker Transport Safety**: `app.runWorker()` now rejects in-memory realtime brokers by default to prevent silent event loss between web and worker processes. Added `allowProcessLocalRealtime?: boolean` flag for workers that do not publish realtime events.
221
+ - Exported `RealtimeTransport` and `createRealtimeFacade` from `bunderstack`.
222
+
223
+ ### Fixed
224
+
225
+ - Fixed test isolation in worker and introspection unit tests when `process.env.REDIS_URL` is set in the execution environment.
226
+
227
+ ## [0.8.0] - 2026-07-25
228
+
229
+ ### Added
230
+
231
+ - **Static Dependency Boundaries**: Clean separation of database, auth, email, and storage adapter boundaries.
232
+ - **JobContext & tRPC Context Realtime**: Wired generic-typed `ctx.realtime` into background job handlers and tRPC procedures.
233
+ - **DB Provisioning Internals**: Standalone `bunderstack/provision` module for database migration tooling.
package/README.md CHANGED
@@ -44,9 +44,19 @@ Use the in-memory Publisher for one process or configure
44
44
  `realtime: { redis: process.env.REDIS_URL! }` for multi-process delivery and
45
45
  replay. Deployment metadata is generated with `bunx bunderstack blueprint`.
46
46
 
47
- See the [workspace documentation](../../README.md) for webhooks, clients,
47
+ See the [workspace documentation](https://github.com/kirill-dev-pro/bunderstack#readme) for webhooks, clients,
48
48
  storage, collections, lifecycle, and complete examples.
49
49
 
50
+ ## Upgrading
51
+
52
+ 0.17 is a breaking release: tRPC became oRPC, generated `list` takes nested
53
+ typed `filters`, error codes are oRPC's own, and realtime names tables by their
54
+ schema key. Every change is listed with before/after code in the migration
55
+ guides, which ship with the package as `CHANGELOG.md` and live in full at:
56
+
57
+ - [Migrating to 0.17](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.17.md)
58
+ - [Migrating to 0.16](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.16.md)
59
+
50
60
  ## License
51
61
 
52
62
  MIT
@@ -0,0 +1,116 @@
1
+ export declare const AUTH_TABLE_NAMES: Set<string>;
2
+ export type AccessUser = {
3
+ id: string;
4
+ email: string;
5
+ name?: string;
6
+ role?: string;
7
+ };
8
+ export type AccessContext = {
9
+ user: AccessUser | null;
10
+ request: Request;
11
+ row?: Record<string, unknown>;
12
+ body?: Record<string, unknown>;
13
+ session?: {
14
+ activeOrganizationId: string | null;
15
+ } | null;
16
+ };
17
+ export type OperationRule = 'public' | 'authenticated' | 'owner' | 'deny' | ((ctx: AccessContext) => boolean | Promise<boolean>);
18
+ export type ScopeMap = Record<string, string | string[]>;
19
+ export type ScopeResolver = (ctx: AccessContext) => ScopeMap;
20
+ export type CrudOperation = 'list' | 'get' | 'create' | 'update' | 'delete';
21
+ export type SortOrder = 'asc' | 'desc';
22
+ export type DefaultSort = {
23
+ column: string;
24
+ order: SortOrder;
25
+ };
26
+ export type TableAccessInput = {
27
+ crud?: boolean;
28
+ /** Opt the BetterAuth `user` table into auto-CRUD (read profiles, owner-update image). */
29
+ exposeAuthTable?: boolean;
30
+ ownerColumn?: string;
31
+ list?: OperationRule;
32
+ get?: OperationRule;
33
+ create?: OperationRule;
34
+ update?: OperationRule;
35
+ delete?: OperationRule;
36
+ /** Explicit write allowlist. Entries override matching system-readonly
37
+ * defaults such as `updatedAt`; `id` remains immutable on update. */
38
+ writableColumns?: string[];
39
+ readonlyColumns?: string[];
40
+ /** Columns matched by `?q=` on list — opt-in; omitted columns are never searched. */
41
+ searchableColumns?: string[];
42
+ /** Columns filterable via flat `?column=value` query params. */
43
+ filterableColumns?: string[];
44
+ /** Columns allowed in `?sort=`. Defaults to `['id']`. */
45
+ sortableColumns?: string[];
46
+ /** Default list ordering when `?sort` is omitted. Defaults to `{ column: 'id', order: 'desc' }`. */
47
+ defaultSort?: DefaultSort;
48
+ scope?: {
49
+ read?: ScopeResolver;
50
+ write?: ScopeResolver;
51
+ };
52
+ };
53
+ export type ResolvedTableAccess = {
54
+ tableKey: string;
55
+ tableName: string;
56
+ enabled: boolean;
57
+ ownerColumn?: string;
58
+ list: OperationRule;
59
+ get: OperationRule;
60
+ create: OperationRule;
61
+ update: OperationRule;
62
+ delete: OperationRule;
63
+ writableColumns?: string[];
64
+ readonlyColumns: string[];
65
+ searchableColumns?: string[];
66
+ filterableColumns: string[];
67
+ sortableColumns: string[];
68
+ defaultSort: DefaultSort;
69
+ readScope?: ScopeResolver;
70
+ writeScope?: ScopeResolver;
71
+ };
72
+ export type ResolvedAccess = Map<string, ResolvedTableAccess>;
73
+ /**
74
+ * Look up a table's resolved access by its physical table name.
75
+ *
76
+ * `ResolvedAccess` is keyed by schema export name, not table name, so every
77
+ * consumer that starts from a physical name needs this scan. It lives here so
78
+ * CRUD, realtime, and route validation cannot drift apart on which tables they
79
+ * consider enabled.
80
+ */
81
+ export declare function tableEntryForName(access: ResolvedAccess, tableName: string): ResolvedTableAccess | undefined;
82
+ export declare function validateAndResolveAccess<TSchema extends Record<string, unknown>>(schema: TSchema, accessInput?: Record<string, TableAccessInput>): ResolvedAccess;
83
+ export declare function defineAccess<TSchema extends Record<string, unknown>, const TRules extends Record<string, TableAccessInput>>(schema: TSchema, rules: TRules): TRules;
84
+ export declare function rowMatchesScope(row: Record<string, unknown>, scope: ScopeMap): boolean;
85
+ export declare function stampScope(values: Record<string, unknown>, scope: ScopeMap): Record<string, unknown>;
86
+ export declare function checkAccessSync(rule: Exclude<OperationRule, (ctx: AccessContext) => boolean | Promise<boolean>>, ctx: AccessContext, ownerColumn?: string): {
87
+ allowed: boolean;
88
+ };
89
+ export declare function checkAccess(rule: OperationRule, ctx: AccessContext, ownerColumn?: string): Promise<{
90
+ allowed: boolean;
91
+ status: 401 | 403;
92
+ }>;
93
+ export declare function sanitizeWriteBody(body: Record<string, unknown>, access: ResolvedTableAccess, mode: 'create' | 'update', userId: string | null): Record<string, unknown>;
94
+ export type AuthSessionResolver = {
95
+ api: {
96
+ getSession: (opts: {
97
+ headers: Headers;
98
+ }) => Promise<{
99
+ user: {
100
+ id: string;
101
+ email: string;
102
+ name?: string;
103
+ role?: string;
104
+ } | null;
105
+ session?: {
106
+ activeOrganizationId?: string | null;
107
+ } | null;
108
+ } | null>;
109
+ };
110
+ };
111
+ export declare function resolveAccessUser(auth: AuthSessionResolver | undefined, headers: Headers): Promise<AccessUser | null>;
112
+ export declare function resolveSession(auth: AuthSessionResolver | undefined, headers: Headers): Promise<{
113
+ user: AccessUser | null;
114
+ activeOrganizationId: string | null;
115
+ }>;
116
+ //# sourceMappingURL=access.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,gBAAgB,aAK3B,CAAA;AAIF,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,OAAO,CAAC,EAAE;QAAE,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;CACzD,CAAA;AAED,MAAM,MAAM,aAAa,GACrB,QAAQ,GACR,eAAe,GACf,OAAO,GACP,MAAM,GACN,CAAC,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;AAExD,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;AACxD,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,aAAa,KAAK,QAAQ,CAAA;AAE5D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE3E,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,CAAA;AAEtC,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,0FAA0F;IAC1F,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,aAAa,CAAA;IACpB,GAAG,CAAC,EAAE,aAAa,CAAA;IACnB,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB;yEACqE;IACrE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,oGAAoG;IACpG,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,aAAa,CAAA;QACpB,KAAK,CAAC,EAAE,aAAa,CAAA;KACtB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,aAAa,CAAA;IACnB,GAAG,EAAE,aAAa,CAAA;IAClB,MAAM,EAAE,aAAa,CAAA;IACrB,MAAM,EAAE,aAAa,CAAA;IACrB,MAAM,EAAE,aAAa,CAAA;IACrB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,WAAW,EAAE,WAAW,CAAA;IACxB,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,UAAU,CAAC,EAAE,aAAa,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;AAE7D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,MAAM,GAChB,mBAAmB,GAAG,SAAS,CAKjC;AA+GD,wBAAgB,wBAAwB,CACtC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEvC,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAC7C,cAAc,CA4IhB;AAED,wBAAgB,YAAY,CAC1B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACrD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGxC;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,KAAK,EAAE,QAAQ,GACd,OAAO,CAWT;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,EAAE,QAAQ,GACd,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMzB;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,OAAO,CACX,aAAa,EACb,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CACnD,EACD,GAAG,EAAE,aAAa,EAClB,WAAW,CAAC,EAAE,MAAM,GACnB;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAWtB;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,aAAa,EAClB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAA;CAAE,CAAC,CAwBlD;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,QAAQ,GAAG,QAAQ,EACzB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA4BzB;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE;QACH,UAAU,EAAE,CAAC,IAAI,EAAE;YAAE,OAAO,EAAE,OAAO,CAAA;SAAE,KAAK,OAAO,CAAC;YAClD,IAAI,EAAE;gBAAE,EAAE,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,CAAC;gBAAC,IAAI,CAAC,EAAE,MAAM,CAAC;gBAAC,IAAI,CAAC,EAAE,MAAM,CAAA;aAAE,GAAG,IAAI,CAAA;YACxE,OAAO,CAAC,EAAE;gBAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;aAAE,GAAG,IAAI,CAAA;SAC1D,GAAG,IAAI,CAAC,CAAA;KACV,CAAA;CACF,CAAA;AAED,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,mBAAmB,GAAG,SAAS,EACrC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAU5B;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,mBAAmB,GAAG,SAAS,EACrC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC;IAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAa3E"}