@distrohelena/canton-typescript-sdk 0.1.4 → 0.1.6

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 (254) hide show
  1. package/README.md +333 -1
  2. package/dist/client/canton-client-options.d.ts +3 -0
  3. package/dist/client/canton-client-options.js +2 -0
  4. package/dist/client/service-registry.js +4 -3
  5. package/dist/core/errors/grpc-transport-error.d.ts +14 -0
  6. package/dist/core/errors/grpc-transport-error.js +76 -0
  7. package/dist/core/signing/sign-command-request.d.ts +4 -0
  8. package/dist/core/signing/sign-command-request.js +4 -0
  9. package/dist/core/signing/sign-command-result.d.ts +2 -0
  10. package/dist/core/signing/sign-command-result.js +9 -0
  11. package/dist/core/transports/transport.interface.d.ts +2 -2
  12. package/dist/core/types/canton-hash-purpose.d.ts +2 -1
  13. package/dist/core/types/canton-hash-purpose.js +1 -0
  14. package/dist/core/types/commands/create-and-exercise-command.js +1 -1
  15. package/dist/core/types/commands/exercise-by-key-command.js +2 -2
  16. package/dist/core/types/commands/exercise-command.js +2 -2
  17. package/dist/core/types/daml-numeric.d.ts +6 -0
  18. package/dist/core/types/daml-numeric.js +14 -0
  19. package/dist/core/types/daml-party.d.ts +6 -0
  20. package/dist/core/types/daml-party.js +14 -0
  21. package/dist/core/types/requests/create-decentralized-party-request.d.ts +41 -0
  22. package/dist/core/types/requests/create-decentralized-party-request.js +82 -0
  23. package/dist/core/types/requests/create-external-party-request.d.ts +42 -0
  24. package/dist/core/types/requests/create-external-party-request.js +47 -0
  25. package/dist/core/types/requests/finalize-decentralized-party-request.d.ts +39 -0
  26. package/dist/core/types/requests/finalize-decentralized-party-request.js +42 -0
  27. package/dist/core/types/requests/get-active-contracts-page-request.d.ts +15 -2
  28. package/dist/core/types/requests/get-active-contracts-page-request.js +4 -0
  29. package/dist/core/types/requests/submit-command-request.d.ts +2 -0
  30. package/dist/core/types/requests/submit-command-request.js +2 -0
  31. package/dist/core/types/topology/topology-signature-format.d.ts +2 -1
  32. package/dist/core/types/topology/topology-signature-format.js +1 -0
  33. package/dist/daml-lf/container/dar-archive-entry.d.ts +8 -0
  34. package/dist/daml-lf/container/dar-archive-entry.js +8 -0
  35. package/dist/daml-lf/container/dar-archive-loader.js +14 -0
  36. package/dist/daml-lf/container/dar-archive.d.ts +6 -0
  37. package/dist/daml-lf/container/dar-archive.js +4 -0
  38. package/dist/daml-lf/container/dar-source-bundle-loader.d.ts +5 -0
  39. package/dist/daml-lf/container/dar-source-bundle-loader.js +33 -0
  40. package/dist/daml-lf/container/dar-source-bundle.d.ts +45 -0
  41. package/dist/daml-lf/container/dar-source-bundle.js +11 -0
  42. package/dist/daml-lf/container/dar-source-file-entry.d.ts +8 -0
  43. package/dist/daml-lf/container/dar-source-file-entry.js +8 -0
  44. package/dist/daml-lf/daml-lf-compilation.d.ts +12 -0
  45. package/dist/daml-lf/daml-lf-compilation.js +35 -0
  46. package/dist/daml-lf/index.d.ts +11 -0
  47. package/dist/daml-lf/index.js +10 -0
  48. package/dist/daml-lf/interpreter/daml-lf-builtin-dispatch.d.ts +43 -0
  49. package/dist/daml-lf/interpreter/daml-lf-builtin-dispatch.js +933 -0
  50. package/dist/daml-lf/interpreter/daml-lf-evaluator.d.ts +95 -0
  51. package/dist/daml-lf/interpreter/daml-lf-evaluator.js +1131 -0
  52. package/dist/daml-lf/interpreter/daml-lf-interpreter-scaffold.d.ts +3 -0
  53. package/dist/daml-lf/interpreter/daml-lf-interpreter-scaffold.js +6 -1
  54. package/dist/daml-lf/interpreter/daml-lf-lexical-scope.d.ts +13 -0
  55. package/dist/daml-lf/interpreter/daml-lf-lexical-scope.js +46 -0
  56. package/dist/daml-lf/interpreter/daml-lf-runtime-frame.d.ts +16 -0
  57. package/dist/daml-lf/interpreter/daml-lf-runtime-frame.js +15 -0
  58. package/dist/daml-lf/interpreter/daml-lf-runtime-value.d.ts +21 -0
  59. package/dist/daml-lf/interpreter/daml-lf-runtime-value.js +4 -1
  60. package/dist/daml-lf/interpreter/daml-lf-step-kind.d.ts +7 -0
  61. package/dist/daml-lf/interpreter/daml-lf-step-kind.js +8 -0
  62. package/dist/daml-lf/interpreter/daml-lf-trace-sink.interface.d.ts +30 -0
  63. package/dist/daml-lf/interpreter/daml-lf-trace-sink.interface.js +1 -0
  64. package/dist/daml-lf/model/daml-lf-builtin-type.d.ts +3 -0
  65. package/dist/daml-lf/model/daml-lf-builtin-type.js +3 -0
  66. package/dist/daml-lf/model/daml-lf-choice.d.ts +5 -0
  67. package/dist/daml-lf/model/daml-lf-choice.js +4 -0
  68. package/dist/daml-lf/model/daml-lf-expression-path.d.ts +2 -0
  69. package/dist/daml-lf/model/daml-lf-expression-path.js +81 -0
  70. package/dist/daml-lf/model/daml-lf-expression.d.ts +146 -0
  71. package/dist/daml-lf/model/daml-lf-expression.js +71 -0
  72. package/dist/daml-lf/model/daml-lf-template.d.ts +2 -0
  73. package/dist/daml-lf/model/daml-lf-template.js +2 -0
  74. package/dist/daml-lf/model/daml-lf-type.d.ts +2 -0
  75. package/dist/daml-lf/model/daml-lf-type.js +4 -0
  76. package/dist/daml-lf/model/lf-2-model-mapper.d.ts +5 -0
  77. package/dist/daml-lf/model/lf-2-model-mapper.js +445 -12
  78. package/dist/debugger/errors/replay-determinism.exception.d.ts +3 -0
  79. package/dist/debugger/errors/replay-determinism.exception.js +3 -0
  80. package/dist/debugger/errors/replay-missing-package.exception.d.ts +3 -0
  81. package/dist/debugger/errors/replay-missing-package.exception.js +3 -0
  82. package/dist/debugger/errors/replay-missing-source.exception.d.ts +3 -0
  83. package/dist/debugger/errors/replay-missing-source.exception.js +3 -0
  84. package/dist/debugger/errors/replay-source-map.exception.d.ts +3 -0
  85. package/dist/debugger/errors/replay-source-map.exception.js +3 -0
  86. package/dist/debugger/errors/replay-state-hydration.exception.d.ts +3 -0
  87. package/dist/debugger/errors/replay-state-hydration.exception.js +3 -0
  88. package/dist/debugger/errors/replay-unsupported-lf-construct.exception.d.ts +3 -0
  89. package/dist/debugger/errors/replay-unsupported-lf-construct.exception.js +3 -0
  90. package/dist/debugger/errors/replay-unsupported-update.exception.d.ts +3 -0
  91. package/dist/debugger/errors/replay-unsupported-update.exception.js +3 -0
  92. package/dist/debugger/index.d.ts +31 -0
  93. package/dist/debugger/index.js +31 -0
  94. package/dist/debugger/ledger-replay-debugger-client.d.ts +31 -0
  95. package/dist/debugger/ledger-replay-debugger-client.js +53 -0
  96. package/dist/debugger/replay/ledger-replay-environment-builder.d.ts +95 -0
  97. package/dist/debugger/replay/ledger-replay-environment-builder.js +249 -0
  98. package/dist/debugger/replay/ledger-replay-session-loader.d.ts +78 -0
  99. package/dist/debugger/replay/ledger-replay-session-loader.js +565 -0
  100. package/dist/debugger/replay/replay-artifact-resolver.d.ts +30 -0
  101. package/dist/debugger/replay/replay-artifact-resolver.js +210 -0
  102. package/dist/debugger/replay/replay-determinism-validator.d.ts +12 -0
  103. package/dist/debugger/replay/replay-determinism-validator.js +161 -0
  104. package/dist/debugger/replay/replay-entrypoint-definition-resolver.d.ts +40 -0
  105. package/dist/debugger/replay/replay-entrypoint-definition-resolver.js +337 -0
  106. package/dist/debugger/replay/replay-entrypoint.d.ts +22 -0
  107. package/dist/debugger/replay/replay-entrypoint.js +14 -0
  108. package/dist/debugger/replay/replay-ledger-value-normalizer.d.ts +7 -0
  109. package/dist/debugger/replay/replay-ledger-value-normalizer.js +194 -0
  110. package/dist/debugger/replay/replay-update-loader.d.ts +24 -0
  111. package/dist/debugger/replay/replay-update-loader.js +94 -0
  112. package/dist/debugger/replay/replay-update-visibility-validator.d.ts +19 -0
  113. package/dist/debugger/replay/replay-update-visibility-validator.js +19 -0
  114. package/dist/debugger/session/in-memory-replay-session-store.d.ts +27 -0
  115. package/dist/debugger/session/in-memory-replay-session-store.js +109 -0
  116. package/dist/debugger/session/replay-phase.d.ts +7 -0
  117. package/dist/debugger/session/replay-phase.js +8 -0
  118. package/dist/debugger/session/replay-scope.d.ts +10 -0
  119. package/dist/debugger/session/replay-scope.js +10 -0
  120. package/dist/debugger/session/replay-session-metadata.d.ts +10 -0
  121. package/dist/debugger/session/replay-session-metadata.js +10 -0
  122. package/dist/debugger/session/replay-session-request.d.ts +6 -0
  123. package/dist/debugger/session/replay-session-request.js +10 -0
  124. package/dist/debugger/session/replay-session.d.ts +12 -0
  125. package/dist/debugger/session/replay-session.js +10 -0
  126. package/dist/debugger/session/replay-source-location.d.ts +17 -0
  127. package/dist/debugger/session/replay-source-location.js +16 -0
  128. package/dist/debugger/session/replay-stack-frame.d.ts +8 -0
  129. package/dist/debugger/session/replay-stack-frame.js +8 -0
  130. package/dist/debugger/session/replay-state-delta.d.ts +29 -0
  131. package/dist/debugger/session/replay-state-delta.js +24 -0
  132. package/dist/debugger/session/replay-step-advance-result.d.ts +24 -0
  133. package/dist/debugger/session/replay-step-advance-result.js +16 -0
  134. package/dist/debugger/session/replay-step.d.ts +30 -0
  135. package/dist/debugger/session/replay-step.js +24 -0
  136. package/dist/debugger/session/replay-value-preview.d.ts +8 -0
  137. package/dist/debugger/session/replay-value-preview.js +15 -0
  138. package/dist/debugger/source/daml-source-mapper.d.ts +12 -0
  139. package/dist/debugger/source/daml-source-mapper.js +21 -0
  140. package/dist/debugger/source/dar-source-map-metadata.d.ts +26 -0
  141. package/dist/debugger/source/dar-source-map-metadata.js +10 -0
  142. package/dist/debugger/source/source-coverage-validator.d.ts +8 -0
  143. package/dist/debugger/source/source-coverage-validator.js +16 -0
  144. package/dist/debugger/source/source-indexed-compilation.d.ts +45 -0
  145. package/dist/debugger/source/source-indexed-compilation.js +110 -0
  146. package/dist/debugger/source/source-mapping-precision.d.ts +5 -0
  147. package/dist/debugger/source/source-mapping-precision.js +4 -0
  148. package/dist/index.d.ts +20 -0
  149. package/dist/index.js +12 -0
  150. package/dist/query/cache/memory-query-cache.d.ts +9 -0
  151. package/dist/query/cache/memory-query-cache.js +24 -0
  152. package/dist/query/cache/query-cache-store.d.ts +5 -0
  153. package/dist/query/cache/query-cache-store.js +1 -0
  154. package/dist/query/canton-manager-options.d.ts +17 -0
  155. package/dist/query/canton-manager-options.js +1 -0
  156. package/dist/query/canton-manager.d.ts +11 -0
  157. package/dist/query/canton-manager.js +42 -0
  158. package/dist/query/errors/pqs-query-error.d.ts +10 -0
  159. package/dist/query/errors/pqs-query-error.js +11 -0
  160. package/dist/query/errors/pqs-schema-profile-error.d.ts +3 -0
  161. package/dist/query/errors/pqs-schema-profile-error.js +3 -0
  162. package/dist/query/errors/query-capability-error.d.ts +7 -0
  163. package/dist/query/errors/query-capability-error.js +10 -0
  164. package/dist/query/grpc/grpc-contract-query-client.d.ts +32 -0
  165. package/dist/query/grpc/grpc-contract-query-client.js +126 -0
  166. package/dist/query/model-types.d.ts +258 -0
  167. package/dist/query/model-types.js +14 -0
  168. package/dist/query/pqs/pqs-pool.d.ts +13 -0
  169. package/dist/query/pqs/pqs-pool.js +18 -0
  170. package/dist/query/pqs/pqs-query-client.d.ts +49 -0
  171. package/dist/query/pqs/pqs-query-client.js +324 -0
  172. package/dist/query/pqs/pqs-schema-profile.d.ts +25 -0
  173. package/dist/query/pqs/pqs-schema-profile.js +120 -0
  174. package/dist/query/pqs/pqs-sql-compiler.d.ts +7 -0
  175. package/dist/query/pqs/pqs-sql-compiler.js +132 -0
  176. package/dist/query/pqs/read-only-sql.d.ts +1 -0
  177. package/dist/query/pqs/read-only-sql.js +35 -0
  178. package/dist/query/query-client.d.ts +61 -0
  179. package/dist/query/query-client.js +1 -0
  180. package/dist/query/query-source.d.ts +4 -0
  181. package/dist/query/query-source.js +5 -0
  182. package/dist/services/commands/command-payload-builder.js +3 -3
  183. package/dist/services/commands/command-submission-pipeline.js +1 -7
  184. package/dist/services/party-management/decentralized-party-lifecycle.d.ts +6 -0
  185. package/dist/services/party-management/decentralized-party-lifecycle.js +82 -0
  186. package/dist/services/party-management/party-management-service-client.d.ts +16 -1
  187. package/dist/services/party-management/party-management-service-client.js +142 -1
  188. package/dist/services/topology-manager-write/topology-signed-transaction-assembler.js +4 -0
  189. package/dist/testing/campaign/campaign-artifact.d.ts +20 -0
  190. package/dist/testing/campaign/campaign-artifact.js +147 -0
  191. package/dist/testing/campaign/campaign-definition.d.ts +9 -0
  192. package/dist/testing/campaign/campaign-definition.js +78 -0
  193. package/dist/testing/campaign/campaign-metrics.d.ts +32 -0
  194. package/dist/testing/campaign/campaign-metrics.js +26 -0
  195. package/dist/testing/campaign/campaign-model.d.ts +11 -0
  196. package/dist/testing/campaign/campaign-model.js +21 -0
  197. package/dist/testing/campaign/campaign-runner.d.ts +99 -0
  198. package/dist/testing/campaign/campaign-runner.js +194 -0
  199. package/dist/testing/campaign/campaign-scheduler.d.ts +40 -0
  200. package/dist/testing/campaign/campaign-scheduler.js +75 -0
  201. package/dist/testing/campaign/campaign-types.d.ts +52 -0
  202. package/dist/testing/campaign/campaign-types.js +11 -0
  203. package/dist/testing/daml/daml-action-arbitrary.d.ts +13 -0
  204. package/dist/testing/daml/daml-action-arbitrary.js +24 -0
  205. package/dist/testing/daml/daml-choice-action-arbitrary.d.ts +18 -0
  206. package/dist/testing/daml/daml-choice-action-arbitrary.js +27 -0
  207. package/dist/testing/daml/daml-create-action-arbitrary.d.ts +19 -0
  208. package/dist/testing/daml/daml-create-action-arbitrary.js +34 -0
  209. package/dist/testing/daml/daml-testing-catalog.d.ts +38 -0
  210. package/dist/testing/daml/daml-testing-catalog.js +40 -0
  211. package/dist/testing/daml/daml-value-arbitrary.d.ts +8 -0
  212. package/dist/testing/daml/daml-value-arbitrary.js +43 -0
  213. package/dist/testing/daml/declarative-campaign-arbitrary.d.ts +15 -0
  214. package/dist/testing/daml/declarative-campaign-arbitrary.js +30 -0
  215. package/dist/testing/errors/invariant-campaign-failure.d.ts +24 -0
  216. package/dist/testing/errors/invariant-campaign-failure.js +37 -0
  217. package/dist/testing/errors/testing-configuration-error.d.ts +3 -0
  218. package/dist/testing/errors/testing-configuration-error.js +6 -0
  219. package/dist/testing/handlers/handler.d.ts +19 -0
  220. package/dist/testing/handlers/handler.js +31 -0
  221. package/dist/testing/index.d.ts +22 -0
  222. package/dist/testing/index.js +22 -0
  223. package/dist/testing/runtime/campaign-isolation.d.ts +14 -0
  224. package/dist/testing/runtime/campaign-isolation.js +23 -0
  225. package/dist/testing/runtime/canton-test-runtime.d.ts +58 -0
  226. package/dist/testing/runtime/canton-test-runtime.js +138 -0
  227. package/dist/testing/runtime/declarative-action-executor.d.ts +16 -0
  228. package/dist/testing/runtime/declarative-action-executor.js +41 -0
  229. package/dist/testing/targets/target.d.ts +49 -0
  230. package/dist/testing/targets/target.js +121 -0
  231. package/dist/transports/grpc/grpc-channel-factory.d.ts +4 -0
  232. package/dist/transports/grpc/grpc-channel-factory.js +42 -1
  233. package/dist/transports/grpc/grpc-transport.d.ts +2 -2
  234. package/dist/transports/grpc/grpc-transport.js +42 -3
  235. package/dist/transports/grpc/mappers/commands-mapper.d.ts +10 -2
  236. package/dist/transports/grpc/mappers/commands-mapper.js +30 -12
  237. package/dist/transports/grpc/mappers/contracts-mapper.d.ts +3 -1
  238. package/dist/transports/grpc/mappers/contracts-mapper.js +16 -3
  239. package/dist/transports/grpc/mappers/interactive-command-mapper.d.ts +15 -0
  240. package/dist/transports/grpc/mappers/interactive-command-mapper.js +54 -0
  241. package/dist/transports/grpc/mappers/topology-manager-write-mapper.js +59 -1
  242. package/dist/transports/json/json-transport.d.ts +2 -2
  243. package/dist/transports/json/json-transport.js +2 -2
  244. package/dist/transports/json/mappers/commands-mapper.js +23 -9
  245. package/node/.generated/start-local/additional-config.extra-participants.conf +37 -0
  246. package/node/.generated/start-local/additional-config.extra-validators.conf +35 -0
  247. package/node/.generated/start-local/compose-extra-participants.yaml +147 -0
  248. package/node/.generated/start-local/extra-participants.env +30 -0
  249. package/node/es256-jwt.mjs +177 -0
  250. package/node/start-local.sh +886 -0
  251. package/node/stop-local.sh +200 -0
  252. package/node/test-start-local.sh +354 -0
  253. package/node/test-stop-local.sh +112 -0
  254. package/package.json +21 -2
@@ -0,0 +1,324 @@
1
+ import { QuerySource } from "../query-source.js";
2
+ import { PqsQueryError } from "../errors/pqs-query-error.js";
3
+ import { compileContractFindMany } from "./pqs-sql-compiler.js";
4
+ import { pqsRelationMetadata, } from "./pqs-schema-profile.js";
5
+ import { assertReadOnlySql } from "./read-only-sql.js";
6
+ export class PqsQueryClient {
7
+ executor;
8
+ profile;
9
+ ready;
10
+ source = QuerySource.pqs;
11
+ contracts = {
12
+ findMany: (args = {}) => this.findContractsAsync(args),
13
+ findUnique: (args) => this.findContractsAsync({
14
+ where: { contractId: { equals: args.where.contractId } },
15
+ select: args.select,
16
+ take: 1,
17
+ }).then((rows) => rows[0]),
18
+ count: async (args = {}) => (await this.findContractsAsync(args)).length,
19
+ aggregate: async (args) => this.aggregateContractsAsync(args),
20
+ };
21
+ contractTypes = this.createPhysicalDelegate("__contract_tpe");
22
+ events = this.createPhysicalDelegate("__events");
23
+ exercises = this.createPhysicalDelegate("__exercises", false);
24
+ exerciseTypes = this.createPhysicalDelegate("__exercise_tpe");
25
+ packages = this.createPhysicalDelegate("__packages");
26
+ transactions = this.createPhysicalDelegate("__transactions");
27
+ watermark = this.createPhysicalDelegate("__watermark");
28
+ constructor(executor, profile, ready = Promise.resolve()) {
29
+ this.executor = executor;
30
+ this.profile = profile;
31
+ this.ready = ready;
32
+ }
33
+ async $queryRaw(sql, values = []) {
34
+ assertReadOnlySql(sql);
35
+ try {
36
+ await this.ready;
37
+ return (await this.executor.query(sql, values)).rows;
38
+ }
39
+ catch (cause) {
40
+ throw this.wrap("$queryRaw", cause);
41
+ }
42
+ }
43
+ createPhysicalDelegate(relation, hasUnique = true) {
44
+ const metadata = pqsRelationMetadata[relation];
45
+ const findMany = async (args = {}) => this.readPhysicalAsync(relation, metadata, args);
46
+ const delegate = {
47
+ findMany,
48
+ count: async (args = {}) => {
49
+ const { where, values } = this.compileWhere(relation, metadata, args.where);
50
+ try {
51
+ await this.ready;
52
+ const result = await this.executor.query(`select count(*)::text as count from ${this.profile.relation(relation)}${where}`, values);
53
+ return Number(result.rows[0]?.count ?? 0);
54
+ }
55
+ catch (cause) {
56
+ throw this.wrap(`${relation}.count`, cause);
57
+ }
58
+ },
59
+ aggregate: async (args) => this.aggregatePhysicalAsync(relation, metadata, args),
60
+ };
61
+ if (!hasUnique) {
62
+ return delegate;
63
+ }
64
+ return {
65
+ ...delegate,
66
+ findUnique: async (args) => {
67
+ this.assertUniqueWhere(relation, metadata, args.where);
68
+ return findMany({
69
+ where: Object.fromEntries(Object.entries(args.where).map(([field, value]) => [field, { equals: value }])),
70
+ select: args.select,
71
+ take: 1,
72
+ }).then((rows) => rows[0]);
73
+ },
74
+ };
75
+ }
76
+ async readPhysicalAsync(relation, metadata, args) {
77
+ this.assertPage(args);
78
+ const selected = this.selectedFields(relation, metadata, args.select);
79
+ const { where, values } = this.compileWhere(relation, metadata, args.where);
80
+ const orderBy = this.compileOrderBy(relation, metadata, args.orderBy);
81
+ const parameters = [...values];
82
+ const add = (value) => {
83
+ parameters.push(value);
84
+ return `$${parameters.length}`;
85
+ };
86
+ const limit = args.take === undefined ? "" : ` limit ${add(args.take)}`;
87
+ const offset = args.skip === undefined ? "" : ` offset ${add(args.skip)}`;
88
+ const selection = selected.map(([field, column]) => `"${column}" as "${field}"`).join(", ");
89
+ try {
90
+ await this.ready;
91
+ const result = await this.executor.query(`select ${selection} from ${this.profile.relation(relation)}${where}${orderBy}${limit}${offset}`, parameters);
92
+ return result.rows.map((row) => this.mapPhysicalRow(row, metadata, selected));
93
+ }
94
+ catch (cause) {
95
+ throw this.wrap(`${relation}.findMany`, cause);
96
+ }
97
+ }
98
+ async aggregatePhysicalAsync(relation, metadata, args) {
99
+ const { where, values } = this.compileWhere(relation, metadata, args.where);
100
+ const selected = [];
101
+ if (args.count) {
102
+ selected.push("count(*)::text as count");
103
+ }
104
+ for (const [operation, fields] of [["min", args.min], ["max", args.max], ["sum", args.sum]]) {
105
+ for (const field of fields ?? []) {
106
+ this.assertNumericField(relation, metadata, field);
107
+ selected.push(`${operation}("${metadata.fields[field]}")::text as "${operation}_${field}"`);
108
+ }
109
+ }
110
+ if (selected.length === 0) {
111
+ throw new Error("aggregate must request at least one result");
112
+ }
113
+ try {
114
+ await this.ready;
115
+ const row = (await this.executor.query(`select ${selected.join(", ")} from ${this.profile.relation(relation)}${where}`, values)).rows[0] ?? {};
116
+ const result = {};
117
+ if (args.count) {
118
+ result.count = Number(row.count ?? 0);
119
+ }
120
+ for (const [operation, fields] of [["min", args.min], ["max", args.max], ["sum", args.sum]]) {
121
+ if (fields !== undefined) {
122
+ result[operation] = Object.fromEntries(fields.map((field) => [field, nullableString(row[`${operation}_${field}`])]));
123
+ }
124
+ }
125
+ return result;
126
+ }
127
+ catch (cause) {
128
+ throw this.wrap(`${relation}.aggregate`, cause);
129
+ }
130
+ }
131
+ compileWhere(relation, metadata, filters) {
132
+ const values = [];
133
+ const add = (value) => {
134
+ values.push(value);
135
+ return `$${values.length}`;
136
+ };
137
+ const compile = (expression) => {
138
+ const conditions = [];
139
+ for (const [field, filter] of Object.entries(expression ?? {})) {
140
+ if (field === "and" || field === "or") {
141
+ if (!Array.isArray(filter))
142
+ throw new Error(`${field} must be an array`);
143
+ conditions.push(filter.length ? `(${filter.map((child) => compile(child)).join(` ${field} `)})` : field === "and" ? "true" : "false");
144
+ continue;
145
+ }
146
+ if (field === "not") {
147
+ if (filter === null || Array.isArray(filter) || typeof filter !== "object")
148
+ throw new Error("not must be an expression");
149
+ conditions.push(`not (${compile(filter)})`);
150
+ continue;
151
+ }
152
+ const column = this.field(relation, metadata, field);
153
+ if (filter === null || Array.isArray(filter) || typeof filter !== "object")
154
+ throw new Error(`${field} must be a filter`);
155
+ const scalar = filter;
156
+ if (scalar.is === null) {
157
+ conditions.push(`"${column}" is null`);
158
+ }
159
+ if (scalar.isNot === null) {
160
+ conditions.push(`"${column}" is not null`);
161
+ }
162
+ if (scalar.equals !== undefined) {
163
+ conditions.push(`"${column}" = ${add(scalar.equals)}`);
164
+ }
165
+ if (scalar.in !== undefined) {
166
+ conditions.push(scalar.in.length === 0 ? "false" : `"${column}" = any(${add(scalar.in)})`);
167
+ }
168
+ if (scalar.has !== undefined) {
169
+ if (!metadata.arrayFields.includes(field)) {
170
+ throw new Error(`${field} is not an array field of ${relation}`);
171
+ }
172
+ conditions.push(`${add(scalar.has)} = any("${column}")`);
173
+ }
174
+ for (const [operator, value] of [["lt", scalar.lt], ["lte", scalar.lte], ["gt", scalar.gt], ["gte", scalar.gte], ["like", scalar.like], ["ilike", scalar.ilike]]) {
175
+ if (value === undefined)
176
+ continue;
177
+ if ((operator === "like" || operator === "ilike") && !metadata.stringFields?.includes(field))
178
+ throw new Error(`${field} does not support ${operator}`);
179
+ if ((operator !== "like" && operator !== "ilike") && !metadata.numericFields.includes(field) && !metadata.dateFields.includes(field) && !metadata.stringFields?.includes(field))
180
+ throw new Error(`${field} does not support ${operator}`);
181
+ conditions.push(`"${column}" ${operator === "lte" ? "<=" : operator === "gte" ? ">=" : operator} ${add(value)}`);
182
+ }
183
+ }
184
+ return conditions.length ? conditions.join(" and ") : "true";
185
+ };
186
+ const where = compile(filters);
187
+ return { where: where === "true" ? "" : ` where ${where}`, values };
188
+ }
189
+ selectedFields(relation, metadata, select) {
190
+ if (select === undefined) {
191
+ return Object.entries(metadata.fields);
192
+ }
193
+ const selected = Object.entries(select).filter(([, enabled]) => enabled).map(([field]) => [field, this.field(relation, metadata, field)]);
194
+ if (selected.length === 0) {
195
+ throw new Error("select must include at least one field");
196
+ }
197
+ return selected;
198
+ }
199
+ compileOrderBy(relation, metadata, orderBy) {
200
+ if (orderBy === undefined) {
201
+ return "";
202
+ }
203
+ const entries = Object.entries(orderBy);
204
+ if (entries.length !== 1) {
205
+ throw new Error("orderBy must specify exactly one field");
206
+ }
207
+ const [field, direction] = entries[0];
208
+ if (direction !== "asc" && direction !== "desc") {
209
+ throw new Error("orderBy direction must be asc or desc");
210
+ }
211
+ return ` order by "${this.field(relation, metadata, field)}" ${direction}`;
212
+ }
213
+ assertUniqueWhere(relation, metadata, where) {
214
+ const fields = Object.keys(where).sort();
215
+ const matches = metadata.uniqueKeys.some((key) => [...key].sort().join("\0") === fields.join("\0"));
216
+ if (!matches) {
217
+ throw new Error(`where is not a stable unique key of ${relation}`);
218
+ }
219
+ }
220
+ assertNumericField(relation, metadata, field) {
221
+ if (!metadata.numericFields.includes(field)) {
222
+ throw new Error(`${field} is not a numeric aggregate field of ${relation}`);
223
+ }
224
+ }
225
+ field(relation, metadata, field) {
226
+ const column = metadata.fields[field];
227
+ if (column === undefined) {
228
+ throw new Error(`${field} is not a field of ${relation}`);
229
+ }
230
+ return column;
231
+ }
232
+ assertPage(args) {
233
+ for (const [name, value] of [["take", args.take], ["skip", args.skip]]) {
234
+ if (value !== undefined && (!Number.isInteger(value) || value < 0)) {
235
+ throw new Error(`${name} must be a non-negative integer`);
236
+ }
237
+ }
238
+ }
239
+ mapPhysicalRow(row, metadata, fields) {
240
+ return Object.fromEntries(fields
241
+ .filter(([field]) => Object.hasOwn(row, field))
242
+ .map(([field]) => [field, mapPhysicalValue(row[field], metadata, field)]));
243
+ }
244
+ async findContractsAsync(args) {
245
+ const compiled = compileContractFindMany(args, this.profile);
246
+ try {
247
+ const rows = (await this.executor.query(compiled.text, compiled.values)).rows.map(mapContractRow);
248
+ const select = "select" in args ? args.select : undefined;
249
+ if (select === undefined) {
250
+ return rows;
251
+ }
252
+ const fields = Object.entries(select).filter(([, enabled]) => enabled).map(([field]) => field);
253
+ if (fields.length === 0) {
254
+ throw new Error("select must include at least one field");
255
+ }
256
+ return rows.map((row) => Object.fromEntries(fields.map((field) => [field, row[field]])));
257
+ }
258
+ catch (cause) {
259
+ throw this.wrap("contracts.findMany", cause);
260
+ }
261
+ }
262
+ async aggregateContractsAsync(args) {
263
+ if (!args.count && args.min === undefined && args.max === undefined && args.sum === undefined) {
264
+ throw new Error("aggregate must request at least one result");
265
+ }
266
+ const rows = await this.findContractsAsync({ where: args.where });
267
+ const result = {};
268
+ if (args.count) {
269
+ result.count = rows.length;
270
+ }
271
+ for (const [operation, fields] of [["min", args.min], ["max", args.max], ["sum", args.sum]]) {
272
+ if (fields !== undefined) {
273
+ result[operation] = Object.fromEntries(fields.map((field) => [field, aggregateNumeric(rows.map((row) => row[field]), operation)]));
274
+ }
275
+ }
276
+ return result;
277
+ }
278
+ wrap(operation, cause) {
279
+ return new PqsQueryError({ operation, code: getPqsCode(cause), cause });
280
+ }
281
+ }
282
+ function mapPhysicalValue(value, metadata, field) {
283
+ if (value === null || value === undefined) {
284
+ return value ?? null;
285
+ }
286
+ else if (metadata.numericFields.includes(field)) {
287
+ return String(value);
288
+ }
289
+ else if (metadata.dateFields.includes(field)) {
290
+ return value instanceof Date ? value : new Date(String(value));
291
+ }
292
+ else if (metadata.binaryFields.includes(field)) {
293
+ return value instanceof Uint8Array ? value : new Uint8Array(value);
294
+ }
295
+ else if (metadata.arrayFields.includes(field)) {
296
+ return Array.isArray(value) ? value.map(String) : [];
297
+ }
298
+ return value;
299
+ }
300
+ function mapContractRow(row) {
301
+ return { contractId: String(row.contract_id), templateId: { packageId: String(row.template_package_id), moduleName: String(row.template_module_name), entityName: String(row.template_entity_name) }, packageId: nullableString(row.package_id), payload: row.payload, witnesses: stringArray(row.witnesses), createdEventOffset: String(row.created_event_offset), createdAt: nullableDate(row.created_at), archivedEventOffset: nullableString(row.archived_event_offset), archivedAt: nullableDate(row.archived_at), active: row.active === true };
302
+ }
303
+ function nullableString(value) {
304
+ return value === null || value === undefined ? null : String(value);
305
+ }
306
+ function nullableDate(value) {
307
+ return value === null || value === undefined ? null : value instanceof Date ? value : new Date(String(value));
308
+ }
309
+ function stringArray(value) {
310
+ return Array.isArray(value) ? value.map(String) : [];
311
+ }
312
+ function getPqsCode(cause) {
313
+ return typeof cause === "object" && cause !== null && "code" in cause && typeof cause.code === "string" ? cause.code : undefined;
314
+ }
315
+ function aggregateNumeric(values, operation) {
316
+ const numbers = values.filter((value) => value !== null).map(BigInt);
317
+ if (numbers.length === 0) {
318
+ return null;
319
+ }
320
+ else if (operation === "sum") {
321
+ return numbers.reduce((total, value) => total + value, 0n).toString();
322
+ }
323
+ return numbers.reduce((result, value) => operation === "min" ? value < result ? value : result : value > result ? value : result).toString();
324
+ }
@@ -0,0 +1,25 @@
1
+ export declare const requiredPqsRelations: readonly ["__contracts", "__contract_tpe", "__events", "__exercises", "__exercise_tpe", "__packages", "__transactions", "__watermark"];
2
+ export type PqsRelation = (typeof requiredPqsRelations)[number];
3
+ export interface PqsRelationMetadata {
4
+ readonly fields: Readonly<Record<string, string>>;
5
+ readonly uniqueKeys: readonly (readonly string[])[];
6
+ readonly numericFields: readonly string[];
7
+ readonly arrayFields: readonly string[];
8
+ readonly dateFields: readonly string[];
9
+ readonly binaryFields: readonly string[];
10
+ readonly stringFields?: readonly string[];
11
+ }
12
+ export declare const pqsRelationMetadata: Readonly<Record<PqsRelation, PqsRelationMetadata>>;
13
+ export declare const requiredPqsColumns: Readonly<Record<PqsRelation, readonly string[]>>;
14
+ export declare class PqsSchemaProfileV1 {
15
+ readonly schema: string;
16
+ constructor(schema?: string);
17
+ relation(relation: PqsRelation): string;
18
+ }
19
+ export interface PqsSchemaClient {
20
+ query(query: string, values: readonly unknown[]): Promise<{
21
+ readonly rows: readonly Record<string, unknown>[];
22
+ }>;
23
+ }
24
+ export declare function validatePqsSchemaAsync(client: PqsSchemaClient, profile: PqsSchemaProfileV1): Promise<void>;
25
+ export declare function assertPqsSchemaIdentifier(schema: string): void;
@@ -0,0 +1,120 @@
1
+ import { PqsSchemaProfileError } from "../errors/pqs-schema-profile-error.js";
2
+ const schemaIdentifier = /^[A-Za-z_][A-Za-z0-9_]*$/;
3
+ export const requiredPqsRelations = [
4
+ "__contracts",
5
+ "__contract_tpe",
6
+ "__events",
7
+ "__exercises",
8
+ "__exercise_tpe",
9
+ "__packages",
10
+ "__transactions",
11
+ "__watermark",
12
+ ];
13
+ export const pqsRelationMetadata = {
14
+ __contracts: { fields: {}, uniqueKeys: [["contractId"]], numericFields: ["createdEventOffset", "archivedEventOffset"], arrayFields: ["witnesses"], dateFields: ["createdAt", "archivedAt"], binaryFields: [] },
15
+ __contract_tpe: { fields: { pk: "pk", payloadType: "payload_type", aliases: "aliases", packageName: "package_name", moduleName: "module_name", entityName: "entity_name", templateFqn: "template_fqn" }, uniqueKeys: [["pk"]], numericFields: ["pk"], arrayFields: ["aliases"], dateFields: [], binaryFields: [] },
16
+ __events: { fields: { pk: "pk", txIx: "tx_ix", eventId: "event_id", type: "type" }, uniqueKeys: [["pk"]], numericFields: ["pk", "txIx"], arrayFields: [], dateFields: [], binaryFields: [], stringFields: ["eventId", "type"] },
17
+ __exercises: { fields: { tpePk: "tpe_pk", contractTpePk: "contract_tpe_pk", exerciseEventPk: "exercise_event_pk", exercisedAtIx: "exercised_at_ix", contractId: "contract_id", argument: "argument", result: "result", redactionId: "redaction_id", packagePk: "package_pk", controllers: "controllers", lastDescendantNodeId: "last_descendant_node_id", witnesses: "witnesses" }, uniqueKeys: [], numericFields: ["tpePk", "contractTpePk", "exerciseEventPk", "exercisedAtIx", "packagePk", "lastDescendantNodeId"], arrayFields: ["controllers", "witnesses"], dateFields: [], binaryFields: [] },
18
+ __exercise_tpe: { fields: { pk: "pk", choice: "choice", consuming: "consuming", aliases: "aliases", packageName: "package_name", moduleName: "module_name", entityName: "entity_name", templateFqn: "template_fqn", choiceFqn: "choice_fqn" }, uniqueKeys: [["pk"]], numericFields: ["pk"], arrayFields: ["aliases"], dateFields: [], binaryFields: [] },
19
+ __packages: { fields: { pk: "pk", name: "name", version: "version", id: "id" }, uniqueKeys: [["pk"], ["id"]], numericFields: ["pk"], arrayFields: [], dateFields: [], binaryFields: [], stringFields: ["name", "version", "id"] },
20
+ __transactions: { fields: { ix: "ix", offset: "offset", transactionId: "transaction_id", effectiveAt: "effective_at", workflowId: "workflow_id", domainId: "domain_id", traceContext: "trace_context", externalTransactionHash: "external_transaction_hash", paidTrafficCost: "paid_traffic_cost" }, uniqueKeys: [["ix"], ["offset"]], numericFields: ["ix", "offset", "paidTrafficCost"], arrayFields: [], dateFields: ["effectiveAt"], binaryFields: ["externalTransactionHash"] },
21
+ __watermark: { fields: { singleton: "singleton", ix: "ix", offset: "offset", instanceId: "instance_id" }, uniqueKeys: [["singleton"]], numericFields: ["ix", "offset"], arrayFields: [], dateFields: [], binaryFields: [] },
22
+ };
23
+ export const requiredPqsColumns = {
24
+ __contracts: [
25
+ "tpe_pk",
26
+ "create_event_pk",
27
+ "created_at_ix",
28
+ "archive_event_pk",
29
+ "archived_at_ix",
30
+ "life_ix",
31
+ "contract_id",
32
+ "payload",
33
+ "contract_key",
34
+ "metadata",
35
+ "redaction_id",
36
+ "package_pk",
37
+ "signatories",
38
+ "observers",
39
+ "witnesses",
40
+ "divulged_only",
41
+ "creation_package_id",
42
+ "contract_key_hash",
43
+ ],
44
+ __contract_tpe: [
45
+ "pk",
46
+ "payload_type",
47
+ "aliases",
48
+ "package_name",
49
+ "module_name",
50
+ "entity_name",
51
+ "template_fqn",
52
+ ],
53
+ __events: ["pk", "tx_ix", "event_id", "type"],
54
+ __exercises: [
55
+ "tpe_pk",
56
+ "contract_tpe_pk",
57
+ "exercise_event_pk",
58
+ "exercised_at_ix",
59
+ "contract_id",
60
+ "argument",
61
+ "result",
62
+ "redaction_id",
63
+ "package_pk",
64
+ "controllers",
65
+ "last_descendant_node_id",
66
+ "witnesses",
67
+ ],
68
+ __exercise_tpe: [
69
+ "pk",
70
+ "choice",
71
+ "consuming",
72
+ "aliases",
73
+ "package_name",
74
+ "module_name",
75
+ "entity_name",
76
+ "template_fqn",
77
+ "choice_fqn",
78
+ ],
79
+ __packages: ["pk", "name", "version", "id"],
80
+ __transactions: [
81
+ "ix",
82
+ "offset",
83
+ "transaction_id",
84
+ "effective_at",
85
+ "workflow_id",
86
+ "domain_id",
87
+ "trace_context",
88
+ "external_transaction_hash",
89
+ "paid_traffic_cost",
90
+ ],
91
+ __watermark: ["singleton", "ix", "offset", "instance_id"],
92
+ };
93
+ export class PqsSchemaProfileV1 {
94
+ schema;
95
+ constructor(schema = "public") {
96
+ assertPqsSchemaIdentifier(schema);
97
+ this.schema = schema;
98
+ }
99
+ relation(relation) {
100
+ return `${quoteIdentifier(this.schema)}.${quoteIdentifier(relation)}`;
101
+ }
102
+ }
103
+ export async function validatePqsSchemaAsync(client, profile) {
104
+ const result = await client.query("select table_name, column_name from information_schema.columns where table_schema = $1 and table_name = any($2::text[])", [profile.schema, requiredPqsRelations]);
105
+ const actual = new Set(result.rows.map((row) => `${String(row.table_name)}.${String(row.column_name)}`));
106
+ const missing = requiredPqsRelations.flatMap((relation) => requiredPqsColumns[relation]
107
+ .filter((column) => !actual.has(`${relation}.${column}`))
108
+ .map((column) => `${relation}.${column}`));
109
+ if (missing.length > 0) {
110
+ throw new PqsSchemaProfileError(`PQS schema does not match v1 profile; missing: ${missing.join(", ")}`);
111
+ }
112
+ }
113
+ export function assertPqsSchemaIdentifier(schema) {
114
+ if (!schemaIdentifier.test(schema)) {
115
+ throw new PqsSchemaProfileError(`Invalid PQS schema identifier: ${schema}`);
116
+ }
117
+ }
118
+ function quoteIdentifier(identifier) {
119
+ return `"${identifier.replaceAll('"', '""')}"`;
120
+ }
@@ -0,0 +1,7 @@
1
+ import { ContractFindManyArgs } from "../model-types.js";
2
+ import { PqsSchemaProfileV1 } from "./pqs-schema-profile.js";
3
+ export interface CompiledPqsQuery {
4
+ readonly text: string;
5
+ readonly values: readonly unknown[];
6
+ }
7
+ export declare function compileContractFindMany(args: ContractFindManyArgs, profile: PqsSchemaProfileV1): CompiledPqsQuery;
@@ -0,0 +1,132 @@
1
+ import { assertQueryPageArgs, } from "../model-types.js";
2
+ export function compileContractFindMany(args, profile) {
3
+ assertQueryPageArgs(args);
4
+ const values = [];
5
+ const addValue = (value) => {
6
+ values.push(value);
7
+ return `$${values.length}`;
8
+ };
9
+ const conditions = [];
10
+ const where = args.where === undefined ? undefined : compileWhere(args.where, addValue);
11
+ if (where !== undefined)
12
+ conditions.push(where);
13
+ if (args.parties !== undefined) {
14
+ conditions.push(`contract_row.witnesses && ${addValue(args.parties)}::text[]`);
15
+ }
16
+ const orderBy = compileOrderBy(args.orderBy);
17
+ const whereSql = conditions.length === 0 ? "" : `where ${conditions.join(" and ")}`;
18
+ const limitSql = args.take === undefined ? "" : `limit ${addValue(args.take)}`;
19
+ const offsetSql = args.skip === undefined ? "" : `offset ${addValue(args.skip)}`;
20
+ return {
21
+ text: `select
22
+ contract_row.contract_id as contract_id,
23
+ contract_row.creation_package_id as package_id,
24
+ contract_row.payload,
25
+ contract_row.witnesses,
26
+ contract_row.created_at_ix::text as created_event_offset,
27
+ created_tx.effective_at as created_at,
28
+ contract_row.archived_at_ix::text as archived_event_offset,
29
+ archived_tx.effective_at as archived_at,
30
+ contract_row.archived_at_ix is null as active,
31
+ contract_row.creation_package_id as template_package_id,
32
+ contract_tpe_row.module_name as template_module_name,
33
+ contract_tpe_row.entity_name as template_entity_name
34
+ from ${profile.relation("__contracts")} contract_row
35
+ join ${profile.relation("__contract_tpe")} contract_tpe_row on contract_tpe_row.pk = contract_row.tpe_pk
36
+ left join ${profile.relation("__transactions")} created_tx on created_tx.ix = contract_row.created_at_ix
37
+ left join ${profile.relation("__transactions")} archived_tx on archived_tx.ix = contract_row.archived_at_ix
38
+ ${whereSql}
39
+ ${orderBy}
40
+ ${limitSql}
41
+ ${offsetSql}`,
42
+ values,
43
+ };
44
+ }
45
+ function compileWhere(where, addValue) {
46
+ const columns = { contractId: "contract_row.contract_id", packageId: "contract_row.creation_package_id", createdEventOffset: "contract_row.created_at_ix", createdAt: "created_tx.effective_at", archivedEventOffset: "contract_row.archived_at_ix", archivedAt: "archived_tx.effective_at" };
47
+ const parts = [];
48
+ for (const [key, value] of Object.entries(where)) {
49
+ if (key === "and" || key === "or") {
50
+ if (!Array.isArray(value))
51
+ throw new Error(`${key} must be an array`);
52
+ parts.push(value.length === 0 ? key === "and" ? "true" : "false" : `(${value.map((child) => compileWhere(child, addValue)).join(` ${key} `)})`);
53
+ continue;
54
+ }
55
+ if (key === "not") {
56
+ parts.push(`not (${compileWhere(value, addValue)})`);
57
+ continue;
58
+ }
59
+ if (key === "active") {
60
+ const active = typeof value === "boolean" ? value : value.equals;
61
+ if (typeof active !== "boolean")
62
+ throw new Error("active supports only equals");
63
+ parts.push(active ? "contract_row.archived_at_ix is null" : "contract_row.archived_at_ix is not null");
64
+ continue;
65
+ }
66
+ if (key === "witnesses") {
67
+ const has = value.has;
68
+ if (has === undefined)
69
+ throw new Error("witnesses supports only has");
70
+ parts.push(`${addValue(has)} = any(contract_row.witnesses)`);
71
+ continue;
72
+ }
73
+ if (key === "payload") {
74
+ const payload = value;
75
+ const path = payload.path;
76
+ if (typeof path !== "string" || path.split(".").some((x) => x.length === 0))
77
+ throw new Error("payload path must contain non-empty segments");
78
+ const ops = ["equals", "lt", "lte", "gt", "gte", "like", "ilike"].filter((op) => payload[op] !== undefined);
79
+ if (ops.length !== 1 || typeof payload[ops[0]] !== "string")
80
+ throw new Error("payload requires exactly one string predicate");
81
+ const op = { equals: "=", lt: "<", lte: "<=", gt: ">", gte: ">=", like: "like", ilike: "ilike" }[ops[0]];
82
+ parts.push(`contract_row.payload #>> ${addValue(path.split("."))}::text[] ${op} ${addValue(payload[ops[0]])}`);
83
+ continue;
84
+ }
85
+ if (key === "templateId") {
86
+ const fields = { packageId: "contract_row.creation_package_id", moduleName: "contract_tpe_row.module_name", entityName: "contract_tpe_row.entity_name" };
87
+ for (const [name, filter] of Object.entries(value))
88
+ for (const [op, operand] of Object.entries(filter)) {
89
+ const sql = { equals: "=", lt: "<", lte: "<=", gt: ">", gte: ">=", like: "like", ilike: "ilike" }[op];
90
+ if (fields[name] === undefined || sql === undefined)
91
+ throw new Error("invalid templateId filter");
92
+ parts.push(`${fields[name]} ${sql} ${addValue(operand)}`);
93
+ }
94
+ continue;
95
+ }
96
+ const column = columns[key];
97
+ if (column === undefined || value === null || typeof value !== "object")
98
+ throw new Error(`${key} is not a supported contract filter`);
99
+ for (const [op, operand] of Object.entries(value)) {
100
+ const sql = { equals: "=", lt: "<", lte: "<=", gt: ">", gte: ">=", like: "like", ilike: "ilike" }[op];
101
+ if (sql !== undefined)
102
+ parts.push(`${column} ${sql} ${addValue(operand)}`);
103
+ else if (op === "is" && operand === null)
104
+ parts.push(`${column} is null`);
105
+ else if (op === "isNot" && operand === null)
106
+ parts.push(`${column} is not null`);
107
+ else if (op === "in" && Array.isArray(operand))
108
+ parts.push(operand.length ? `${column} = any(${addValue(operand)})` : "false");
109
+ else
110
+ throw new Error(`${op} is not supported for ${key}`);
111
+ }
112
+ }
113
+ return parts.length === 0 ? "true" : parts.join(" and ");
114
+ }
115
+ function compileOrderBy(orderBy) {
116
+ if (orderBy === undefined) {
117
+ return "order by contract_row.contract_id asc";
118
+ }
119
+ const fields = {
120
+ contractId: "contract_row.contract_id",
121
+ createdEventOffset: "contract_row.created_at_ix",
122
+ createdAt: "created_tx.effective_at",
123
+ archivedEventOffset: "contract_row.archived_at_ix",
124
+ archivedAt: "archived_tx.effective_at",
125
+ };
126
+ const entries = Object.entries(orderBy);
127
+ if (entries.length !== 1) {
128
+ throw new Error("orderBy must specify exactly one field");
129
+ }
130
+ const [field, direction] = entries[0];
131
+ return `order by ${fields[field]} ${direction}`;
132
+ }
@@ -0,0 +1 @@
1
+ export declare function assertReadOnlySql(sql: string): void;
@@ -0,0 +1,35 @@
1
+ const allowedStarts = new Set(["select", "with", "explain", "show"]);
2
+ const mutationTokens = new Set([
3
+ "insert",
4
+ "update",
5
+ "delete",
6
+ "merge",
7
+ "create",
8
+ "alter",
9
+ "drop",
10
+ "truncate",
11
+ "grant",
12
+ "revoke",
13
+ "copy",
14
+ ]);
15
+ export function assertReadOnlySql(sql) {
16
+ const normalized = stripLiteralsAndComments(sql).trim().toLowerCase();
17
+ const tokens = normalized.match(/[a-z_]+|;/g) ?? [];
18
+ const firstToken = tokens[0];
19
+ if (firstToken === undefined || !allowedStarts.has(firstToken)) {
20
+ throw new Error("PQS raw queries must be read-only statements.");
21
+ }
22
+ else if (tokens.some((token) => token === ";")) {
23
+ throw new Error("PQS raw queries must contain one read-only statement.");
24
+ }
25
+ else if (tokens.some((token) => mutationTokens.has(token))) {
26
+ throw new Error("PQS raw queries must be read-only statements.");
27
+ }
28
+ }
29
+ function stripLiteralsAndComments(sql) {
30
+ return sql
31
+ .replace(/--[^\n]*/g, "")
32
+ .replace(/\/\*[\s\S]*?\*\//g, "")
33
+ .replace(/'(?:''|[^'])*'/g, "''")
34
+ .replace(/"(?:""|[^"])*"/g, '""');
35
+ }