@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,70 @@
1
+ /** How long a person's reads stay on the primary after they write: well past a healthy replica's lag. */
2
+ export declare const FRESH_READ_MS = 10000;
3
+ /** How long a replica that failed is passed over before it is tried again. */
4
+ export declare const REPLICA_BACKOFF_MS = 30000;
5
+ /** The most replicas one connection may name. Past this, a pooler or a load balancer is the tool. */
6
+ export declare const MAX_REPLICAS = 8;
7
+ /**
8
+ * Who the current work is for, as far as read-your-write cares. Set by the
9
+ * HTTP layer for the whole request, so a write anywhere in it and a read
10
+ * anywhere after it agree.
11
+ */
12
+ export interface ReadContext {
13
+ /** The request arrived with a fresh write marker, or wrote since: its reads stay on the primary. */
14
+ fresh: boolean;
15
+ /** A caller with no cookie jar (a bearer token): its writes are remembered here, in this process, under this key. */
16
+ readonly key?: string;
17
+ /** Called on the request's first write: the HTTP layer sets the marker the browser carries back. */
18
+ readonly onWrite?: () => void;
19
+ }
20
+ /** Run `work` for `context`: its writes keep its later reads on the primary. */
21
+ export declare function readsAs<T>(context: ReadContext, work: () => T): T;
22
+ /** Run `work` with its reads allowed on a replica, unless something around it pinned the primary. */
23
+ export declare function lagTolerantReads<T>(work: () => T): T;
24
+ /** Run `work` with every read on the primary, whatever runs inside it. */
25
+ export declare function primaryReads<T>(work: () => T): T;
26
+ /** A write began for the current caller: its reads go to the primary for FRESH_READ_MS. Background work is nobody's. */
27
+ export declare function noteWrite(now?: number): void;
28
+ /** Whether a read starting now may go to a replica. */
29
+ export declare function replicaReadWanted(now?: number): boolean;
30
+ /** A replica read that must go to the primary instead, for a reason the replica's own error does not say. */
31
+ export declare class ReplicaUnavailable extends Error {
32
+ readonly failure: 'down' | 'retry';
33
+ constructor(failure: 'down' | 'retry', message: string, options?: {
34
+ cause?: unknown;
35
+ });
36
+ }
37
+ /**
38
+ * Why a replica's read failed, as far as routing cares:
39
+ * `down` — it could not be reached or lost its connection: pass it over and use the primary;
40
+ * `retry` — this read cannot be answered there now (its pool is full, it lags behind a
41
+ * migration, recovery cancelled it): use the primary, keep the replica;
42
+ * undefined — the primary would refuse it too, so the error is the answer.
43
+ */
44
+ export declare function replicaFailure(error: unknown): 'down' | 'retry' | undefined;
45
+ /** One connection's replicas, taken in turn, each passed over for a while after it fails. */
46
+ export declare class ReplicaSet<Pool> {
47
+ readonly pools: readonly Pool[];
48
+ private readonly now;
49
+ private next;
50
+ private readonly downUntil;
51
+ /** Reads answered by each replica, and reads that fell back to the primary from it. */
52
+ readonly served: number[];
53
+ readonly fellBack: number[];
54
+ constructor(pools: readonly Pool[], now?: () => number);
55
+ /** The next replica that is not being passed over, or undefined when every one is. */
56
+ pick(): {
57
+ index: number;
58
+ pool: Pool;
59
+ } | undefined;
60
+ /** Pass replica `index` over for REPLICA_BACKOFF_MS. */
61
+ down(index: number): void;
62
+ /** Whether replica `index` is in use now (not being passed over). */
63
+ healthy(index: number): boolean;
64
+ /**
65
+ * Run one read: on a replica when the work wants one and one is in turn,
66
+ * else on the primary. A replica that cannot answer hands the read to the
67
+ * primary (replicaFailure); any other failure is the read's own.
68
+ */
69
+ read<T>(onReplica: (pool: Pool) => Promise<T>, onPrimary: () => Promise<T>): Promise<T>;
70
+ }
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Read replicas: which database a read goes to.
3
+ *
4
+ * A connection may name replicas (`"replicas": [url, …]` in its config). A
5
+ * read goes to one only when three things hold, and to the primary otherwise:
6
+ *
7
+ * - The work it runs in said it tolerates lag (`lagTolerantReads`): a list,
8
+ * a dashboard's breakdowns, a count, an export, the Workbench grid. The
9
+ * HTTP layer says so per route (packages/engine/src/server/http/readRouting.ts). Nothing
10
+ * else does, so a read nobody classified — a record page, a command, the
11
+ * catalog, a store — stays on the primary by default.
12
+ * - No enclosing work pinned the primary (`primaryReads`): a write's own
13
+ * reads, a record page composed from list reads, the catalog. A pin is not
14
+ * undone by a lag-tolerant route nested inside it.
15
+ * - Whoever is asking has not written in the last FRESH_READ_MS. A write
16
+ * sends that browser's reads to the primary for that long, so the list it
17
+ * returns to after a save shows the save. The marker travels with the
18
+ * browser, not the process (a short-lived cookie, readRouting.ts), so it
19
+ * holds across pods and two anonymous visitors never share one. A client
20
+ * without cookies — a bearer-token API or MCP caller — is keyed by its
21
+ * token in this process instead: per pod, which is a replica's lag and
22
+ * nothing worse.
23
+ *
24
+ * Replicas take turns. One that fails to connect, or loses its connection,
25
+ * is passed over for REPLICA_BACKOFF_MS and the read runs again on the
26
+ * primary; a read the primary would refuse as well (a bad filter, a
27
+ * cancel) is not run twice. Replica sessions are read-only the way the
28
+ * primary's readers are (postgresPool.ts), so a write that
29
+ * reached one by mistake would be refused by the server.
30
+ */
31
+ import { AsyncLocalStorage } from 'node:async_hooks';
32
+ import { currentSpan } from './telemetry/trace.js';
33
+ import { isPoolBusy } from './poolMetrics.js';
34
+ import { StatementStopped } from './statementControl.js';
35
+ import { inBackgroundWork } from './writeLanes.js';
36
+ /** How long a person's reads stay on the primary after they write: well past a healthy replica's lag. */
37
+ export const FRESH_READ_MS = 10_000;
38
+ /** How long a replica that failed is passed over before it is tried again. */
39
+ export const REPLICA_BACKOFF_MS = 30_000;
40
+ /** The most replicas one connection may name. Past this, a pooler or a load balancer is the tool. */
41
+ export const MAX_REPLICAS = 8;
42
+ const preference = new AsyncLocalStorage();
43
+ const reader = new AsyncLocalStorage();
44
+ /** Run `work` for `context`: its writes keep its later reads on the primary. */
45
+ export function readsAs(context, work) {
46
+ return reader.run(context, work);
47
+ }
48
+ /** Run `work` with its reads allowed on a replica, unless something around it pinned the primary. */
49
+ export function lagTolerantReads(work) {
50
+ return preference.getStore() === 'primary' ? work() : preference.run('replica', work);
51
+ }
52
+ /** Run `work` with every read on the primary, whatever runs inside it. */
53
+ export function primaryReads(work) {
54
+ return preference.getStore() === 'primary' ? work() : preference.run('primary', work);
55
+ }
56
+ /* Whether any connection in this process has replicas. Until one does, a
57
+ write sets no marker: a deployment without replicas sends no cookie. */
58
+ let replicasConfigured = false;
59
+ /* Last write per keyed caller, in this process. Pruned as it grows, so many
60
+ tokens cannot grow it without bound. */
61
+ const wrote = new Map();
62
+ const PRUNE_AT = 4_096;
63
+ /** A write began for the current caller: its reads go to the primary for FRESH_READ_MS. Background work is nobody's. */
64
+ export function noteWrite(now = Date.now()) {
65
+ if (!replicasConfigured || inBackgroundWork())
66
+ return;
67
+ const context = reader.getStore();
68
+ if (!context)
69
+ return;
70
+ if (!context.fresh) {
71
+ context.fresh = true;
72
+ context.onWrite?.();
73
+ }
74
+ if (context.key === undefined)
75
+ return;
76
+ wrote.delete(context.key);
77
+ wrote.set(context.key, now);
78
+ if (wrote.size > PRUNE_AT) {
79
+ for (const [key, at] of wrote) {
80
+ if (now - at < FRESH_READ_MS)
81
+ break;
82
+ wrote.delete(key);
83
+ }
84
+ }
85
+ }
86
+ /** Whether a read starting now may go to a replica. */
87
+ export function replicaReadWanted(now = Date.now()) {
88
+ if (preference.getStore() !== 'replica')
89
+ return false;
90
+ const context = reader.getStore();
91
+ if (context?.fresh)
92
+ return false;
93
+ const at = context?.key === undefined ? undefined : wrote.get(context.key);
94
+ return at === undefined || now - at >= FRESH_READ_MS;
95
+ }
96
+ /** A replica read that must go to the primary instead, for a reason the replica's own error does not say. */
97
+ export class ReplicaUnavailable extends Error {
98
+ failure;
99
+ constructor(failure, message, options) {
100
+ super(message, options);
101
+ this.failure = failure;
102
+ this.name = 'ReplicaUnavailable';
103
+ }
104
+ }
105
+ /**
106
+ * Why a replica's read failed, as far as routing cares:
107
+ * `down` — it could not be reached or lost its connection: pass it over and use the primary;
108
+ * `retry` — this read cannot be answered there now (its pool is full, it lags behind a
109
+ * migration, recovery cancelled it): use the primary, keep the replica;
110
+ * undefined — the primary would refuse it too, so the error is the answer.
111
+ */
112
+ export function replicaFailure(error) {
113
+ if (error instanceof ReplicaUnavailable)
114
+ return error.failure;
115
+ if (error instanceof StatementStopped)
116
+ return undefined;
117
+ if (isPoolBusy(error))
118
+ return 'retry';
119
+ const e = (error ?? {});
120
+ const code = typeof e.code === 'string' ? e.code : '';
121
+ const message = typeof e.message === 'string' ? e.message : '';
122
+ if (NETWORK.has(code) || e.fatal === true)
123
+ return 'down';
124
+ /* PostgreSQL: connection exceptions (08), the server going away (57P01–03),
125
+ no room (53300), credentials (28) and a database missing (3D000) are the
126
+ replica's state, not the read's. */
127
+ if (/^(08|28)[0-9A-Z]{3}$/.test(code) || ['57P01', '57P02', '57P03', '53300', '3D000'].includes(code))
128
+ return 'down';
129
+ /* A standby cancels a read that conflicts with replay; a relation or column
130
+ missing on the replica is a migration that has not reached it yet. */
131
+ if (code === '40001' && /recovery/i.test(message))
132
+ return 'retry';
133
+ if (code === '42P01' || code === '42703')
134
+ return 'retry';
135
+ if (/Connection terminated|timeout exceeded when trying to connect|connect ECONNREFUSED/i.test(message))
136
+ return 'down';
137
+ return undefined;
138
+ }
139
+ const NETWORK = new Set(['ECONNREFUSED', 'ECONNRESET', 'ETIMEDOUT', 'ENOTFOUND', 'EHOSTUNREACH', 'ENETUNREACH', 'EPIPE', 'EAI_AGAIN']);
140
+ /** One connection's replicas, taken in turn, each passed over for a while after it fails. */
141
+ export class ReplicaSet {
142
+ pools;
143
+ now;
144
+ next = 0;
145
+ downUntil;
146
+ /** Reads answered by each replica, and reads that fell back to the primary from it. */
147
+ served;
148
+ fellBack;
149
+ constructor(pools, now = () => Date.now()) {
150
+ this.pools = pools;
151
+ this.now = now;
152
+ if (pools.length > 0)
153
+ replicasConfigured = true;
154
+ this.downUntil = pools.map(() => 0);
155
+ this.served = pools.map(() => 0);
156
+ this.fellBack = pools.map(() => 0);
157
+ }
158
+ /** The next replica that is not being passed over, or undefined when every one is. */
159
+ pick() {
160
+ const at = this.now();
161
+ for (let tried = 0; tried < this.pools.length; tried++) {
162
+ const index = (this.next + tried) % this.pools.length;
163
+ if (this.downUntil[index] <= at) {
164
+ this.next = (index + 1) % this.pools.length;
165
+ return { index, pool: this.pools[index] };
166
+ }
167
+ }
168
+ return undefined;
169
+ }
170
+ /** Pass replica `index` over for REPLICA_BACKOFF_MS. */
171
+ down(index) {
172
+ this.downUntil[index] = this.now() + REPLICA_BACKOFF_MS;
173
+ }
174
+ /** Whether replica `index` is in use now (not being passed over). */
175
+ healthy(index) {
176
+ return this.downUntil[index] <= this.now();
177
+ }
178
+ /**
179
+ * Run one read: on a replica when the work wants one and one is in turn,
180
+ * else on the primary. A replica that cannot answer hands the read to the
181
+ * primary (replicaFailure); any other failure is the read's own.
182
+ */
183
+ async read(onReplica, onPrimary) {
184
+ const chosen = replicaReadWanted() ? this.pick() : undefined;
185
+ const span = currentSpan();
186
+ if (!chosen) {
187
+ span?.setAttribute('mistri.read.pool', 'primary');
188
+ return onPrimary();
189
+ }
190
+ try {
191
+ const out = await onReplica(chosen.pool);
192
+ this.served[chosen.index] += 1;
193
+ span?.setAttribute('mistri.read.pool', 'replica');
194
+ return out;
195
+ }
196
+ catch (error) {
197
+ const failure = replicaFailure(error);
198
+ if (!failure)
199
+ throw error;
200
+ if (failure === 'down')
201
+ this.down(chosen.index);
202
+ this.fellBack[chosen.index] += 1;
203
+ span?.event('replica fallback', { 'mistri.replica': chosen.index + 1, 'mistri.replica.failure': failure });
204
+ span?.setAttribute('mistri.read.pool', 'primary');
205
+ return onPrimary();
206
+ }
207
+ }
208
+ }
@@ -0,0 +1,38 @@
1
+ import type { DatabaseSchema } from '../shared/schema.js';
2
+ import { Refusal } from './adapter.js';
3
+ import type { PgQuery } from './postgresPool.js';
4
+ type Dialect = DatabaseSchema['dialect'];
5
+ export declare const RESERVED_SCHEMAS: readonly string[];
6
+ /** Whether a relation, as the engine names it, is tablewalk's own. */
7
+ export declare function isReservedRelation(schema: string | undefined, name: string): boolean;
8
+ /** The refusal for a statement found to touch `name`, by whichever half found it. */
9
+ export declare function reservedRefusal(name: string): Refusal;
10
+ /**
11
+ * Why this statement must not run under the guard, or null when nothing in
12
+ * its text reaches a reserved relation.
13
+ */
14
+ export declare function reservedInText(sql: string, dialect: Dialect): string | null;
15
+ /** @throws Refusal when the statement's text reaches a reserved relation. */
16
+ export declare function refuseReservedText(sql: string, dialect: Dialect): void;
17
+ /**
18
+ * The Postgres check before a statement is given a connection: its text,
19
+ * and for a read, whether the planner can list what it reads — the engine
20
+ * half below needs a plan, so a statement the planner cannot explain is
21
+ * refused rather than run unchecked.
22
+ */
23
+ export declare function refusePostgresReserved(sql: string, write?: boolean): void;
24
+ /**
25
+ * The Postgres engine half: the planner's own list of what a statement
26
+ * scans, read inside the transaction it will run in, so views, search_path
27
+ * and CTEs resolve as they will there.
28
+ */
29
+ export declare function refuseReservedPlan(db: PgQuery, sql: string, params: unknown[]): Promise<void>;
30
+ /**
31
+ * The first reserved relation a Postgres `EXPLAIN (VERBOSE, FORMAT JSON)`
32
+ * plan reads. The plan is the planner's list of what the statement will
33
+ * actually scan — views expanded, search_path resolved, CTEs and subqueries
34
+ * included. What a function reads by a computed name is not in it; the
35
+ * lexical half refuses those functions by name.
36
+ */
37
+ export declare function reservedInPlan(plan: unknown): string | null;
38
+ export {};
@@ -0,0 +1,264 @@
1
+ /**
2
+ * The guard a caller can put in front of raw SQL: a statement that touches
3
+ * tablewalk's own runtime tables (the `__mistri_` prefix on every engine, and
4
+ * PostgreSQL's runtime schema, shared/runtimeTables.ts) is refused before it
5
+ * runs. The MCP `sql` and `explain` tools ask for it.
6
+ *
7
+ * This file is the lexical half, and it is conservative on purpose. It reads
8
+ * every identifier, quoted or not, every string and every comment, and
9
+ * refuses when one of them spells a reserved name — a string can become a
10
+ * relation through a cast. It refuses the constructs that reach a relation whose name is
11
+ * only computed when the statement runs (regclass casts, the functions that
12
+ * run SQL text they are handed), and escapes it will not decode, because a
13
+ * guard that cannot read a statement should not wave it through. The engine
14
+ * half lives in the adapters: SQLite's authorizer and Postgres's plan both
15
+ * name the relations a statement actually reads, views and search_path
16
+ * included, which no reading of the text can.
17
+ *
18
+ * Not a sandbox. A function the database's own users wrote reads what its
19
+ * owner may; the database role is the boundary for that.
20
+ */
21
+ import { isRuntimeTable, RUNTIME_SCHEMA, RUNTIME_TABLE_PREFIXES } from '../shared/runtimeTables.js';
22
+ import { looksWrappable, Refusal, trimStatement } from './adapter.js';
23
+ /* PostgreSQL keeps every runtime table, sign-in's included, in one schema
24
+ (shared/runtimeTables.ts): never listed, not even when `--schema` names it,
25
+ and refused as a generic write target. The prefix rule cannot say this,
26
+ because the tables inside are named plainly (`command`, `auth_user`); the
27
+ schema does. The name is the engine's, not an import of a store: the engine
28
+ hides it in a database the browser opens with no App framework installed. */
29
+ export const RESERVED_SCHEMAS = [RUNTIME_SCHEMA];
30
+ /** Whether a relation, as the engine names it, is tablewalk's own. */
31
+ export function isReservedRelation(schema, name) {
32
+ return isRuntimeTable(name) || (schema !== undefined && RESERVED_SCHEMAS.includes(schema.toLowerCase()));
33
+ }
34
+ /** The refusal for a statement found to touch `name`, by whichever half found it. */
35
+ export function reservedRefusal(name) {
36
+ return new Refusal(`This statement touches "${name}", one of the runtime or sign-in tables ` +
37
+ `(the reserved ${RUNTIME_TABLE_PREFIXES.join(' and ')} prefix and the ${RESERVED_SCHEMAS.join(', ')} schema), which raw SQL here does not read.`);
38
+ }
39
+ /* Postgres names that reach a relation only when the statement runs: a
40
+ regclass cast turns any text or number into a table, and these functions
41
+ run the SQL text, or read the relation, they are handed. `table_to_xml`
42
+ takes a bare oid, so there is not even a name to read. */
43
+ const COMPUTED_RELATION = /^(?:regclass|to_regclass|\w*_to_xml\w*|ts_stat|dblink\w*|crosstab\d*|connectby|get_raw_page)$/i;
44
+ /**
45
+ * The statement's words, quoted identifiers and texts (strings, dollar
46
+ * bodies, comments), in order — or the reason it cannot be read.
47
+ */
48
+ function tokenize(sql, dialect) {
49
+ const tokens = [];
50
+ const n = sql.length;
51
+ let i = 0;
52
+ /* A quoted run with its closing character doubled as the escape. A
53
+ backslash escape (Postgres's E'…') can only make the run longer when read
54
+ as one, which the text check still reads. */
55
+ const quoted = (close, backslash) => {
56
+ let value = '';
57
+ i += 1;
58
+ while (i < n) {
59
+ const ch = sql[i];
60
+ if (backslash && ch === '\\' && i + 1 < n) {
61
+ value += sql[i + 1];
62
+ i += 2;
63
+ continue;
64
+ }
65
+ if (ch === close && sql[i + 1] === close) {
66
+ value += close;
67
+ i += 2;
68
+ continue;
69
+ }
70
+ if (ch === close) {
71
+ i += 1;
72
+ break;
73
+ }
74
+ value += ch;
75
+ i += 1;
76
+ }
77
+ return value;
78
+ };
79
+ while (i < n) {
80
+ const ch = sql[i];
81
+ const next = sql[i + 1];
82
+ if (/\s/.test(ch)) {
83
+ i += 1;
84
+ continue;
85
+ }
86
+ if (ch === '-' && next === '-') {
87
+ const end = sql.indexOf('\n', i);
88
+ tokens.push({ kind: 'text', value: sql.slice(i, end < 0 ? n : end) });
89
+ i = end < 0 ? n : end + 1;
90
+ continue;
91
+ }
92
+ if (ch === '/' && next === '*') {
93
+ /* Postgres nests block comments; the others end at the first close. */
94
+ let depth = 0;
95
+ const start = i;
96
+ while (i < n) {
97
+ if (sql[i] === '/' && sql[i + 1] === '*') {
98
+ depth += 1;
99
+ i += 2;
100
+ continue;
101
+ }
102
+ if (sql[i] === '*' && sql[i + 1] === '/') {
103
+ depth -= 1;
104
+ i += 2;
105
+ if (depth === 0 || dialect !== 'postgres')
106
+ break;
107
+ continue;
108
+ }
109
+ i += 1;
110
+ }
111
+ tokens.push({ kind: 'text', value: sql.slice(start, i) });
112
+ continue;
113
+ }
114
+ if (ch === '$' && dialect === 'postgres') {
115
+ const tag = /^\$[A-Za-z_]\w*\$|^\$\$/.exec(sql.slice(i))?.[0];
116
+ if (tag) {
117
+ const end = sql.indexOf(tag, i + tag.length);
118
+ tokens.push({ kind: 'text', value: sql.slice(i + tag.length, end < 0 ? n : end) });
119
+ i = end < 0 ? n : end + tag.length;
120
+ continue;
121
+ }
122
+ }
123
+ if (dialect === 'postgres' && /^u&["']/i.test(sql.slice(i, i + 3))) {
124
+ /* A Unicode-escaped identifier or string spells a name in code points
125
+ this check does not decode; one without escapes reads as it is. */
126
+ i += 2;
127
+ const close = sql[i];
128
+ const value = quoted(close, false);
129
+ if (value.includes('\\') || /^\s*uescape\b/i.test(sql.slice(i))) {
130
+ return ('This statement spells a name with Unicode escapes (U&"…"), which the reserved-table check does not decode, ' +
131
+ 'so it is refused rather than run. Spell the name plainly.');
132
+ }
133
+ tokens.push({ kind: close === '"' ? 'quoted' : 'text', value });
134
+ continue;
135
+ }
136
+ if (ch === "'") {
137
+ /* E'…' is Postgres's backslash-escaped string. */
138
+ const escaped = dialect === 'postgres' && /[eE]$/.test(sql.slice(Math.max(0, i - 1), i));
139
+ tokens.push({ kind: 'text', value: quoted("'", escaped) });
140
+ continue;
141
+ }
142
+ if (ch === '"') {
143
+ tokens.push({ kind: 'quoted', value: quoted('"', false) });
144
+ continue;
145
+ }
146
+ if (ch === '`' && dialect !== 'postgres') {
147
+ tokens.push({ kind: 'quoted', value: quoted('`', false) });
148
+ continue;
149
+ }
150
+ if (ch === '[' && dialect === 'sqlite') {
151
+ tokens.push({ kind: 'quoted', value: quoted(']', false) });
152
+ continue;
153
+ }
154
+ const word = /^[A-Za-z_€-￿][\w$€-￿]*/.exec(sql.slice(i))?.[0];
155
+ if (word) {
156
+ tokens.push({ kind: 'word', value: word });
157
+ i += word.length;
158
+ continue;
159
+ }
160
+ i += 1;
161
+ }
162
+ return tokens;
163
+ }
164
+ // A match in text (a comment, a string)
165
+ // takes the rest of the name, so the refusal names the table, not the prefix.
166
+ const RESERVED_TEXT = new RegExp(`(?:${RUNTIME_TABLE_PREFIXES.join('|')})[\\w$]*|\\b(?:${RESERVED_SCHEMAS.join('|')})\\b`, 'i');
167
+ /**
168
+ * Why this statement must not run under the guard, or null when nothing in
169
+ * its text reaches a reserved relation.
170
+ */
171
+ export function reservedInText(sql, dialect) {
172
+ const tokens = tokenize(sql, dialect);
173
+ if (typeof tokens === 'string')
174
+ return tokens;
175
+ for (const token of tokens) {
176
+ if (token.kind === 'text') {
177
+ const found = RESERVED_TEXT.exec(token.value);
178
+ if (found)
179
+ return reservedRefusal(found[0]).message;
180
+ continue;
181
+ }
182
+ const name = token.value;
183
+ if (isRuntimeTable(name) || (dialect === 'postgres' && RESERVED_SCHEMAS.includes(name.toLowerCase()))) {
184
+ return reservedRefusal(name).message;
185
+ }
186
+ if (dialect === 'postgres' && COMPUTED_RELATION.test(name)) {
187
+ return (`This statement uses ${name}, which reaches a relation by a name computed when it runs, so it is refused ` +
188
+ `rather than run: raw SQL here does not read the runtime or sign-in tables, and a name ` +
189
+ 'that is not written down cannot be checked.');
190
+ }
191
+ }
192
+ return null;
193
+ }
194
+ /** @throws Refusal when the statement's text reaches a reserved relation. */
195
+ export function refuseReservedText(sql, dialect) {
196
+ const reason = reservedInText(sql, dialect);
197
+ if (reason)
198
+ throw new Refusal(reason);
199
+ }
200
+ /**
201
+ * The Postgres check before a statement is given a connection: its text,
202
+ * and for a read, whether the planner can list what it reads — the engine
203
+ * half below needs a plan, so a statement the planner cannot explain is
204
+ * refused rather than run unchecked.
205
+ */
206
+ export function refusePostgresReserved(sql, write = false) {
207
+ refuseReservedText(sql, 'postgres');
208
+ if (!write && !looksWrappable(sql)) {
209
+ throw new Refusal("The reserved-table check reads the planner's list of what a statement scans, so it " +
210
+ 'runs the statements the planner can explain: SELECT, WITH, TABLE and VALUES.');
211
+ }
212
+ }
213
+ /**
214
+ * The Postgres engine half: the planner's own list of what a statement
215
+ * scans, read inside the transaction it will run in, so views, search_path
216
+ * and CTEs resolve as they will there.
217
+ */
218
+ export async function refuseReservedPlan(db, sql, params) {
219
+ /* On the extended protocol even with no parameters: on the simple one,
220
+ Postgres would run a statement stacked behind the EXPLAIN before any
221
+ plan came back to read. */
222
+ const planned = await db.query({
223
+ text: `EXPLAIN (VERBOSE, FORMAT JSON) ${trimStatement(sql)}`,
224
+ values: params,
225
+ rowMode: 'array',
226
+ queryMode: 'extended',
227
+ });
228
+ const found = reservedInPlan(planned.rows[0]?.[0]);
229
+ if (found)
230
+ throw reservedRefusal(found);
231
+ }
232
+ /**
233
+ * The first reserved relation a Postgres `EXPLAIN (VERBOSE, FORMAT JSON)`
234
+ * plan reads. The plan is the planner's list of what the statement will
235
+ * actually scan — views expanded, search_path resolved, CTEs and subqueries
236
+ * included. What a function reads by a computed name is not in it; the
237
+ * lexical half refuses those functions by name.
238
+ */
239
+ export function reservedInPlan(plan) {
240
+ if (Array.isArray(plan)) {
241
+ for (const item of plan) {
242
+ const found = reservedInPlan(item);
243
+ if (found)
244
+ return found;
245
+ }
246
+ return null;
247
+ }
248
+ if (!plan || typeof plan !== 'object')
249
+ return null;
250
+ const node = plan;
251
+ const relation = node['Relation Name'];
252
+ const schema = typeof node.Schema === 'string' ? node.Schema : undefined;
253
+ if (typeof relation === 'string' && isReservedRelation(schema, relation)) {
254
+ return schema ? `${schema}.${relation}` : relation;
255
+ }
256
+ for (const value of Object.values(node)) {
257
+ if (value && typeof value === 'object') {
258
+ const found = reservedInPlan(value);
259
+ if (found)
260
+ return found;
261
+ }
262
+ }
263
+ return null;
264
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * A database role's reach beyond reading, behind `Adapter.privileges`: one
3
+ * catalog query on PostgreSQL. Every read runs
4
+ * in a read-only transaction, which holds for everything tablewalk sends but
5
+ * not for a superuser (`COPY … TO PROGRAM` is a read); the role is the
6
+ * boundary that always holds, so the registry says when it is wider than a
7
+ * read-only connection.
8
+ */
9
+ import type { RolePrivileges } from './adapter.js';
10
+ type Reader = {
11
+ query(text: string, params?: unknown[]): Promise<{
12
+ rows: unknown[];
13
+ }>;
14
+ };
15
+ /** Superuser, write grants on the browsed tables, CREATE in a browsed schema. */
16
+ export declare function postgresPrivileges(db: Reader, browsed: readonly string[], system: readonly string[]): Promise<RolePrivileges>;
17
+ export {};
@@ -0,0 +1,22 @@
1
+ import { RESERVED_SCHEMAS } from './reservedSql.js';
2
+ import { notExtensionMember } from './postgresCatalog.js';
3
+ /** Superuser, write grants on the browsed tables, CREATE in a browsed schema. */
4
+ export async function postgresPrivileges(db, browsed, system) {
5
+ const schemas = browsed.length ? browsed.filter((schema) => !RESERVED_SCHEMAS.includes(schema)) : [...system, ...RESERVED_SCHEMAS];
6
+ // Temporary and toast namespaces are the session's own, not the database's.
7
+ const within = `${browsed.length ? 'n.nspname = ANY($1)' : 'n.nspname <> ALL($1)'} AND n.nspname NOT LIKE 'pg\\_%'`;
8
+ const { rows } = await db.query(`SELECT r.rolsuper AS superuser,
9
+ (SELECT count(*)::int FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
10
+ WHERE c.relkind IN ('r', 'p') AND ${notExtensionMember('c')} AND ${within}
11
+ AND (has_table_privilege(c.oid, 'INSERT') OR has_table_privilege(c.oid, 'UPDATE')
12
+ OR has_table_privilege(c.oid, 'DELETE') OR has_table_privilege(c.oid, 'TRUNCATE'))) AS writable,
13
+ EXISTS (SELECT 1 FROM pg_namespace n WHERE ${within} AND has_schema_privilege(n.oid, 'CREATE')) AS can_create
14
+ FROM pg_roles r WHERE r.rolname = current_user`, [schemas]);
15
+ const row = rows[0] ?? {};
16
+ const writable = Number(row.writable ?? 0);
17
+ return {
18
+ superuser: row.superuser === true,
19
+ create: row.can_create === true,
20
+ writes: writable ? [`INSERT/UPDATE/DELETE on ${writable} table${writable === 1 ? '' : 's'}`] : [],
21
+ };
22
+ }