bunderstack 0.17.0-beta.0 → 0.17.0-beta.3

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 (337) hide show
  1. package/CHANGELOG.md +227 -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 +76 -0
  60. package/dist/config.d.ts.map +1 -0
  61. package/dist/config.js +81 -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 +477 -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 +81 -29
  272. package/src/access.ts +0 -552
  273. package/src/api/api-types.types.ts +0 -106
  274. package/src/api/builder.ts +0 -52
  275. package/src/api/context.ts +0 -83
  276. package/src/api/crud-router.ts +0 -321
  277. package/src/api/openapi.ts +0 -184
  278. package/src/api/realtime-router.ts +0 -75
  279. package/src/api/registry.ts +0 -338
  280. package/src/api/router.ts +0 -34
  281. package/src/api/storage-router.ts +0 -224
  282. package/src/api/types.ts +0 -84
  283. package/src/auth.ts +0 -117
  284. package/src/blueprint-generator.ts +0 -203
  285. package/src/blueprint.ts +0 -264
  286. package/src/cli.ts +0 -90
  287. package/src/config.ts +0 -215
  288. package/src/cron.ts +0 -3
  289. package/src/crud-operations.ts +0 -488
  290. package/src/database/adapter.ts +0 -26
  291. package/src/database/bun-sql.ts +0 -23
  292. package/src/database/libsql.ts +0 -28
  293. package/src/database/pglite.ts +0 -33
  294. package/src/database/postgres-js.ts +0 -33
  295. package/src/db.ts +0 -61
  296. package/src/dialect.ts +0 -38
  297. package/src/email/smtp.ts +0 -45
  298. package/src/email.ts +0 -154
  299. package/src/env.ts +0 -180
  300. package/src/errors.ts +0 -118
  301. package/src/handler.ts +0 -30
  302. package/src/idempotency.ts +0 -97
  303. package/src/index.ts +0 -822
  304. package/src/internal-tables.ts +0 -149
  305. package/src/jobs/cron.ts +0 -87
  306. package/src/jobs/define.ts +0 -283
  307. package/src/jobs/index.ts +0 -37
  308. package/src/jobs/queue.ts +0 -67
  309. package/src/jobs/runtime.ts +0 -58
  310. package/src/jobs/slots.ts +0 -52
  311. package/src/jobs/worker.ts +0 -369
  312. package/src/lifecycle.ts +0 -49
  313. package/src/list-query.ts +0 -416
  314. package/src/manifest.ts +0 -297
  315. package/src/provision-internals.ts +0 -29
  316. package/src/provision.ts +0 -128
  317. package/src/rate-limit.ts +0 -71
  318. package/src/realtime/facade.ts +0 -55
  319. package/src/realtime/filter.ts +0 -77
  320. package/src/realtime/heartbeat.ts +0 -80
  321. package/src/realtime/publisher.ts +0 -46
  322. package/src/schema-export-pg.ts +0 -7
  323. package/src/schema-export.ts +0 -5
  324. package/src/scope.ts +0 -17
  325. package/src/standard-schema.ts +0 -59
  326. package/src/storage/buckets.ts +0 -308
  327. package/src/storage/delete.ts +0 -26
  328. package/src/storage/file-meta.ts +0 -222
  329. package/src/storage/index.ts +0 -39
  330. package/src/storage/local.ts +0 -69
  331. package/src/storage/operations.ts +0 -398
  332. package/src/storage/registry.ts +0 -40
  333. package/src/storage/s3.ts +0 -99
  334. package/src/storage/sweep.ts +0 -25
  335. package/src/storage/thumbnails.ts +0 -65
  336. package/src/testing.ts +0 -31
  337. package/src/typeid.ts +0 -116
package/CHANGELOG.md ADDED
@@ -0,0 +1,227 @@
1
+ # Changelog
2
+
3
+ All notable changes to `bunderstack` will be documented in this file.
4
+
5
+ ## [0.17.0-beta.3] - 2026-08-12
6
+
7
+ ### Breaking
8
+
9
+ - **The package publishes built `dist`, not raw `src`.** Every entry point now
10
+ resolves to `dist/<entry>.js` with `dist/<entry>.d.ts` beside it, and the
11
+ tarball no longer contains TypeScript sources. Consumers therefore typecheck
12
+ our *declarations*, which `skipLibCheck` can suppress — previously our sources
13
+ were compiled under the app's own flags, where `exactOptionalPropertyTypes`
14
+ alone produced 168 errors inside `node_modules` and
15
+ `noPropertyAccessFromIndexSignature` another 79. A strict app now sees zero
16
+ (`bun run verify:consumer` packs, installs, and proves it).
17
+ - **`createAuth` returns better-auth's plain `Auth`** instead of the
18
+ plugin-parameterised instance type. The value is unchanged; only the declared
19
+ type is narrower, because the inferred one did not survive declaration emit.
20
+ Plugin endpoints are still reachable through runtime checks.
21
+ - **Relative imports inside the published JS and declarations carry `.js`
22
+ extensions**, so the build no longer depends on bundler-style resolution.
23
+
24
+ ### Fixed
25
+
26
+ - **Generated CRUD types survive publishing.** Declaration emit inlined
27
+ drizzle-valibot's internal generics (`TRefinements`, `TType`) into the
28
+ published `.d.ts`, where they are unbound — a `notNull` column silently became
29
+ optional for consumers. `select`, `update`, and `list` schemas now state their
30
+ types explicitly, which also makes the emitted API dramatically smaller.
31
+ - `lookupIdempotency` no longer takes an unused config parameter, and
32
+ `Bun.Image` is typed locally so image transforms compile against any
33
+ `bun-types` version and report a clear error on an older Bun.
34
+
35
+ ### Added
36
+
37
+ - `bun run build` (and `prepare`/`prepack`) build every package;
38
+ `scripts/build-package.ts` fails the build if an emitted import resolves to
39
+ nothing.
40
+ - `bun run verify:consumer` — packs the tarballs, installs them into a scratch
41
+ app with the strictest common flags and `skipLibCheck: false`, then typechecks
42
+ and smoke-runs it.
43
+ - `noUnusedParameters` and `noImplicitReturns` are on in every package.
44
+ - The tarball now includes `CHANGELOG.md`, and the README links to the migration
45
+ guides with absolute URLs so they are reachable from an installed package.
46
+
47
+ ## [0.17.0-beta.2] - 2026-08-12
48
+
49
+ Migration guide: [docs/MIGRATION-0.17.md](https://github.com/kirill-dev-pro/bunderstack/blob/main/docs/MIGRATION-0.17.md).
50
+
51
+ ### Breaking
52
+
53
+ - **Generated `list` takes a typed, nested `filters` object.** Filter, sort, and
54
+ paging parameters are now declared by a per-table schema derived from the
55
+ table's columns and its `access` allowlists, and query strings are coerced to
56
+ those types by oRPC's `SmartCoercionHandlerPlugin`. `?filters[authorId]=u1`
57
+ replaces `?authorId=u1`, `?filters[id][]=a&filters[id][]=b` replaces the
58
+ comma-separated `?id=a,b`, and a bare query param is now a 400 instead of a
59
+ silent filter. On the client, `filters` autocompletes to real columns and
60
+ rejects wrong value types at compile time.
61
+ - **Error codes are oRPC's own codes.** `VALIDATION_ERROR` → `BAD_REQUEST`,
62
+ `RATE_LIMITED` → `TOO_MANY_REQUESTS`. `BUNDERSTACK_ERROR_STATUS_MAP` is
63
+ removed along with the handlers' `errorStatusMap` override.
64
+ - **Realtime events and subscriptions name tables by schema key**, not SQL table
65
+ name, so one name works for procedures, subscriptions, and events. Only
66
+ affects apps whose schema key differs from the table name.
67
+ - **`ScopedCollectionOptions.filter` → `filters`** in `bunderstack-sync`, and
68
+ `table.list(input)` forwards its input to the procedure unchanged.
69
+ - **`filterableColumns` / `sortableColumns` no longer reject** column names like
70
+ `limit` or `sort`; nesting removed the collision that made the rule necessary.
71
+
72
+ ### Fixed
73
+
74
+ - **Client errors answer 4xx instead of 500.** Because the custom status map had
75
+ no entry for oRPC's own codes, every schema failure and every rate-limit
76
+ rejection answered HTTP 500 with a 4xx code in the body — on both REST and
77
+ RPC. Validation responses now also carry `details` naming the failing field.
78
+ - **REST list parameters work.** `?offset=` and `?count=` failed validation
79
+ because only `limit` was coerced from its query string; numeric, boolean, and
80
+ date filters had no way through at all.
81
+ - **`operations.list` no longer reads the raw request URL.** The validated input
82
+ is the only source, so a query param can no longer bypass the procedure schema
83
+ and reach the WHERE clause.
84
+ - **Realtime updates reach sync collections** for tables whose schema key is not
85
+ the SQL name; they previously degraded to refetch-only.
86
+ - **Packages compile under a consumer's `noUnusedLocals`.** Type-probe files are
87
+ excluded from the tarball, unused imports are gone, and every package builds
88
+ with the flag on so this cannot rot again (`scripts/packaging-contract.test.ts`).
89
+
90
+ ### Added
91
+
92
+ - **`ApiContext` is exported**, so shared middleware can be declared as
93
+ `os.$context<ApiContext<typeof schema>>()` instead of over a hand-written
94
+ minimal context.
95
+ - `@orpc/json-schema` as a direct dependency (query/body coercion plugin).
96
+
97
+ ## [0.17.0-beta.0] - 2026-08-11
98
+
99
+ The oRPC-first redesign: one procedure graph for CRUD, storage, realtime, and
100
+ custom procedures, served as RPC at `/api/rpc/*` and REST/OpenAPI at `/api/*`.
101
+
102
+ ### Breaking
103
+
104
+ - **tRPC is replaced by oRPC.** `trpc:` → `api:`, `.query()`/`.mutation()` →
105
+ `.handler()`, `ctx` → `context`. `@trpc/server` is no longer a dependency.
106
+ - **Validation is Standard Schema** (valibot in the box; zod and arktype work,
107
+ with valibot the only vendor the bundled OpenAPI generator can convert).
108
+ - **Realtime runs on oRPC Publisher** as an event-iterator procedure at
109
+ `/api/realtime`, with heartbeats and `Last-Event-ID` resume; the previous
110
+ in-house broker is gone.
111
+ - **Storage and CRUD are procedures**, not bespoke Hono handlers.
112
+ - **`bunderstack-query` exposes oRPC's TanStack Query utilities.**
113
+ `queryOptions(input, opts)` → `queryOptions({ input, ...opts })`,
114
+ `keys.all` → `key()`; `listQuery`/`getQuery` are gone.
115
+
116
+ ## [0.16.0] - 2026-08-07
117
+
118
+ ### Breaking
119
+
120
+ - **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**.
121
+ - **Removed `app.startCronScheduler()`.** Cron runs through the same tick everywhere, so the development/production split no longer exists.
122
+ - **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.
123
+ - **`bunderstack/cron` export changed.** It no longer re-exports the signing helpers; it now exports `parseCron`, `cronMatches`, `slotsDue`, `floorSlot`, `CRON_PREFIX`, and `SLOT_MS`.
124
+ - **`JobsRuntimeFacade.tick()` returns `TickResult`** (`{ claimed, ran, failed }`) instead of `void`.
125
+ - **Queue job names may not begin with `cron:`** — the prefix is reserved and rejected at startup.
126
+ - **`concurrency` is rejected on cron definitions** at startup; cron slots are already unique.
127
+ - **Removed the `envSource` config option**, replaced by `processEnv` (see below).
128
+
129
+ ### Added
130
+
131
+ - **`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 }`.
132
+ - **`app.backgroundRunning`** reports whether this process runs the background loop.
133
+ - **Cron definitions gained `retries`, `backoff`, `timeout`, and `onFailed`**, matching queue jobs. Previously a throwing cron handler was never retried.
134
+ - **Cron definitions gained `catchUp`** (`'latest'` default, or `'all'`) and `catchUpWindow` (default 1 hour) controlling how missed slots are handled after downtime.
135
+ - **`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`.
136
+ - **`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.
137
+ - **`typecheck` script** on the package.
138
+
139
+ ### Fixed
140
+
141
+ - **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.
142
+ - **Retry backoff is jittered** (±20%), so jobs failed by a shared outage no longer retry in lockstep.
143
+ - **Custom routes are rate limited.** Routes mounted via `routes` sit inside the rate-limited app; the previous external-wrapper workaround left them uncovered.
144
+ - **`bunderstack/cron` no longer imports a deleted module.** The entry point was broken at runtime.
145
+ - **Succeeded-row reaping moved off the per-tick path** to at most hourly. Retention is unchanged at 24h.
146
+ - `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.
147
+
148
+ ## [0.15.2] - 2026-08-05
149
+
150
+ ### Fixed
151
+
152
+ - S3 uploads carry the correct content type.
153
+ - Documented the nested `node_modules` resolution issue for consumers.
154
+
155
+ ## [0.15.1] - 2026-08-04
156
+
157
+ ### Fixed
158
+
159
+ - Blueprint generator tests use a cross-platform temp directory; the CLI is
160
+ marked executable.
161
+
162
+ ## [0.15.0] - 2026-08-04
163
+
164
+ ### Added
165
+
166
+ - **Deployment blueprints** (`bunderstack blueprint`) — static deploy metadata a
167
+ hosting platform can read without executing application code.
168
+
169
+ ## [0.13.0] - 2026-08-01
170
+
171
+ ### Added
172
+
173
+ - **`StorageFacade.upload()`** for server-generated files.
174
+ - Nested file paths in the storage `GET`/`DELETE` routes.
175
+
176
+ ## [0.12.0] - 2026-07-31
177
+
178
+ ### Added
179
+
180
+ - **`storage` in the procedure context**, alongside `db`, `env`, and the rest.
181
+
182
+ ### Fixed
183
+
184
+ - Presign fallback uses the configured default bucket.
185
+
186
+ ## [0.11.0] - 2026-07-30
187
+
188
+ ### Added
189
+
190
+ - **`BunderstackJobContext`** exported as a type alias for typing job handlers.
191
+
192
+ ## [0.10.0] - 2026-07-28
193
+
194
+ ### Added
195
+
196
+ - **Static Deployment Metadata**: Preserve cron schedule literals in the public jobs type so hosting platforms can infer deployment requirements without executing application code.
197
+
198
+ ### Fixed
199
+
200
+ - **Browser Timer Compatibility**: Accept numeric timer handles in the local cron scheduler.
201
+
202
+ ## [0.9.1] - 2026-07-26
203
+
204
+ ### Fixed
205
+
206
+ - **npm Publish Workspace Resolution**: Automatically sanitize `workspace:*` dependency protocols to exact version specifiers (`^0.9.1`) during `npm publish` in CI/CD pipeline.
207
+
208
+ ## [0.9.0] - 2026-07-26
209
+
210
+ ### Added
211
+
212
+ - **Realtime Transport Metadata**: Added `realtime.transport` (`'disabled' | 'memory' | 'redis'`) to `RealtimeFacade` and `app.realtime`.
213
+ - **Manifest Transport Inspection**: Added `realtimeTransport` field to `BunderstackManifest` and `buildManifest()` for platform introspection (Bunderhost).
214
+ - **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.
215
+ - Exported `RealtimeTransport` and `createRealtimeFacade` from `bunderstack`.
216
+
217
+ ### Fixed
218
+
219
+ - Fixed test isolation in worker and introspection unit tests when `process.env.REDIS_URL` is set in the execution environment.
220
+
221
+ ## [0.8.0] - 2026-07-25
222
+
223
+ ### Added
224
+
225
+ - **Static Dependency Boundaries**: Clean separation of database, auth, email, and storage adapter boundaries.
226
+ - **JobContext & tRPC Context Realtime**: Wired generic-typed `ctx.realtime` into background job handlers and tRPC procedures.
227
+ - **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":"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"}