@distrohelena/canton-typescript-sdk 0.1.56 → 1.0.1

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.
@@ -29,7 +29,8 @@ class CantonManager {
29
29
  if (options.querySource === query_source_js_1.QuerySource.pqs) {
30
30
  this.pqsPool = pqs_pool_js_1.PqsPool.create(options.pqs.connectionString);
31
31
  const profile = new pqs_schema_profile_js_1.PqsSchemaProfileV1(options.pqs.schema);
32
- this.query = new pqs_query_client_js_1.PqsQueryClient(this.pqsPool.pool, profile, (0, pqs_schema_profile_js_1.validatePqsSchemaAsync)(this.pqsPool.pool, profile));
32
+ const pool = this.pqsPool.pool;
33
+ this.query = new pqs_query_client_js_1.PqsQueryClient(pool, profile, () => (0, pqs_schema_profile_js_1.validatePqsSchemaAsync)(pool, profile));
33
34
  }
34
35
  else {
35
36
  this.query = new grpc_query_client_js_1.GrpcQueryClient({
@@ -23,7 +23,6 @@ function normalizedUniqueAsFindMany(query) {
23
23
  class PqsQueryClient {
24
24
  executor;
25
25
  profile;
26
- ready;
27
26
  source = query_source_js_1.QuerySource.pqs;
28
27
  contracts = {
29
28
  findMany: async (args = {}) => await this.findContractsAsync((0, query_normalizer_js_1.normalizeFindMany)("contracts", args)),
@@ -39,15 +38,31 @@ class PqsQueryClient {
39
38
  packages = this.createPhysicalDelegate("__packages");
40
39
  transactions = this.createPhysicalDelegate("__transactions");
41
40
  watermark = this.createPhysicalDelegate("__watermark");
42
- constructor(executor, profile, ready = Promise.resolve()) {
41
+ checkReadyAsync;
42
+ readyPromise;
43
+ constructor(executor, profile, readiness = () => Promise.resolve()) {
43
44
  this.executor = executor;
44
45
  this.profile = profile;
45
- this.ready = ready;
46
+ this.checkReadyAsync = typeof readiness === "function" ? readiness : () => readiness;
47
+ }
48
+ /**
49
+ * Awaits the readiness check, memoizing success so validation runs once,
50
+ * but clearing the memo on rejection so a transiently unreachable PQS is
51
+ * revalidated on the next query instead of pinning the first failure.
52
+ */
53
+ ready() {
54
+ if (this.readyPromise === undefined) {
55
+ this.readyPromise = Promise.resolve(this.checkReadyAsync()).catch((cause) => {
56
+ this.readyPromise = undefined;
57
+ throw cause;
58
+ });
59
+ }
60
+ return this.readyPromise;
46
61
  }
47
62
  async $queryRaw(sql, values = []) {
48
63
  (0, read_only_sql_js_1.assertReadOnlySql)(sql);
49
64
  try {
50
- await this.ready;
65
+ await this.ready();
51
66
  return (await this.executor.query(sql, values)).rows;
52
67
  }
53
68
  catch (cause) {
@@ -77,7 +92,7 @@ class PqsQueryClient {
77
92
  async readPhysicalAsync(relation, query) {
78
93
  const compiled = (0, pqs_relational_sql_compiler_js_1.compilePqsRelationFindMany)(relation, query, this.profile);
79
94
  try {
80
- await this.ready;
95
+ await this.ready();
81
96
  return (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => this.mapPhysicalRow(row, compiled.resultShape));
82
97
  }
83
98
  catch (cause) {
@@ -87,7 +102,7 @@ class PqsQueryClient {
87
102
  async countPhysicalAsync(relation, query) {
88
103
  const compiled = (0, pqs_relational_sql_compiler_js_1.compilePqsRelationCount)(relation, query, this.profile);
89
104
  try {
90
- await this.ready;
105
+ await this.ready();
91
106
  return Number((await this.executor.query(compiled.text, compiled.values)).rows[0]?.count ?? 0);
92
107
  }
93
108
  catch (cause) {
@@ -97,7 +112,7 @@ class PqsQueryClient {
97
112
  async aggregatePhysicalAsync(relation, query) {
98
113
  const compiled = (0, pqs_relational_sql_compiler_js_1.compilePqsRelationAggregate)(relation, query, this.profile);
99
114
  try {
100
- await this.ready;
115
+ await this.ready();
101
116
  const row = (await this.executor.query(compiled.text, compiled.values)).rows[0] ?? {};
102
117
  const result = {};
103
118
  if (query.aggregates.count)
@@ -115,7 +130,7 @@ class PqsQueryClient {
115
130
  async groupPhysicalAsync(relation, query) {
116
131
  const compiled = (0, pqs_relational_sql_compiler_js_1.compilePqsRelationGroupBy)(relation, query, this.profile);
117
132
  try {
118
- await this.ready;
133
+ await this.ready();
119
134
  return (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => Object.fromEntries(Object.entries(row).map(([name, value]) => [name, name === "count" ? Number(value) : value instanceof Date ? value : value === null ? null : String(value)])));
120
135
  }
121
136
  catch (cause) {
@@ -148,7 +163,7 @@ class PqsQueryClient {
148
163
  async findContractsAsync(query) {
149
164
  const compiled = (0, pqs_sql_compiler_js_1.compileContractFindMany)(query, this.profile);
150
165
  try {
151
- await this.ready;
166
+ await this.ready();
152
167
  return (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => this.mapPhysicalRow(contractRootRow(row), compiled.resultShape, contractRootScalars(row)));
153
168
  }
154
169
  catch (cause) {
@@ -158,7 +173,7 @@ class PqsQueryClient {
158
173
  async countContractsAsync(query) {
159
174
  const compiled = (0, pqs_sql_compiler_js_1.compileContractCount)(query, this.profile);
160
175
  try {
161
- await this.ready;
176
+ await this.ready();
162
177
  return Number((await this.executor.query(compiled.text, compiled.values)).rows[0]?.count ?? 0);
163
178
  }
164
179
  catch (cause) {
@@ -168,7 +183,7 @@ class PqsQueryClient {
168
183
  async aggregateContractsAsync(normalized) {
169
184
  const compiled = (0, pqs_sql_compiler_js_1.compileContractAggregate)(normalized, this.profile);
170
185
  try {
171
- await this.ready;
186
+ await this.ready();
172
187
  const row = (await this.executor.query(compiled.text, compiled.values)).rows[0] ?? {};
173
188
  const result = {};
174
189
  if (normalized.aggregates.count)
@@ -186,7 +201,7 @@ class PqsQueryClient {
186
201
  async groupContractsAsync(query) {
187
202
  const compiled = (0, pqs_sql_compiler_js_1.compileContractGroupBy)(query, this.profile);
188
203
  try {
189
- await this.ready;
204
+ await this.ready();
190
205
  return (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => Object.fromEntries(Object.entries(row).map(([name, value]) => [name, name === "count" ? Number(value) : value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value instanceof Date ? value : String(value)])));
191
206
  }
192
207
  catch (cause) {
@@ -26,7 +26,8 @@ export class CantonManager {
26
26
  if (options.querySource === QuerySource.pqs) {
27
27
  this.pqsPool = PqsPool.create(options.pqs.connectionString);
28
28
  const profile = new PqsSchemaProfileV1(options.pqs.schema);
29
- this.query = new PqsQueryClient(this.pqsPool.pool, profile, validatePqsSchemaAsync(this.pqsPool.pool, profile));
29
+ const pool = this.pqsPool.pool;
30
+ this.query = new PqsQueryClient(pool, profile, () => validatePqsSchemaAsync(pool, profile));
30
31
  }
31
32
  else {
32
33
  this.query = new GrpcQueryClient({
@@ -10,7 +10,6 @@ export interface PqsQueryExecutor {
10
10
  export declare class PqsQueryClient implements QueryClient {
11
11
  private readonly executor;
12
12
  private readonly profile;
13
- private readonly ready;
14
13
  readonly source = QuerySource.pqs;
15
14
  readonly contracts: {
16
15
  findMany: <TArgs extends ContractFindManyArgs>(args?: TArgs) => Promise<readonly (import("../model-types.js").ContractRow & import("../model-types.js").ContractRelationRow & JsonProjectionResult<TArgs>)[]>;
@@ -31,7 +30,15 @@ export declare class PqsQueryClient implements QueryClient {
31
30
  readonly packages: QueryClient["packages"];
32
31
  readonly transactions: QueryClient["transactions"];
33
32
  readonly watermark: QueryClient["watermark"];
34
- constructor(executor: PqsQueryExecutor, profile: PqsSchemaProfileV1, ready?: Promise<void>);
33
+ private readonly checkReadyAsync;
34
+ private readyPromise?;
35
+ constructor(executor: PqsQueryExecutor, profile: PqsSchemaProfileV1, readiness?: Promise<void> | (() => Promise<void>));
36
+ /**
37
+ * Awaits the readiness check, memoizing success so validation runs once,
38
+ * but clearing the memo on rejection so a transiently unreachable PQS is
39
+ * revalidated on the next query instead of pinning the first failure.
40
+ */
41
+ private ready;
35
42
  $queryRaw<TRow>(sql: string, values?: readonly unknown[]): Promise<readonly TRow[]>;
36
43
  cacheContracts(_args?: ContractCacheArgs): Promise<ContractCacheResult>;
37
44
  invalidateContractsCache(_args?: ContractCacheArgs): Promise<void>;
@@ -20,7 +20,6 @@ function normalizedUniqueAsFindMany(query) {
20
20
  export class PqsQueryClient {
21
21
  executor;
22
22
  profile;
23
- ready;
24
23
  source = QuerySource.pqs;
25
24
  contracts = {
26
25
  findMany: async (args = {}) => await this.findContractsAsync(normalizeFindMany("contracts", args)),
@@ -36,15 +35,31 @@ export class PqsQueryClient {
36
35
  packages = this.createPhysicalDelegate("__packages");
37
36
  transactions = this.createPhysicalDelegate("__transactions");
38
37
  watermark = this.createPhysicalDelegate("__watermark");
39
- constructor(executor, profile, ready = Promise.resolve()) {
38
+ checkReadyAsync;
39
+ readyPromise;
40
+ constructor(executor, profile, readiness = () => Promise.resolve()) {
40
41
  this.executor = executor;
41
42
  this.profile = profile;
42
- this.ready = ready;
43
+ this.checkReadyAsync = typeof readiness === "function" ? readiness : () => readiness;
44
+ }
45
+ /**
46
+ * Awaits the readiness check, memoizing success so validation runs once,
47
+ * but clearing the memo on rejection so a transiently unreachable PQS is
48
+ * revalidated on the next query instead of pinning the first failure.
49
+ */
50
+ ready() {
51
+ if (this.readyPromise === undefined) {
52
+ this.readyPromise = Promise.resolve(this.checkReadyAsync()).catch((cause) => {
53
+ this.readyPromise = undefined;
54
+ throw cause;
55
+ });
56
+ }
57
+ return this.readyPromise;
43
58
  }
44
59
  async $queryRaw(sql, values = []) {
45
60
  assertReadOnlySql(sql);
46
61
  try {
47
- await this.ready;
62
+ await this.ready();
48
63
  return (await this.executor.query(sql, values)).rows;
49
64
  }
50
65
  catch (cause) {
@@ -74,7 +89,7 @@ export class PqsQueryClient {
74
89
  async readPhysicalAsync(relation, query) {
75
90
  const compiled = compilePqsRelationFindMany(relation, query, this.profile);
76
91
  try {
77
- await this.ready;
92
+ await this.ready();
78
93
  return (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => this.mapPhysicalRow(row, compiled.resultShape));
79
94
  }
80
95
  catch (cause) {
@@ -84,7 +99,7 @@ export class PqsQueryClient {
84
99
  async countPhysicalAsync(relation, query) {
85
100
  const compiled = compilePqsRelationCount(relation, query, this.profile);
86
101
  try {
87
- await this.ready;
102
+ await this.ready();
88
103
  return Number((await this.executor.query(compiled.text, compiled.values)).rows[0]?.count ?? 0);
89
104
  }
90
105
  catch (cause) {
@@ -94,7 +109,7 @@ export class PqsQueryClient {
94
109
  async aggregatePhysicalAsync(relation, query) {
95
110
  const compiled = compilePqsRelationAggregate(relation, query, this.profile);
96
111
  try {
97
- await this.ready;
112
+ await this.ready();
98
113
  const row = (await this.executor.query(compiled.text, compiled.values)).rows[0] ?? {};
99
114
  const result = {};
100
115
  if (query.aggregates.count)
@@ -112,7 +127,7 @@ export class PqsQueryClient {
112
127
  async groupPhysicalAsync(relation, query) {
113
128
  const compiled = compilePqsRelationGroupBy(relation, query, this.profile);
114
129
  try {
115
- await this.ready;
130
+ await this.ready();
116
131
  return (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => Object.fromEntries(Object.entries(row).map(([name, value]) => [name, name === "count" ? Number(value) : value instanceof Date ? value : value === null ? null : String(value)])));
117
132
  }
118
133
  catch (cause) {
@@ -145,7 +160,7 @@ export class PqsQueryClient {
145
160
  async findContractsAsync(query) {
146
161
  const compiled = compileContractFindMany(query, this.profile);
147
162
  try {
148
- await this.ready;
163
+ await this.ready();
149
164
  return (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => this.mapPhysicalRow(contractRootRow(row), compiled.resultShape, contractRootScalars(row)));
150
165
  }
151
166
  catch (cause) {
@@ -155,7 +170,7 @@ export class PqsQueryClient {
155
170
  async countContractsAsync(query) {
156
171
  const compiled = compileContractCount(query, this.profile);
157
172
  try {
158
- await this.ready;
173
+ await this.ready();
159
174
  return Number((await this.executor.query(compiled.text, compiled.values)).rows[0]?.count ?? 0);
160
175
  }
161
176
  catch (cause) {
@@ -165,7 +180,7 @@ export class PqsQueryClient {
165
180
  async aggregateContractsAsync(normalized) {
166
181
  const compiled = compileContractAggregate(normalized, this.profile);
167
182
  try {
168
- await this.ready;
183
+ await this.ready();
169
184
  const row = (await this.executor.query(compiled.text, compiled.values)).rows[0] ?? {};
170
185
  const result = {};
171
186
  if (normalized.aggregates.count)
@@ -183,7 +198,7 @@ export class PqsQueryClient {
183
198
  async groupContractsAsync(query) {
184
199
  const compiled = compileContractGroupBy(query, this.profile);
185
200
  try {
186
- await this.ready;
201
+ await this.ready();
187
202
  return (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => Object.fromEntries(Object.entries(row).map(([name, value]) => [name, name === "count" ? Number(value) : value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value instanceof Date ? value : String(value)])));
188
203
  }
189
204
  catch (cause) {
@@ -1380,10 +1380,12 @@ start_ledger_stack() {
1380
1380
  if [[ "$auth_mode" == "shared-secret" ]]; then
1381
1381
  grant_localnet_validator_read_rights "$extra_participants"
1382
1382
  fi
1383
- provision_extra_pqs "$extra_participants"
1384
- local extra_pqs_services_list=()
1385
- mapfile -t extra_pqs_services_list < <(extra_pqs_services "$extra_participants")
1386
- docker_compose "${compose_args[@]}" up -d --no-recreate "${extra_pqs_services_list[@]}"
1383
+ if [[ "$(resolve_pqs_enabled)" == "1" ]]; then
1384
+ provision_extra_pqs "$extra_participants"
1385
+ local extra_pqs_services_list=()
1386
+ mapfile -t extra_pqs_services_list < <(extra_pqs_services "$extra_participants")
1387
+ docker_compose "${compose_args[@]}" up -d --no-recreate "${extra_pqs_services_list[@]}"
1388
+ fi
1387
1389
  fi
1388
1390
  }
1389
1391
 
@@ -126,6 +126,10 @@ EOF
126
126
  #!/usr/bin/env bash
127
127
  set -euo pipefail
128
128
  docker_mode="__DOCKER_MODE__"
129
+ if [[ "${1:-}" == "ps" ]]; then
130
+ printf 'splice-onboarding\n'
131
+ exit 0
132
+ fi
129
133
  printf 'stub env MODULES_DIR=%s\n' "${MODULES_DIR:-}"
130
134
  printf 'stub env LOCALNET_DIR=%s\n' "${LOCALNET_DIR:-}"
131
135
  printf 'stub env IMAGE_TAG=%s\n' "${IMAGE_TAG:-}"
@@ -332,12 +336,23 @@ EOF
332
336
  exit 1
333
337
  fi
334
338
 
339
+ LAST_RUN_CASE_OUTPUT="$output"
340
+
335
341
  if ! grep -Fxq "$expected_output" <<<"$output"; then
336
342
  printf 'expected output line %q, got:\n%s\n' "$expected_output" "$output" >&2
337
343
  exit 1
338
344
  fi
339
345
  }
340
346
 
347
+ assert_last_case_output_not_contains() {
348
+ local unexpected="$1"
349
+
350
+ if grep -Fq "$unexpected" <<<"$LAST_RUN_CASE_OUTPUT"; then
351
+ printf 'expected most recent case output not to contain %q, got:\n%s\n' "$unexpected" "$LAST_RUN_CASE_OUTPUT" >&2
352
+ exit 1
353
+ fi
354
+ }
355
+
341
356
  assert_file_contains() {
342
357
  local path="$1"
343
358
  local expected="$2"
@@ -487,6 +502,8 @@ run_case $'.PHONY: start\nstart:\n' 'stub docker compose -f compose.yaml -f '"$t
487
502
  run_case $'.PHONY: start\nstart:\n' 'stub docker-compose -f compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/localnet/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/splice-onboarding/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/pqs/compose.yaml --env-file .env --env-file .env.local --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/compose.env --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/env/common.env --env-file '"$tmpdir"'/quickstart/docker/modules/pqs/compose.env --profile app-provider --profile pqs-app-provider --profile pqs-sv down -v --remove-orphans' shared-secret compose-v1
488
503
  run_case $'.PHONY: start\nstart:\n' 'stub docker compose -f compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/localnet/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/splice-onboarding/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/pqs/compose.yaml --env-file .env --env-file .env.local --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/compose.env --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/env/common.env --env-file '"$tmpdir"'/quickstart/docker/modules/pqs/compose.env --profile app-provider --profile pqs-app-provider --profile pqs-sv -f '"$tmpdir"'/generated/compose-extra-participants.yaml --env-file '"$tmpdir"'/generated/extra-participants.env down -v --remove-orphans' shared-secret default 3
489
504
  run_case $'.PHONY: start\nstart:\n' 'stub docker compose -f compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/localnet/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/splice-onboarding/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/pqs/compose.yaml --env-file .env --env-file .env.local --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/compose.env --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/env/common.env --env-file '"$tmpdir"'/quickstart/docker/modules/pqs/compose.env --profile app-provider --profile pqs-app-provider --profile pqs-sv -f '"$tmpdir"'/generated/compose-extra-participants.yaml --env-file '"$tmpdir"'/generated/extra-participants.env up -d --no-recreate pqs-extra-1 pqs-extra-2 pqs-extra-3' shared-secret default 3
505
+ run_case $'.PHONY: start\nstart:\n' 'stub docker compose -f compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/localnet/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/splice-onboarding/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/pqs/compose.yaml --env-file .env --env-file .env.local --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/compose.env --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/env/common.env --env-file '"$tmpdir"'/quickstart/docker/modules/pqs/compose.env --profile app-provider --profile pqs-app-provider --profile pqs-sv -f '"$tmpdir"'/generated/compose-extra-participants.yaml --env-file '"$tmpdir"'/generated/extra-participants.env up -d --no-recreate postgres canton' shared-secret default 3 '' 'LOCALNET_PQS=0'
506
+ assert_last_case_output_not_contains 'stub extra pqs startup'
490
507
  run_case $'.PHONY: start\nstart:\n' 'ES256 bearer token written to '"$tmpdir"'/es256/ledger-api-user.token' shared-secret default 3 '' '' 1
491
508
  assert_file_contains_text "$tmpdir/docker-state/extra-healthcheck-command" 'wget -q --timeout=2 --tries=1 -O /dev/null http://localhost:5900/health'
492
509
  assert_file_contains_text "$tmpdir/docker-state/extra-healthcheck-command" 'wget -q --timeout=2 --tries=1 -O /dev/null http://localhost:6900/health'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@distrohelena/canton-typescript-sdk",
3
- "version": "0.1.56",
3
+ "version": "1.0.1",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",