@mistriwork/engine 0.0.0-stage → 1.0.0-rc.10

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 (546) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -2
  3. package/dist/adapters/adapter.d.ts +693 -0
  4. package/dist/adapters/adapter.js +444 -0
  5. package/dist/adapters/cache/cacheStore.d.ts +75 -0
  6. package/dist/adapters/cache/cacheStore.js +160 -0
  7. package/dist/adapters/cache/resp.d.ts +52 -0
  8. package/dist/adapters/cache/resp.js +237 -0
  9. package/dist/adapters/commands/canonicalJson.d.ts +19 -0
  10. package/dist/adapters/commands/canonicalJson.js +154 -0
  11. package/dist/adapters/connect.d.ts +29 -0
  12. package/dist/adapters/connect.js +40 -0
  13. package/dist/adapters/connectionBudget.d.ts +101 -0
  14. package/dist/adapters/connectionBudget.js +128 -0
  15. package/dist/adapters/dbLatency.d.ts +35 -0
  16. package/dist/adapters/dbLatency.js +79 -0
  17. package/dist/adapters/epochCache.d.ts +50 -0
  18. package/dist/adapters/epochCache.js +85 -0
  19. package/dist/adapters/http/egress.d.ts +48 -0
  20. package/dist/adapters/http/egress.js +175 -0
  21. package/dist/adapters/http/httpAdapter.d.ts +71 -0
  22. package/dist/adapters/http/httpAdapter.js +512 -0
  23. package/dist/adapters/http/httpDescription.d.ts +32 -0
  24. package/dist/adapters/http/httpDescription.js +246 -0
  25. package/dist/adapters/http/openapi.d.ts +98 -0
  26. package/dist/adapters/http/openapi.js +487 -0
  27. package/dist/adapters/layoutRefusal.d.ts +24 -0
  28. package/dist/adapters/layoutRefusal.js +35 -0
  29. package/dist/adapters/net/networkPolicy.d.ts +44 -0
  30. package/dist/adapters/net/networkPolicy.js +123 -0
  31. package/dist/adapters/net/untrustedDatabase.d.ts +18 -0
  32. package/dist/adapters/net/untrustedDatabase.js +120 -0
  33. package/dist/adapters/poolAdmission.d.ts +43 -0
  34. package/dist/adapters/poolAdmission.js +184 -0
  35. package/dist/adapters/poolMetrics.d.ts +121 -0
  36. package/dist/adapters/poolMetrics.js +185 -0
  37. package/dist/adapters/postgres.d.ts +436 -0
  38. package/dist/adapters/postgres.js +1890 -0
  39. package/dist/adapters/postgresCatalog.d.ts +96 -0
  40. package/dist/adapters/postgresCatalog.js +387 -0
  41. package/dist/adapters/postgresCatalogDigest.d.ts +30 -0
  42. package/dist/adapters/postgresCatalogDigest.js +87 -0
  43. package/dist/adapters/postgresCatalogRows.d.ts +62 -0
  44. package/dist/adapters/postgresCatalogRows.js +37 -0
  45. package/dist/adapters/postgresDates.d.ts +1 -0
  46. package/dist/adapters/postgresDates.js +39 -0
  47. package/dist/adapters/postgresMaintenance.d.ts +33 -0
  48. package/dist/adapters/postgresMaintenance.js +179 -0
  49. package/dist/adapters/postgresPool.d.ts +255 -0
  50. package/dist/adapters/postgresPool.js +838 -0
  51. package/dist/adapters/postgresPooler.d.ts +28 -0
  52. package/dist/adapters/postgresPooler.js +267 -0
  53. package/dist/adapters/postgresReadCatalog.d.ts +31 -0
  54. package/dist/adapters/postgresReadCatalog.js +226 -0
  55. package/dist/adapters/postgresReadSnapshot.d.ts +46 -0
  56. package/dist/adapters/postgresReadSnapshot.js +133 -0
  57. package/dist/adapters/postgresSchemaEpoch.d.ts +24 -0
  58. package/dist/adapters/postgresSchemaEpoch.js +149 -0
  59. package/dist/adapters/postgresTransactionHandle.d.ts +173 -0
  60. package/dist/adapters/postgresTransactionHandle.js +524 -0
  61. package/dist/adapters/postgresValues.d.ts +30 -0
  62. package/dist/adapters/postgresValues.js +75 -0
  63. package/dist/adapters/replicas.d.ts +70 -0
  64. package/dist/adapters/replicas.js +208 -0
  65. package/dist/adapters/reservedSql.d.ts +38 -0
  66. package/dist/adapters/reservedSql.js +264 -0
  67. package/dist/adapters/rolePrivileges.d.ts +17 -0
  68. package/dist/adapters/rolePrivileges.js +22 -0
  69. package/dist/adapters/scoped/keyRows.d.ts +65 -0
  70. package/dist/adapters/scoped/keyRows.js +173 -0
  71. package/dist/adapters/scoped/postgresScopeCatalog.d.ts +16 -0
  72. package/dist/adapters/scoped/postgresScopeCatalog.js +117 -0
  73. package/dist/adapters/scoped/scopedCommandOperations.d.ts +5 -0
  74. package/dist/adapters/scoped/scopedCommandOperations.js +48 -0
  75. package/dist/adapters/scoped/scopedReads.d.ts +20 -0
  76. package/dist/adapters/scoped/scopedReads.js +174 -0
  77. package/dist/adapters/scoped/scopedTransaction.d.ts +89 -0
  78. package/dist/adapters/scoped/scopedTransaction.js +303 -0
  79. package/dist/adapters/scoped/sqliteScopeCatalog.d.ts +16 -0
  80. package/dist/adapters/scoped/sqliteScopeCatalog.js +241 -0
  81. package/dist/adapters/scoped/updateGuard.d.ts +3 -0
  82. package/dist/adapters/scoped/updateGuard.js +40 -0
  83. package/dist/adapters/serverSettings.d.ts +45 -0
  84. package/dist/adapters/serverSettings.js +46 -0
  85. package/dist/adapters/sqlite.d.ts +262 -0
  86. package/dist/adapters/sqlite.js +1434 -0
  87. package/dist/adapters/sqliteCostlyReads.d.ts +33 -0
  88. package/dist/adapters/sqliteCostlyReads.js +49 -0
  89. package/dist/adapters/sqliteDecimals.d.ts +22 -0
  90. package/dist/adapters/sqliteDecimals.js +57 -0
  91. package/dist/adapters/sqliteHandles.d.ts +43 -0
  92. package/dist/adapters/sqliteHandles.js +143 -0
  93. package/dist/adapters/sqliteStatementProcess.d.ts +29 -0
  94. package/dist/adapters/sqliteStatementProcess.js +131 -0
  95. package/dist/adapters/statementControl.d.ts +34 -0
  96. package/dist/adapters/statementControl.js +90 -0
  97. package/dist/adapters/storeHost.d.ts +130 -0
  98. package/dist/adapters/storeHost.js +13 -0
  99. package/dist/adapters/telemetry/drivers.d.ts +21 -0
  100. package/dist/adapters/telemetry/drivers.js +321 -0
  101. package/dist/adapters/telemetry/metrics.d.ts +63 -0
  102. package/dist/adapters/telemetry/metrics.js +122 -0
  103. package/dist/adapters/telemetry/otlp.d.ts +12 -0
  104. package/dist/adapters/telemetry/otlp.js +320 -0
  105. package/dist/adapters/telemetry/otlpEncode.d.ts +48 -0
  106. package/dist/adapters/telemetry/otlpEncode.js +366 -0
  107. package/dist/adapters/telemetry/otlpEnv.d.ts +1 -0
  108. package/dist/adapters/telemetry/otlpEnv.js +12 -0
  109. package/dist/adapters/telemetry/serverTiming.d.ts +83 -0
  110. package/dist/adapters/telemetry/serverTiming.js +503 -0
  111. package/dist/adapters/telemetry/start.d.ts +10 -0
  112. package/dist/adapters/telemetry/start.js +25 -0
  113. package/dist/adapters/telemetry/statement.d.ts +16 -0
  114. package/dist/adapters/telemetry/statement.js +134 -0
  115. package/dist/adapters/telemetry/trace.d.ts +127 -0
  116. package/dist/adapters/telemetry/trace.js +295 -0
  117. package/dist/adapters/writeAhead.d.ts +27 -0
  118. package/dist/adapters/writeAhead.js +46 -0
  119. package/dist/adapters/writeAttribution.d.ts +18 -0
  120. package/dist/adapters/writeAttribution.js +23 -0
  121. package/dist/adapters/writeCapture.d.ts +73 -0
  122. package/dist/adapters/writeCapture.js +20 -0
  123. package/dist/adapters/writeLanes.d.ts +94 -0
  124. package/dist/adapters/writeLanes.js +232 -0
  125. package/dist/engine.d.ts +15 -0
  126. package/dist/engine.js +13 -0
  127. package/dist/server/auth/credentials.d.ts +61 -0
  128. package/dist/server/auth/credentials.js +260 -0
  129. package/dist/server/cacheService.d.ts +50 -0
  130. package/dist/server/cacheService.js +110 -0
  131. package/dist/server/cli/args.d.ts +176 -0
  132. package/dist/server/cli/args.js +342 -0
  133. package/dist/server/cli/bin.d.ts +5 -0
  134. package/dist/server/cli/bin.js +66 -0
  135. package/dist/server/cli/browser.d.ts +15 -0
  136. package/dist/server/cli/browser.js +37 -0
  137. package/dist/server/cli/config.d.ts +50 -0
  138. package/dist/server/cli/config.js +206 -0
  139. package/dist/server/cli/startup.d.ts +36 -0
  140. package/dist/server/cli/startup.js +128 -0
  141. package/dist/server/cli/startupOptions.d.ts +63 -0
  142. package/dist/server/cli/startupOptions.js +143 -0
  143. package/dist/server/cli/subcommand.d.ts +28 -0
  144. package/dist/server/cli/subcommand.js +32 -0
  145. package/dist/server/cli/usage.d.ts +13 -0
  146. package/dist/server/cli/usage.js +31 -0
  147. package/dist/server/clientHttp.d.ts +184 -0
  148. package/dist/server/clientHttp.js +700 -0
  149. package/dist/server/clientSurface.d.ts +128 -0
  150. package/dist/server/clientSurface.js +182 -0
  151. package/dist/server/columnGrants.d.ts +103 -0
  152. package/dist/server/columnGrants.js +730 -0
  153. package/dist/server/compileCache.d.ts +1 -0
  154. package/dist/server/compileCache.js +30 -0
  155. package/dist/server/config/locations.d.ts +1 -0
  156. package/dist/server/config/locations.js +15 -0
  157. package/dist/server/configPaths.d.ts +7 -0
  158. package/dist/server/configPaths.js +34 -0
  159. package/dist/server/configSections.d.ts +64 -0
  160. package/dist/server/configSections.js +72 -0
  161. package/dist/server/connectionRedaction.d.ts +30 -0
  162. package/dist/server/connectionRedaction.js +77 -0
  163. package/dist/server/connections.d.ts +353 -0
  164. package/dist/server/connections.js +978 -0
  165. package/dist/server/constraints.d.ts +82 -0
  166. package/dist/server/constraints.js +169 -0
  167. package/dist/server/demo.d.ts +9 -0
  168. package/dist/server/demo.js +554 -0
  169. package/dist/server/devclient.d.ts +108 -0
  170. package/dist/server/devclient.js +361 -0
  171. package/dist/server/evidence.d.ts +55 -0
  172. package/dist/server/evidence.js +323 -0
  173. package/dist/server/hiddenColumns.d.ts +32 -0
  174. package/dist/server/hiddenColumns.js +238 -0
  175. package/dist/server/http/baselineHeaders.d.ts +24 -0
  176. package/dist/server/http/baselineHeaders.js +12 -0
  177. package/dist/server/http/captured.d.ts +35 -0
  178. package/dist/server/http/captured.js +73 -0
  179. package/dist/server/http/clock.d.ts +1 -0
  180. package/dist/server/http/clock.js +14 -0
  181. package/dist/server/http/connectionSource.d.ts +4 -0
  182. package/dist/server/http/connectionSource.js +48 -0
  183. package/dist/server/http/context.d.ts +189 -0
  184. package/dist/server/http/context.js +11 -0
  185. package/dist/server/http/crawlerText.d.ts +15 -0
  186. package/dist/server/http/crawlerText.js +32 -0
  187. package/dist/server/http/dataRoutes.d.ts +88 -0
  188. package/dist/server/http/dataRoutes.js +137 -0
  189. package/dist/server/http/door.d.ts +57 -0
  190. package/dist/server/http/door.js +39 -0
  191. package/dist/server/http/exportRoute.d.ts +15 -0
  192. package/dist/server/http/exportRoute.js +320 -0
  193. package/dist/server/http/firstPaint.d.ts +108 -0
  194. package/dist/server/http/firstPaint.js +262 -0
  195. package/dist/server/http/httpOperationRoutes.d.ts +11 -0
  196. package/dist/server/http/httpOperationRoutes.js +50 -0
  197. package/dist/server/http/pageReads.d.ts +20 -0
  198. package/dist/server/http/pageReads.js +205 -0
  199. package/dist/server/http/pageRoutes.d.ts +39 -0
  200. package/dist/server/http/pageRoutes.js +291 -0
  201. package/dist/server/http/probes.d.ts +22 -0
  202. package/dist/server/http/probes.js +27 -0
  203. package/dist/server/http/rateLimit.d.ts +131 -0
  204. package/dist/server/http/rateLimit.js +351 -0
  205. package/dist/server/http/readRoutes.d.ts +9 -0
  206. package/dist/server/http/readRoutes.js +131 -0
  207. package/dist/server/http/readRouting.d.ts +20 -0
  208. package/dist/server/http/readRouting.js +80 -0
  209. package/dist/server/http/recordCompose.d.ts +67 -0
  210. package/dist/server/http/recordCompose.js +167 -0
  211. package/dist/server/http/recordWrites.d.ts +89 -0
  212. package/dist/server/http/recordWrites.js +298 -0
  213. package/dist/server/http/refusalReport.d.ts +38 -0
  214. package/dist/server/http/refusalReport.js +63 -0
  215. package/dist/server/http/reply.d.ts +130 -0
  216. package/dist/server/http/reply.js +394 -0
  217. package/dist/server/http/requestOrigin.d.ts +11 -0
  218. package/dist/server/http/requestOrigin.js +8 -0
  219. package/dist/server/http/router.d.ts +45 -0
  220. package/dist/server/http/router.js +22 -0
  221. package/dist/server/http/serverCore.d.ts +68 -0
  222. package/dist/server/http/serverCore.js +177 -0
  223. package/dist/server/http/traceRequest.d.ts +30 -0
  224. package/dist/server/http/traceRequest.js +224 -0
  225. package/dist/server/http/trust.d.ts +261 -0
  226. package/dist/server/http/trust.js +472 -0
  227. package/dist/server/http/writeRefusal.d.ts +33 -0
  228. package/dist/server/http/writeRefusal.js +24 -0
  229. package/dist/server/httpConnection.d.ts +49 -0
  230. package/dist/server/httpConnection.js +170 -0
  231. package/dist/server/impact.d.ts +55 -0
  232. package/dist/server/impact.js +47 -0
  233. package/dist/server/journal.d.ts +134 -0
  234. package/dist/server/journal.js +398 -0
  235. package/dist/server/keysetReadHttp.d.ts +52 -0
  236. package/dist/server/keysetReadHttp.js +85 -0
  237. package/dist/server/layouts.d.ts +49 -0
  238. package/dist/server/layouts.js +192 -0
  239. package/dist/server/migrate/cli.d.ts +55 -0
  240. package/dist/server/migrate/cli.js +517 -0
  241. package/dist/server/migrate/database.d.ts +37 -0
  242. package/dist/server/migrate/database.js +247 -0
  243. package/dist/server/migrate/desired.d.ts +76 -0
  244. package/dist/server/migrate/desired.js +292 -0
  245. package/dist/server/migrate/files.d.ts +34 -0
  246. package/dist/server/migrate/files.js +141 -0
  247. package/dist/server/migrate/flyway.d.ts +7 -0
  248. package/dist/server/migrate/flyway.js +69 -0
  249. package/dist/server/migrate/history.d.ts +70 -0
  250. package/dist/server/migrate/history.js +211 -0
  251. package/dist/server/migrate/runner.d.ts +100 -0
  252. package/dist/server/migrate/runner.js +409 -0
  253. package/dist/server/migrate/snapshot.d.ts +30 -0
  254. package/dist/server/migrate/snapshot.js +239 -0
  255. package/dist/server/migrate/target.d.ts +33 -0
  256. package/dist/server/migrate/target.js +82 -0
  257. package/dist/server/openapiDraft.d.ts +25 -0
  258. package/dist/server/openapiDraft.js +171 -0
  259. package/dist/server/operations/diagnostics.d.ts +101 -0
  260. package/dist/server/operations/diagnostics.js +284 -0
  261. package/dist/server/operations/requestMetrics.d.ts +33 -0
  262. package/dist/server/operations/requestMetrics.js +94 -0
  263. package/dist/server/packageVersion.d.ts +1 -0
  264. package/dist/server/packageVersion.js +11 -0
  265. package/dist/server/poolConfig.d.ts +34 -0
  266. package/dist/server/poolConfig.js +114 -0
  267. package/dist/server/product.d.ts +20 -0
  268. package/dist/server/product.js +12 -0
  269. package/dist/server/recordHistoryOperations.d.ts +39 -0
  270. package/dist/server/recordHistoryOperations.js +43 -0
  271. package/dist/server/recordWriteOperations.d.ts +111 -0
  272. package/dist/server/recordWriteOperations.js +329 -0
  273. package/dist/server/resourceReadHttp.d.ts +81 -0
  274. package/dist/server/resourceReadHttp.js +606 -0
  275. package/dist/server/resourceReadOperations.d.ts +147 -0
  276. package/dist/server/resourceReadOperations.js +452 -0
  277. package/dist/server/scaffoldMachine.d.ts +54 -0
  278. package/dist/server/scaffoldMachine.js +184 -0
  279. package/dist/server/seed/cli.d.ts +20 -0
  280. package/dist/server/seed/cli.js +164 -0
  281. package/dist/server/seed/lexicon.d.ts +26 -0
  282. package/dist/server/seed/lexicon.js +585 -0
  283. package/dist/server/seed/seed.d.ts +70 -0
  284. package/dist/server/seed/seed.js +779 -0
  285. package/dist/server/seed/words.d.ts +21 -0
  286. package/dist/server/seed/words.js +164 -0
  287. package/dist/server/serverRequests.d.ts +6 -0
  288. package/dist/server/serverRequests.js +33 -0
  289. package/dist/server/serverTimeouts.d.ts +33 -0
  290. package/dist/server/serverTimeouts.js +32 -0
  291. package/dist/server/shapeonly.d.ts +32 -0
  292. package/dist/server/shapeonly.js +110 -0
  293. package/dist/server/startupWarnings.d.ts +32 -0
  294. package/dist/server/startupWarnings.js +92 -0
  295. package/dist/shared/addressParams.d.ts +28 -0
  296. package/dist/shared/addressParams.js +47 -0
  297. package/dist/shared/appCards.d.ts +123 -0
  298. package/dist/shared/appCards.js +385 -0
  299. package/dist/shared/appComponents.d.ts +177 -0
  300. package/dist/shared/appComponents.js +422 -0
  301. package/dist/shared/appDocuments.d.ts +43 -0
  302. package/dist/shared/appDocuments.js +131 -0
  303. package/dist/shared/appEmbeds.d.ts +21 -0
  304. package/dist/shared/appEmbeds.js +24 -0
  305. package/dist/shared/appIcons.d.ts +28 -0
  306. package/dist/shared/appIcons.js +223 -0
  307. package/dist/shared/appLinks.d.ts +17 -0
  308. package/dist/shared/appLinks.js +124 -0
  309. package/dist/shared/appListColumns.d.ts +3 -0
  310. package/dist/shared/appListColumns.js +66 -0
  311. package/dist/shared/appLocale.d.ts +36 -0
  312. package/dist/shared/appLocale.js +86 -0
  313. package/dist/shared/appMessages.d.ts +44 -0
  314. package/dist/shared/appMessages.js +78 -0
  315. package/dist/shared/appNoun.d.ts +21 -0
  316. package/dist/shared/appNoun.js +32 -0
  317. package/dist/shared/autoBucket.d.ts +98 -0
  318. package/dist/shared/autoBucket.js +305 -0
  319. package/dist/shared/autoValues.d.ts +25 -0
  320. package/dist/shared/autoValues.js +25 -0
  321. package/dist/shared/breakdown.d.ts +228 -0
  322. package/dist/shared/breakdown.js +557 -0
  323. package/dist/shared/breakdowntext.d.ts +41 -0
  324. package/dist/shared/breakdowntext.js +400 -0
  325. package/dist/shared/builtInThemes.d.ts +2 -0
  326. package/dist/shared/builtInThemes.js +771 -0
  327. package/dist/shared/chartSeparation.d.ts +11 -0
  328. package/dist/shared/chartSeparation.js +58 -0
  329. package/dist/shared/clauses.d.ts +22 -0
  330. package/dist/shared/clauses.js +97 -0
  331. package/dist/shared/columnCaption.d.ts +16 -0
  332. package/dist/shared/columnCaption.js +90 -0
  333. package/dist/shared/commandFieldPath.d.ts +2 -0
  334. package/dist/shared/commandFieldPath.js +7 -0
  335. package/dist/shared/commandWire.d.ts +26 -0
  336. package/dist/shared/commandWire.js +41 -0
  337. package/dist/shared/computed.d.ts +161 -0
  338. package/dist/shared/computed.js +378 -0
  339. package/dist/shared/computedParse.d.ts +13 -0
  340. package/dist/shared/computedParse.js +278 -0
  341. package/dist/shared/computedValue.d.ts +47 -0
  342. package/dist/shared/computedValue.js +191 -0
  343. package/dist/shared/connection.d.ts +30 -0
  344. package/dist/shared/connection.js +1 -0
  345. package/dist/shared/csv.d.ts +20 -0
  346. package/dist/shared/csv.js +63 -0
  347. package/dist/shared/dashLayout.d.ts +30 -0
  348. package/dist/shared/dashLayout.js +132 -0
  349. package/dist/shared/dashboardAsks.d.ts +93 -0
  350. package/dist/shared/dashboardAsks.js +129 -0
  351. package/dist/shared/dashboardTrend.d.ts +20 -0
  352. package/dist/shared/dashboardTrend.js +50 -0
  353. package/dist/shared/declaredReferences.d.ts +50 -0
  354. package/dist/shared/declaredReferences.js +202 -0
  355. package/dist/shared/definedFields.d.ts +63 -0
  356. package/dist/shared/definedFields.js +103 -0
  357. package/dist/shared/definedValues.d.ts +63 -0
  358. package/dist/shared/definedValues.js +184 -0
  359. package/dist/shared/displayDefaults.d.ts +135 -0
  360. package/dist/shared/displayDefaults.js +529 -0
  361. package/dist/shared/dueDate.d.ts +6 -0
  362. package/dist/shared/dueDate.js +6 -0
  363. package/dist/shared/duration.d.ts +4 -0
  364. package/dist/shared/duration.js +23 -0
  365. package/dist/shared/fileBounds.d.ts +9 -0
  366. package/dist/shared/fileBounds.js +9 -0
  367. package/dist/shared/filter.d.ts +217 -0
  368. package/dist/shared/filter.js +305 -0
  369. package/dist/shared/firstPaint.d.ts +24 -0
  370. package/dist/shared/firstPaint.js +33 -0
  371. package/dist/shared/form.d.ts +21 -0
  372. package/dist/shared/form.js +25 -0
  373. package/dist/shared/formValues.d.ts +104 -0
  374. package/dist/shared/formValues.js +352 -0
  375. package/dist/shared/funnel.d.ts +45 -0
  376. package/dist/shared/funnel.js +108 -0
  377. package/dist/shared/httpOperations.d.ts +48 -0
  378. package/dist/shared/httpOperations.js +9 -0
  379. package/dist/shared/iconGlyphs.d.ts +4 -0
  380. package/dist/shared/iconGlyphs.js +151 -0
  381. package/dist/shared/iconWeights.d.ts +3 -0
  382. package/dist/shared/iconWeights.js +162 -0
  383. package/dist/shared/imageWidths.d.ts +32 -0
  384. package/dist/shared/imageWidths.js +38 -0
  385. package/dist/shared/keysetPage.d.ts +64 -0
  386. package/dist/shared/keysetPage.js +161 -0
  387. package/dist/shared/like.d.ts +20 -0
  388. package/dist/shared/like.js +29 -0
  389. package/dist/shared/listEmpty.d.ts +12 -0
  390. package/dist/shared/listEmpty.js +36 -0
  391. package/dist/shared/listFilters.d.ts +28 -0
  392. package/dist/shared/listFilters.js +84 -0
  393. package/dist/shared/listPresentations.d.ts +199 -0
  394. package/dist/shared/listPresentations.js +7 -0
  395. package/dist/shared/listQuestion.d.ts +52 -0
  396. package/dist/shared/listQuestion.js +137 -0
  397. package/dist/shared/lookPalettes.d.ts +62 -0
  398. package/dist/shared/lookPalettes.js +306 -0
  399. package/dist/shared/maskQuoted.d.ts +24 -0
  400. package/dist/shared/maskQuoted.js +48 -0
  401. package/dist/shared/mentionLabel.d.ts +19 -0
  402. package/dist/shared/mentionLabel.js +38 -0
  403. package/dist/shared/mentionLookup.d.ts +17 -0
  404. package/dist/shared/mentionLookup.js +64 -0
  405. package/dist/shared/menuCounts.d.ts +16 -0
  406. package/dist/shared/menuCounts.js +74 -0
  407. package/dist/shared/model.d.ts +79 -0
  408. package/dist/shared/model.js +153 -0
  409. package/dist/shared/money.d.ts +44 -0
  410. package/dist/shared/money.js +81 -0
  411. package/dist/shared/moneyEntry.d.ts +7 -0
  412. package/dist/shared/moneyEntry.js +27 -0
  413. package/dist/shared/mount.d.ts +118 -0
  414. package/dist/shared/mount.js +248 -0
  415. package/dist/shared/niceTicks.d.ts +26 -0
  416. package/dist/shared/niceTicks.js +50 -0
  417. package/dist/shared/order.d.ts +59 -0
  418. package/dist/shared/order.js +133 -0
  419. package/dist/shared/page.d.ts +135 -0
  420. package/dist/shared/page.js +1187 -0
  421. package/dist/shared/pageAnatomy.d.ts +99 -0
  422. package/dist/shared/pageAnatomy.js +370 -0
  423. package/dist/shared/pageConfig.d.ts +25 -0
  424. package/dist/shared/pageConfig.js +1308 -0
  425. package/dist/shared/pageEmptyActions.d.ts +12 -0
  426. package/dist/shared/pageEmptyActions.js +20 -0
  427. package/dist/shared/pageLayouts.d.ts +72 -0
  428. package/dist/shared/pageLayouts.js +205 -0
  429. package/dist/shared/pageModel.d.ts +785 -0
  430. package/dist/shared/pageModel.js +121 -0
  431. package/dist/shared/pagePaths.d.ts +180 -0
  432. package/dist/shared/pagePaths.js +869 -0
  433. package/dist/shared/pagePlans.d.ts +52 -0
  434. package/dist/shared/pagePlans.js +108 -0
  435. package/dist/shared/pageRoutes.d.ts +9 -0
  436. package/dist/shared/pageRoutes.js +9 -0
  437. package/dist/shared/query.d.ts +166 -0
  438. package/dist/shared/query.js +1302 -0
  439. package/dist/shared/queryDates.d.ts +12 -0
  440. package/dist/shared/queryDates.js +101 -0
  441. package/dist/shared/queryOperands.d.ts +99 -0
  442. package/dist/shared/queryOperands.js +131 -0
  443. package/dist/shared/reads.d.ts +103 -0
  444. package/dist/shared/reads.js +154 -0
  445. package/dist/shared/recordLabel.d.ts +51 -0
  446. package/dist/shared/recordLabel.js +123 -0
  447. package/dist/shared/recordReadKeys.d.ts +30 -0
  448. package/dist/shared/recordReadKeys.js +51 -0
  449. package/dist/shared/recordReads.d.ts +268 -0
  450. package/dist/shared/recordReads.js +368 -0
  451. package/dist/shared/recordview.d.ts +198 -0
  452. package/dist/shared/recordview.js +356 -0
  453. package/dist/shared/referenceModel.d.ts +58 -0
  454. package/dist/shared/referenceModel.js +194 -0
  455. package/dist/shared/refusal.d.ts +64 -0
  456. package/dist/shared/refusal.js +144 -0
  457. package/dist/shared/relatedCreate.d.ts +30 -0
  458. package/dist/shared/relatedCreate.js +162 -0
  459. package/dist/shared/resourceHttp.d.ts +464 -0
  460. package/dist/shared/resourceHttp.js +1 -0
  461. package/dist/shared/richText.d.ts +85 -0
  462. package/dist/shared/richText.js +305 -0
  463. package/dist/shared/rollups.d.ts +143 -0
  464. package/dist/shared/rollups.js +64 -0
  465. package/dist/shared/rowScope.d.ts +72 -0
  466. package/dist/shared/rowScope.js +376 -0
  467. package/dist/shared/runtimeTables.d.ts +44 -0
  468. package/dist/shared/runtimeTables.js +79 -0
  469. package/dist/shared/schema.d.ts +523 -0
  470. package/dist/shared/schema.js +627 -0
  471. package/dist/shared/schematext.d.ts +38 -0
  472. package/dist/shared/schematext.js +101 -0
  473. package/dist/shared/scopeCatalog.d.ts +29 -0
  474. package/dist/shared/scopeCatalog.js +468 -0
  475. package/dist/shared/servedApp.d.ts +681 -0
  476. package/dist/shared/servedApp.js +45 -0
  477. package/dist/shared/sessionLease.d.ts +34 -0
  478. package/dist/shared/sessionLease.js +3 -0
  479. package/dist/shared/shape.d.ts +55 -0
  480. package/dist/shared/shape.js +168 -0
  481. package/dist/shared/slug.d.ts +1 -0
  482. package/dist/shared/slug.js +12 -0
  483. package/dist/shared/sortText.d.ts +14 -0
  484. package/dist/shared/sortText.js +26 -0
  485. package/dist/shared/sqlRelation.d.ts +4 -0
  486. package/dist/shared/sqlRelation.js +8 -0
  487. package/dist/shared/sqlsaved.d.ts +44 -0
  488. package/dist/shared/sqlsaved.js +63 -0
  489. package/dist/shared/stitchedPaths.d.ts +27 -0
  490. package/dist/shared/stitchedPaths.js +38 -0
  491. package/dist/shared/structuredFilter.d.ts +22 -0
  492. package/dist/shared/structuredFilter.js +1 -0
  493. package/dist/shared/subtitlePath.d.ts +20 -0
  494. package/dist/shared/subtitlePath.js +24 -0
  495. package/dist/shared/suggest.d.ts +18 -0
  496. package/dist/shared/suggest.js +59 -0
  497. package/dist/shared/tableSizing.d.ts +4 -0
  498. package/dist/shared/tableSizing.js +9 -0
  499. package/dist/shared/tagLists.d.ts +57 -0
  500. package/dist/shared/tagLists.js +34 -0
  501. package/dist/shared/textRules.d.ts +54 -0
  502. package/dist/shared/textRules.js +133 -0
  503. package/dist/shared/theme.d.ts +94 -0
  504. package/dist/shared/theme.js +800 -0
  505. package/dist/shared/themeColor.d.ts +34 -0
  506. package/dist/shared/themeColor.js +109 -0
  507. package/dist/shared/themeFaces.d.ts +30 -0
  508. package/dist/shared/themeFaces.js +42 -0
  509. package/dist/shared/themeInk.d.ts +20 -0
  510. package/dist/shared/themeInk.js +52 -0
  511. package/dist/shared/themeLooks.d.ts +9 -0
  512. package/dist/shared/themeLooks.js +572 -0
  513. package/dist/shared/themeParts.d.ts +26 -0
  514. package/dist/shared/themeParts.js +71 -0
  515. package/dist/shared/themePartsCheck.d.ts +21 -0
  516. package/dist/shared/themePartsCheck.js +91 -0
  517. package/dist/shared/themePresets.d.ts +85 -0
  518. package/dist/shared/themePresets.js +139 -0
  519. package/dist/shared/themeRecipeWords.d.ts +156 -0
  520. package/dist/shared/themeRecipeWords.js +156 -0
  521. package/dist/shared/themeRecipes.d.ts +213 -0
  522. package/dist/shared/themeRecipes.js +234 -0
  523. package/dist/shared/themeResolve.d.ts +55 -0
  524. package/dist/shared/themeResolve.js +52 -0
  525. package/dist/shared/themeTokens.d.ts +107 -0
  526. package/dist/shared/themeTokens.js +116 -0
  527. package/dist/shared/themeType.d.ts +38 -0
  528. package/dist/shared/themeType.js +205 -0
  529. package/dist/shared/unitWord.d.ts +4 -0
  530. package/dist/shared/unitWord.js +37 -0
  531. package/dist/shared/view.d.ts +195 -0
  532. package/dist/shared/view.js +987 -0
  533. package/dist/shared/viewLabels.d.ts +47 -0
  534. package/dist/shared/viewLabels.js +459 -0
  535. package/dist/shared/viewPaths.d.ts +248 -0
  536. package/dist/shared/viewPaths.js +294 -0
  537. package/dist/shared/viewtext.d.ts +57 -0
  538. package/dist/shared/viewtext.js +282 -0
  539. package/dist/shared/vocabulary.d.ts +71 -0
  540. package/dist/shared/vocabulary.js +249 -0
  541. package/dist/shared/weekStart.d.ts +7 -0
  542. package/dist/shared/weekStart.js +36 -0
  543. package/mark.svg +1 -0
  544. package/package.json +261 -4
  545. package/schema/model.d.ts +298 -0
  546. package/schema/theme.d.ts +587 -0
@@ -0,0 +1,65 @@
1
+ /**
2
+ * A record's row, read once in full through the row scope by its key, and
3
+ * every later read of that record by the same key, in the same transaction
4
+ * and under the same scope, answered from it: the columns it asks for, in its
5
+ * order, from the row already read.
6
+ *
7
+ * A command reads its target by key several times before it writes — whether
8
+ * it is visible, its revision, the columns its machine moves, the before image
9
+ * its audit keeps, the guard the write checks — each a round trip of its own,
10
+ * each the same row. Read under the row lock the transaction takes first
11
+ * (postgres.ts sends both ahead, behind its BEGIN), the row cannot move
12
+ * underneath it, and a row scope's visibility is decided by the row's own
13
+ * columns (shared/rowScope.ts), so the projection is what each read would
14
+ * have answered.
15
+ *
16
+ * Only while the transaction has sent nothing that could change it: a row is
17
+ * kept with the transaction's statement generation (postgresTransactionHandle
18
+ * generationOf), which moves with every statement that is not a read or a
19
+ * lock — its own write, a savepoint, a rollback, a failure — and a row kept
20
+ * under an older generation answers nothing. Only reads that name the
21
+ * table's primary key by equality, from the first row, with no order, are
22
+ * answered; anything else is asked in its turn. A read that also names other
23
+ * columns by equality (a guard: the record, and only in the state it moves
24
+ * from) is answered only where the kept row holds exactly the value asked,
25
+ * identical in type and content: identical values are equal under any
26
+ * collation or type the server compares them by, so that answer is the
27
+ * server's. Where they differ (a numeric's text, a citext's case, a bytea),
28
+ * the read is asked in its turn rather than answered with no row.
29
+ */
30
+ import { type Filter, type QueryRequest, type ScopedReads, type SqlFragment } from '../adapter.js';
31
+ import type { DatabaseSchema, TableMeta } from '../../shared/schema.js';
32
+ import type { RowScope } from '../../shared/rowScope.js';
33
+ type Row = Record<string, unknown>;
34
+ type Reads = Pick<ScopedReads, 'query'> & Partial<ScopedReads>;
35
+ export declare class KeyRows {
36
+ #private;
37
+ /** The transaction's statement generation now; undefined where it has none (nothing is kept). */
38
+ private readonly generation;
39
+ constructor(
40
+ /** The transaction's statement generation now; undefined where it has none (nothing is kept). */
41
+ generation: () => number | undefined);
42
+ /** Keep nothing more and answer nothing from what was kept (the catalog the rows were read under is not the transaction's). */
43
+ forget(): void;
44
+ /** Keep the rows a full read of `table` by its key will answer (`rows`, the driver's own, unconverted). */
45
+ keep(scope: RowScope, table: TableMeta, filter: Filter, rows: Promise<readonly Row[]>, take?: () => void): void;
46
+ /**
47
+ * `reads`, with every read by key answered from a kept row where one is
48
+ * kept. `statementOf` says the statement the read would have sent (its
49
+ * `sql`); `format` turns a driver row into the read's own (binary or not, as
50
+ * the read's executor would). With `keeps`, a full read by key that is asked
51
+ * in its turn is kept for those after it (a guard's read: its rows are the
52
+ * driver's own). With `widen`, a read by key of a row the transaction holds
53
+ * locked (`held`), with nothing kept of it since the transaction last
54
+ * changed something, is sent as a full read through `widen.reads` (whose
55
+ * rows are the driver's own) and kept, and answered from it: the row cannot
56
+ * move while the lock is held, so the reads of it that follow — the guard
57
+ * reads of the write it is read for — are answered from it too, rather
58
+ * than each asked in its turn.
59
+ */
60
+ over<R extends Reads>(reads: R, scope: RowScope, schema: DatabaseSchema, statementOf: (request: QueryRequest) => SqlFragment | undefined, format: (row: Row, request: QueryRequest) => Row, keeps: boolean, widen?: {
61
+ held(table: TableMeta, key: Readonly<Record<string, string | number>>): boolean;
62
+ reads: Pick<ScopedReads, 'query'>;
63
+ }): R;
64
+ }
65
+ export {};
@@ -0,0 +1,173 @@
1
+ /**
2
+ * A record's row, read once in full through the row scope by its key, and
3
+ * every later read of that record by the same key, in the same transaction
4
+ * and under the same scope, answered from it: the columns it asks for, in its
5
+ * order, from the row already read.
6
+ *
7
+ * A command reads its target by key several times before it writes — whether
8
+ * it is visible, its revision, the columns its machine moves, the before image
9
+ * its audit keeps, the guard the write checks — each a round trip of its own,
10
+ * each the same row. Read under the row lock the transaction takes first
11
+ * (postgres.ts sends both ahead, behind its BEGIN), the row cannot move
12
+ * underneath it, and a row scope's visibility is decided by the row's own
13
+ * columns (shared/rowScope.ts), so the projection is what each read would
14
+ * have answered.
15
+ *
16
+ * Only while the transaction has sent nothing that could change it: a row is
17
+ * kept with the transaction's statement generation (postgresTransactionHandle
18
+ * generationOf), which moves with every statement that is not a read or a
19
+ * lock — its own write, a savepoint, a rollback, a failure — and a row kept
20
+ * under an older generation answers nothing. Only reads that name the
21
+ * table's primary key by equality, from the first row, with no order, are
22
+ * answered; anything else is asked in its turn. A read that also names other
23
+ * columns by equality (a guard: the record, and only in the state it moves
24
+ * from) is answered only where the kept row holds exactly the value asked,
25
+ * identical in type and content: identical values are equal under any
26
+ * collation or type the server compares them by, so that answer is the
27
+ * server's. Where they differ (a numeric's text, a citext's case, a bytea),
28
+ * the read is asked in its turn rather than answered with no row.
29
+ */
30
+ import { clampLimit } from '../adapter.js';
31
+ export class KeyRows {
32
+ generation;
33
+ #entries = new Map();
34
+ #scopes = new WeakMap();
35
+ #next = 0;
36
+ constructor(
37
+ /** The transaction's statement generation now; undefined where it has none (nothing is kept). */
38
+ generation) {
39
+ this.generation = generation;
40
+ }
41
+ /** Keep nothing more and answer nothing from what was kept (the catalog the rows were read under is not the transaction's). */
42
+ forget() {
43
+ this.#entries.clear();
44
+ }
45
+ #scope(scope) {
46
+ let id = this.#scopes.get(scope);
47
+ if (id === undefined)
48
+ this.#scopes.set(scope, (id = this.#next++));
49
+ return id;
50
+ }
51
+ /** The key a read of `table` by `filter` is kept under: undefined unless the filter is exactly the primary key by equality. */
52
+ #keyOf(scope, table, filter) {
53
+ const found = this.#guarded(scope, table, filter);
54
+ return found && !found.also.length ? found.key : undefined;
55
+ }
56
+ /** The key of a read by the primary key by equality, and the other columns it names by equality (`also`). */
57
+ #guarded(scope, table, filter) {
58
+ const pk = table.columns.filter((column) => column.primaryKey).map((column) => column.name);
59
+ const group = filter?.groups.length === 1 ? filter.groups[0] : undefined;
60
+ if (!pk.length || !group || group.length < pk.length)
61
+ return undefined;
62
+ const values = {};
63
+ const also = [];
64
+ for (const condition of group) {
65
+ if (condition.op !== '=' || Object.keys(condition).length !== 3)
66
+ return undefined;
67
+ if (pk.includes(condition.column)) {
68
+ if (typeof condition.value !== 'string' && typeof condition.value !== 'number')
69
+ return undefined;
70
+ if (Object.hasOwn(values, condition.column))
71
+ return undefined;
72
+ values[condition.column] = condition.value;
73
+ continue;
74
+ }
75
+ const column = table.columns.find((candidate) => candidate.name === condition.column);
76
+ // json has no equality operator: the server refuses that read, so it is sent for the server to say so.
77
+ if (!column || /^json$/i.test(column.type))
78
+ return undefined;
79
+ if (typeof condition.value !== 'string' && typeof condition.value !== 'number' && typeof condition.value !== 'boolean')
80
+ return undefined;
81
+ also.push({ column: condition.column, value: condition.value });
82
+ }
83
+ if (Object.keys(values).length !== pk.length)
84
+ return undefined;
85
+ return { key: JSON.stringify([this.#scope(scope), table.id, pk.map((column) => values[column])]), values, also };
86
+ }
87
+ /** Keep the rows a full read of `table` by its key will answer (`rows`, the driver's own, unconverted). */
88
+ keep(scope, table, filter, rows, take) {
89
+ const generation = this.generation(), key = this.#keyOf(scope, table, filter);
90
+ if (generation === undefined || key === undefined)
91
+ return;
92
+ this.#entries.set(key, {
93
+ generation,
94
+ // A failed read answers nothing: each read is then asked in its turn.
95
+ rows: rows.then((found) => found, () => undefined),
96
+ take,
97
+ });
98
+ }
99
+ /**
100
+ * `reads`, with every read by key answered from a kept row where one is
101
+ * kept. `statementOf` says the statement the read would have sent (its
102
+ * `sql`); `format` turns a driver row into the read's own (binary or not, as
103
+ * the read's executor would). With `keeps`, a full read by key that is asked
104
+ * in its turn is kept for those after it (a guard's read: its rows are the
105
+ * driver's own). With `widen`, a read by key of a row the transaction holds
106
+ * locked (`held`), with nothing kept of it since the transaction last
107
+ * changed something, is sent as a full read through `widen.reads` (whose
108
+ * rows are the driver's own) and kept, and answered from it: the row cannot
109
+ * move while the lock is held, so the reads of it that follow — the guard
110
+ * reads of the write it is read for — are answered from it too, rather
111
+ * than each asked in its turn.
112
+ */
113
+ over(reads, scope, schema, statementOf, format, keeps, widen) {
114
+ const query = async (request) => {
115
+ const table = schema.tables.find((candidate) => candidate.id === request?.table);
116
+ const guarded = table && !request.orderBy?.length && !request.offset && clampLimit(request.limit) >= 1
117
+ ? this.#guarded(scope, table, request.filter)
118
+ : undefined;
119
+ const key = guarded && !guarded.also.length ? guarded.key : undefined;
120
+ // Asked again after a statement that moved the generation, of a column the row does not carry, or of a value it does not hold exactly: in its turn.
121
+ const answer = async (kept) => {
122
+ const rows = await kept.rows;
123
+ const names = request.columns?.length ? request.columns : table.columns.map((column) => column.name);
124
+ const sql = statementOf(request);
125
+ if (!rows ||
126
+ !sql ||
127
+ kept.generation !== this.generation() ||
128
+ !rows.every((row) => names.every((name) => Object.hasOwn(row, name))) ||
129
+ !rows.every((row) => guarded.also.every((condition) => Object.hasOwn(row, condition.column) && row[condition.column] === condition.value)))
130
+ return undefined;
131
+ kept.take?.();
132
+ return {
133
+ columns: [...names],
134
+ rows: rows
135
+ .slice(0, clampLimit(request.limit))
136
+ .map((row) => format(Object.fromEntries(names.map((name) => [name, row[name]])), request)),
137
+ ms: 0,
138
+ sql,
139
+ };
140
+ };
141
+ const current = this.generation();
142
+ const kept = guarded === undefined ? undefined : this.#entries.get(guarded.key);
143
+ if (kept && kept.generation === current) {
144
+ const answered = await answer(kept);
145
+ if (answered)
146
+ return answered;
147
+ }
148
+ else if (key !== undefined && current !== undefined && widen?.held(table, guarded.values)) {
149
+ const sent = widen.reads.query({ table: request.table, filter: request.filter, limit: 2, offset: 0 });
150
+ /* Its generation is the one it was sent under: what waited for the COMMIT leaves in front of it, in its flight
151
+ (postgresTransactionHandle), moving the generation as it goes, and the row it reads is after that. Kept
152
+ under the generation before it was sent, it would answer nothing after it. Reads are sent as they are
153
+ asked (createScopedReads compiles before it executes), so this is that moment. */
154
+ const generation = this.generation();
155
+ // A failure is the read's own: thrown as it would have been asked.
156
+ const full = await sent;
157
+ const read = { generation: generation ?? current, rows: Promise.resolve(full.rows) };
158
+ this.#entries.set(key, read);
159
+ const answered = await answer(read);
160
+ if (answered)
161
+ return answered;
162
+ }
163
+ if (!keeps || key === undefined || request.columns?.length)
164
+ return reads.query(request);
165
+ const generation = this.generation();
166
+ const result = await reads.query(request);
167
+ if (generation !== undefined && generation === this.generation())
168
+ this.#entries.set(key, { generation, rows: Promise.resolve(result.rows) });
169
+ return result;
170
+ };
171
+ return Object.freeze({ ...reads, query });
172
+ }
173
+ }
@@ -0,0 +1,16 @@
1
+ import type { DatabaseSchema } from '../../shared/schema.js';
2
+ import type { RowScope } from '../../shared/rowScope.js';
3
+ import type { PgQuery } from '../postgresPool.js';
4
+ import { type ScopeCatalog } from './scopedTransaction.js';
5
+ export interface PostgresScopeCatalog extends ScopeCatalog {
6
+ /** Ordinary tables the writer role may UPDATE, and so lock rows in. A
7
+ * superset of `writable`: a lockable table with a trigger is still refused
8
+ * as a target, but its rows can be held for a parent-visibility check. */
9
+ lockable: ReadonlySet<string>;
10
+ /** The relations this read pinned, quoted, in order: what a later transaction under the same epoch pins before it reads the epoch. */
11
+ pinned: readonly string[];
12
+ }
13
+ /** Call only on the leased writer inside its transaction, before any read of
14
+ * user data. The describe callback is the adapter's own introspection so the
15
+ * evidence has the same shape as the catalog the permissions were bound to. */
16
+ export declare function readPostgresScopeCatalog(client: PgQuery, scope: RowScope, describe: (client: PgQuery) => Promise<DatabaseSchema>): Promise<PostgresScopeCatalog>;
@@ -0,0 +1,117 @@
1
+ /**
2
+ * The scope catalog on PostgreSQL.
3
+ *
4
+ * SQLite reads its physical metadata inside `BEGIN IMMEDIATE`, where nothing
5
+ * else can write, so what it attests is what the transaction will see until
6
+ * COMMIT. PostgreSQL has no such fence: DDL from another session commits
7
+ * under a READ COMMITTED transaction unless something holds a lock on the
8
+ * relation it touches. So the tables this scope may write are pinned first,
9
+ * with `LOCK TABLE … IN ROW EXCLUSIVE MODE` — the lock an UPDATE takes
10
+ * anyway, compatible with every ordinary reader and writer and in conflict
11
+ * with everything that would change what a write means: ALTER TABLE, CREATE
12
+ * TRIGGER, ADD FOREIGN KEY (on either side), CREATE INDEX, ENABLE ROW LEVEL
13
+ * SECURITY. The catalog is read *after* the pin, so drift that committed
14
+ * before it is what the attestation compares, and drift after it waits for
15
+ * this transaction to end.
16
+ *
17
+ * Only tables in the scope that the writer role may update are pinned. That
18
+ * is not a loophole: a table outside the scope is unreadable here (`WHERE
19
+ * 1 = 0`), and one the role cannot update cannot be written by it, locked
20
+ * for update, or have its rows held for a parent check — so it is never in
21
+ * `writable` and the guarantee it lacks is one it could not use.
22
+ *
23
+ * What is described is exactly what `introspect()` describes, on the leased
24
+ * writer inside the transaction, so the deployed catalog and this evidence
25
+ * differ only when the database does.
26
+ */
27
+ import { POSTGRES_STYLE, Refusal } from '../adapter.js';
28
+ import { captureScopeCatalog } from '../../shared/scopeCatalog.js';
29
+ import { triggerNames } from './scopedTransaction.js';
30
+ const refuse = () => {
31
+ throw new Refusal('PostgreSQL scoped transactions require a complete catalog and an ordinary table the writer may update.');
32
+ };
33
+ /** The adapter's own id convention: `schema.name`, or `name` in public. */
34
+ function located(id) {
35
+ const dot = id.indexOf('.');
36
+ return dot === -1 ? { schema: 'public', name: id } : { schema: id.slice(0, dot), name: id.slice(dot + 1) };
37
+ }
38
+ const key = (at) => `${at.schema}.${at.name}`;
39
+ /** Everything that decides whether a write to a relation means what the
40
+ * scope assumes: its kind, row security, and the presence of triggers,
41
+ * rules and policies — and whether this role may update it at all. */
42
+ async function facts(client, targets) {
43
+ const result = new Map();
44
+ if (!targets.length)
45
+ return result;
46
+ const rows = await client.query(`SELECT n.nspname AS schema, c.relname AS name, c.relkind::text AS kind, c.relrowsecurity AS rls,
47
+ EXISTS (SELECT 1 FROM pg_trigger t WHERE t.tgrelid = c.oid AND NOT t.tgisinternal) AS triggers,
48
+ ARRAY(SELECT t.tgname::text FROM pg_trigger t WHERE t.tgrelid = c.oid AND NOT t.tgisinternal ORDER BY 1) AS trigger_names,
49
+ EXISTS (SELECT 1 FROM pg_rewrite r WHERE r.ev_class = c.oid) AS rules,
50
+ EXISTS (SELECT 1 FROM pg_policy p WHERE p.polrelid = c.oid) AS policies,
51
+ has_table_privilege(c.oid, 'UPDATE') AS updatable
52
+ FROM pg_class c
53
+ JOIN pg_namespace n ON n.oid = c.relnamespace
54
+ JOIN unnest($1::text[], $2::text[]) AS wanted(schema, name) ON wanted.schema = n.nspname AND wanted.name = c.relname`, [targets.map((target) => target.schema), targets.map((target) => target.name)]);
55
+ for (const row of rows.rows) {
56
+ if (typeof row.schema !== 'string' ||
57
+ typeof row.name !== 'string' ||
58
+ typeof row.kind !== 'string' ||
59
+ [row.rls, row.triggers, row.rules, row.policies, row.updatable].some((value) => typeof value !== 'boolean') ||
60
+ !Array.isArray(row.trigger_names) ||
61
+ row.trigger_names.some((name) => typeof name !== 'string') ||
62
+ result.has(key(row)))
63
+ return refuse();
64
+ result.set(key(row), row);
65
+ }
66
+ return result;
67
+ }
68
+ const lockable = (fact) => fact !== undefined && ['r', 'p'].includes(fact.kind) && fact.updatable;
69
+ const clean = (fact) => !fact.rls && !fact.triggers && !fact.rules && !fact.policies;
70
+ /** What makes a table unclean, as a refusal names it. */
71
+ const unclean = (fact) => [fact.triggers ? triggerNames(fact.trigger_names) : '', fact.rules ? 'a rule' : '', fact.policies || fact.rls ? 'row-level security' : '']
72
+ .filter(Boolean)
73
+ .join(' and ');
74
+ /** Call only on the leased writer inside its transaction, before any read of
75
+ * user data. The describe callback is the adapter's own introspection so the
76
+ * evidence has the same shape as the catalog the permissions were bound to. */
77
+ export async function readPostgresScopeCatalog(client, scope, describe) {
78
+ try {
79
+ const wanted = Object.keys(scope).map(located);
80
+ const before = await facts(client, wanted);
81
+ const pinned = wanted.filter((target) => lockable(before.get(key(target))));
82
+ const relations = pinned.map((target) => `${POSTGRES_STYLE.quote(target.schema)}.${POSTGRES_STYLE.quote(target.name)}`);
83
+ if (pinned.length)
84
+ await client.query(`LOCK TABLE ${relations.join(', ')} IN ROW EXCLUSIVE MODE`);
85
+ const described = await describe(client);
86
+ const schema = captureScopeCatalog({ ...described, label: 'PostgreSQL scoped transaction', readAt: new Date().toISOString() });
87
+ const after = facts(client, schema.tables.map((table) => ({ schema: table.schema, name: table.name })));
88
+ const held = new Set(pinned.map(key));
89
+ const writable = new Set();
90
+ const blockedBy = new Map();
91
+ const locks = new Set();
92
+ for (const table of schema.tables) {
93
+ const fact = (await after).get(key(table));
94
+ // A relation the catalog listed a moment ago and cannot describe now
95
+ // was dropped under this transaction; nothing here may rely on it.
96
+ if (!fact || table.id !== key(table))
97
+ return refuse();
98
+ if (!lockable(fact))
99
+ continue;
100
+ locks.add(table.id);
101
+ // Writable means pinned: a table that became clean after the pin
102
+ // decision could be dirtied again before COMMIT, so it stays read-only.
103
+ if (held.has(table.id) && clean(fact) && !table.isView && table.columns.some((column) => column.primaryKey))
104
+ writable.add(table.id);
105
+ else if (!clean(fact))
106
+ blockedBy.set(table.id, unclean(fact));
107
+ }
108
+ return { schema, writable, ...(blockedBy.size ? { blockedBy } : {}), lockable: locks, pinned: relations };
109
+ }
110
+ catch (error) {
111
+ if (error instanceof Refusal)
112
+ throw error;
113
+ // A lock the role may not take, a vanished relation or unknown metadata
114
+ // cannot weaken the boundary; the failure aborts the transaction anyway.
115
+ return refuse();
116
+ }
117
+ }
@@ -0,0 +1,5 @@
1
+ /** Adapter-owned command queue capture and failure accounting within a scoped transaction. */
2
+ import { type TransactionOperations } from '../adapter.js';
3
+ /** Shared adapter queue boundary: capture before waiting; caught malformed or
4
+ * failed operations still poison the transaction. No writer escapes here. */
5
+ export declare function scopedCommandInvoker(operations: TransactionOperations, scoped: boolean, command: boolean, runtime: (table: string) => boolean, verify?: () => void): <A, R>(input: A, work: (input: A) => Promise<R>, read?: boolean) => Promise<R>;
@@ -0,0 +1,48 @@
1
+ /** Adapter-owned command queue capture and failure accounting within a scoped transaction. */
2
+ import { Refusal } from '../adapter.js';
3
+ import { snapshotScopedData } from './scopedReads.js';
4
+ /** Shared adapter queue boundary: capture before waiting; caught malformed or
5
+ * failed operations still poison the transaction. No writer escapes here. */
6
+ export function scopedCommandInvoker(operations, scoped, command, runtime, verify = () => { }) {
7
+ let failed = false;
8
+ /* `read`: the work only reads, so on a transaction that sends together it may start beside reads in flight
9
+ (TransactionOperations.read); a failure still poisons every operation after it, in the order asked. */
10
+ return (input, work, read = false) => {
11
+ let captured = input;
12
+ let invalid;
13
+ if (scoped) {
14
+ try {
15
+ captured = snapshotScopedData(input);
16
+ }
17
+ catch (error) {
18
+ invalid = { error };
19
+ }
20
+ }
21
+ const job = async () => {
22
+ if (scoped && failed)
23
+ throw new Refusal('This scoped transaction has failed.');
24
+ try {
25
+ if (invalid)
26
+ throw invalid.error;
27
+ verify();
28
+ if (command &&
29
+ scoped &&
30
+ captured &&
31
+ typeof captured === 'object' &&
32
+ 'table' in captured &&
33
+ typeof captured.table === 'string' &&
34
+ runtime(captured.table)) {
35
+ throw new Refusal('Reserved resources are runtime-only.');
36
+ }
37
+ const result = await work(captured);
38
+ verify();
39
+ return result;
40
+ }
41
+ catch (error) {
42
+ failed = true;
43
+ throw error;
44
+ }
45
+ };
46
+ return read ? operations.read(job) : operations.run(job);
47
+ };
48
+ }
@@ -0,0 +1,20 @@
1
+ import { type QueryResult, type ScopedReads, type SqlFragment, type SqlStyle } from '../adapter.js';
2
+ import { type DatabaseSchema } from '../../shared/schema.js';
3
+ import { type RowScope } from '../../shared/rowScope.js';
4
+ /** Structured read arguments must not retain mutable values across driver
5
+ * waits. This is deliberately separate from stricter nonempty policy filters:
6
+ * an empty user filter is fine, because it never replaces the bound policy. */
7
+ export declare function snapshotScopedData<T>(input: T): T;
8
+ /** Dialect-independent policy binding. The driver only executes compiler output
9
+ * on its existing read handle; consumers never receive that execute function.
10
+ * Snapshot the trusted catalog too, so a later refresh cannot change the
11
+ * graph/columns against which this capability was bound — except a catalog
12
+ * `captureScopeCatalog` already detached and deeply froze, which nothing can
13
+ * change: a tenant source binds a reader per operation over one of those, and
14
+ * copying it each time cost milliseconds per read on a wide catalog.
15
+ */
16
+ export declare function createScopedReads(catalog: DatabaseSchema, input: RowScope, style: SqlStyle,
17
+ /** Execution formatting only: it never changes the compiled statement or scope. */
18
+ execute: (statement: SqlFragment, hint?: {
19
+ binary?: true;
20
+ }) => Promise<QueryResult>): ScopedReads;
@@ -0,0 +1,174 @@
1
+ import { buildWhere, clampLimit, orderClause, clampOffset, countStatement, Refusal, } from '../adapter.js';
2
+ import { findTable } from '../../shared/schema.js';
3
+ import { COUNT_EACH_MAX, countEachRows } from '../../shared/reads.js';
4
+ import { isCapturedScopeCatalog } from '../../shared/scopeCatalog.js';
5
+ import { ScopedRelations, snapshotRowScope } from '../../shared/rowScope.js';
6
+ import { compileView, compileViewCount } from '../../shared/view.js';
7
+ import { compileBreakdown, compileBreakdownCount } from '../../shared/breakdown.js';
8
+ /** Structured read arguments must not retain mutable values across driver
9
+ * waits. This is deliberately separate from stricter nonempty policy filters:
10
+ * an empty user filter is fine, because it never replaces the bound policy. */
11
+ export function snapshotScopedData(input) {
12
+ let nodes = 0;
13
+ let characters = 0;
14
+ let bytes = 0;
15
+ const fail = () => {
16
+ throw new Refusal('Invalid structured operation.');
17
+ };
18
+ const copy = (value, depth = 0) => {
19
+ if (++nodes > 32_768 || depth > 16)
20
+ return fail();
21
+ if (value === undefined || value === null || typeof value === 'boolean')
22
+ return value;
23
+ if (typeof value === 'string') {
24
+ characters += value.length;
25
+ if (characters > 1_048_576)
26
+ return fail();
27
+ return value;
28
+ }
29
+ if (typeof value === 'number' && Number.isFinite(value))
30
+ return value;
31
+ // A file's bytes: copied, and bounded as the characters are (the largest upload an App may accept).
32
+ if (value instanceof Uint8Array && (Object.getPrototypeOf(value) === Uint8Array.prototype || Buffer.isBuffer(value))) {
33
+ bytes += value.byteLength;
34
+ if (bytes > 26_214_400)
35
+ return fail();
36
+ return Buffer.from(value);
37
+ }
38
+ if (typeof value !== 'object')
39
+ return fail();
40
+ const array = Array.isArray(value);
41
+ const proto = Object.getPrototypeOf(value);
42
+ if (array ? proto !== Array.prototype : proto !== Object.prototype && proto !== null)
43
+ return fail();
44
+ const keys = Reflect.ownKeys(value);
45
+ if (keys.length > 8193)
46
+ return fail();
47
+ if (array) {
48
+ const length = Object.getOwnPropertyDescriptor(value, 'length')?.value;
49
+ if (!Number.isInteger(length) || length > 8192 || keys.length !== length + 1)
50
+ return fail();
51
+ const result = [];
52
+ for (let i = 0; i < length; i++) {
53
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(i));
54
+ if (!descriptor || !descriptor.enumerable || !('value' in descriptor))
55
+ return fail();
56
+ result.push(copy(descriptor.value, depth + 1));
57
+ }
58
+ return result;
59
+ }
60
+ const result = Object.create(null);
61
+ for (const key of keys) {
62
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
63
+ if (typeof key !== 'string' || !descriptor.enumerable || !('value' in descriptor))
64
+ return fail();
65
+ characters += key.length;
66
+ if (characters > 1_048_576)
67
+ return fail();
68
+ result[key] = copy(descriptor.value, depth + 1);
69
+ }
70
+ return result;
71
+ };
72
+ return copy(input);
73
+ }
74
+ /** Dialect-independent policy binding. The driver only executes compiler output
75
+ * on its existing read handle; consumers never receive that execute function.
76
+ * Snapshot the trusted catalog too, so a later refresh cannot change the
77
+ * graph/columns against which this capability was bound — except a catalog
78
+ * `captureScopeCatalog` already detached and deeply froze, which nothing can
79
+ * change: a tenant source binds a reader per operation over one of those, and
80
+ * copying it each time cost milliseconds per read on a wide catalog.
81
+ */
82
+ export function createScopedReads(catalog, input, style,
83
+ /** Execution formatting only: it never changes the compiled statement or scope. */
84
+ execute) {
85
+ const schema = isCapturedScopeCatalog(catalog) ? catalog : structuredClone(catalog);
86
+ const scope = snapshotRowScope(schema, input);
87
+ const tableFor = (id) => {
88
+ const table = findTable(schema, id);
89
+ if (!table)
90
+ throw new Refusal('Unknown resource in scoped read.');
91
+ return table;
92
+ };
93
+ const from = (id, filter) => {
94
+ const table = tableFor(id);
95
+ const column = (name) => {
96
+ if (!table.columns.some((column) => column.name === name))
97
+ throw new Refusal('Unknown column in scoped read.');
98
+ return style.quote(name);
99
+ };
100
+ const relations = new ScopedRelations(schema, style, scope);
101
+ const relation = relations.table(id);
102
+ const prefix = relations.finish();
103
+ const where = buildWhere(filter, style, prefix.params.length + 1, column);
104
+ return { table, column, relation, prefix, where, params: [...prefix.params, ...where.params] };
105
+ };
106
+ const counted = async (statement) => {
107
+ const result = await execute(statement);
108
+ return Number(result.rows[0]?.n ?? 0);
109
+ };
110
+ return Object.freeze({
111
+ async query(input) {
112
+ const request = snapshotScopedData(input);
113
+ const plan = from(request.table, request.filter);
114
+ const names = request.columns?.length ? request.columns : plan.table.columns.map((column) => column.name);
115
+ const columns = names.map(plan.column);
116
+ const order = orderClause(request.orderBy, plan.table, style, plan.params.length + 1, plan.column);
117
+ const n = plan.params.length + order.params.length;
118
+ const text = `${plan.prefix.text}SELECT ${columns.join(', ')} FROM ${plan.relation}${plan.where.text}${order.text}` +
119
+ ` LIMIT ${style.placeholder(n + 1)} OFFSET ${style.placeholder(n + 2)}`;
120
+ const result = await execute({ text, params: [...plan.params, ...order.params, clampLimit(request.limit), clampOffset(request.offset)] }, request.binary ? { binary: true } : undefined);
121
+ return { ...result, columns: [...names] };
122
+ },
123
+ async count(table, filter, limit) {
124
+ const plan = from(table, snapshotScopedData(filter));
125
+ // One plan either way: a bound wraps the scoped relation, never replaces it.
126
+ return counted({ text: `${plan.prefix.text}${countStatement(`${plan.relation}${plan.where.text}`, limit)}`, params: plan.params });
127
+ },
128
+ /* Several tables' counts, each under its own scope and filter, as one
129
+ statement: the scope's CTEs are defined once, ahead of one bounded
130
+ count per item joined by UNION ALL. Each branch reads the relation
131
+ `count` would, so no item sees a row its own count would not. */
132
+ async countEach(items, limit) {
133
+ const given = snapshotScopedData(items);
134
+ if (!given.length || given.length > COUNT_EACH_MAX)
135
+ throw new Refusal(`One statement counts 1 to ${COUNT_EACH_MAX} things.`);
136
+ const relations = new ScopedRelations(schema, style, scope);
137
+ const planned = given.map((item) => {
138
+ const table = tableFor(item.table);
139
+ const column = (name) => {
140
+ if (!table.columns.some((column) => column.name === name))
141
+ throw new Refusal('Unknown column in scoped read.');
142
+ return style.quote(name);
143
+ };
144
+ return { relation: relations.table(item.table), column, filter: item.filter };
145
+ });
146
+ const prefix = relations.finish();
147
+ const params = [...prefix.params];
148
+ const branches = planned.map(({ relation, column, filter }, i) => {
149
+ const where = buildWhere(filter, style, params.length + 1, column);
150
+ params.push(...where.params);
151
+ const counted = countStatement(`${relation}${where.text}`, limit);
152
+ return counted.replace(/^SELECT COUNT\(\*\) AS n/, `SELECT ${i} AS i, COUNT(*) AS n`);
153
+ });
154
+ const result = await execute({ text: `${prefix.text}${branches.join('\nUNION ALL\n')}`, params });
155
+ return countEachRows(result.rows, given.length);
156
+ },
157
+ async runView(view, offset = 0) {
158
+ const compiled = compileView(schema, snapshotScopedData(view), style, offset, scope);
159
+ const result = await execute(compiled);
160
+ return { ...result, columns: compiled.columns.map((column) => column.name), resolved: compiled.columns, joins: compiled.joins };
161
+ },
162
+ async countView(view, limit) {
163
+ return counted(compileViewCount(schema, snapshotScopedData(view), style, scope, limit));
164
+ },
165
+ async runBreakdown(breakdown, offset = 0) {
166
+ const compiled = compileBreakdown(schema, snapshotScopedData(breakdown), style, offset, scope);
167
+ const result = await execute(compiled);
168
+ return { ...result, columns: compiled.columns.map((column) => column.name), resolved: compiled.columns };
169
+ },
170
+ async countBreakdown(breakdown, limit) {
171
+ return counted(compileBreakdownCount(schema, snapshotScopedData(breakdown), style, scope, limit));
172
+ },
173
+ });
174
+ }