@blamejs/blamejs-shop 0.5.12 → 0.5.13

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 (521) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/vendor/MANIFEST.json +632 -416
  4. package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
  5. package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
  6. package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
  7. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  8. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
  9. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
  10. package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
  11. package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
  12. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
  13. package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
  14. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
  15. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  16. package/lib/vendor/blamejs/.gitignore +2 -0
  17. package/lib/vendor/blamejs/CHANGELOG.md +122 -0
  18. package/lib/vendor/blamejs/NOTICE +26 -1
  19. package/lib/vendor/blamejs/SECURITY.md +1 -1
  20. package/lib/vendor/blamejs/api-snapshot.json +207 -5
  21. package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
  22. package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
  23. package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
  24. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
  25. package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
  26. package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
  27. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
  28. package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
  29. package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
  30. package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
  31. package/lib/vendor/blamejs/index.js +6 -0
  32. package/lib/vendor/blamejs/lib/a2a.js +4 -4
  33. package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
  34. package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
  35. package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
  36. package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
  37. package/lib/vendor/blamejs/lib/archive-read.js +8 -0
  38. package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
  39. package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
  40. package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
  41. package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
  42. package/lib/vendor/blamejs/lib/audit.js +71 -8
  43. package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
  44. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
  45. package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
  46. package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
  47. package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
  48. package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
  49. package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
  50. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
  51. package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
  52. package/lib/vendor/blamejs/lib/backup/index.js +16 -5
  53. package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
  54. package/lib/vendor/blamejs/lib/base32.js +21 -0
  55. package/lib/vendor/blamejs/lib/break-glass.js +19 -10
  56. package/lib/vendor/blamejs/lib/bundler.js +5 -1
  57. package/lib/vendor/blamejs/lib/cache-status.js +3 -7
  58. package/lib/vendor/blamejs/lib/calendar.js +21 -1
  59. package/lib/vendor/blamejs/lib/cbor.js +12 -1
  60. package/lib/vendor/blamejs/lib/cert.js +29 -11
  61. package/lib/vendor/blamejs/lib/cli.js +94 -24
  62. package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
  63. package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
  64. package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
  65. package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
  66. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
  67. package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
  68. package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
  69. package/lib/vendor/blamejs/lib/content-digest.js +2 -1
  70. package/lib/vendor/blamejs/lib/cookies.js +13 -3
  71. package/lib/vendor/blamejs/lib/cose.js +31 -16
  72. package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
  73. package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
  74. package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
  75. package/lib/vendor/blamejs/lib/crypto.js +314 -19
  76. package/lib/vendor/blamejs/lib/csp.js +11 -3
  77. package/lib/vendor/blamejs/lib/daemon.js +270 -24
  78. package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
  79. package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
  80. package/lib/vendor/blamejs/lib/db-query.js +34 -7
  81. package/lib/vendor/blamejs/lib/db.js +18 -6
  82. package/lib/vendor/blamejs/lib/dbsc.js +17 -0
  83. package/lib/vendor/blamejs/lib/dev.js +21 -2
  84. package/lib/vendor/blamejs/lib/dsr.js +157 -102
  85. package/lib/vendor/blamejs/lib/external-db.js +41 -2
  86. package/lib/vendor/blamejs/lib/file-upload.js +25 -7
  87. package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
  88. package/lib/vendor/blamejs/lib/forms.js +113 -27
  89. package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
  90. package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
  91. package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
  92. package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
  93. package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
  94. package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
  95. package/lib/vendor/blamejs/lib/guard-html.js +26 -53
  96. package/lib/vendor/blamejs/lib/guard-image.js +24 -5
  97. package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
  98. package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
  99. package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
  100. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
  101. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
  102. package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
  103. package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
  104. package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
  105. package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
  106. package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
  107. package/lib/vendor/blamejs/lib/guard-time.js +1 -1
  108. package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
  109. package/lib/vendor/blamejs/lib/html-balance.js +3 -3
  110. package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
  111. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
  112. package/lib/vendor/blamejs/lib/http-client.js +39 -7
  113. package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
  114. package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
  115. package/lib/vendor/blamejs/lib/i18n.js +35 -21
  116. package/lib/vendor/blamejs/lib/incident-report.js +8 -1
  117. package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
  118. package/lib/vendor/blamejs/lib/json-path.js +23 -1
  119. package/lib/vendor/blamejs/lib/jwk.js +20 -3
  120. package/lib/vendor/blamejs/lib/link-header.js +2 -1
  121. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
  122. package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
  123. package/lib/vendor/blamejs/lib/log-stream.js +8 -3
  124. package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
  125. package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
  126. package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
  127. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
  128. package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
  129. package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
  130. package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
  131. package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
  132. package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
  133. package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
  134. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
  135. package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
  136. package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
  137. package/lib/vendor/blamejs/lib/mail.js +15 -5
  138. package/lib/vendor/blamejs/lib/metrics.js +268 -63
  139. package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
  140. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
  141. package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
  142. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
  143. package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
  144. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
  145. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
  146. package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
  147. package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
  148. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
  149. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
  150. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
  151. package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
  152. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
  153. package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
  154. package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
  155. package/lib/vendor/blamejs/lib/network-dns.js +21 -2
  156. package/lib/vendor/blamejs/lib/network-tls.js +69 -7
  157. package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
  158. package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
  159. package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
  160. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
  161. package/lib/vendor/blamejs/lib/outbox.js +1 -1
  162. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
  163. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
  164. package/lib/vendor/blamejs/lib/permissions.js +6 -3
  165. package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
  166. package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
  167. package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
  168. package/lib/vendor/blamejs/lib/pubsub.js +20 -9
  169. package/lib/vendor/blamejs/lib/queue-local.js +8 -1
  170. package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
  171. package/lib/vendor/blamejs/lib/redact.js +54 -0
  172. package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
  173. package/lib/vendor/blamejs/lib/restore.js +19 -0
  174. package/lib/vendor/blamejs/lib/retention.js +12 -4
  175. package/lib/vendor/blamejs/lib/router.js +60 -6
  176. package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
  177. package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
  178. package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
  179. package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
  180. package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
  181. package/lib/vendor/blamejs/lib/safe-object.js +80 -0
  182. package/lib/vendor/blamejs/lib/safe-path.js +52 -4
  183. package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
  184. package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
  185. package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
  186. package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
  187. package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
  188. package/lib/vendor/blamejs/lib/scheduler.js +8 -1
  189. package/lib/vendor/blamejs/lib/security-assert.js +6 -6
  190. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
  191. package/lib/vendor/blamejs/lib/self-update.js +517 -87
  192. package/lib/vendor/blamejs/lib/server-timing.js +2 -4
  193. package/lib/vendor/blamejs/lib/session.js +34 -12
  194. package/lib/vendor/blamejs/lib/sql.js +15 -1
  195. package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
  196. package/lib/vendor/blamejs/lib/static.js +55 -13
  197. package/lib/vendor/blamejs/lib/storage.js +8 -2
  198. package/lib/vendor/blamejs/lib/subject.js +6 -1
  199. package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
  200. package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
  201. package/lib/vendor/blamejs/lib/tsa.js +34 -13
  202. package/lib/vendor/blamejs/lib/uri-template.js +8 -1
  203. package/lib/vendor/blamejs/lib/vault/index.js +13 -0
  204. package/lib/vendor/blamejs/lib/vc.js +44 -5
  205. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
  206. package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
  207. package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
  208. package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
  209. package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
  210. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
  211. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
  212. package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
  213. package/lib/vendor/blamejs/lib/watcher.js +89 -17
  214. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
  215. package/lib/vendor/blamejs/lib/webhook.js +12 -2
  216. package/lib/vendor/blamejs/lib/ws-client.js +32 -1
  217. package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
  218. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
  219. package/lib/vendor/blamejs/package-lock.json +2 -2
  220. package/lib/vendor/blamejs/package.json +1 -1
  221. package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
  222. package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
  223. package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
  224. package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
  225. package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
  226. package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
  227. package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
  228. package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
  229. package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
  230. package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
  231. package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
  232. package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
  233. package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
  234. package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
  235. package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
  236. package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
  237. package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
  238. package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
  239. package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
  240. package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
  241. package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
  242. package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
  243. package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
  244. package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
  245. package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
  246. package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
  247. package/lib/vendor/blamejs/socket.yml +94 -0
  248. package/lib/vendor/blamejs/test/00-primitives.js +605 -0
  249. package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
  250. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
  251. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
  252. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
  253. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
  254. package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
  255. package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
  256. package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
  257. package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
  258. package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
  259. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
  260. package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
  262. package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
  263. package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
  264. package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
  268. package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
  270. package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
  271. package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
  272. package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
  273. package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
  275. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
  277. package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
  278. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
  282. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
  283. package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
  284. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
  287. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
  288. package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
  293. package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
  294. package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
  296. package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
  302. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
  307. package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
  308. package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
  309. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
  310. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
  311. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
  312. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
  313. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
  314. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
  315. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
  316. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
  317. package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
  318. package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
  319. package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
  320. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
  321. package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
  322. package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
  323. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
  324. package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
  325. package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
  326. package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
  327. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
  328. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
  329. package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
  330. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
  331. package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
  332. package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
  333. package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
  334. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
  335. package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
  336. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
  337. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
  338. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
  339. package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
  340. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
  341. package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
  342. package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
  344. package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
  345. package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
  346. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
  347. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
  348. package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
  349. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
  351. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
  352. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  353. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
  365. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
  366. package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
  368. package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
  376. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
  377. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
  379. package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
  387. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
  388. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
  389. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
  390. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
  391. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
  392. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
  393. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
  394. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
  395. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
  396. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
  397. package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
  398. package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
  399. package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
  400. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
  401. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
  402. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
  403. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
  404. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
  405. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
  406. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
  407. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
  408. package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
  409. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
  410. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
  411. package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
  412. package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
  413. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
  414. package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
  415. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
  416. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
  417. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
  418. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
  419. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
  420. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
  421. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
  422. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
  423. package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
  424. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
  425. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
  426. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
  427. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
  428. package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
  429. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
  430. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
  431. package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
  432. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
  433. package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
  434. package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
  435. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
  436. package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
  437. package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
  438. package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
  439. package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
  440. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
  441. package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
  442. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
  443. package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
  444. package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
  445. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
  446. package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
  447. package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
  448. package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
  449. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
  450. package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
  451. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
  452. package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
  453. package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
  454. package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
  455. package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
  456. package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
  457. package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
  458. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
  459. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
  460. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
  461. package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
  462. package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
  463. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
  464. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
  465. package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
  466. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
  467. package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
  468. package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
  469. package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
  470. package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
  471. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
  472. package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
  473. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
  474. package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
  475. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
  476. package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
  477. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
  478. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
  479. package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
  480. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
  481. package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
  482. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
  483. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
  484. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
  485. package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
  486. package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
  487. package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
  488. package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
  489. package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
  490. package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
  491. package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
  492. package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
  493. package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
  494. package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
  495. package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
  496. package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
  497. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
  498. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
  499. package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
  500. package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
  501. package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
  502. package/lib/vendor/blamejs/test/smoke.js +2 -0
  503. package/package.json +1 -1
  504. package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
  505. package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
  506. package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
  507. package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
  508. package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
  509. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
  510. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
  511. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
  512. package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
  513. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
  514. package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
  515. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
  516. package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
  517. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
  518. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
  519. package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
  520. package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
  521. package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
@@ -7,6 +7,13 @@
7
7
  * where-family checks inherited from the executing query builder
8
8
  * (operator allowlist, IN-expansion, JSONB injection guard +
9
9
  * jsonb_exists emission), and every _assertEmittable boundary code.
10
+ * Also drives the ordinary builder surface: aggregates, DISTINCT, the
11
+ * JOIN family, GROUP BY / HAVING, ORDER BY / LIMIT / OFFSET validation,
12
+ * the LIKE-mode + BETWEEN + nested-group + EXISTS / scalar-subquery
13
+ * where helpers, CTE composition, setRaw, the column-membership gate
14
+ * modes, the alterTable / dropTable / createIndex option branches, DDL
15
+ * DEFAULT rendering, table-reference shapes, and the fn / cast / casWon
16
+ * / output-gate boundary codes.
10
17
  */
11
18
 
12
19
  var helpers = require("../helpers");
@@ -22,6 +29,392 @@ function rejects(label, fn, code) {
22
29
  check(label, threw && threw.code === code);
23
30
  }
24
31
 
32
+ async function runBuilderSurface() {
33
+ var sql = b.sql;
34
+
35
+ // ================= projection: aggregates + DISTINCT =================
36
+ check("count(*) with alias quotes the alias",
37
+ sql.select("t").count("*", "n").toSql().sql === 'SELECT COUNT(*) AS "n" FROM t');
38
+ check("count() defaults col to * (no alias)",
39
+ sql.select("t").count().toSql().sql === "SELECT COUNT(*) FROM t");
40
+ check("countDistinct emits COUNT(DISTINCT col)",
41
+ sql.select("t").countDistinct("email", "c").toSql().sql ===
42
+ 'SELECT COUNT(DISTINCT "email") AS "c" FROM t');
43
+ check("max/min/sum/avg each quote their column",
44
+ sql.select("t").max("a").min("b").sum("c").avg("d").toSql().sql ===
45
+ 'SELECT MAX("a"), MIN("b"), SUM("c"), AVG("d") FROM t');
46
+ check("distinct() emits SELECT DISTINCT",
47
+ sql.select("t").distinct().columns(["a"]).toSql().sql === 'SELECT DISTINCT "a" FROM t');
48
+ check("aggregate alias is validated (quoted)",
49
+ sql.select("t").count("*", "row_count").toSql().sql.indexOf('AS "row_count"') !== -1);
50
+
51
+ // ================= JOIN family =======================================
52
+ var ij = sql.select("u", { alias: "u" }).columns(["u.id"])
53
+ .join(sql.table("orders", { alias: "o" }), "u.id", "=", "o.uid").toSql();
54
+ check("innerJoin quotes both ON operands + emits table alias",
55
+ ij.sql === 'SELECT "u"."id" FROM u "u" INNER JOIN orders "o" ON "u"."id" = "o"."uid"');
56
+ check("leftJoin with a null op defaults to '='",
57
+ sql.select("u").leftJoin("o", "u.id", null, "o.uid").toSql().sql ===
58
+ 'SELECT * FROM u LEFT JOIN o ON "u"."id" = "o"."uid"');
59
+ check("rightJoin emits RIGHT JOIN",
60
+ sql.select("u").rightJoin("o", "u.id", "=", "o.uid").toSql().sql.indexOf("RIGHT JOIN") !== -1);
61
+ check("fullJoin emits FULL JOIN",
62
+ sql.select("u").fullJoin("o", "u.id", "=", "o.uid").toSql().sql.indexOf("FULL JOIN") !== -1);
63
+ check("crossJoin emits CROSS JOIN with no ON",
64
+ sql.select("u").crossJoin("o").toSql().sql === "SELECT * FROM u CROSS JOIN o");
65
+ rejects("join without both ON operands refused", function () {
66
+ return sql.select("u").join("o", "u.id").toSql();
67
+ }, "sql-builder/bad-join-on");
68
+ rejects("join with an off-allowlist ON operator refused", function () {
69
+ return sql.select("u").join("o", "u.id", "EVIL", "o.uid").toSql();
70
+ }, "sql-builder/bad-operator");
71
+ check("joinRaw passes a guarded raw join fragment through",
72
+ sql.select("u").joinRaw('INNER JOIN o ON "o"."uid" = "u"."id"').toSql().sql ===
73
+ 'SELECT * FROM u INNER JOIN o ON "o"."uid" = "u"."id"');
74
+
75
+ // ================= GROUP BY / HAVING =================================
76
+ check("groupBy + having compose",
77
+ sql.select("t").count("*", "n").groupBy("cat").having("cat", ">", 1).toSql().sql ===
78
+ 'SELECT COUNT(*) AS "n" FROM t GROUP BY "cat" HAVING "cat" > ?');
79
+ check("groupBy accepts a single string (not just an array)",
80
+ sql.select("t").groupBy("a").toSql().sql === 'SELECT * FROM t GROUP BY "a"');
81
+ var hr = sql.select("t").count("*", "n").groupBy("cat").havingRaw("COUNT(*) > ?", [5]).toSql();
82
+ check("havingRaw guards + parenthesizes the raw HAVING fragment",
83
+ hr.sql.indexOf("HAVING (COUNT(*) > ?)") !== -1 && hr.params.length === 1 && hr.params[0] === 5);
84
+
85
+ // ================= ORDER BY / LIMIT / OFFSET =========================
86
+ check("orderBy defaults to ASC",
87
+ sql.select("t").orderBy("a").toSql().sql === 'SELECT * FROM t ORDER BY "a" ASC');
88
+ rejects("orderBy rejects a non-asc/desc direction", function () {
89
+ return sql.select("t").orderBy("a", "sideways");
90
+ }, "sql-builder/bad-direction");
91
+ check("offset emits OFFSET after LIMIT",
92
+ sql.select("t").limit(10).offset(20).toSql().sql === "SELECT * FROM t LIMIT 10 OFFSET 20");
93
+ check("limit(0) is a valid non-negative integer",
94
+ sql.select("t").limit(0).toSql().sql === "SELECT * FROM t LIMIT 0");
95
+ rejects("limit rejects a negative integer", function () { return sql.select("t").limit(-1); },
96
+ "sql-builder/bad-limit");
97
+ rejects("limit rejects a non-integer", function () { return sql.select("t").limit(1.5); },
98
+ "sql-builder/bad-limit");
99
+ rejects("offset rejects a negative integer", function () { return sql.select("t").offset(-1); },
100
+ "sql-builder/bad-offset");
101
+
102
+ // ================= LIKE modes / BETWEEN ==============================
103
+ check("whereLike substring wraps live % around the escaped term",
104
+ sql.select("t").whereLike("n", "a%b").toSql().params[0] === "%a~%b%");
105
+ check("whereLike prefix keeps a trailing live %",
106
+ sql.select("t").whereLike("n", "a%b", "prefix").toSql().params[0] === "a~%b%");
107
+ check("whereLike exact escapes without adding a wildcard",
108
+ sql.select("t").whereLike("n", "a%b", "exact").toSql().params[0] === "a~%b");
109
+ check("orWhereLike joins with OR",
110
+ sql.select("t").where("a", 1).orWhereLike("n", "x").toSql().sql.indexOf('OR "n" LIKE ?') !== -1);
111
+ rejects("whereLike rejects an unknown mode", function () {
112
+ return sql.select("t").whereLike("n", "x", "evil");
113
+ }, "sql-builder/bad-like-mode");
114
+ rejects("whereLike rejects a non-string term", function () {
115
+ return sql.select("t").whereLike("n", 5);
116
+ }, "sql-builder/bad-like-term");
117
+ var bt = sql.select("t").whereBetween("age", 18, 65).toSql();
118
+ check("whereBetween emits col BETWEEN ? AND ? binding both bounds",
119
+ bt.sql.indexOf('"age" BETWEEN ? AND ?') !== -1 && bt.params.length === 2 &&
120
+ bt.params[0] === 18 && bt.params[1] === 65);
121
+ rejects("BETWEEN operator rejects a non-pair", function () {
122
+ return sql.select("t").where("age", "BETWEEN", [1]).toSql();
123
+ }, "sql-builder/bad-between");
124
+
125
+ // ================= nested groups / EXISTS / scalar sub ===============
126
+ check("whereGroup parenthesizes an AND/OR sub-group",
127
+ sql.select("t").whereGroup(function (q) { q.where("a", 1).orWhere("b", 2); }).where("c", 3)
128
+ .toSql().sql === 'SELECT * FROM t WHERE ("a" = ? OR "b" = ?) AND "c" = ?');
129
+ check("orWhereGroup joins the group with OR",
130
+ sql.select("t").where("a", 1).orWhereGroup(function (q) { q.where("b", 2); }).toSql().sql ===
131
+ 'SELECT * FROM t WHERE "a" = ? OR ("b" = ?)');
132
+ check("an empty whereGroup contributes nothing (no dangling parens)",
133
+ sql.select("t").where("a", 1).whereGroup(function () {}).toSql().sql ===
134
+ 'SELECT * FROM t WHERE "a" = ?');
135
+ rejects("whereGroup requires a function", function () {
136
+ return sql.select("t").whereGroup("nope");
137
+ }, "sql-builder/bad-closure");
138
+ check("whereExists composes a correlated EXISTS subquery",
139
+ sql.select("u").whereExists(
140
+ sql.select("o").columns(["id"]).whereRaw('"o"."uid" = "u"."id"')).toSql().sql ===
141
+ 'SELECT * FROM u WHERE EXISTS (SELECT "id" FROM o WHERE ("o"."uid" = "u"."id"))');
142
+ check("whereNotExists emits NOT EXISTS",
143
+ sql.select("u").whereNotExists(sql.select("o").columns(["id"])).toSql().sql ===
144
+ 'SELECT * FROM u WHERE NOT EXISTS (SELECT "id" FROM o)');
145
+ rejects("whereExists rejects a non-builder", function () {
146
+ return sql.select("u").whereExists("nope");
147
+ }, "sql-builder/bad-subquery");
148
+ check("whereSub composes a scalar-subquery comparison",
149
+ sql.select("u").whereSub("cnt", ">", sql.select("o").count("*", "c")).toSql().sql ===
150
+ 'SELECT * FROM u WHERE "cnt" > (SELECT COUNT(*) AS "c" FROM o)');
151
+ rejects("whereSub rejects an off-allowlist operator", function () {
152
+ return sql.select("u").whereSub("cnt", "EVIL", sql.select("o"));
153
+ }, "sql-builder/bad-operator");
154
+ check("selectSub embeds an aliased scalar subquery in the projection",
155
+ sql.select("u").columns(["id"]).selectSub(sql.select("o").count("*", "c"), "order_count")
156
+ .toSql().sql === 'SELECT "id", (SELECT COUNT(*) AS "c" FROM o) AS "order_count" FROM u');
157
+ rejects("selectSub rejects a non-builder", function () {
158
+ return sql.select("u").selectSub("nope", "a");
159
+ }, "sql-builder/bad-subquery");
160
+
161
+ // ================= orWhereIn / whereNotIn ============================
162
+ check("orWhereIn joins an IN list with OR",
163
+ sql.select("t").where("a", 1).orWhereIn("b", [2, 3]).toSql().sql ===
164
+ 'SELECT * FROM t WHERE "a" = ? OR "b" IN (?, ?)');
165
+ check("whereNotIn emits NOT IN",
166
+ sql.select("t").whereNotIn("id", [1, 2]).toSql().sql ===
167
+ 'SELECT * FROM t WHERE "id" NOT IN (?, ?)');
168
+
169
+ // ================= CTE composition ===================================
170
+ check("with(name, builder) prepends a quoted CTE clause",
171
+ sql.select("main").with("cte", sql.select("src").columns(["id"])).columns(["id"]).toSql().sql ===
172
+ 'WITH "cte" AS (SELECT "id" FROM src) SELECT "id" FROM main');
173
+ rejects("with rejects a non-builder/non-string body", function () {
174
+ return sql.select("t").with("c", 42).toSql();
175
+ }, "sql-builder/bad-cte");
176
+
177
+ // ================= UPDATE setRaw + allowNoWhere ======================
178
+ var srw = sql.update("t").setRaw("count", '"count" + ?', [1]).where("id", 1).toSql();
179
+ check("setRaw quotes the column + guards the raw RHS",
180
+ srw.sql === 'UPDATE t SET "count" = "count" + ? WHERE "id" = ?' &&
181
+ srw.params.length === 2 && srw.params[0] === 1 && srw.params[1] === 1);
182
+ check("update allowNoWhere() opts into a full-table write",
183
+ sql.update("t").set({ a: 1 }).allowNoWhere().toSql().sql === 'UPDATE t SET "a" = ?');
184
+ check("delete allowNoWhere() opts into a full-table delete",
185
+ sql.delete("t").allowNoWhere().toSql().sql === "DELETE FROM t");
186
+
187
+ // ================= column-membership gate modes ======================
188
+ rejects("allowedColumns(reject) refuses an unknown projection column", function () {
189
+ return sql.select("t").allowedColumns(["a"]).columns(["ghost"]).toSql();
190
+ }, "sql-builder/unknown-column");
191
+ check("columnGate('warn') permits an unknown column",
192
+ sql.select("t").allowedColumns(["a"]).columnGate("warn").columns(["ghost"]).toSql().sql ===
193
+ 'SELECT "ghost" FROM t');
194
+ check("columnGate('off') permits an unknown column",
195
+ sql.select("t").allowedColumns(["a"]).columnGate("off").columns(["ghost"]).toSql().sql ===
196
+ 'SELECT "ghost" FROM t');
197
+ rejects("columnGate rejects an unknown mode", function () {
198
+ return sql.select("t").columnGate("evil");
199
+ }, "sql-builder/bad-gate-mode");
200
+ rejects("allowedColumns rejects an empty array", function () {
201
+ return sql.select("t").allowedColumns([]);
202
+ }, "sql-builder/bad-allowed-columns");
203
+ rejects("allowedColumns opt at construction rejects a non-array", function () {
204
+ return sql.select("t", { allowedColumns: "a" });
205
+ }, "sql-builder/bad-allowed-columns");
206
+ check("allowedColumns gate also fences orderBy",
207
+ (function () {
208
+ try { sql.select("t").allowedColumns(["a"]).columns(["a"]).orderBy("ghost").toSql(); return false; }
209
+ catch (e) { return e.code === "sql-builder/unknown-column"; }
210
+ })());
211
+
212
+ // ================= alterTable branches ===============================
213
+ check("alterTable dropColumn quotes the column",
214
+ sql.alterTable("t", { dropColumn: "old" }, { dialect: "postgres" }).sql ===
215
+ 'ALTER TABLE t DROP COLUMN "old"');
216
+ check("alterTable renameColumn quotes both names",
217
+ sql.alterTable("t", { renameColumn: { from: "a", to: "b" } }, { dialect: "postgres" }).sql ===
218
+ 'ALTER TABLE t RENAME COLUMN "a" TO "b"');
219
+ check("alterTable addColumn NOT NULL + DEFAULT",
220
+ sql.alterTable("t", { addColumn: { name: "active", type: "boolean", notNull: true, default: false } },
221
+ { dialect: "postgres" }).sql === 'ALTER TABLE t ADD COLUMN "active" BOOLEAN NOT NULL DEFAULT FALSE');
222
+ rejects("alterTable with an empty change descriptor refused", function () {
223
+ return sql.alterTable("t", {}, { dialect: "postgres" });
224
+ }, "sql-builder/bad-alter");
225
+ rejects("alterTable with no change descriptor refused", function () {
226
+ return sql.alterTable("t", null);
227
+ }, "sql-builder/bad-alter");
228
+ rejects("alterTable renameColumn requires from + to", function () {
229
+ return sql.alterTable("t", { renameColumn: { from: "a" } }, { dialect: "postgres" });
230
+ }, "sql-builder/bad-alter");
231
+
232
+ // ================= dropTable / createIndex option branches ===========
233
+ check("dropTable ifExists:false drops the IF EXISTS clause",
234
+ sql.dropTable("t", { ifExists: false, dialect: "postgres" }).sql === "DROP TABLE t");
235
+ check("dropTable cascade is ignored on a non-postgres dialect",
236
+ sql.dropTable("t", { cascade: true, dialect: "sqlite" }).sql === "DROP TABLE IF EXISTS t");
237
+ check("dropTable cascade emits CASCADE on postgres",
238
+ sql.dropTable("t", { cascade: true, dialect: "postgres" }).sql === "DROP TABLE IF EXISTS t CASCADE");
239
+ check("createIndex unique + ifNotExists:false",
240
+ sql.createIndex("i", "t", ["a"], { unique: true, ifNotExists: false, dialect: "postgres" }).sql ===
241
+ 'CREATE UNIQUE INDEX "i" ON t ("a")');
242
+ rejects("createIndex rejects an empty columns array", function () {
243
+ return sql.createIndex("i", "t", [], { dialect: "postgres" });
244
+ }, "sql-builder/bad-columns");
245
+
246
+ // ================= DDL DEFAULT rendering =============================
247
+ check("string DEFAULT is single-quoted with the quote doubled",
248
+ sql.createTable("t", [{ name: "s", type: "text", default: "x'y" }], { dialect: "postgres" }).sql ===
249
+ 'CREATE TABLE IF NOT EXISTS t ("s" TEXT DEFAULT \'x\'\'y\')');
250
+ check("boolean DEFAULT renders TRUE/FALSE",
251
+ sql.createTable("t", [{ name: "b", type: "boolean", default: true }], { dialect: "postgres" })
252
+ .sql.indexOf("DEFAULT TRUE") !== -1);
253
+ check("null DEFAULT renders NULL",
254
+ sql.createTable("t", [{ name: "n", type: "int", default: null }], { dialect: "postgres" })
255
+ .sql.indexOf("DEFAULT NULL") !== -1);
256
+ check("numeric DEFAULT renders inline",
257
+ sql.createTable("t", [{ name: "n", type: "int", default: 5 }], { dialect: "postgres" })
258
+ .sql.indexOf("DEFAULT 5") !== -1);
259
+ rejects("object DEFAULT refused", function () {
260
+ return sql.createTable("t", [{ name: "n", type: "int", default: {} }], { dialect: "postgres" });
261
+ }, "sql-builder/bad-default");
262
+ // A hostile string DEFAULT cannot break out of the doubled-quote literal:
263
+ // the whole thing stays one balanced single-statement (catalog output gate).
264
+ check("hostile string DEFAULT stays inside one balanced literal",
265
+ sql.createTable("t", [{ name: "s", type: "text", default: "'); DROP TABLE x; --" }],
266
+ { dialect: "postgres" }).sql ===
267
+ 'CREATE TABLE IF NOT EXISTS t ("s" TEXT DEFAULT \'\'\'); DROP TABLE x; --\')');
268
+ // A verbatim column type that tries to stack a statement is caught by the
269
+ // quote-aware catalog output gate (defence-in-depth backstop).
270
+ rejects("verbatim type that stacks a statement is refused", function () {
271
+ return sql.createTable("t", [{ name: "c", type: "int); DROP TABLE x; --" }], { dialect: "postgres" });
272
+ }, "sql-builder/stacked-statement");
273
+ rejects("verbatim type with an unbalanced paren is refused", function () {
274
+ return sql.createTable("t", [{ name: "c", type: "NUMERIC(10" }], { dialect: "postgres" });
275
+ }, "sql-builder/unbalanced");
276
+ check("verbatim (unrecognized) type is emitted as-is in type position",
277
+ sql.createTable("t", [{ name: "c", type: "GEOGRAPHY" }], { dialect: "postgres" })
278
+ .sql.indexOf('"c" GEOGRAPHY') !== -1);
279
+ rejects("empty column type refused", function () {
280
+ return sql.createTable("t", [{ name: "c", type: "" }], { dialect: "postgres" });
281
+ }, "sql-builder/bad-type");
282
+ check("createTable CHECK constraint rides the guarded raw path",
283
+ sql.createTable("t", [{ name: "age", type: "int", constraints: 'CHECK ("age" >= 0)' }],
284
+ { dialect: "postgres" }).sql === 'CREATE TABLE IF NOT EXISTS t ("age" BIGINT CHECK ("age" >= 0))');
285
+ rejects("createTable constraint that smuggles a comment is refused", function () {
286
+ return sql.createTable("t", [{ name: "age", type: "int", constraints: "CHECK (1=1)); DROP TABLE x; --" }],
287
+ { dialect: "postgres" });
288
+ }, "sql-builder/guard-refused");
289
+ check("createTable ifNotExists:false drops IF NOT EXISTS",
290
+ sql.createTable("t", [{ name: "a", type: "int" }], { dialect: "postgres", ifNotExists: false }).sql ===
291
+ 'CREATE TABLE t ("a" BIGINT)');
292
+ rejects("createTable column that is not an object refused", function () {
293
+ return sql.createTable("t", ["notanobject"], { dialect: "postgres" });
294
+ }, "sql-builder/bad-column");
295
+
296
+ // ================= table() reference shapes ==========================
297
+ check("table('schema.table') quotes both segments",
298
+ sql.table("public.users").toString("postgres") === '"public"."users"');
299
+ check("table prefix is prepended then quoted as one identifier",
300
+ sql.table("orders", { prefix: "shop_" }).toString("sqlite") === '"shop_orders"');
301
+ check("table alias is appended for joins",
302
+ sql.table("orders", { alias: "o" }).toString("postgres") === 'orders "o"');
303
+ check("bare default table stays unquoted (clusterStorage rewrite target)",
304
+ sql.table("audit_log").toString() === "audit_log");
305
+ check("quoteName forces a bare default name to be quoted",
306
+ sql.table("audit_log", { quoteName: true }).toString("postgres") === '"audit_log"');
307
+ rejects("three-segment dotted table refused", function () { return sql.table("a.b.c"); },
308
+ "sql-builder/bad-table");
309
+ rejects("trailing-dot table refused", function () { return sql.table("a."); },
310
+ "sql-builder/bad-table");
311
+ rejects("empty table name refused", function () { return sql.table(""); },
312
+ "sql-builder/bad-table");
313
+ rejects("qualified column with three segments refused", function () {
314
+ return sql.select("t").columns(["a.b.c"]).toSql();
315
+ }, "sql-builder/bad-column");
316
+
317
+ // ================= fn / cast boundary codes ==========================
318
+ rejects("fn(NOW) is refused on sqlite (no portable form)", function () {
319
+ return sql.insert("t", { dialect: "sqlite" }).values({ at: sql.fn("NOW") }).toSql();
320
+ }, "sql-builder/fn-unsupported");
321
+ rejects("fn rejects a non-string name", function () { return sql.fn(5); },
322
+ "sql-builder/bad-fn");
323
+ rejects("cast rejects a non-string type", function () { return sql.cast("x", 5); },
324
+ "sql-builder/bad-cast");
325
+ rejects("cast rejects an empty type", function () { return sql.cast("x", ""); },
326
+ "sql-builder/bad-cast");
327
+
328
+ // ================= casWon field variants ============================
329
+ check("casWon reads the raw-mysql rowsAffected field",
330
+ sql.casWon({ rowsAffected: 1 }).won === true);
331
+ check("casWon prioritizes rowCount over a raw driver field",
332
+ sql.casWon({ rowCount: 1, changes: 5 }).won === true &&
333
+ sql.casWon({ rowCount: 1, changes: 5 }).rowCount === 1);
334
+ rejects("casWon treats a non-numeric row count as indeterminate", function () {
335
+ return sql.casWon({ rowCount: "1" });
336
+ }, "sql-builder/no-row-count");
337
+
338
+ // ================= output-gate boundaries (string / count) ===========
339
+ rejects("a bound string over the per-value ceiling is refused", function () {
340
+ return sql.insert("t").values({ a: "x".repeat(64 * 1024 * 1024 + 1) }).toSql();
341
+ }, "sql-builder/param-too-large");
342
+ rejects("a statement over the bind-parameter wire ceiling is refused", function () {
343
+ var big = [];
344
+ for (var i = 0; i < 65536; i += 1) big.push(i);
345
+ return sql.select("t").whereIn("id", big).toSql();
346
+ }, "sql-builder/too-many-params");
347
+ // A Date / bigint value binds cleanly (concrete-value param check passes).
348
+ check("Date + bigint bind as concrete params",
349
+ sql.insert("t").values({ at: new Date(0), n: 10n }).toSql().params.length === 2);
350
+
351
+ // ================= multi-row INSERT ==================================
352
+ var mr = sql.insert("t", { dialect: "postgres" })
353
+ .values([{ a: 1, b: sql.fn("NOW") }, { a: 2, b: 3 }]).toSql();
354
+ check("multi-row insert resolves each row's cells (fn per-row, no param)",
355
+ mr.sql === 'INSERT INTO t ("a", "b") VALUES (?, NOW()), (?, ?)' &&
356
+ mr.params.length === 3 && mr.params[0] === 1 && mr.params[1] === 2 && mr.params[2] === 3);
357
+ rejects("multi-row insert with a heterogeneous key set refused (no silent drop)", function () {
358
+ return sql.insert("t").values([{ a: 1, b: 2 }, { a: 3, c: 4 }]).toSql();
359
+ }, "sql-builder/missing-column");
360
+
361
+ // ================= upsert doUpdate / conflict paths ==================
362
+ check("upsert doUpdate({col: rawExpr}) draws its ? from exprParams",
363
+ sql.upsert("kv", { dialect: "postgres" }).columns(["k", "n"]).values({ k: "a", n: 1 })
364
+ .onConflict(["k"]).doUpdate({ n: 'EXCLUDED."n" + ?' }, [10]).toSql().sql ===
365
+ 'INSERT INTO kv ("k", "n") VALUES (?, ?) ON CONFLICT ("k") DO UPDATE SET "n" = EXCLUDED."n" + ?');
366
+ check("upsert doUpdate({col: '?'}) re-binds the column to a supplied param",
367
+ sql.upsert("kv", { dialect: "postgres" }).columns(["k", "n"]).values({ k: "a", n: 1 })
368
+ .onConflict(["k"]).doUpdate({ n: "?" }, [99]).toSql().params.join(",") === "a,1,99");
369
+ check("upsert conflictWhere fences the DO UPDATE on postgres",
370
+ sql.upsert("kv", { dialect: "postgres" }).columns(["k", "v"]).values({ k: "a", v: 5 })
371
+ .onConflict(["k"]).doUpdateFromExcluded(["v"]).conflictWhere('kv."v" < ?', [5]).toSql().sql
372
+ .indexOf('DO UPDATE SET "v" = EXCLUDED."v" WHERE kv."v" < ?') !== -1);
373
+ check("upsert mysql doNothing no-ops a key column to itself",
374
+ sql.upsert("kv", { dialect: "mysql" }).columns(["k", "v"]).values({ k: "a", v: 1 })
375
+ .onConflict(["k"]).doNothing().toSql().sql ===
376
+ "INSERT INTO kv (`k`, `v`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `k` = `k`");
377
+ rejects("upsert without a conflict action refused", function () {
378
+ return sql.upsert("kv").columns(["k"]).values({ k: "a" }).toSql();
379
+ }, "sql-builder/conflict-action");
380
+ rejects("upsert doUpdate without onConflict refused on postgres", function () {
381
+ return sql.upsert("kv", { dialect: "postgres" }).values({ k: "a", v: 1 }).doUpdateFromExcluded(["v"]).toSql();
382
+ }, "sql-builder/bad-conflict");
383
+ rejects("upsert values() rejects a non-object row", function () {
384
+ return sql.upsert("kv").columns(["k"]).values([1]);
385
+ }, "sql-builder/bad-values");
386
+
387
+ // ================= whereInArray dialect degrade + IS-non-null ========
388
+ check("whereInArray degrades to an expanded IN list on mysql",
389
+ sql.select("t", { dialect: "mysql" }).whereInArray("id", [1, 2, 3]).toSql().sql ===
390
+ "SELECT * FROM t WHERE `id` IN (?, ?, ?)");
391
+
392
+ // ================= createPolicy secondary branches ===================
393
+ check("createPolicy RESTRICTIVE with no role + no withCheck",
394
+ sql.createPolicy("p", "t", { permissive: false, using: "col = 1", allowLiterals: false },
395
+ { dialect: "postgres" }).sql === 'CREATE POLICY "p" ON "t" AS RESTRICTIVE FOR ALL USING (col = 1)');
396
+ rejects("createPolicy rejects an off-allowlist command", function () {
397
+ return sql.createPolicy("p", "t", { command: "TRUNCATE", using: "x" }, { dialect: "postgres" });
398
+ }, "sql-builder/bad-rls-command");
399
+
400
+ // ================= createVirtualTable no-tokenize + FK pluralizer =====
401
+ check("createVirtualTable without tokenize omits the tokenize clause",
402
+ sql.createVirtualTable("fts", { columns: ["a", "b"] }).sql ===
403
+ 'CREATE VIRTUAL TABLE IF NOT EXISTS "fts" USING fts5("a", "b")');
404
+ check("defineTable FK pluralizer: x-ending entity -> ...es (boxId -> boxes)",
405
+ sql.defineTable("t", [{ name: "boxId", type: "int" }], { dialect: "postgres" })
406
+ .statements[0].sql.indexOf("REFERENCES boxes") !== -1);
407
+ check("defineTable FK pluralizer: s-ending entity -> ...es (classId -> classes)",
408
+ sql.defineTable("t", [{ name: "classId", type: "int" }], { dialect: "postgres" })
409
+ .statements[0].sql.indexOf("REFERENCES classes") !== -1);
410
+
411
+ // ================= toExternalSql translates casts ($N + ::type) =======
412
+ check("toExternalSql renumbers ? -> $N and preserves the ::type suffix",
413
+ sql.insert("d", { dialect: "postgres" })
414
+ .values({ id: 1, meta: sql.cast('{"a":1}', "jsonb") }).toExternalSql("postgres").sql ===
415
+ 'INSERT INTO d ("id", "meta") VALUES ($1, $2::jsonb)');
416
+ }
417
+
25
418
  async function run() {
26
419
  var sql = b.sql;
27
420
  var safeSql = b.safeSql;
@@ -807,6 +1200,803 @@ async function run() {
807
1200
  edb.prepare("SELECT status FROM orders WHERE id = 7").get().status === "shipped");
808
1201
  edb.close();
809
1202
  }
1203
+
1204
+ // ==== ordinary builder surface (aggregates, joins, grouping, DDL option branches) ====
1205
+ await runBuilderSurface();
1206
+
1207
+ // ==== error / adversarial / defensive / option-default branch coverage ====
1208
+ runDialectTypeAndErrorBranches();
1209
+ runJsonbAndWhereFamilyBranches();
1210
+ runRawFragmentAndEmitBranches();
1211
+ runColumnGateCteAndProjectionBranches();
1212
+ runInsertUpdateDeleteBranches();
1213
+ runUpsertBranches();
1214
+ runDdlBranches();
1215
+ runRlsCatalogPragmaDefineBranches();
1216
+ }
1217
+
1218
+ // The framework's dialect / logical-type normalizers reject an off-allowlist
1219
+ // dialect at the config-time entry point, map every logical DDL type token to
1220
+ // its dialect-final form, and refuse a non-identifier in identifier position.
1221
+ function runDialectTypeAndErrorBranches() {
1222
+ var sql = b.sql;
1223
+
1224
+ // Off-allowlist dialect throws at the entry point (every verb / DDL routes
1225
+ // through _normDialect).
1226
+ rejects("select on an unknown dialect refused", function () {
1227
+ return sql.select("t", { dialect: "oracle" });
1228
+ }, "sql-builder/bad-dialect");
1229
+ rejects("createTable on an unknown dialect refused", function () {
1230
+ return sql.createTable("t", [{ name: "a", type: "int" }], { dialect: "db2" });
1231
+ }, "sql-builder/bad-dialect");
1232
+
1233
+ // The SqlBuilderError public constructor defaults its code when none is
1234
+ // supplied (the fallback that keeps `.code` always present).
1235
+ check("SqlBuilderError defaults its code",
1236
+ new sql.SqlBuilderError("boom").code === "sql-builder/invalid");
1237
+ check("SqlBuilderError keeps an explicit code",
1238
+ new sql.SqlBuilderError("boom", "sql-builder/custom").code === "sql-builder/custom");
1239
+
1240
+ // Logical DDL types map to their dialect-final tokens - the binary / real /
1241
+ // numeric / timestamp / json families across the three dialects.
1242
+ check("blob -> BYTEA on postgres",
1243
+ sql.createTable("t", [{ name: "d", type: "blob" }], { dialect: "postgres" }).sql ===
1244
+ 'CREATE TABLE IF NOT EXISTS t ("d" BYTEA)');
1245
+ check("blob -> LONGBLOB on mysql",
1246
+ sql.createTable("t", [{ name: "d", type: "blob" }], { dialect: "mysql" }).sql ===
1247
+ "CREATE TABLE IF NOT EXISTS t (`d` LONGBLOB)");
1248
+ check("bytea alias -> BLOB on sqlite",
1249
+ sql.createTable("t", [{ name: "d", type: "bytea" }]).sql ===
1250
+ 'CREATE TABLE IF NOT EXISTS t ("d" BLOB)');
1251
+ check("binary alias -> LONGBLOB on mysql",
1252
+ sql.createTable("t", [{ name: "d", type: "binary" }], { dialect: "mysql" }).sql ===
1253
+ "CREATE TABLE IF NOT EXISTS t (`d` LONGBLOB)");
1254
+ check("float -> REAL",
1255
+ sql.createTable("t", [{ name: "d", type: "float" }]).sql.indexOf('"d" REAL') !== -1);
1256
+ check("decimal -> NUMERIC",
1257
+ sql.createTable("t", [{ name: "d", type: "decimal" }]).sql.indexOf('"d" NUMERIC') !== -1);
1258
+ check("timestamp -> TIMESTAMP",
1259
+ sql.createTable("t", [{ name: "d", type: "timestamp" }]).sql.indexOf('"d" TIMESTAMP') !== -1);
1260
+ check("json -> JSON on mysql",
1261
+ sql.createTable("t", [{ name: "d", type: "json" }], { dialect: "mysql" }).sql.indexOf("`d` JSON") !== -1);
1262
+
1263
+ // A non-string / empty column name is refused in identifier position - both
1264
+ // the list-validated path (columns) and the expression path (orderBy).
1265
+ rejects("columns([<non-string>]) refused (identifier validate)", function () {
1266
+ return sql.insert("t").columns([5]);
1267
+ }, "sql-builder/bad-column");
1268
+ rejects("orderBy(<non-string>) refused (qualified-column validate)", function () {
1269
+ return sql.select("t").orderBy(123);
1270
+ }, "sql-builder/bad-column");
1271
+ }
1272
+
1273
+ // The JSONB operator family + the where-helper set: containment / key-existence
1274
+ // shape checks (Postgres-only), the FTS MATCH operator through _cmp, the OR
1275
+ // object / 3-arg forms, and the array / json_each / between membership helpers.
1276
+ function runJsonbAndWhereFamilyBranches() {
1277
+ var sql = b.sql;
1278
+ var pg = function () { return sql.select("t", { dialect: "postgres" }); };
1279
+
1280
+ // @> containment: a JSON-string operand is parsed + validated; an object
1281
+ // operand is walked then canonically stringified; a non-JSON string refuses.
1282
+ check("where @> with an object operand binds canonical JSON",
1283
+ JSON.stringify(pg().where("meta", "@>", { a: 1 }).toSql().params) === '["{\\"a\\":1}"]');
1284
+ check("where @> with a JSON-string operand binds it",
1285
+ pg().where("meta", "@>", '{"a":1}').toSql().sql === 'SELECT * FROM t WHERE "meta" @> ?');
1286
+ rejects("where @> with an invalid JSON string refused", function () {
1287
+ return pg().where("meta", "@>", "not json").toSql();
1288
+ }, "sql-builder/bad-jsonb-value");
1289
+
1290
+ // Key-existence operators: `?` needs a string key; `?|`/`?&` need a non-empty
1291
+ // array; they emit the jsonb_exists* function family (placeholder-safe).
1292
+ rejects("where '?' with a non-string key refused", function () {
1293
+ return pg().where("meta", "?", 123).toSql();
1294
+ }, "sql-builder/bad-jsonb-key");
1295
+ rejects("where '?|' with a non-array refused", function () {
1296
+ return pg().where("meta", "?|", "x").toSql();
1297
+ }, "sql-builder/bad-jsonb-keys");
1298
+ rejects("where '?&' with an empty array refused", function () {
1299
+ return pg().where("meta", "?&", []).toSql();
1300
+ }, "sql-builder/bad-jsonb-keys");
1301
+ check("where '?&' emits jsonb_exists_all binding the key array",
1302
+ pg().where("meta", "?&", ["a", "b"]).toSql().sql ===
1303
+ 'SELECT * FROM t WHERE jsonb_exists_all("meta", ?)');
1304
+ check("where '?' emits jsonb_exists binding the single key",
1305
+ pg().where("meta", "?", "k").toSql().sql ===
1306
+ 'SELECT * FROM t WHERE jsonb_exists("meta", ?)');
1307
+
1308
+ // The FTS MATCH operator through the generic whereOp path: non-sqlite refuses,
1309
+ // an empty query string refuses, a valid one binds.
1310
+ rejects("whereOp(col, 'MATCH', ...) on postgres refused", function () {
1311
+ return pg().whereOp("c", "MATCH", "x").toSql();
1312
+ }, "sql-builder/match-sqlite-only");
1313
+ rejects("whereOp(col, 'MATCH', '') refused (empty query)", function () {
1314
+ return sql.select("t").whereOp("c", "MATCH", "").toSql();
1315
+ }, "sql-builder/bad-match");
1316
+ check("whereMatch binds the FTS query as one placeholder",
1317
+ sql.select("t").whereMatch("fts", "hello").toSql().sql ===
1318
+ 'SELECT * FROM t WHERE "fts" MATCH ?');
1319
+ check("whereOp(col, 'MATCH', term) on sqlite binds the query",
1320
+ sql.select("t").whereOp("fts", "MATCH", "hello").toSql().sql ===
1321
+ 'SELECT * FROM t WHERE "fts" MATCH ?');
1322
+ check("orWhereMatch OR-joins an FTS MATCH on sqlite",
1323
+ sql.select("t").where("a", 1).orWhereMatch("fts", "x").toSql().sql ===
1324
+ 'SELECT * FROM t WHERE "a" = ? OR "fts" MATCH ?');
1325
+ rejects("orWhereMatch on a non-sqlite dialect refused", function () {
1326
+ return sql.select("t", { dialect: "postgres" }).orWhereMatch("fts", "x");
1327
+ }, "sql-builder/match-sqlite-only");
1328
+ rejects("orWhereMatch with an empty query refused", function () {
1329
+ return sql.select("t").orWhereMatch("fts", "");
1330
+ }, "sql-builder/bad-match");
1331
+
1332
+ // orWhere object-form fans out to OR-joined equalities; orWhere 3-arg keeps
1333
+ // the operator.
1334
+ check("orWhere({obj}) OR-joins each key equality",
1335
+ sql.select("t").where("a", 1).orWhere({ b: 2, c: 3 }).toSql().sql ===
1336
+ 'SELECT * FROM t WHERE "a" = ? OR "b" = ? OR "c" = ?');
1337
+ check("orWhere(field, op, value) keeps the operator",
1338
+ sql.select("t").where("a", 1).orWhere("b", ">", 2).toSql().sql ===
1339
+ 'SELECT * FROM t WHERE "a" = ? OR "b" > ?');
1340
+
1341
+ // Array / json_each / between membership helpers.
1342
+ check("whereBetween emits a BETWEEN pair",
1343
+ sql.select("t").whereBetween("age", 18, 65).toSql().sql ===
1344
+ 'SELECT * FROM t WHERE "age" BETWEEN ? AND ?');
1345
+ check("whereInArray on postgres binds the whole array to = ANY(?)",
1346
+ sql.select("t", { dialect: "postgres" }).whereInArray("id", [1, 2, 3]).toSql().sql ===
1347
+ 'SELECT * FROM t WHERE "id" = ANY(?)');
1348
+ rejects("whereInArray with an undefined element refused", function () {
1349
+ return sql.select("t").whereInArray("id", [1, undefined]);
1350
+ }, "sql-builder/bad-in-value");
1351
+ check("whereInJsonEach unrolls a JSON-array string via json_each",
1352
+ sql.select("t").whereInJsonEach("id", "[1,2,3]").toSql().sql ===
1353
+ 'SELECT * FROM t WHERE "id" IN (SELECT value FROM json_each(?))');
1354
+ rejects("whereInJsonEach with a non-string refused", function () {
1355
+ return sql.select("t").whereInJsonEach("id", 5);
1356
+ }, "sql-builder/bad-json-each");
1357
+ rejects("whereSub with a non-builder subquery refused", function () {
1358
+ return sql.select("t").whereSub("c", "=", 5);
1359
+ }, "sql-builder/bad-subquery");
1360
+ rejects("whereLike with an unknown mode refused", function () {
1361
+ return sql.select("t").whereLike("n", "x", "weird");
1362
+ }, "sql-builder/bad-like-mode");
1363
+
1364
+ // `col != NULL` / `col <> NULL` are UNKNOWN in SQL - refused like `= NULL`.
1365
+ rejects("where(col, '!=', null) refused (never true in SQL)", function () {
1366
+ return sql.select("t").where("a", "!=", null);
1367
+ }, "sql-builder/null-equality");
1368
+ rejects("where(col, '<>', null) refused (never true in SQL)", function () {
1369
+ return sql.select("t").where("a", "<>", null);
1370
+ }, "sql-builder/null-equality");
1371
+ }
1372
+
1373
+ // The raw-fragment guard's shape / parity checks and the final output gate's
1374
+ // param-shape refusals + the positional-translation terminal.
1375
+ function runRawFragmentAndEmitBranches() {
1376
+ var sql = b.sql;
1377
+
1378
+ rejects("whereRaw with a non-string sql refused", function () {
1379
+ return sql.select("t").whereRaw(123, []);
1380
+ }, "sql-builder/bad-raw");
1381
+ rejects("whereRaw with an empty sql refused", function () {
1382
+ return sql.select("t").whereRaw("");
1383
+ }, "sql-builder/bad-raw");
1384
+ check("whereRaw coerces a scalar param into a one-element bind list",
1385
+ JSON.stringify(sql.select("t").whereRaw("c = ?", 5).toSql().params) === "[5]");
1386
+ check("whereRaw with no params + zero placeholders binds nothing",
1387
+ sql.select("t").whereRaw('"a" IS NOT NULL').toSql().params.length === 0);
1388
+ rejects("whereRaw placeholder/param count mismatch refused", function () {
1389
+ return sql.select("t").whereRaw("c = ?", []).toSql();
1390
+ }, "sql-builder/placeholder-mismatch");
1391
+ // A raw fragment carrying a double-quoted identifier exercises the
1392
+ // quote-skipping pass of the raw JSONB-key-operator scanner - including a
1393
+ // doubled-quote escape inside the identifier.
1394
+ check("whereRaw passes a double-quoted identifier fragment through",
1395
+ sql.select("t").whereRaw('"c" = ?', [1]).toSql().sql ===
1396
+ 'SELECT * FROM t WHERE ("c" = ?)');
1397
+ check("whereRaw skips a doubled-quote escape inside a quoted identifier",
1398
+ sql.select("t").whereRaw('"a""b" = ?', [1]).toSql().sql ===
1399
+ 'SELECT * FROM t WHERE ("a""b" = ?)');
1400
+
1401
+ // The output gate refuses a param that is not a concrete bindable value.
1402
+ rejects("binding a function value refused at the output gate", function () {
1403
+ return sql.insert("t").values({ a: function () {} }).toSql();
1404
+ }, "sql-builder/bad-param-value");
1405
+ rejects("binding a symbol value refused at the output gate", function () {
1406
+ return sql.insert("t").values({ a: Symbol("x") }).toSql();
1407
+ }, "sql-builder/bad-param-value");
1408
+
1409
+ // toExternalSql: the free-function form on a builder + the chainable form
1410
+ // defaulting to the builder's own dialect both translate ? -> $N on postgres.
1411
+ check("toExternalSql(builder, 'postgres') translates ? -> $N",
1412
+ sql.toExternalSql(sql.select("t", { dialect: "postgres" }).where("a", 1), "postgres").sql ===
1413
+ 'SELECT * FROM t WHERE "a" = $1');
1414
+ check("builder.toExternalSql() defaults to the builder's dialect",
1415
+ sql.select("t", { dialect: "postgres" }).where("a", 1).toExternalSql().sql ===
1416
+ 'SELECT * FROM t WHERE "a" = $1');
1417
+ rejects("toExternalSql on a non-builder / non-result refused", function () {
1418
+ return sql.toExternalSql(42, "postgres");
1419
+ }, "sql-builder/bad-external-input");
1420
+ }
1421
+
1422
+ // The column-membership gate (opt + chainable + warn/reject/qualified), the WITH
1423
+ // (CTE) composition (raw body + recursive), and the SELECT projection helpers.
1424
+ function runColumnGateCteAndProjectionBranches() {
1425
+ var sql = b.sql;
1426
+
1427
+ rejects("allowedColumns opt must be a non-empty array", function () {
1428
+ return sql.select("t", { allowedColumns: [] });
1429
+ }, "sql-builder/bad-allowed-columns");
1430
+ rejects("allowedColumns() chainable form rejects an empty array", function () {
1431
+ return sql.select("t").allowedColumns([]);
1432
+ }, "sql-builder/bad-allowed-columns");
1433
+ check("columnGate 'warn' admits an unknown column",
1434
+ sql.select("t", { allowedColumns: ["a"], columnGateMode: "warn" })
1435
+ .columns(["a", "zzz"]).toSql().sql === 'SELECT "a", "zzz" FROM t');
1436
+ rejects("columnGate 'reject' (default with a set) refuses an unknown column", function () {
1437
+ return sql.select("t", { allowedColumns: ["a"] }).where("secret", 1).toSql();
1438
+ }, "sql-builder/unknown-column");
1439
+ check("column gate matches on the bare segment of a qualified column",
1440
+ sql.select("t", { allowedColumns: ["a"] }).where("x.a", 1).toSql().sql ===
1441
+ 'SELECT * FROM t WHERE "x"."a" = ?');
1442
+ rejects("columnGate mode must be reject | warn | off", function () {
1443
+ return sql.select("t").columnGate("bogus");
1444
+ }, "sql-builder/bad-gate-mode");
1445
+
1446
+ // A raw CTE body rides the same guarded-fragment path; a recursive CTE marks
1447
+ // the WITH clause RECURSIVE and concatenates the sub's params first.
1448
+ check("with(name, rawFragment, params) composes a guarded raw CTE",
1449
+ sql.select("main").with("c", '"a" > ?', [1]).columns(["x"]).toSql().sql ===
1450
+ 'WITH "c" AS ("a" > ?) SELECT "x" FROM main');
1451
+ check("withRecursive marks RECURSIVE and folds the sub-builder params first",
1452
+ sql.select("tree").withRecursive("tree", sql.select("nodes").where("parent", 5)).toSql().sql ===
1453
+ 'WITH RECURSIVE "tree" AS (SELECT * FROM nodes WHERE "parent" = ?) SELECT * FROM tree');
1454
+ check("with(name, rawFragment, params, { guardProfile }) honours the opt",
1455
+ sql.select("m").with("c", '"a" > ?', [1], { guardProfile: "strict" }).columns(["x"]).toSql().sql ===
1456
+ 'WITH "c" AS ("a" > ?) SELECT "x" FROM m');
1457
+ rejects("with(name, <non-builder-non-string>) refused", function () {
1458
+ return sql.select("t").with("c", 5);
1459
+ }, "sql-builder/bad-cte");
1460
+
1461
+ // Projection helpers: raw projection with a bound param, a raw join with a
1462
+ // bound param, a scalar subquery projection, and its non-builder refusal.
1463
+ check("selectRaw carries a bound param into the projection",
1464
+ JSON.stringify(sql.select("t").selectRaw("? + 1", [10]).toSql().params) === "[10]");
1465
+ check("joinRaw carries a bound param into the join",
1466
+ JSON.stringify(sql.select("t").joinRaw("INNER JOIN o ON o.x = ?", [3]).toSql().params) === "[3]");
1467
+ check("selectSub composes a scalar subquery projection",
1468
+ sql.select("t").selectSub(sql.select("o").count("*", "c"), "cnt").toSql().sql ===
1469
+ 'SELECT (SELECT COUNT(*) AS "c" FROM o) AS "cnt" FROM t');
1470
+ rejects("selectSub with a non-builder refused", function () {
1471
+ return sql.select("t").selectSub(5, "x");
1472
+ }, "sql-builder/bad-subquery");
1473
+ rejects("select columns() with a non-array refused", function () {
1474
+ return sql.select("t").columns("x");
1475
+ }, "sql-builder/bad-columns");
1476
+ check("groupBy accepts an array of columns",
1477
+ sql.select("t").groupBy(["a", "b"]).toSql().sql === 'SELECT * FROM t GROUP BY "a", "b"');
1478
+
1479
+ // Row-locking option branches (Postgres): FOR SHARE + SKIP LOCKED, FOR UPDATE
1480
+ // NOWAIT.
1481
+ check("forShare SKIP LOCKED emits on postgres",
1482
+ sql.select("t", { dialect: "postgres" }).where("a", 1).forShare({ skipLocked: true }).toSql().sql
1483
+ .indexOf("FOR SHARE SKIP LOCKED") !== -1);
1484
+ check("forUpdate NOWAIT emits on postgres",
1485
+ sql.select("t", { dialect: "postgres" }).where("a", 1).forUpdate({ noWait: true }).toSql().sql
1486
+ .indexOf("FOR UPDATE NOWAIT") !== -1);
1487
+ }
1488
+
1489
+ // INSERT column / value shape checks, UPDATE set forms, DELETE allow-no-where,
1490
+ // RETURNING normalization, and the INSERT...SELECT...WHERE conditional verb.
1491
+ function runInsertUpdateDeleteBranches() {
1492
+ var sql = b.sql;
1493
+
1494
+ // INSERT column / value shapes.
1495
+ rejects("insert columns() with a non-array refused", function () {
1496
+ return sql.insert("t").columns("x");
1497
+ }, "sql-builder/bad-columns");
1498
+ rejects("insert values(array) without a prior columns() refused", function () {
1499
+ return sql.insert("t").values([1, 2]);
1500
+ }, "sql-builder/no-columns");
1501
+ rejects("insert values(array) with a count mismatch refused", function () {
1502
+ return sql.insert("t").columns(["a", "b"]).values([1]);
1503
+ }, "sql-builder/value-count");
1504
+ check("insert values(array) aligned to columns() emits one row",
1505
+ sql.insert("t").columns(["a", "b"]).values([1, 2]).toSql().sql ===
1506
+ 'INSERT INTO t ("a", "b") VALUES (?, ?)');
1507
+ rejects("insert values() with a non-object non-array refused", function () {
1508
+ return sql.insert("t").values(5);
1509
+ }, "sql-builder/bad-values");
1510
+ rejects("insert values({}) empty row refused", function () {
1511
+ return sql.insert("t").values({});
1512
+ }, "sql-builder/empty-values");
1513
+ rejects("insert row missing a declared column refused", function () {
1514
+ return sql.insert("t").columns(["a", "b"]).values({ a: 1 });
1515
+ }, "sql-builder/missing-column");
1516
+ rejects("insert row with an extra column refused (no silent drop)", function () {
1517
+ return sql.insert("t").columns(["a"]).values({ a: 1, z: 9 });
1518
+ }, "sql-builder/extra-column");
1519
+ rejects("insert render without any values() row refused", function () {
1520
+ return sql.insert("t").columns(["a"]).toSql();
1521
+ }, "sql-builder/empty-values");
1522
+ check("insert values([{},{}]) emits a multi-row tuple list",
1523
+ sql.insert("t").values([{ a: 1 }, { a: 2 }]).toSql().sql ===
1524
+ 'INSERT INTO t ("a") VALUES (?), (?)');
1525
+
1526
+ // RETURNING normalization: "*" default + array + the MySQL refusal.
1527
+ check("insert returning(array) quotes each column",
1528
+ sql.insert("t", { dialect: "postgres" }).values({ a: 1 }).returning(["a", "b"]).toSql().sql
1529
+ .indexOf('RETURNING "a", "b"') !== -1);
1530
+ check("insert returning('*') emits RETURNING *",
1531
+ sql.insert("t", { dialect: "postgres" }).values({ a: 1 }).returning("*").toSql().sql
1532
+ .indexOf("RETURNING *") !== -1);
1533
+ check("insert returning(<single string>) wraps the one column",
1534
+ sql.insert("t", { dialect: "postgres" }).values({ a: 1 }).returning("a").toSql().sql
1535
+ .indexOf('RETURNING "a"') !== -1);
1536
+ rejects("RETURNING on a MySQL delete refused", function () {
1537
+ return sql.delete("t", { dialect: "mysql" }).where("a", 1).returning(["a"]).toSql();
1538
+ }, "sql-builder/returning-unsupported");
1539
+
1540
+ // UPDATE set forms.
1541
+ rejects("update set({}) empty object refused", function () {
1542
+ return sql.update("t").set({}).where("a", 1);
1543
+ }, "sql-builder/empty-set");
1544
+ check("update set(col, value) single-assignment form",
1545
+ sql.update("t").set("x", 5).where("a", 1).toSql().sql ===
1546
+ 'UPDATE t SET "x" = ? WHERE "a" = ?');
1547
+ check("update setRaw composes a guarded raw assignment",
1548
+ sql.update("t").setRaw("n", '"n" + ?', [1]).where("a", 1).toSql().sql ===
1549
+ 'UPDATE t SET "n" = "n" + ? WHERE "a" = ?');
1550
+
1551
+ // DELETE deliberate unconditional opt-in.
1552
+ check("delete allowNoWhere() emits an unconditional DELETE",
1553
+ sql.delete("t").allowNoWhere().toSql().sql === "DELETE FROM t");
1554
+
1555
+ // INSERT ... SELECT ... WHERE (the conditional append-only verb).
1556
+ rejects("insertSelectWhere columns() with a non-array refused", function () {
1557
+ return sql.insertSelectWhere("t").columns("x");
1558
+ }, "sql-builder/bad-columns");
1559
+ rejects("insertSelectWhere values(array) without columns() refused", function () {
1560
+ return sql.insertSelectWhere("t").values([1]);
1561
+ }, "sql-builder/no-columns");
1562
+ rejects("insertSelectWhere values(array) count mismatch refused", function () {
1563
+ return sql.insertSelectWhere("t").columns(["a", "b"]).values([1]);
1564
+ }, "sql-builder/value-count");
1565
+ check("insertSelectWhere values(array) + where emits a guarded conditional insert",
1566
+ sql.insertSelectWhere("t").columns(["a"]).values([1]).where("bal", ">", 0).toSql().sql ===
1567
+ 'INSERT INTO t ("a") SELECT ? WHERE "bal" > ?');
1568
+ rejects("insertSelectWhere values({}) empty object refused", function () {
1569
+ return sql.insertSelectWhere("t").values({});
1570
+ }, "sql-builder/empty-values");
1571
+ rejects("insertSelectWhere row missing a column refused", function () {
1572
+ return sql.insertSelectWhere("t").columns(["a", "b"]).values({ a: 1 });
1573
+ }, "sql-builder/missing-column");
1574
+ rejects("insertSelectWhere row with an extra column refused", function () {
1575
+ return sql.insertSelectWhere("t").columns(["a"]).values({ a: 1, z: 2 });
1576
+ }, "sql-builder/extra-column");
1577
+ rejects("insertSelectWhere values() with a bad shape refused", function () {
1578
+ return sql.insertSelectWhere("t").values(5);
1579
+ }, "sql-builder/bad-values");
1580
+ check("insertSelectWhere object row + whereExists composes a balance fence",
1581
+ sql.insertSelectWhere("ledger").values({ amt: -5 })
1582
+ .whereExists(sql.select("ledger").selectRaw("1").whereRaw('"bal" >= ?', [5])).toSql().sql ===
1583
+ 'INSERT INTO ledger ("amt") SELECT ? WHERE EXISTS (SELECT 1 FROM ledger WHERE ("bal" >= ?))');
1584
+ check("insertSelectWhere allowNoWhere() opts out of the guard requirement",
1585
+ sql.insertSelectWhere("t").values({ a: 1 }).allowNoWhere().toSql().sql ===
1586
+ 'INSERT INTO t ("a") SELECT ?');
1587
+ rejects("insertSelectWhere without a where() (and no opt-in) refused", function () {
1588
+ return sql.insertSelectWhere("t").values({ a: 1 }).toSql();
1589
+ }, "sql-builder/no-where");
1590
+ }
1591
+
1592
+ // The UPSERT verb - the dialect-divergence centrepiece: standard (Postgres /
1593
+ // SQLite) ON CONFLICT paths, the MySQL ON DUPLICATE KEY paths (including the
1594
+ // guarded IF-eval-order form + the auto-emitted readback SELECT), and every
1595
+ // conflict-action / value-shape refusal.
1596
+ function runUpsertBranches() {
1597
+ var sql = b.sql;
1598
+
1599
+ rejects("upsert columns() non-array refused", function () {
1600
+ return sql.upsert("t").columns("x");
1601
+ }, "sql-builder/bad-columns");
1602
+ rejects("upsert values() non-object refused", function () {
1603
+ return sql.upsert("t").values([1]);
1604
+ }, "sql-builder/bad-values");
1605
+ rejects("upsert values({}) empty refused", function () {
1606
+ return sql.upsert("t").values({});
1607
+ }, "sql-builder/empty-values");
1608
+ rejects("upsert row missing a column refused", function () {
1609
+ return sql.upsert("t").columns(["a", "b"]).values({ a: 1 });
1610
+ }, "sql-builder/missing-column");
1611
+ rejects("upsert row with an extra column refused", function () {
1612
+ return sql.upsert("t").columns(["a"]).values({ a: 1, z: 2 });
1613
+ }, "sql-builder/extra-column");
1614
+ rejects("upsert onConflict([]) empty refused", function () {
1615
+ return sql.upsert("t").onConflict([]);
1616
+ }, "sql-builder/bad-conflict");
1617
+ rejects("upsert doUpdateFromExcluded([]) empty refused", function () {
1618
+ return sql.upsert("t").doUpdateFromExcluded([]);
1619
+ }, "sql-builder/conflict-action");
1620
+ rejects("upsert doUpdate(<scalar>) refused", function () {
1621
+ return sql.upsert("t").doUpdate(5);
1622
+ }, "sql-builder/conflict-action");
1623
+ rejects("upsert doUpdate({}) empty map refused", function () {
1624
+ return sql.upsert("t").doUpdate({});
1625
+ }, "sql-builder/conflict-action");
1626
+ rejects("upsert render without values() refused", function () {
1627
+ return sql.upsert("t").doNothing().toSql();
1628
+ }, "sql-builder/empty-values");
1629
+ rejects("upsert render without a conflict action refused", function () {
1630
+ return sql.upsert("t").values({ id: 1 }).toSql();
1631
+ }, "sql-builder/conflict-action");
1632
+ rejects("upsert doUpdate without onConflict on postgres refused", function () {
1633
+ return sql.upsert("t", { dialect: "postgres" }).values({ id: 1, n: 2 })
1634
+ .doUpdateFromExcluded(["n"]).toSql();
1635
+ }, "sql-builder/bad-conflict");
1636
+
1637
+ // Standard (Postgres / SQLite) conflict actions.
1638
+ var pgU = function () { return sql.upsert("t", { dialect: "postgres" }); };
1639
+ check("upsert DO UPDATE SET col = EXCLUDED.col",
1640
+ pgU().values({ id: 1, n: 2 }).onConflict(["id"]).doUpdateFromExcluded(["n"]).toSql().sql ===
1641
+ 'INSERT INTO t ("id", "n") VALUES (?, ?) ON CONFLICT ("id") DO UPDATE SET "n" = EXCLUDED."n"');
1642
+ check("upsert onConflict(<single string>) wraps to a one-key target",
1643
+ pgU().values({ id: 1, n: 2 }).onConflict("id").doUpdateFromExcluded(["n"]).toSql().sql
1644
+ .indexOf('ON CONFLICT ("id")') !== -1);
1645
+ check("upsert doUpdate(<array>) delegates to doUpdateFromExcluded",
1646
+ pgU().values({ id: 1, n: 2 }).onConflict(["id"]).doUpdate(["n"]).toSql().sql ===
1647
+ 'INSERT INTO t ("id", "n") VALUES (?, ?) ON CONFLICT ("id") DO UPDATE SET "n" = EXCLUDED."n"');
1648
+ check("upsert doUpdate scalar exprParams is coerced to a one-element list",
1649
+ JSON.stringify(pgU().values({ id: 1, n: 2 }).onConflict(["id"]).doUpdate({ n: "?" }, 7)
1650
+ .toSql().params) === "[1,2,7]");
1651
+ check("upsert DO NOTHING without an onConflict target emits a bare ON CONFLICT",
1652
+ pgU().values({ id: 1 }).doNothing().toSql().sql ===
1653
+ 'INSERT INTO t ("id") VALUES (?) ON CONFLICT DO NOTHING');
1654
+ check("upsert doUpdate({col:'?'}) re-binds a supplied param",
1655
+ JSON.stringify(pgU().values({ id: 1, n: 2 }).onConflict(["id"]).doUpdate({ n: "?" }, [9])
1656
+ .toSql().params) === "[1,2,9]");
1657
+ check("upsert doUpdate({col:rawExpr}) composes a guarded raw assignment",
1658
+ pgU().values({ id: 1, n: 2 }).onConflict(["id"]).doUpdate({ n: 'EXCLUDED."n" + ?' }, [1])
1659
+ .toSql().sql.indexOf('DO UPDATE SET "n" = EXCLUDED."n" + ?') !== -1);
1660
+ rejects("upsert doUpdate expr that is neither '?' nor a string refused (standard)", function () {
1661
+ return pgU().values({ id: 1, n: 2 }).onConflict(["id"]).doUpdate({ n: 5 }).toSql();
1662
+ }, "sql-builder/conflict-action");
1663
+ check("upsert DO NOTHING on postgres",
1664
+ pgU().values({ id: 1 }).onConflict(["id"]).doNothing().toSql().sql ===
1665
+ 'INSERT INTO t ("id") VALUES (?) ON CONFLICT ("id") DO NOTHING');
1666
+ check("upsert conflictWhere fences the DO UPDATE",
1667
+ pgU().values({ id: 1, n: 2 }).onConflict(["id"]).doUpdateFromExcluded(["n"])
1668
+ .conflictWhere('EXCLUDED."n" > "t"."n"', []).toSql().sql
1669
+ .indexOf('WHERE EXCLUDED."n" > "t"."n"') !== -1);
1670
+
1671
+ // MySQL ON DUPLICATE KEY paths.
1672
+ var myU = function () { return sql.upsert("t", { dialect: "mysql" }); };
1673
+ check("upsert MySQL DO NOTHING no-ops a key column",
1674
+ myU().values({ id: 1, n: 2 }).onConflict(["id"]).doNothing().toSql().sql ===
1675
+ "INSERT INTO t (`id`, `n`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `id` = `id`");
1676
+ check("upsert MySQL update-from-excluded emits VALUES(col)",
1677
+ myU().values({ id: 1, n: 2 }).doUpdateFromExcluded(["n"]).toSql().sql
1678
+ .indexOf("ON DUPLICATE KEY UPDATE `n` = VALUES(`n`)") !== -1);
1679
+ check("upsert MySQL doUpdate({col:'?'}) re-binds",
1680
+ myU().values({ id: 1, n: 2 }).doUpdate({ n: "?" }, [7]).toSql().sql
1681
+ .indexOf("ON DUPLICATE KEY UPDATE `n` = ?") !== -1);
1682
+ check("upsert MySQL doUpdate({col:rawExpr}) composes a guarded raw assignment",
1683
+ myU().values({ id: 1, n: 2 }).doUpdate({ n: '"n" + ?' }, [1]).toSql().sql
1684
+ .indexOf('ON DUPLICATE KEY UPDATE `n` = "n" + ?') !== -1);
1685
+ rejects("upsert MySQL doUpdate expr that is neither '?' nor a string refused", function () {
1686
+ return myU().values({ id: 1, n: 2 }).doUpdate({ n: 5 }).toSql();
1687
+ }, "sql-builder/conflict-action");
1688
+ check("upsert MySQL readback without an onConflict key falls back to the first column",
1689
+ myU().values({ id: 1, n: 2 }).doUpdateFromExcluded(["n"]).returning(["id"]).toSql()
1690
+ .readbackSql.sql === "SELECT `id` FROM t WHERE `id` = ?");
1691
+ rejects("upsert MySQL readback with a conflict key outside the value set refused", function () {
1692
+ return myU().columns(["a", "b"]).values({ a: 1, b: 2 }).onConflict(["c"])
1693
+ .doUpdateFromExcluded(["b"]).returning(["a"]).toSql();
1694
+ }, "sql-builder/bad-conflict");
1695
+ check("upsert MySQL guarded conflictWhere wraps each SET in IF(...) and orders the guard column last",
1696
+ myU().values({ id: 1, ver: 2, n: 3 }).doUpdate({ n: "?", ver: "?" }, [3, 2])
1697
+ .conflictWhere('"ver" < ?', [2], { guardColumn: "ver" }).toSql().sql
1698
+ .indexOf("`n` = IF(") !== -1);
1699
+ check("upsert MySQL guarded conflictWhere with the guard column declared first still orders it last",
1700
+ myU().values({ id: 1, ver: 2, n: 3 }).doUpdate({ ver: "?", n: "?" }, [2, 3])
1701
+ .conflictWhere('"ver" < ?', [2], { guardColumn: "ver" }).toSql().sql
1702
+ .indexOf('`n` = IF("ver" < ?, ?, `n`), `ver` = IF(') !== -1);
1703
+ check("upsert MySQL guarded conflictWhere without a guardColumn keeps declared order",
1704
+ myU().values({ id: 1, n: 3 }).doUpdate({ n: "?" }, [3])
1705
+ .conflictWhere('"n" < ?', [3]).toSql().sql.indexOf('`n` = IF("n" < ?, ?, `n`)') !== -1);
1706
+ check("upsert MySQL DO NOTHING without an onConflict no-ops the first column",
1707
+ myU().values({ id: 1, n: 2 }).doNothing().toSql().sql ===
1708
+ "INSERT INTO t (`id`, `n`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `id` = `id`");
1709
+ check("upsert MySQL returning() auto-emits a keyed readback SELECT",
1710
+ myU().values({ id: 1, n: 2 }).onConflict(["id"]).doUpdateFromExcluded(["n"]).returning(["id", "n"])
1711
+ .toSql().readbackSql.sql === "SELECT `id`, `n` FROM t WHERE `id` = ?");
1712
+ rejects("upsert MySQL readback on a server-function conflict key refused", function () {
1713
+ return myU().values({ id: sql.fn("CURRENT_TIMESTAMP"), n: 2 }).onConflict(["id"])
1714
+ .doUpdateFromExcluded(["n"]).returning("*").toSql();
1715
+ }, "sql-builder/bad-conflict");
1716
+ }
1717
+
1718
+ // DDL builders - createTable (auto-increment / references / composite PK /
1719
+ // defaults / verbatim constraints), createIndex, alterTable, dropTable, and the
1720
+ // sqlite FTS5 virtual-table builder.
1721
+ function runDdlBranches() {
1722
+ var sql = b.sql;
1723
+
1724
+ rejects("createTable with a non-array columns refused", function () {
1725
+ return sql.createTable("t", "x");
1726
+ }, "sql-builder/bad-columns");
1727
+ rejects("createTable with a non-object column spec refused", function () {
1728
+ return sql.createTable("t", ["x"]);
1729
+ }, "sql-builder/bad-column");
1730
+ check("createTable autoIncrement -> BIGSERIAL on postgres",
1731
+ sql.createTable("t", [{ name: "id", autoIncrement: true }], { dialect: "postgres" }).sql ===
1732
+ 'CREATE TABLE IF NOT EXISTS t ("id" BIGSERIAL PRIMARY KEY)');
1733
+ check("createTable serial -> AUTO_INCREMENT on mysql",
1734
+ sql.createTable("t", [{ name: "id", serial: true }], { dialect: "mysql" }).sql ===
1735
+ "CREATE TABLE IF NOT EXISTS t (`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY)");
1736
+ rejects("createTable autoIncrement + default is contradictory", function () {
1737
+ return sql.createTable("t", [{ name: "id", autoIncrement: true, default: 1 }]);
1738
+ }, "sql-builder/bad-column");
1739
+ check("createTable autoIncrement + verbatim constraints appends the guarded fragment",
1740
+ sql.createTable("t", [{ name: "id", autoIncrement: true, constraints: "CHECK (id > 0)" }]).sql
1741
+ .indexOf("INTEGER PRIMARY KEY AUTOINCREMENT CHECK (id > 0)") !== -1);
1742
+ check("createTable column notNull + unique + default compose",
1743
+ sql.createTable("t", [{ name: "e", type: "text", notNull: true, unique: true, default: "x" }]).sql ===
1744
+ 'CREATE TABLE IF NOT EXISTS t ("e" TEXT NOT NULL UNIQUE DEFAULT \'x\')');
1745
+ check("createTable references (string) defaults to (id)",
1746
+ sql.createTable("t", [{ name: "uid", type: "int", references: "users" }]).sql
1747
+ .indexOf('REFERENCES users ("id")') !== -1);
1748
+ check("createTable references object with ON DELETE / ON UPDATE actions",
1749
+ sql.createTable("t", [{ name: "uid", type: "int",
1750
+ references: { table: "users", column: "id", onDelete: "CASCADE", onUpdate: "RESTRICT" } }]).sql
1751
+ .indexOf("ON DELETE CASCADE ON UPDATE RESTRICT") !== -1);
1752
+ rejects("createTable references without a table refused", function () {
1753
+ return sql.createTable("t", [{ name: "uid", type: "int", references: {} }]);
1754
+ }, "sql-builder/bad-references");
1755
+ rejects("createTable references with an empty table name refused", function () {
1756
+ return sql.createTable("t", [{ name: "uid", type: "int", references: { table: "" } }]);
1757
+ }, "sql-builder/bad-references");
1758
+ rejects("createTable references with a falsy non-false spec refused", function () {
1759
+ return sql.createTable("t", [{ name: "uid", type: "int", references: 0 }]);
1760
+ }, "sql-builder/bad-references");
1761
+ rejects("createTable references with an off-allowlist FK action refused", function () {
1762
+ return sql.createTable("t", [{ name: "uid", type: "int",
1763
+ references: { table: "users", onDelete: "EXPLODE" } }]);
1764
+ }, "sql-builder/bad-fk-action");
1765
+ check("createTable composite opts.primaryKey emits a table-level PK",
1766
+ sql.createTable("t", [{ name: "a", type: "int" }, { name: "b", type: "int" }],
1767
+ { primaryKey: ["a", "b"] }).sql.indexOf('PRIMARY KEY ("a", "b")') !== -1);
1768
+ rejects("createTable column PK + composite PK is refused (double PRIMARY KEY)", function () {
1769
+ return sql.createTable("t", [{ name: "a", type: "int", primaryKey: true }], { primaryKey: ["a"] });
1770
+ }, "sql-builder/bad-column");
1771
+ rejects("createTable column default of an unsupported type refused", function () {
1772
+ return sql.createTable("t", [{ name: "a", type: "int", default: {} }]);
1773
+ }, "sql-builder/bad-default");
1774
+ check("createTable ifNotExists:false drops the IF NOT EXISTS",
1775
+ sql.createTable("t", [{ name: "a", type: "int" }], { ifNotExists: false }).sql ===
1776
+ 'CREATE TABLE t ("a" INTEGER)');
1777
+
1778
+ // createIndex option branches.
1779
+ rejects("createIndex with a non-array columns refused", function () {
1780
+ return sql.createIndex("i", "t", []);
1781
+ }, "sql-builder/bad-columns");
1782
+ rejects("createIndex partial (where) on mysql refused", function () {
1783
+ return sql.createIndex("i", "t", ["a"], { dialect: "mysql", where: "a = 1" });
1784
+ }, "sql-builder/partial-index-unsupported");
1785
+ check("createIndex partial where + whereParams on postgres",
1786
+ sql.createIndex("i", "t", ["a"], { dialect: "postgres", where: '"a" > ?', whereParams: [1],
1787
+ allowLiterals: false }).sql.indexOf('WHERE "a" > ?') !== -1);
1788
+ check("createIndex unique + ifNotExists:false",
1789
+ sql.createIndex("i", "t", ["a"], { unique: true, ifNotExists: false }).sql ===
1790
+ 'CREATE UNIQUE INDEX "i" ON t ("a")');
1791
+
1792
+ // alterTable change descriptors.
1793
+ rejects("alterTable without a change descriptor refused", function () {
1794
+ return sql.alterTable("t", null);
1795
+ }, "sql-builder/bad-alter");
1796
+ rejects("alterTable addColumn without a name refused", function () {
1797
+ return sql.alterTable("t", { addColumn: { type: "int" } });
1798
+ }, "sql-builder/bad-column");
1799
+ check("alterTable addColumn with notNull / unique / default",
1800
+ sql.alterTable("t", { addColumn: { name: "c", type: "int", notNull: true, unique: true, default: 3 } })
1801
+ .sql === 'ALTER TABLE t ADD COLUMN "c" INTEGER NOT NULL UNIQUE DEFAULT 3');
1802
+ check("alterTable dropColumn quotes the column",
1803
+ sql.alterTable("t", { dropColumn: "c" }).sql === 'ALTER TABLE t DROP COLUMN "c"');
1804
+ check("alterTable renameColumn quotes both names",
1805
+ sql.alterTable("t", { renameColumn: { from: "a", to: "b" } }).sql ===
1806
+ 'ALTER TABLE t RENAME COLUMN "a" TO "b"');
1807
+ rejects("alterTable renameColumn without both from/to refused", function () {
1808
+ return sql.alterTable("t", { renameColumn: { from: "a" } });
1809
+ }, "sql-builder/bad-alter");
1810
+ rejects("alterTable with an unknown change refused", function () {
1811
+ return sql.alterTable("t", { foo: 1 });
1812
+ }, "sql-builder/bad-alter");
1813
+
1814
+ // dropTable option branches.
1815
+ check("dropTable cascade on postgres",
1816
+ sql.dropTable("t", { dialect: "postgres", cascade: true }).sql === "DROP TABLE IF EXISTS t CASCADE");
1817
+ check("dropTable cascade is ignored on a non-postgres dialect",
1818
+ sql.dropTable("t", { cascade: true }).sql === "DROP TABLE IF EXISTS t");
1819
+ check("dropTable ifExists:false drops the IF EXISTS",
1820
+ sql.dropTable("t", { ifExists: false }).sql === "DROP TABLE t");
1821
+ check("dropTable with no opts defaults to sqlite + IF EXISTS",
1822
+ sql.dropTable("t").sql === "DROP TABLE IF EXISTS t");
1823
+
1824
+ rejects("createVirtualTable with no opts refused (no columns)", function () {
1825
+ return sql.createVirtualTable("f");
1826
+ }, "sql-builder/bad-columns");
1827
+
1828
+ // sqlite FTS5 virtual table.
1829
+ rejects("createVirtualTable on a non-sqlite dialect refused", function () {
1830
+ return sql.createVirtualTable("f", { dialect: "postgres", columns: ["a"] });
1831
+ }, "sql-builder/vtable-sqlite-only");
1832
+ rejects("createVirtualTable with an empty columns array refused", function () {
1833
+ return sql.createVirtualTable("f", { columns: [] });
1834
+ }, "sql-builder/bad-columns");
1835
+ check("createVirtualTable emits UNINDEXED + an allowlisted tokenize clause",
1836
+ sql.createVirtualTable("f", { columns: [{ name: "id", unindexed: true }, "body"],
1837
+ tokenize: "unicode61 remove_diacritics 2" }).sql ===
1838
+ 'CREATE VIRTUAL TABLE IF NOT EXISTS "f" USING fts5("id" UNINDEXED, "body", ' +
1839
+ "tokenize = 'unicode61 remove_diacritics 2')");
1840
+ rejects("createVirtualTable with an unsupported per-column option refused", function () {
1841
+ return sql.createVirtualTable("f", { columns: [{ name: "id", weird: 1 }] });
1842
+ }, "sql-builder/bad-vtable-column");
1843
+ rejects("createVirtualTable with a non-built-in tokenizer refused", function () {
1844
+ return sql.createVirtualTable("f", { columns: ["a"], tokenize: "customtok" });
1845
+ }, "sql-builder/bad-tokenize");
1846
+ rejects("createVirtualTable with an off-allowlist tokenize argument refused", function () {
1847
+ return sql.createVirtualTable("f", { columns: ["a"], tokenize: "porter zzz" });
1848
+ }, "sql-builder/bad-tokenize");
1849
+ rejects("createVirtualTable with a non-string tokenize refused", function () {
1850
+ return sql.createVirtualTable("f", { columns: ["a"], tokenize: 5 });
1851
+ }, "sql-builder/bad-tokenize");
1852
+ check("createVirtualTable ifNotExists:false drops the IF NOT EXISTS",
1853
+ sql.createVirtualTable("f", { columns: ["a"], ifNotExists: false }).sql ===
1854
+ 'CREATE VIRTUAL TABLE "f" USING fts5("a")');
1855
+ check("createVirtualTable accepts a plain { name } column object (no UNINDEXED)",
1856
+ sql.createVirtualTable("f", { columns: [{ name: "body" }] }).sql ===
1857
+ 'CREATE VIRTUAL TABLE IF NOT EXISTS "f" USING fts5("body")');
1858
+ }
1859
+
1860
+ // Postgres RLS builders, the audited sqlite catalog / PRAGMA sub-API, and the
1861
+ // defineTable schema-optimizer's option branches.
1862
+ function runRlsCatalogPragmaDefineBranches() {
1863
+ var sql = b.sql;
1864
+
1865
+ // Row-Level Security (Postgres-only; every builder refuses a non-pg dialect).
1866
+ rejects("enableRowLevelSecurity on sqlite refused", function () {
1867
+ return sql.enableRowLevelSecurity("t", { dialect: "sqlite" });
1868
+ }, "sql-builder/rls-postgres-only");
1869
+ check("enableRowLevelSecurity force emits FORCE",
1870
+ sql.enableRowLevelSecurity("sessions", { force: true }).sql ===
1871
+ 'ALTER TABLE "sessions" FORCE ROW LEVEL SECURITY');
1872
+ check("enableRowLevelSecurity default emits ENABLE",
1873
+ sql.enableRowLevelSecurity("sessions").sql ===
1874
+ 'ALTER TABLE "sessions" ENABLE ROW LEVEL SECURITY');
1875
+ check("disableRowLevelSecurity quotes a schema-qualified table",
1876
+ sql.disableRowLevelSecurity("sessions", { schema: "public" }).sql ===
1877
+ 'ALTER TABLE "public"."sessions" DISABLE ROW LEVEL SECURITY');
1878
+ check("disableRowLevelSecurity with no opts defaults to postgres",
1879
+ sql.disableRowLevelSecurity("s").sql === 'ALTER TABLE "s" DISABLE ROW LEVEL SECURITY');
1880
+ rejects("disableRowLevelSecurity on mysql refused", function () {
1881
+ return sql.disableRowLevelSecurity("t", { dialect: "mysql" });
1882
+ }, "sql-builder/rls-postgres-only");
1883
+ rejects("createPolicy with no spec refused (no using predicate)", function () {
1884
+ return sql.createPolicy("p", "t");
1885
+ }, "sql-builder/bad-rls-predicate");
1886
+ check("dropPolicy with no opts defaults to postgres + IF EXISTS",
1887
+ sql.dropPolicy("p", "s").sql === 'DROP POLICY IF EXISTS "p" ON "s"');
1888
+ rejects("createPolicy on sqlite refused", function () {
1889
+ return sql.createPolicy("p", "t", { using: "x" }, { dialect: "sqlite" });
1890
+ }, "sql-builder/rls-postgres-only");
1891
+ rejects("createPolicy with an off-allowlist command refused", function () {
1892
+ return sql.createPolicy("p", "t", { command: "TRUNCATE", using: "1=1" });
1893
+ }, "sql-builder/bad-rls-command");
1894
+ rejects("createPolicy without a using predicate refused", function () {
1895
+ return sql.createPolicy("p", "t", {});
1896
+ }, "sql-builder/bad-rls-predicate");
1897
+ check("createPolicy composes the full clause order (RESTRICTIVE / role / USING / WITH CHECK)",
1898
+ sql.createPolicy("iso", "sessions", { role: "app_user", command: "SELECT", permissive: false,
1899
+ using: '"tenant_id" = ?', usingParams: [1], withCheck: '"tenant_id" = ?', withCheckParams: [1] },
1900
+ { schema: "public" }).sql ===
1901
+ 'CREATE POLICY "iso" ON "public"."sessions" AS RESTRICTIVE FOR SELECT TO "app_user" ' +
1902
+ 'USING ("tenant_id" = ?) WITH CHECK ("tenant_id" = ?)');
1903
+ check("dropPolicy IF EXISTS by default",
1904
+ sql.dropPolicy("iso", "sessions", { schema: "public" }).sql ===
1905
+ 'DROP POLICY IF EXISTS "iso" ON "public"."sessions"');
1906
+ check("dropPolicy ifExists:false drops the IF EXISTS",
1907
+ sql.dropPolicy("iso", "sessions", { ifExists: false }).sql ===
1908
+ 'DROP POLICY "iso" ON "sessions"');
1909
+ rejects("dropPolicy on mysql refused", function () {
1910
+ return sql.dropPolicy("p", "t", { dialect: "mysql" });
1911
+ }, "sql-builder/rls-postgres-only");
1912
+
1913
+ // Catalog sub-API.
1914
+ check("catalog.listTables emits the sqlite_master scan",
1915
+ sql.catalog.listTables().sql ===
1916
+ "SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'");
1917
+ check("catalog.tableExists binds the name as a parameter",
1918
+ JSON.stringify(sql.catalog.tableExists("audit").params) === '["audit"]');
1919
+ rejects("catalog.tableExists with an empty name refused", function () {
1920
+ return sql.catalog.tableExists("");
1921
+ }, "sql-builder/bad-table");
1922
+ check("catalog.tableInfo quotes the table into the PRAGMA",
1923
+ sql.catalog.tableInfo("audit").sql === 'PRAGMA table_info("audit")');
1924
+ rejects("catalog.tableInfo with a non-string name refused", function () {
1925
+ return sql.catalog.tableInfo(5);
1926
+ }, "sql-builder/bad-table");
1927
+ check("catalog.changes emits the changes() probe",
1928
+ sql.catalog.changes().sql === "SELECT changes() AS c");
1929
+ check("catalog.sampleRandom with a column list binds the limit",
1930
+ sql.catalog.sampleRandom("s", ["a", "b"], { limit: 5 }).sql ===
1931
+ 'SELECT "a", "b" FROM "s" ORDER BY RANDOM() LIMIT ?');
1932
+ check("catalog.sampleRandom without columns projects *",
1933
+ sql.catalog.sampleRandom("s", null, { limit: 5 }).sql ===
1934
+ 'SELECT * FROM "s" ORDER BY RANDOM() LIMIT ?');
1935
+ rejects("catalog.sampleRandom with an empty columns array refused", function () {
1936
+ return sql.catalog.sampleRandom("s", [], { limit: 5 });
1937
+ }, "sql-builder/bad-columns");
1938
+ rejects("catalog.sampleRandom with a non-positive limit refused", function () {
1939
+ return sql.catalog.sampleRandom("s", null, { limit: 0 });
1940
+ }, "sql-builder/bad-limit");
1941
+ rejects("catalog.sampleRandom with no opts refused (limit required)", function () {
1942
+ return sql.catalog.sampleRandom("s");
1943
+ }, "sql-builder/bad-limit");
1944
+
1945
+ // PRAGMA sub-API (narrow allowlist).
1946
+ rejects("pragma with an off-allowlist verb refused", function () {
1947
+ return sql.pragma("foo");
1948
+ }, "sql-builder/bad-pragma");
1949
+ rejects("pragma('table_info') routes callers to catalog.tableInfo", function () {
1950
+ return sql.pragma("table_info");
1951
+ }, "sql-builder/bad-pragma");
1952
+ check("pragma wal_checkpoint defaults to PASSIVE",
1953
+ sql.pragma("wal_checkpoint").sql === "PRAGMA wal_checkpoint(PASSIVE)");
1954
+ check("pragma wal_checkpoint with an allowlisted mode",
1955
+ sql.pragma("wal_checkpoint", "TRUNCATE").sql === "PRAGMA wal_checkpoint(TRUNCATE)");
1956
+ rejects("pragma wal_checkpoint with an off-allowlist mode refused", function () {
1957
+ return sql.pragma("wal_checkpoint", "NOPE");
1958
+ }, "sql-builder/bad-pragma-arg");
1959
+ check("pragma journal_mode read (no arg)",
1960
+ sql.pragma("journal_mode").sql === "PRAGMA journal_mode");
1961
+ check("pragma journal_mode set with an allowlisted token",
1962
+ sql.pragma("journal_mode", "WAL").sql === "PRAGMA journal_mode=WAL");
1963
+ check("pragma synchronous set with an allowlisted level",
1964
+ sql.pragma("synchronous", "NORMAL").sql === "PRAGMA synchronous=NORMAL");
1965
+ rejects("pragma journal_mode with an off-vocabulary arg refused", function () {
1966
+ return sql.pragma("journal_mode", "BOGUS");
1967
+ }, "sql-builder/bad-pragma-arg");
1968
+
1969
+ // defineTable schema optimizer.
1970
+ rejects("defineTable with an empty spec refused", function () {
1971
+ return sql.defineTable("t", []);
1972
+ }, "sql-builder/bad-columns");
1973
+ rejects("defineTable with a non-object column refused", function () {
1974
+ return sql.defineTable("t", ["x"]);
1975
+ }, "sql-builder/bad-column");
1976
+ check("defineTable auto-PK/FK/index yields CREATE TABLE + two indexes",
1977
+ sql.defineTable("orders", [{ name: "userId", type: "int" }, { name: "email", type: "text",
1978
+ index: true }], { dialect: "postgres" }).statements.length === 3);
1979
+ check("defineTable with a composite opts.primaryKey suppresses the auto identity PK",
1980
+ sql.defineTable("t", [{ name: "a", type: "int" }, { name: "b", type: "int" }],
1981
+ { primaryKey: ["a", "b"] }).statements.length === 1);
1982
+ check("defineTable references:false opts a column out of FK inference",
1983
+ sql.defineTable("t", [{ name: "userId", type: "int", references: false }]).statements.length === 1);
1984
+ check("defineTable explicit opts.indexes honored with autoIndex off",
1985
+ sql.defineTable("t", [{ name: "a", type: "int" }],
1986
+ { autoIndex: false, indexes: [{ columns: ["a"], unique: true, name: "myidx" }] })
1987
+ .statements.length === 2);
1988
+ rejects("defineTable index entry without a columns array refused", function () {
1989
+ return sql.defineTable("t", [{ name: "a", type: "int" }], { indexes: [{ columns: [] }] });
1990
+ }, "sql-builder/bad-index");
1991
+ rejects("defineTable index referencing an undeclared column refused", function () {
1992
+ return sql.defineTable("t", [{ name: "a", type: "int" }], { indexes: [{ columns: ["zzz"] }] });
1993
+ }, "sql-builder/unknown-column");
1994
+ check("defineTable with default opts (no opts arg) builds a single statement",
1995
+ sql.defineTable("solo", [{ name: "x", type: "int" }]).statements.length === 1);
810
1996
  }
811
1997
 
812
1998
  module.exports = { run: run };
1999
+ if (require.main === module) {
2000
+ run().then(function () { console.log("OK"); })
2001
+ .catch(function (e) { console.error(e); process.exit(1); });
2002
+ }