@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,444 @@
1
+ /**
2
+ * What a database adapter has to provide, and — just as importantly — what it
3
+ * is not allowed to decide.
4
+ *
5
+ * An adapter reads a dialect's catalog and runs parameterised reads. It does
6
+ * not build WHERE clauses from user input, does not decide what a row is
7
+ * called, and never returns SQL for something upstream to concatenate. Every
8
+ * value the user supplies reaches the database as a bound parameter, because
9
+ * a browsing tool that interpolates a filter into SQL is a SQL injection
10
+ * vulnerability with a nice front end.
11
+ */
12
+ import { declaredOrder } from '../shared/schema.js';
13
+ import { Refusal } from '../shared/refusal.js';
14
+ import { orderClauseSql } from '../shared/filter.js';
15
+ /* The filter, the limit policy and Refusal live in shared/, where the query
16
+ language and views reach them without depending on the adapters. Adapter
17
+ and server code keep reaching them through this contract. */
18
+ export { ANSI_STYLE, OPS, POSTGRES_STYLE, buildWhere, } from '../shared/filter.js';
19
+ export { DEFAULT_LIMIT, ESTIMATE_ABOVE, MAX_LIMIT, clampLimit, clampOffset, countStatement, countEachStatement, countEachRows, } from '../shared/reads.js';
20
+ /**
21
+ * Whether one scan can answer every item (countEachStatement's `together`):
22
+ * they all read one table, and the catalog says that table holds no more
23
+ * rows than the bound — so reading all of it costs no more than one bounded
24
+ * count would. Unbounded, one scan always beats one per item.
25
+ */
26
+ export function countsTogether(schema, items, limit) {
27
+ if (!items.every((item) => item.table === items[0]?.table))
28
+ return false;
29
+ if (limit === undefined)
30
+ return true;
31
+ const rows = schema?.tables.find((table) => table.id === items[0].table)?.approxRows;
32
+ return typeof rows === 'number' && rows <= limit;
33
+ }
34
+ export { Refusal } from '../shared/refusal.js';
35
+ /**
36
+ * A read's ORDER BY, or nothing: each column by its value, or by its declared
37
+ * vocabulary where the catalog has one over text (shared/schema.ts
38
+ * `declaredOrder`), its values bound from `startIndex`. Every adapter's plain
39
+ * read and a scoped read say it the same way, so a list sorts alike on all
40
+ * three engines.
41
+ */
42
+ export function orderClause(order, table, style, startIndex, quote = (column) => style.quote(column)) {
43
+ return orderClauseSql((order ?? []).map((o) => ({
44
+ expression: quote(o.column),
45
+ direction: o.direction,
46
+ declared: declaredOrder(table?.columns.find((column) => column.name === o.column)),
47
+ })), style, startIndex);
48
+ }
49
+ /* Registered, not a local symbol: a command handler catches the conflict its
50
+ `tx.update` threw and rethrows through the copy of tablewalk it imported,
51
+ which need not be this one (see businessCommandExecution.ts). */
52
+ const conflictBrand = Symbol.for('mistri.writeConflict');
53
+ /** A conditional update matched no row and did not apply its proposed values. */
54
+ export class WriteConflict extends Error {
55
+ [conflictBrand] = true;
56
+ constructor() {
57
+ super('This record changed or was removed since it was read. Reload it and review your changes before applying them again.');
58
+ this.name = 'WriteConflict';
59
+ }
60
+ }
61
+ /** The native class, or a branded twin from another copy of the package. */
62
+ export function isWriteConflict(error) {
63
+ return error instanceof WriteConflict || (error instanceof Error && error[conflictBrand] === true);
64
+ }
65
+ /** A transaction acknowledgement could not establish whether writes landed.
66
+ * Never inherit Refusal or driver constraint codes: callers must not turn a
67
+ * failed rollback of a rejected operation into permission to retry it. */
68
+ export class TransactionOutcomeUnknown extends Error {
69
+ outcome = 'unknown';
70
+ constructor(cause) {
71
+ super('The transaction outcome could not be confirmed. Refresh and reconcile the records before making another change.', { cause });
72
+ this.name = 'TransactionOutcomeUnknown';
73
+ }
74
+ }
75
+ /**
76
+ * Refuse anything that is more than one statement.
77
+ *
78
+ * Not a SQL parser and not trying to be one — it answers exactly one question,
79
+ * "is there a second statement here", and it answers it by scanning for a
80
+ * semicolon that has something after it. Everything that can contain a
81
+ * semicolon harmlessly is skipped: quoted strings and names, line comments,
82
+ * block comments, and Postgres's dollar-quoted bodies, which is how a function
83
+ * definition carries semicolons without being several statements.
84
+ *
85
+ * Each of those is read the way the dialect's own lexer reads it, because a
86
+ * scanner that ends a string or a comment somewhere other than where the
87
+ * database does can hide a real `;`: Postgres nests block comments, honours
88
+ * backslash escapes in an E'…' string, and reads `x$$` as one identifier
89
+ * rather than an opening dollar-quote. It is not the only line: Postgres runs
90
+ * user text on the extended protocol (postgres.ts runSql), which carries one
91
+ * statement, and SQLite's prepare compiles only the first.
92
+ *
93
+ * Stacking is refused rather than truncated. Running the first half of what
94
+ * someone typed and discarding the rest is worse than refusing both: they
95
+ * asked for two things and would be told about neither.
96
+ *
97
+ * Returns null when the text is a single statement, or the reason it is not.
98
+ */
99
+ export function refuseStacked(text, dialect = 'postgres') {
100
+ const postgres = dialect === 'postgres';
101
+ let i = 0;
102
+ const n = text.length;
103
+ /* A quoted run that starts at `i`, read to just past its close. A doubled
104
+ close is an escaped close; a backslash escapes only where the dialect
105
+ says so (Postgres's E'…'). Everywhere else a backslash is a character:
106
+ Postgres (standard-conforming strings, the default since 9.1) and SQLite
107
+ both read `'\'` as a one-character string, and reading it as an escape
108
+ would scan `'\'; drop table x; --'` as one long string. */
109
+ const quoted = (close, backslash) => {
110
+ i += 1;
111
+ while (i < n) {
112
+ if (backslash && text[i] === '\\') {
113
+ i += 2;
114
+ continue;
115
+ }
116
+ if (text[i] === close && text[i + 1] === close) {
117
+ i += 2;
118
+ continue;
119
+ }
120
+ if (text[i] === close) {
121
+ i += 1;
122
+ return;
123
+ }
124
+ i += 1;
125
+ }
126
+ };
127
+ while (i < n) {
128
+ const ch = text[i];
129
+ // Line comment, to end of line.
130
+ if (ch === '-' && text[i + 1] === '-') {
131
+ const nl = text.indexOf('\n', i);
132
+ i = nl < 0 ? n : nl + 1;
133
+ continue;
134
+ }
135
+ // Block comment. Postgres nests them; SQLite ends at the first close.
136
+ if (ch === '/' && text[i + 1] === '*') {
137
+ let depth = 1;
138
+ i += 2;
139
+ while (i < n && depth) {
140
+ if (postgres && text[i] === '/' && text[i + 1] === '*') {
141
+ depth += 1;
142
+ i += 2;
143
+ }
144
+ else if (text[i] === '*' && text[i + 1] === '/') {
145
+ depth -= 1;
146
+ i += 2;
147
+ }
148
+ else
149
+ i += 1;
150
+ }
151
+ continue;
152
+ }
153
+ /* A name or keyword, read whole: `$` continues one in both dialects, so
154
+ the `$$` of `x$$` belongs to the name and opens nothing. */
155
+ IDENTIFIER.lastIndex = i;
156
+ const word = IDENTIFIER.exec(text)?.[0];
157
+ if (word) {
158
+ i += word.length;
159
+ if (postgres && (word === 'E' || word === 'e') && text[i] === "'") {
160
+ quoted("'", true);
161
+ /* A string continued on the next line is still an E'…' string. */
162
+ for (let more = CONTINUED.exec(text.slice(i)); more; more = CONTINUED.exec(text.slice(i))) {
163
+ i += more[0].length - 1;
164
+ quoted("'", true);
165
+ }
166
+ }
167
+ continue;
168
+ }
169
+ /* A number, read whole, so `1x$$` is the number and the name `x$$`. A
170
+ number directly before `$$` leaves the `$` to open a quote, as the
171
+ Postgres releases that still allow trailing junk read it. */
172
+ NUMBER.lastIndex = i;
173
+ const number = NUMBER.exec(text)?.[0];
174
+ if (number) {
175
+ i += number.length;
176
+ continue;
177
+ }
178
+ // Dollar-quoted body: $$…$$ or $tag$…$tag$. Postgres only.
179
+ if (ch === '$' && postgres) {
180
+ const tag = /^\$[A-Za-z_]\w*\$|^\$\$/.exec(text.slice(i))?.[0];
181
+ if (tag) {
182
+ const end = text.indexOf(tag, i + tag.length);
183
+ i = end < 0 ? n : end + tag.length;
184
+ continue;
185
+ }
186
+ }
187
+ // A backquote quotes a name in SQLite and is an operator character in Postgres.
188
+ if (ch === "'" || ch === '"' || (ch === '`' && !postgres)) {
189
+ quoted(ch, false);
190
+ continue;
191
+ }
192
+ if (ch === '[' && !postgres) {
193
+ quoted(']', false);
194
+ continue;
195
+ }
196
+ if (ch === ';') {
197
+ // A trailing semicolon is punctuation, not a second statement.
198
+ if (text.slice(i + 1).trim() === '')
199
+ return null;
200
+ return 'One statement at a time. Remove the semicolon and everything after it, or run them separately.';
201
+ }
202
+ i += 1;
203
+ }
204
+ return null;
205
+ }
206
+ /* An identifier as both dialects lex one: a letter, underscore or non-ASCII
207
+ character, then any of those, digits or `$`. */
208
+ const IDENTIFIER = /[A-Za-z_\u0080-\uffff][\w$\u0080-\uffff]*/y;
209
+ const NUMBER = /\d+(?:\.\d*)?(?:[eE][+-]?\d+)?/y;
210
+ /* Postgres's quote continuation: a newline (and any further space or line
211
+ comments) between two quoted runs joins them into one string. */
212
+ const CONTINUED = /^[ \t\f]*[\n\r](?:[ \t\n\r\f\v]|--[^\n\r]*[\n\r])*'/;
213
+ /**
214
+ * Output column names, with collisions given a suffix.
215
+ *
216
+ * `SELECT id, id FROM t` names both columns `id`. Left alone, the grid draws
217
+ * one header twice and nothing says which value belongs to which. The suffix
218
+ * is the same answer `compileView` gives an explicit collision, for the same
219
+ * reason: one column quietly standing in for two is worse than an ugly name.
220
+ */
221
+ export function dedupe(names) {
222
+ const seen = new Map();
223
+ return names.map((name) => {
224
+ const count = seen.get(name) ?? 0;
225
+ seen.set(name, count + 1);
226
+ return count ? `${name}_${count + 1}` : name;
227
+ });
228
+ }
229
+ /** A statement with its trailing semicolon and surrounding space removed. */
230
+ export function trimStatement(text) {
231
+ /* The whitespace *before* the semicolon goes too. `select 1 ;` left a
232
+ trailing space, which is invisible in the editor and shows up in the
233
+ reported statement as a difference between what ran and what was typed. */
234
+ return text.trim().replace(/\s*;+\s*$/, '');
235
+ }
236
+ /**
237
+ * Wrap a statement so it cannot return more rows than asked for.
238
+ *
239
+ * `clampLimit` is the invariant everywhere else in this file, and it has no
240
+ * application point in a statement this process did not build — there is no
241
+ * request object to clamp. Wrapping is the equivalent: the database is asked
242
+ * for a bounded result rather than trusted to have been asked politely.
243
+ *
244
+ * One more row than the caller wanted, so "there is more than this" is known
245
+ * without a second query — the same trick `runView` uses.
246
+ *
247
+ * The limit is interpolated rather than bound, which is the one deliberate
248
+ * exception to the rule that nothing is interpolated. It is an integer this
249
+ * process computed from `clampLimit`, never a value that came from outside,
250
+ * and it is asserted to be one before it is used. Binding it would need a
251
+ * dialect-specific placeholder here, which is a lot of machinery to parameterise a number we
252
+ * chose ourselves.
253
+ *
254
+ * Not every statement can be wrapped — `EXPLAIN`, `PRAGMA`, a `WITH` that ends
255
+ * in `INSERT … RETURNING` — so the caller is told whether it applied and can
256
+ * fall back to running the statement bare and saying so.
257
+ */
258
+ export function boundStatement(text, limit) {
259
+ if (!Number.isSafeInteger(limit) || limit < 1) {
260
+ throw new Error(`A row limit must be a positive integer, not ${String(limit)}.`);
261
+ }
262
+ /* The inner statement sits on its own line. A trailing line comment —
263
+ `select * from huge -- note` — would otherwise swallow the closing
264
+ parenthesis and the LIMIT with it, the wrap would fail to parse, and the
265
+ fallback ran the statement *unbounded* and materialised every row before
266
+ slicing. A newline ends the comment; the wrapper survives. */
267
+ return `SELECT * FROM (\n${trimStatement(text)}\n) AS mistri_bounded LIMIT ${limit + 1}`;
268
+ }
269
+ /**
270
+ * Refuse a statement that `EXPLAIN` would *execute* rather than plan.
271
+ *
272
+ * `EXPLAIN` is offered as the planner's account of a statement without
273
+ * running it. `EXPLAIN ANALYZE …` (Postgres) and the option
274
+ * form `EXPLAIN (ANALYZE) …` run the statement to measure it, so text that
275
+ * begins with `analyze` or `(` turned a plan-only tool into an execute tool.
276
+ * Both sit inside a read-only transaction, so no row could be written — but
277
+ * a `pg_sleep(60)` or a full scan runs all the same, and the contract said
278
+ * it would not. Leading comments are skipped so the check reads the
279
+ * statement, not a note above it.
280
+ */
281
+ export function refuseAnalyze(text) {
282
+ const first = trimStatement(text).replace(/^\s*(?:--[^\n]*\n|\/\*[\s\S]*?\*\/|\s)+/g, '');
283
+ if (/^(?:\(|analy[sz]e\b|explain\b)/i.test(first)) {
284
+ return 'explain plans a statement without running it: give it the statement itself, not ' + 'an EXPLAIN, ANALYZE or (option) form.';
285
+ }
286
+ return null;
287
+ }
288
+ /**
289
+ * Whether a statement is worth trying to wrap.
290
+ *
291
+ * A conservative first token test, and deliberately not a parse. Getting this
292
+ * wrong in the cautious direction costs a bounded result; getting it wrong in
293
+ * the other direction costs a confusing syntax error from the database about a
294
+ * statement the user did not write. `WITH` is included because a CTE ending in
295
+ * a SELECT is the common case, and the wrap failing on one that does not is
296
+ * handled by the fallback rather than by being clever here.
297
+ */
298
+ export function looksWrappable(text) {
299
+ const first = trimStatement(text).replace(/^\s*(?:--[^\n]*\n|\/\*[\s\S]*?\*\/|\s)+/g, '');
300
+ /* `(select …) union (select …)` is a SELECT too, and unwrapped it ran unbounded. */
301
+ return /^(?:\(|(?:select|with|table|values)\b)/i.test(first);
302
+ }
303
+ /**
304
+ * A queue of one.
305
+ *
306
+ * Every adapter here writes through a single connection, and a transaction is
307
+ * a span of statements on it that nothing else may enter. Node is
308
+ * single-threaded but `await` is not: two requests arriving together interleave
309
+ * at every await point, so a plain `/api/update` can land in the middle of
310
+ * somebody's open transaction and be rolled back with it — a write that
311
+ * succeeded, reported success, and then quietly did not happen.
312
+ *
313
+ * So writes queue. The cost is that two concurrent edits are applied one after
314
+ * the other rather than at once, which is what a single connection was always
315
+ * going to do anyway.
316
+ */
317
+ export class Serial {
318
+ tail = Promise.resolve();
319
+ run(work) {
320
+ /* The chain must not break on a failure: `catch` here keeps the *queue*
321
+ going while the caller still gets the rejection from `next`. */
322
+ const next = this.tail.then(work, work);
323
+ this.tail = next.catch(() => { });
324
+ return next;
325
+ }
326
+ }
327
+ /**
328
+ * Drain accepted operations before commit/rollback, then refuse escaped handles.
329
+ *
330
+ * Each operation starts once every operation asked before it has settled
331
+ * (`run`), so a handler's statements reach the database in the order it asked
332
+ * them. Reads asked together — a handler's `Promise.all` — waited on each
333
+ * other all the same, a round trip each, though nothing in one could change
334
+ * what another reads. On a transaction told its writer sends together
335
+ * (`together`, a pipelining PostgreSQL writer), a read (`read`) starts beside
336
+ * the reads still in flight, in the order asked, so they leave in one flight;
337
+ * it still waits for every write asked before it, and every write waits for
338
+ * every read before it. Only operations in flight together overlap: one
339
+ * awaited before the next is asked is answered before the next starts.
340
+ *
341
+ * What a caller hears is unchanged. Each operation settles in the order asked,
342
+ * after the ones before it, and the first failure in that order is every later
343
+ * operation's failure, whether the later one had started or not — a read that
344
+ * ran beside a failed one is answered with that failure, never its own rows —
345
+ * and finish() rethrows it. Elsewhere `read` is `run`.
346
+ */
347
+ export class TransactionOperations {
348
+ together;
349
+ active = true;
350
+ failure;
351
+ /** Settles once every operation asked so far has: where the next write starts, and where each one settles. */
352
+ settled = Promise.resolve();
353
+ /** Settles once the last operation that was not a read has: where a read starts, beside the reads after it. */
354
+ written = Promise.resolve();
355
+ constructor(together = false) {
356
+ this.together = together;
357
+ }
358
+ run(work) {
359
+ return this.enqueue(work, false);
360
+ }
361
+ /** A read: it changes nothing another operation reads, so on a transaction that sends together it starts beside reads in flight. */
362
+ read(work) {
363
+ return this.enqueue(work, this.together);
364
+ }
365
+ enqueue(work, beside) {
366
+ if (!this.active)
367
+ return Promise.reject(new Refusal('This transaction is no longer active.'));
368
+ const before = this.settled;
369
+ const ran = (beside ? this.written : before).then(() => {
370
+ // Some engine errors roll back the transaction themselves. Running a
371
+ // later queued write (including a receipt) could then autocommit it.
372
+ if (this.failure)
373
+ throw this.failure.error;
374
+ return work();
375
+ });
376
+ // Settled in the order asked: a failure before this one is this one's, and this one's is recorded only in its turn.
377
+ const result = ran.then((value) => before.then(() => {
378
+ if (this.failure)
379
+ throw this.failure.error;
380
+ return value;
381
+ }), (error) => before.then(() => {
382
+ if (this.failure)
383
+ throw this.failure.error;
384
+ this.failure = { error };
385
+ throw error;
386
+ }));
387
+ this.settled = result.catch(() => { });
388
+ if (!beside)
389
+ this.written = this.settled;
390
+ // Fire-and-forget failures are still observed and rethrown by finish().
391
+ void result.catch(() => { });
392
+ return result;
393
+ }
394
+ async finish() {
395
+ this.active = false;
396
+ await this.settled;
397
+ if (this.failure)
398
+ throw this.failure.error;
399
+ }
400
+ }
401
+ /** Capture before queue waits, including failures: a caught malformed lock must
402
+ * still poison the owning transaction just like a failed database operation. */
403
+ export function queueRecordLock(operations, input, work) {
404
+ let request;
405
+ let invalid;
406
+ try {
407
+ const data = (value) => {
408
+ if (!value || typeof value !== 'object' || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value)))
409
+ throw new Refusal('Malformed record lock request.');
410
+ const entries = Reflect.ownKeys(value).map((key) => {
411
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
412
+ if (typeof key !== 'string' || !descriptor.enumerable || !('value' in descriptor))
413
+ throw new Refusal('Malformed record lock request.');
414
+ return [key, descriptor.value];
415
+ });
416
+ return Object.fromEntries(entries);
417
+ };
418
+ const root = data(input);
419
+ if (typeof root.table !== 'string' || !root.table.length)
420
+ throw new Refusal('Malformed record lock table.');
421
+ const key = data(root.key);
422
+ if (!Object.keys(key).length ||
423
+ Object.values(key).some((value) => typeof value !== 'string' && !(typeof value === 'number' && Number.isFinite(value))))
424
+ throw new Refusal('Malformed record lock key.');
425
+ request = { table: root.table, key: key };
426
+ }
427
+ catch (error) {
428
+ invalid = { error };
429
+ }
430
+ return operations.run(() => {
431
+ if (invalid)
432
+ throw invalid.error;
433
+ return work(request);
434
+ });
435
+ }
436
+ /** Catalog-attested complete key only; callers supply the writer's metadata. */
437
+ export function recordLockFilter(request, primary) {
438
+ if (!primary.length)
439
+ throw new Refusal(`${request.table} has no primary key, so no single row can be identified.`);
440
+ if (Object.keys(request.key).length !== primary.length || primary.some((column) => !Object.hasOwn(request.key, column))) {
441
+ throw new Refusal(`Locking ${request.table} needs exactly its primary key (${primary.join(', ')}).`);
442
+ }
443
+ return { groups: [primary.map((column) => ({ column, op: '=', value: request.key[column] }))] };
444
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Somewhere to keep a value for a while: in this process by default, in a
3
+ * Valkey cache when the config names one, so every instance of a deployment
4
+ * shares it.
5
+ *
6
+ * Never a source of truth. Everything here is a copy or a count that is
7
+ * allowed to vanish — a cached API answer, a rate-limit window — so every
8
+ * write carries a time to live (there is no "forever"), a read that cannot
9
+ * reach the cache is a miss, and a write that cannot is dropped. The one
10
+ * caller that must know the difference, the rate limiter, is told through
11
+ * `incr`, which throws `CacheUnavailable` rather than inventing a count.
12
+ */
13
+ import { type RespClient } from './resp.js';
14
+ export { CacheUnavailable } from './resp.js';
15
+ export interface CacheStore {
16
+ readonly kind: 'memory' | 'valkey';
17
+ get(key: string): Promise<string | undefined>;
18
+ set(key: string, value: string, ttlMs: number): Promise<void>;
19
+ delete(key: string): Promise<void>;
20
+ /**
21
+ * Count one under `key`. A new key starts a window of `ttlMs`; the answer is
22
+ * the count within it and the milliseconds it has left. Throws
23
+ * CacheUnavailable when the count cannot be kept.
24
+ */
25
+ incr(key: string, ttlMs: number): Promise<{
26
+ count: number;
27
+ ttlMs: number;
28
+ }>;
29
+ close(): Promise<void>;
30
+ }
31
+ /**
32
+ * The process's own cache: a Map in least-recently-used order, bounded, so a
33
+ * stream of distinct keys (an API's pages, a flood of client addresses) cannot
34
+ * grow it without end. Expiry is read, not scheduled: no timers to clean up.
35
+ */
36
+ export declare class MemoryCacheStore implements CacheStore {
37
+ private readonly maxEntries;
38
+ private readonly now;
39
+ readonly kind: 'memory';
40
+ private readonly entries;
41
+ constructor(maxEntries?: number, now?: () => number);
42
+ get(key: string): Promise<string | undefined>;
43
+ set(key: string, value: string, ttlMs: number): Promise<void>;
44
+ delete(key: string): Promise<void>;
45
+ incr(key: string, ttlMs: number): Promise<{
46
+ count: number;
47
+ ttlMs: number;
48
+ }>;
49
+ close(): Promise<void>;
50
+ /** How many entries are held; tests read it. */
51
+ get size(): number;
52
+ private live;
53
+ private trim;
54
+ }
55
+ /**
56
+ * A Valkey cache shared by every instance. `onUnavailable` hears each
57
+ * outage's reason — the server logs it once — while reads carry on as misses.
58
+ */
59
+ export declare class ValkeyCacheStore implements CacheStore {
60
+ private readonly client;
61
+ private readonly onUnavailable;
62
+ readonly kind: 'valkey';
63
+ constructor(client: RespClient, onUnavailable?: (message: string) => void);
64
+ get(key: string): Promise<string | undefined>;
65
+ set(key: string, value: string, ttlMs: number): Promise<void>;
66
+ delete(key: string): Promise<void>;
67
+ incr(key: string, ttlMs: number): Promise<{
68
+ count: number;
69
+ ttlMs: number;
70
+ }>;
71
+ close(): Promise<void>;
72
+ private unavailable;
73
+ }
74
+ /** The same store under a key prefix: `tw:<app>:http:<connection>:`, say. */
75
+ export declare function scopedCache(store: CacheStore, prefix: string): CacheStore;
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Somewhere to keep a value for a while: in this process by default, in a
3
+ * Valkey cache when the config names one, so every instance of a deployment
4
+ * shares it.
5
+ *
6
+ * Never a source of truth. Everything here is a copy or a count that is
7
+ * allowed to vanish — a cached API answer, a rate-limit window — so every
8
+ * write carries a time to live (there is no "forever"), a read that cannot
9
+ * reach the cache is a miss, and a write that cannot is dropped. The one
10
+ * caller that must know the difference, the rate limiter, is told through
11
+ * `incr`, which throws `CacheUnavailable` rather than inventing a count.
12
+ */
13
+ import { CacheUnavailable, RespReplyError } from './resp.js';
14
+ export { CacheUnavailable } from './resp.js';
15
+ /* Thirty days: a copy kept longer than that is a copy nobody meant to keep. */
16
+ const MAX_TTL_MS = 30 * 24 * 3_600_000;
17
+ function assertTtl(ttlMs) {
18
+ if (!Number.isSafeInteger(ttlMs) || ttlMs < 1 || ttlMs > MAX_TTL_MS) {
19
+ throw new Error(`A cached value needs a time to live between 1 ms and 30 days; ${ttlMs} is not one.`);
20
+ }
21
+ }
22
+ /**
23
+ * The process's own cache: a Map in least-recently-used order, bounded, so a
24
+ * stream of distinct keys (an API's pages, a flood of client addresses) cannot
25
+ * grow it without end. Expiry is read, not scheduled: no timers to clean up.
26
+ */
27
+ export class MemoryCacheStore {
28
+ maxEntries;
29
+ now;
30
+ kind = 'memory';
31
+ entries = new Map();
32
+ constructor(maxEntries = 10_000, now = Date.now) {
33
+ this.maxEntries = maxEntries;
34
+ this.now = now;
35
+ }
36
+ async get(key) {
37
+ const entry = this.live(key);
38
+ if (!entry)
39
+ return undefined;
40
+ this.entries.delete(key);
41
+ this.entries.set(key, entry);
42
+ return entry.value;
43
+ }
44
+ async set(key, value, ttlMs) {
45
+ assertTtl(ttlMs);
46
+ this.entries.delete(key);
47
+ this.entries.set(key, { value, expires: this.now() + ttlMs });
48
+ this.trim();
49
+ }
50
+ async delete(key) {
51
+ this.entries.delete(key);
52
+ }
53
+ async incr(key, ttlMs) {
54
+ assertTtl(ttlMs);
55
+ const entry = this.live(key);
56
+ const now = this.now();
57
+ const next = entry ? { value: String(Number(entry.value) + 1), expires: entry.expires } : { value: '1', expires: now + ttlMs };
58
+ this.entries.delete(key);
59
+ this.entries.set(key, next);
60
+ this.trim();
61
+ return { count: Number(next.value), ttlMs: next.expires - now };
62
+ }
63
+ async close() {
64
+ this.entries.clear();
65
+ }
66
+ /** How many entries are held; tests read it. */
67
+ get size() {
68
+ return this.entries.size;
69
+ }
70
+ live(key) {
71
+ const entry = this.entries.get(key);
72
+ if (entry && entry.expires <= this.now()) {
73
+ this.entries.delete(key);
74
+ return undefined;
75
+ }
76
+ return entry;
77
+ }
78
+ trim() {
79
+ while (this.entries.size > this.maxEntries)
80
+ this.entries.delete(this.entries.keys().next().value);
81
+ }
82
+ }
83
+ /* One round trip, and atomic: a window that is counted is a window that
84
+ expires, even if this process stops between the two steps. */
85
+ const COUNT_IN_WINDOW = `local n = redis.call('INCR', KEYS[1])
86
+ if n == 1 then redis.call('PEXPIRE', KEYS[1], ARGV[1]) end
87
+ local t = redis.call('PTTL', KEYS[1])
88
+ if t < 0 then redis.call('PEXPIRE', KEYS[1], ARGV[1]) t = tonumber(ARGV[1]) end
89
+ return {n, t}`;
90
+ /**
91
+ * A Valkey cache shared by every instance. `onUnavailable` hears each
92
+ * outage's reason — the server logs it once — while reads carry on as misses.
93
+ */
94
+ export class ValkeyCacheStore {
95
+ client;
96
+ onUnavailable;
97
+ kind = 'valkey';
98
+ constructor(client, onUnavailable = () => { }) {
99
+ this.client = client;
100
+ this.onUnavailable = onUnavailable;
101
+ }
102
+ async get(key) {
103
+ try {
104
+ const value = await this.client.command('GET', key);
105
+ return typeof value === 'string' ? value : undefined;
106
+ }
107
+ catch (error) {
108
+ this.unavailable(error);
109
+ return undefined;
110
+ }
111
+ }
112
+ async set(key, value, ttlMs) {
113
+ assertTtl(ttlMs);
114
+ try {
115
+ await this.client.command('SET', key, value, 'PX', ttlMs);
116
+ }
117
+ catch (error) {
118
+ this.unavailable(error);
119
+ }
120
+ }
121
+ async delete(key) {
122
+ try {
123
+ await this.client.command('DEL', key);
124
+ }
125
+ catch (error) {
126
+ this.unavailable(error);
127
+ }
128
+ }
129
+ async incr(key, ttlMs) {
130
+ assertTtl(ttlMs);
131
+ let reply;
132
+ try {
133
+ reply = await this.client.command('EVAL', COUNT_IN_WINDOW, 1, key, ttlMs);
134
+ }
135
+ catch (error) {
136
+ this.unavailable(error);
137
+ throw error instanceof CacheUnavailable ? error : new CacheUnavailable('the cache refused a count.');
138
+ }
139
+ if (!Array.isArray(reply) || typeof reply[0] !== 'number' || typeof reply[1] !== 'number')
140
+ throw new CacheUnavailable('the cache answered a count in an unexpected shape.');
141
+ return { count: reply[0], ttlMs: reply[1] };
142
+ }
143
+ async close() {
144
+ await this.client.close();
145
+ }
146
+ unavailable(error) {
147
+ this.onUnavailable(error instanceof CacheUnavailable || error instanceof RespReplyError ? error.message : 'the cache failed.');
148
+ }
149
+ }
150
+ /** The same store under a key prefix: `tw:<app>:http:<connection>:`, say. */
151
+ export function scopedCache(store, prefix) {
152
+ return {
153
+ kind: store.kind,
154
+ get: (key) => store.get(prefix + key),
155
+ set: (key, value, ttlMs) => store.set(prefix + key, value, ttlMs),
156
+ delete: (key) => store.delete(prefix + key),
157
+ incr: (key, ttlMs) => store.incr(prefix + key, ttlMs),
158
+ close: () => store.close(),
159
+ };
160
+ }