@distrohelena/canton-typescript-sdk 0.1.36 → 0.1.37

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 (99) hide show
  1. package/README.md +104 -34
  2. package/dist/cjs/core/types/requests/{submit-command-request.js → submit-commands-request.js} +10 -6
  3. package/dist/cjs/index.js +10 -8
  4. package/dist/cjs/query/canonical/in-memory-query-evaluator.js +291 -0
  5. package/dist/cjs/query/canonical/public-identity.js +41 -0
  6. package/dist/cjs/query/canonical/query-ast.js +2 -0
  7. package/dist/cjs/query/canonical/query-dataset.js +351 -0
  8. package/dist/cjs/query/canonical/query-normalizer.js +655 -0
  9. package/dist/cjs/query/canonical/query-schema.js +86 -0
  10. package/dist/cjs/query/canton-manager.js +14 -5
  11. package/dist/cjs/query/errors/query-snapshot-incomplete-error.js +19 -0
  12. package/dist/cjs/query/grpc/grpc-contract-cache.js +484 -0
  13. package/dist/cjs/query/grpc/grpc-package-relation-reader.js +218 -0
  14. package/dist/cjs/query/grpc/grpc-query-client.js +249 -0
  15. package/dist/cjs/query/grpc/grpc-query-snapshot-reader.js +238 -0
  16. package/dist/cjs/query/grpc/grpc-query-value-mapper.js +204 -0
  17. package/dist/cjs/query/grpc/grpc-relation-mapper.js +794 -0
  18. package/dist/cjs/query/pqs/pqs-query-client.js +151 -582
  19. package/dist/cjs/query/pqs/pqs-relational-sql-compiler.js +138 -95
  20. package/dist/cjs/query/pqs/pqs-result-shape.js +28 -0
  21. package/dist/cjs/query/pqs/pqs-schema-profile.js +49 -48
  22. package/dist/cjs/query/pqs/pqs-sql-compiler.js +343 -289
  23. package/dist/cjs/query/pqs/pqs-sql-syntax.js +10 -0
  24. package/dist/cjs/services/command/command-service-client.js +16 -3
  25. package/dist/cjs/services/commands/command-payload-builder.js +1 -1
  26. package/dist/cjs/services/commands/command-submission-pipeline.js +21 -6
  27. package/dist/cjs/testing/runtime/declarative-action-executor.js +3 -3
  28. package/dist/cjs/transports/grpc/grpc-transport.js +2 -2
  29. package/dist/cjs/transports/grpc/mappers/commands-mapper.js +6 -6
  30. package/dist/cjs/transports/grpc/mappers/interactive-command-mapper.js +1 -1
  31. package/dist/cjs/transports/json/json-transport.js +1 -1
  32. package/dist/cjs/transports/json/mappers/commands-mapper.js +3 -3
  33. package/dist/core/transports/transport.interface.d.ts +4 -4
  34. package/dist/core/types/prepared-command-submission.d.ts +3 -3
  35. package/dist/core/types/requests/{submit-command-request.d.ts → submit-commands-request.d.ts} +8 -4
  36. package/dist/core/types/requests/{submit-command-request.js → submit-commands-request.js} +8 -4
  37. package/dist/index.d.ts +5 -2
  38. package/dist/index.js +2 -1
  39. package/dist/query/canonical/in-memory-query-evaluator.d.ts +22 -0
  40. package/dist/query/canonical/in-memory-query-evaluator.js +287 -0
  41. package/dist/query/canonical/public-identity.d.ts +14 -0
  42. package/dist/query/canonical/public-identity.js +35 -0
  43. package/dist/query/canonical/query-ast.d.ts +104 -0
  44. package/dist/query/canonical/query-ast.js +1 -0
  45. package/dist/query/canonical/query-dataset.d.ts +63 -0
  46. package/dist/query/canonical/query-dataset.js +343 -0
  47. package/dist/query/canonical/query-normalizer.d.ts +10 -0
  48. package/dist/query/canonical/query-normalizer.js +646 -0
  49. package/dist/query/canonical/query-schema.d.ts +25 -0
  50. package/dist/query/canonical/query-schema.js +83 -0
  51. package/dist/query/canton-manager.js +14 -5
  52. package/dist/query/errors/query-snapshot-incomplete-error.d.ts +14 -0
  53. package/dist/query/errors/query-snapshot-incomplete-error.js +15 -0
  54. package/dist/query/grpc/grpc-contract-cache.d.ts +27 -0
  55. package/dist/query/grpc/grpc-contract-cache.js +479 -0
  56. package/dist/query/grpc/grpc-package-relation-reader.d.ts +43 -0
  57. package/dist/query/grpc/grpc-package-relation-reader.js +213 -0
  58. package/dist/query/grpc/grpc-query-client.d.ts +42 -0
  59. package/dist/query/grpc/grpc-query-client.js +245 -0
  60. package/dist/query/grpc/grpc-query-snapshot-reader.d.ts +33 -0
  61. package/dist/query/grpc/grpc-query-snapshot-reader.js +233 -0
  62. package/dist/query/grpc/grpc-query-value-mapper.d.ts +15 -0
  63. package/dist/query/grpc/grpc-query-value-mapper.js +195 -0
  64. package/dist/query/grpc/grpc-relation-mapper.d.ts +67 -0
  65. package/dist/query/grpc/grpc-relation-mapper.js +789 -0
  66. package/dist/query/pqs/pqs-query-client.d.ts +10 -20
  67. package/dist/query/pqs/pqs-query-client.js +154 -585
  68. package/dist/query/pqs/pqs-relational-sql-compiler.d.ts +9 -17
  69. package/dist/query/pqs/pqs-relational-sql-compiler.js +136 -95
  70. package/dist/query/pqs/pqs-result-shape.d.ts +25 -0
  71. package/dist/query/pqs/pqs-result-shape.js +25 -0
  72. package/dist/query/pqs/pqs-schema-profile.js +49 -48
  73. package/dist/query/pqs/pqs-sql-compiler.d.ts +18 -3
  74. package/dist/query/pqs/pqs-sql-compiler.js +337 -288
  75. package/dist/query/pqs/pqs-sql-syntax.d.ts +2 -0
  76. package/dist/query/pqs/pqs-sql-syntax.js +6 -0
  77. package/dist/query/query-client.d.ts +15 -0
  78. package/dist/services/command/command-service-client.d.ts +9 -4
  79. package/dist/services/command/command-service-client.js +16 -3
  80. package/dist/services/command-submission/command-submission-service-client.d.ts +2 -2
  81. package/dist/services/commands/command-payload-builder.d.ts +2 -2
  82. package/dist/services/commands/command-payload-builder.js +1 -1
  83. package/dist/services/commands/command-submission-pipeline.d.ts +5 -4
  84. package/dist/services/commands/command-submission-pipeline.js +21 -6
  85. package/dist/testing/runtime/declarative-action-executor.js +3 -3
  86. package/dist/transports/grpc/grpc-transport.d.ts +4 -4
  87. package/dist/transports/grpc/grpc-transport.js +3 -3
  88. package/dist/transports/grpc/mappers/commands-mapper.d.ts +3 -3
  89. package/dist/transports/grpc/mappers/commands-mapper.js +4 -4
  90. package/dist/transports/grpc/mappers/interactive-command-mapper.d.ts +3 -3
  91. package/dist/transports/grpc/mappers/interactive-command-mapper.js +1 -1
  92. package/dist/transports/json/json-transport.d.ts +2 -2
  93. package/dist/transports/json/json-transport.js +2 -2
  94. package/dist/transports/json/mappers/commands-mapper.d.ts +2 -2
  95. package/dist/transports/json/mappers/commands-mapper.js +2 -2
  96. package/package.json +4 -3
  97. package/dist/cjs/query/grpc/grpc-contract-query-client.js +0 -178
  98. package/dist/query/grpc/grpc-contract-query-client.d.ts +0 -33
  99. package/dist/query/grpc/grpc-contract-query-client.js +0 -174
@@ -5,36 +5,32 @@ const query_source_js_1 = require("../query-source.js");
5
5
  const pqs_query_error_js_1 = require("../errors/pqs-query-error.js");
6
6
  const pqs_sql_compiler_js_1 = require("./pqs-sql-compiler.js");
7
7
  const pqs_relational_sql_compiler_js_1 = require("./pqs-relational-sql-compiler.js");
8
+ const query_normalizer_js_1 = require("../canonical/query-normalizer.js");
8
9
  const pqs_schema_profile_js_1 = require("./pqs-schema-profile.js");
9
10
  const read_only_sql_js_1 = require("./read-only-sql.js");
10
- const logicalContractFields = [
11
- "contractId",
12
- "templateId",
13
- "packageId",
14
- "payload",
15
- "witnesses",
16
- "createdEventOffset",
17
- "createdAt",
18
- "archivedEventOffset",
19
- "archivedAt",
20
- "active",
21
- ];
11
+ const queryRelationForPqs = {
12
+ __contracts: "contracts", __contract_tpe: "contractTypes", __events: "events", __exercises: "exercises",
13
+ __exercise_tpe: "exerciseTypes", __packages: "packages", __transactions: "transactions", __watermark: "watermark",
14
+ };
15
+ function normalizedUniqueAsFindMany(query) {
16
+ return {
17
+ kind: "findMany", relation: query.relation, predicate: query.predicate,
18
+ select: query.select, includes: query.includes,
19
+ orderBy: query.relation === "contracts" ? [{ path: ["contractId"], direction: "asc" }] : [],
20
+ skip: 0, take: 1, activeOnly: false,
21
+ };
22
+ }
22
23
  class PqsQueryClient {
23
24
  executor;
24
25
  profile;
25
26
  ready;
26
27
  source = query_source_js_1.QuerySource.pqs;
27
28
  contracts = {
28
- findMany: (args = {}) => this.findContractsAsync(args),
29
- findUnique: (args) => this.findContractsAsync({
30
- where: { contractId: { equals: args.where.contractId } },
31
- select: args.select,
32
- include: args.include,
33
- take: 1,
34
- }).then((rows) => rows[0]),
35
- count: async (args = {}) => (await this.findContractsAsync(args)).length,
36
- aggregate: async (args) => this.aggregateContractsAsync(args),
37
- groupBy: async (args) => this.groupContractsAsync(args),
29
+ findMany: async (args = {}) => await this.findContractsAsync((0, query_normalizer_js_1.normalizeFindMany)("contracts", args)),
30
+ findUnique: async (args) => (await this.findContractsAsync(normalizedUniqueAsFindMany((0, query_normalizer_js_1.normalizeFindUnique)("contracts", args))))[0],
31
+ count: async (args = {}) => this.countContractsAsync((0, query_normalizer_js_1.normalizeCount)("contracts", args)),
32
+ aggregate: async (args) => this.aggregateContractsAsync((0, query_normalizer_js_1.normalizeAggregate)("contracts", args)),
33
+ groupBy: async (args) => this.groupContractsAsync((0, query_normalizer_js_1.normalizeGroupBy)("contracts", args)),
38
34
  };
39
35
  contractTypes = this.createPhysicalDelegate("__contract_tpe");
40
36
  events = this.createPhysicalDelegate("__events");
@@ -58,105 +54,54 @@ class PqsQueryClient {
58
54
  throw this.wrap("$queryRaw", cause);
59
55
  }
60
56
  }
57
+ async cacheContracts(_args) {
58
+ return { source: query_source_js_1.QuerySource.pqs, cached: false };
59
+ }
60
+ async invalidateContractsCache(_args) { }
61
61
  createPhysicalDelegate(relation, hasUnique = true) {
62
- const metadata = pqs_schema_profile_js_1.pqsRelationMetadata[relation];
63
- const findMany = async (args = {}) => this.readPhysicalAsync(relation, metadata, args);
62
+ const queryRelation = queryRelationForPqs[relation];
64
63
  const delegate = {
65
- findMany,
66
- count: async (args = {}) => {
67
- const { where, values } = this.compileWhere(relation, metadata, args.where);
68
- try {
69
- await this.ready;
70
- const result = await this.executor.query(`select count(*)::text as count from ${this.profile.relation(relation)}${where}`, values);
71
- return Number(result.rows[0]?.count ?? 0);
72
- }
73
- catch (cause) {
74
- throw this.wrap(`${relation}.count`, cause);
75
- }
76
- },
77
- aggregate: async (args) => this.aggregatePhysicalAsync(relation, metadata, args),
78
- groupBy: async (args) => this.groupPhysicalAsync(relation, args),
64
+ findMany: async (args = {}) => this.readPhysicalAsync(relation, (0, query_normalizer_js_1.normalizeFindMany)(queryRelation, args)),
65
+ count: async (args = {}) => this.countPhysicalAsync(relation, (0, query_normalizer_js_1.normalizeCount)(queryRelation, args)),
66
+ aggregate: async (args) => this.aggregatePhysicalAsync(relation, (0, query_normalizer_js_1.normalizeAggregate)(queryRelation, args)),
67
+ groupBy: async (args) => this.groupPhysicalAsync(relation, (0, query_normalizer_js_1.normalizeGroupBy)(queryRelation, args)),
79
68
  };
80
- if (!hasUnique) {
81
- return delegate;
82
- }
83
- return {
69
+ return hasUnique ? {
84
70
  ...delegate,
85
- findUnique: async (args) => {
86
- this.assertUniqueWhere(relation, metadata, args.where);
87
- return findMany({
88
- where: Object.fromEntries(Object.entries(args.where).map(([field, value]) => [field, { equals: value }])),
89
- select: args.select,
90
- include: args.include,
91
- take: 1,
92
- }).then((rows) => rows[0]);
93
- },
94
- };
71
+ findUnique: async (args) => (await this.readPhysicalAsync(relation, normalizedUniqueAsFindMany((0, query_normalizer_js_1.normalizeFindUnique)(queryRelation, args))))[0],
72
+ } : delegate;
95
73
  }
96
- async groupPhysicalAsync(relation, args) {
97
- const root = relation === "__events" ? '"event"' : '"root"';
98
- const filter = this.compileWhere(relation, pqs_schema_profile_js_1.pqsRelationMetadata[relation], args.where, undefined, root);
99
- const compiled = (0, pqs_relational_sql_compiler_js_1.compilePqsRelationGroupBy)(relation, args, this.profile, filter.values.length);
100
- const text = filter.where.length === 0 ? compiled.text : compiled.text.replace(" group by ", `${filter.where} group by `);
74
+ async readPhysicalAsync(relation, query) {
75
+ const compiled = (0, pqs_relational_sql_compiler_js_1.compilePqsRelationFindMany)(relation, query, this.profile);
101
76
  try {
102
77
  await this.ready;
103
- return (await this.executor.query(text, [...filter.values, ...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)])));
78
+ return (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => this.mapPhysicalRow(row, compiled.resultShape));
104
79
  }
105
80
  catch (cause) {
106
- throw this.wrap(`${relation}.groupBy`, cause);
81
+ throw this.wrap(`${relation}.findMany`, cause);
107
82
  }
108
83
  }
109
- async readPhysicalAsync(relation, metadata, args) {
110
- this.assertPage(args);
111
- const selected = this.selectedFields(relation, metadata, args.select);
112
- const { where, values } = this.compileWhere(relation, metadata, args.where);
113
- const orderBy = this.compileOrderBy(relation, metadata, args.orderBy);
114
- const parameters = [...values];
115
- const add = (value) => {
116
- parameters.push(value);
117
- return `$${parameters.length}`;
118
- };
119
- const limit = args.take === undefined ? "" : ` limit ${add(args.take)}`;
120
- const offset = args.skip === undefined ? "" : ` offset ${add(args.skip)}`;
121
- const selection = selected.map(([field, column]) => `"${column}" as "${field}"`).join(", ");
122
- const includes = this.compileIncludes(relation, args.include, add);
123
- const json = this.compileJsonSelections(relation, args.select?.json, add);
124
- const fullSelection = [selection, ...json.selection, ...includes.selection].filter((value) => value.length > 0).join(", ");
84
+ async countPhysicalAsync(relation, query) {
85
+ const compiled = (0, pqs_relational_sql_compiler_js_1.compilePqsRelationCount)(relation, query, this.profile);
125
86
  try {
126
87
  await this.ready;
127
- const result = await this.executor.query(`select ${fullSelection} from ${this.profile.relation(relation)}${where}${orderBy}${limit}${offset}`, parameters);
128
- return result.rows.map((row) => this.mapPhysicalRow(row, metadata, selected, includes.values, json.fields));
88
+ return Number((await this.executor.query(compiled.text, compiled.values)).rows[0]?.count ?? 0);
129
89
  }
130
90
  catch (cause) {
131
- throw this.wrap(`${relation}.findMany`, cause);
91
+ throw this.wrap(`${relation}.count`, cause);
132
92
  }
133
93
  }
134
- async aggregatePhysicalAsync(relation, metadata, args) {
135
- const { where, values } = this.compileWhere(relation, metadata, args.where);
136
- const selected = [];
137
- if (args.count) {
138
- selected.push("count(*)::text as count");
139
- }
140
- for (const [operation, fields] of [["min", args.min], ["max", args.max], ["sum", args.sum]]) {
141
- for (const field of fields ?? []) {
142
- this.assertNumericField(relation, metadata, field);
143
- selected.push(`${operation}("${metadata.fields[field]}")::text as "${operation}_${field}"`);
144
- }
145
- }
146
- if (selected.length === 0) {
147
- throw new Error("aggregate must request at least one result");
148
- }
94
+ async aggregatePhysicalAsync(relation, query) {
95
+ const compiled = (0, pqs_relational_sql_compiler_js_1.compilePqsRelationAggregate)(relation, query, this.profile);
149
96
  try {
150
97
  await this.ready;
151
- const row = (await this.executor.query(`select ${selected.join(", ")} from ${this.profile.relation(relation)}${where}`, values)).rows[0] ?? {};
98
+ const row = (await this.executor.query(compiled.text, compiled.values)).rows[0] ?? {};
152
99
  const result = {};
153
- if (args.count) {
100
+ if (query.aggregates.count)
154
101
  result.count = Number(row.count ?? 0);
155
- }
156
- for (const [operation, fields] of [["min", args.min], ["max", args.max], ["sum", args.sum]]) {
157
- if (fields !== undefined) {
102
+ for (const [operation, fields] of [["min", query.aggregates.min], ["max", query.aggregates.max], ["sum", query.aggregates.sum]]) {
103
+ if (fields.length > 0)
158
104
  result[operation] = Object.fromEntries(fields.map((field) => [field, nullableString(row[`${operation}_${field}`])]));
159
- }
160
105
  }
161
106
  return result;
162
107
  }
@@ -164,403 +109,79 @@ class PqsQueryClient {
164
109
  throw this.wrap(`${relation}.aggregate`, cause);
165
110
  }
166
111
  }
167
- compileWhere(relation, metadata, filters, externalAdd, parentExpression = this.profile.relation(relation)) {
168
- const values = [];
169
- const add = externalAdd ?? ((value) => {
170
- values.push(value);
171
- return `$${values.length}`;
172
- });
173
- if (relation === "__contracts") {
174
- const where = this.compileLogicalContractWhere(filters, add, parentExpression);
175
- return { where: where === "true" ? "" : ` where ${where}`, values };
176
- }
177
- const compile = (expression) => {
178
- const conditions = [];
179
- for (const [field, filter] of Object.entries(expression ?? {})) {
180
- if (field === "and" || field === "or") {
181
- if (!Array.isArray(filter))
182
- throw new Error(`${field} must be an array`);
183
- conditions.push(filter.length ? `(${filter.map((child) => compile(child)).join(` ${field} `)})` : field === "and" ? "true" : "false");
184
- continue;
185
- }
186
- if (field === "not") {
187
- if (filter === null || Array.isArray(filter) || typeof filter !== "object")
188
- throw new Error("not must be an expression");
189
- conditions.push(`not (${compile(filter)})`);
190
- continue;
191
- }
192
- const edge = pqs_schema_profile_js_1.pqsRelationEdges[relation]?.[field];
193
- if (edge !== undefined) {
194
- if (filter === null || Array.isArray(filter) || typeof filter !== "object")
195
- throw new Error(`${field} must be a relation filter`);
196
- const related = filter;
197
- const alias = `"${field}"`;
198
- const relatedCondition = (child) => {
199
- const where = this.compileWhere(edge.target, pqs_schema_profile_js_1.pqsRelationMetadata[edge.target], child, add, alias).where;
200
- return where.length === 0 ? "true" : where.slice(" where ".length);
201
- };
202
- const join = `${alias}."${edge.targetColumn}" = ${parentExpression}."${edge.sourceColumn}"`;
203
- if (edge.cardinality === "one") {
204
- if (Object.keys(related).some((name) => ["some", "none", "every"].includes(name)))
205
- throw new Error(`${field} is a to-one relation`);
206
- conditions.push(`exists (select 1 from ${this.profile.relation(edge.target)} ${alias} where ${join} and (${relatedCondition(related)}))`);
207
- }
208
- else {
209
- const operators = ["some", "none", "every"].filter((name) => related[name] !== undefined);
210
- if (operators.length !== 1)
211
- throw new Error(`${field} requires exactly one of some, none, or every`);
212
- const operator = operators[0];
213
- const predicate = related[operator];
214
- const condition = relatedCondition(predicate);
215
- const subquery = `select 1 from ${this.profile.relation(edge.target)} ${alias} where ${join} and (${condition})`;
216
- if (operator === "some")
217
- conditions.push(`exists (${subquery})`);
218
- else if (operator === "none")
219
- conditions.push(`not exists (${subquery})`);
220
- else
221
- conditions.push(`not exists (select 1 from ${this.profile.relation(edge.target)} ${alias} where ${join} and not (${condition}))`);
222
- }
223
- continue;
224
- }
225
- const column = this.field(relation, metadata, field);
226
- if (filter === null || Array.isArray(filter) || typeof filter !== "object")
227
- throw new Error(`${field} must be a filter`);
228
- const scalar = filter;
229
- if (pqs_schema_profile_js_1.PqsSchemaProfileV1.jsonField(relation, field) && scalar.path !== undefined) {
230
- if (scalar.path.length === 0 || scalar.path.some((segment) => segment.length === 0))
231
- throw new Error(`${field}.path must be a non-empty JSON path`);
232
- const expression = `"${column}" #>> ${add(scalar.path)}::text[]`;
233
- if (scalar.is === null)
234
- conditions.push(`${expression} is null`);
235
- if (scalar.isNot === null)
236
- conditions.push(`${expression} is not null`);
237
- if (scalar.equals !== undefined)
238
- conditions.push(`${expression} = ${add(scalar.equals)}`);
239
- if (scalar.in !== undefined)
240
- conditions.push(scalar.in.length === 0 ? "false" : `${expression} = any(${add(scalar.in)})`);
241
- for (const [operator, value] of [["lt", scalar.lt], ["lte", scalar.lte], ["gt", scalar.gt], ["gte", scalar.gte], ["like", scalar.like], ["ilike", scalar.ilike]]) {
242
- if (value !== undefined)
243
- conditions.push(`${expression} ${operator === "lte" ? "<=" : operator === "gte" ? ">=" : operator} ${add(value)}`);
244
- }
245
- continue;
246
- }
247
- if (scalar.is === null) {
248
- conditions.push(`"${column}" is null`);
249
- }
250
- if (scalar.isNot === null) {
251
- conditions.push(`"${column}" is not null`);
252
- }
253
- if (scalar.equals !== undefined) {
254
- conditions.push(`"${column}" = ${add(scalar.equals)}`);
255
- }
256
- if (scalar.in !== undefined) {
257
- conditions.push(scalar.in.length === 0 ? "false" : `"${column}" = any(${add(scalar.in)})`);
258
- }
259
- if (scalar.has !== undefined) {
260
- if (!metadata.arrayFields.includes(field)) {
261
- throw new Error(`${field} is not an array field of ${relation}`);
262
- }
263
- conditions.push(`${add(scalar.has)} = any("${column}")`);
264
- }
265
- for (const [operator, value] of [["lt", scalar.lt], ["lte", scalar.lte], ["gt", scalar.gt], ["gte", scalar.gte], ["like", scalar.like], ["ilike", scalar.ilike]]) {
266
- if (value === undefined)
267
- continue;
268
- if ((operator === "like" || operator === "ilike") && !metadata.stringFields?.includes(field))
269
- throw new Error(`${field} does not support ${operator}`);
270
- if ((operator !== "like" && operator !== "ilike") && !metadata.numericFields.includes(field) && !metadata.dateFields.includes(field) && !metadata.stringFields?.includes(field))
271
- throw new Error(`${field} does not support ${operator}`);
272
- conditions.push(`"${column}" ${operator === "lte" ? "<=" : operator === "gte" ? ">=" : operator} ${add(value)}`);
273
- }
274
- }
275
- return conditions.length ? conditions.join(" and ") : "true";
276
- };
277
- const where = compile(filters);
278
- return { where: where === "true" ? "" : ` where ${where}`, values };
279
- }
280
- compileLogicalContractWhere(filters, add, alias) {
281
- const compile = (expression) => {
282
- const conditions = [];
283
- for (const [field, filter] of Object.entries(expression ?? {})) {
284
- if (field === "and" || field === "or") {
285
- if (!Array.isArray(filter))
286
- throw new Error(`${field} must be an array`);
287
- conditions.push(filter.length === 0 ? field === "and" ? "true" : "false" : `(${filter.map((child) => compile(child)).join(` ${field} `)})`);
288
- continue;
289
- }
290
- if (field === "not") {
291
- conditions.push(`not (${compile(filter)})`);
292
- continue;
293
- }
294
- if (field === "active") {
295
- const value = typeof filter === "boolean" ? filter : filter.equals;
296
- if (typeof value !== "boolean")
297
- throw new Error("active supports only equals");
298
- conditions.push(`${alias}."archived_at_ix" is ${value ? "null" : "not null"}`);
299
- continue;
300
- }
301
- if (field === "witnesses") {
302
- const value = filter.has;
303
- if (typeof value !== "string")
304
- throw new Error("witnesses supports only has");
305
- conditions.push(`${add(value)} = any(${alias}."witnesses")`);
306
- continue;
307
- }
308
- if (field === "payload") {
309
- const match = filter.match;
310
- if (match === undefined || typeof match !== "object" || match === null)
311
- throw new Error("payload requires match");
312
- for (const [key, value] of Object.entries(match))
313
- if (value.equals !== undefined)
314
- conditions.push(`${alias}."payload" #>> ${add([key])}::text[] = ${add(value.equals)}`);
315
- continue;
316
- }
317
- const columns = { contractId: "contract_id", packageId: "creation_package_id", createdEventOffset: "created_at_ix", archivedEventOffset: "archived_at_ix" };
318
- const column = columns[field];
319
- if (column === undefined || filter === null || typeof filter !== "object")
320
- throw new Error(`${field} is not a supported contract filter`);
321
- const value = filter;
322
- if (value.equals !== undefined)
323
- conditions.push(`${alias}."${column}" = ${add(value.equals)}`);
324
- else if (value.in !== undefined)
325
- conditions.push(value.in.length === 0 ? "false" : `${alias}."${column}" = any(${add(value.in)})`);
326
- else
327
- throw new Error(`${field} requires equals or in`);
328
- }
329
- return conditions.length === 0 ? "true" : conditions.join(" and ");
330
- };
331
- return compile(filters);
332
- }
333
- selectedFields(relation, metadata, select) {
334
- if (select === undefined) {
335
- return Object.entries(metadata.fields);
336
- }
337
- const selected = Object.entries(select).filter(([field, enabled]) => field !== "json" && enabled === true).map(([field]) => [field, this.field(relation, metadata, field)]);
338
- if (selected.length === 0 && Object.keys(select.json ?? {}).length === 0) {
339
- throw new Error("select must include at least one field");
340
- }
341
- return selected;
342
- }
343
- compileOrderBy(relation, metadata, orderBy) {
344
- if (orderBy === undefined) {
345
- return "";
346
- }
347
- const entries = orderBy.flatMap((entry) => Object.entries(entry));
348
- if (entries.length === 0 || entries.some(([, direction]) => direction !== "asc" && direction !== "desc")) {
349
- throw new Error("orderBy must be a non-empty list of one-field entries");
350
- }
351
- return ` order by ${entries.map(([field, direction]) => `"${this.field(relation, metadata, field)}" ${direction}`).join(", ")}`;
352
- }
353
- assertUniqueWhere(relation, metadata, where) {
354
- const fields = Object.keys(where).sort();
355
- const matches = metadata.uniqueKeys.some((key) => [...key].sort().join("\0") === fields.join("\0"));
356
- if (!matches) {
357
- throw new Error(`where is not a stable unique key of ${relation}`);
358
- }
359
- }
360
- assertNumericField(relation, metadata, field) {
361
- if (!metadata.numericFields.includes(field)) {
362
- throw new Error(`${field} is not a numeric aggregate field of ${relation}`);
112
+ async groupPhysicalAsync(relation, query) {
113
+ const compiled = (0, pqs_relational_sql_compiler_js_1.compilePqsRelationGroupBy)(relation, query, this.profile);
114
+ try {
115
+ await this.ready;
116
+ 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)])));
363
117
  }
364
- }
365
- field(relation, metadata, field) {
366
- const column = metadata.fields[field];
367
- if (column === undefined) {
368
- throw new Error(`${field} is not a field of ${relation}`);
118
+ catch (cause) {
119
+ throw this.wrap(`${relation}.groupBy`, cause);
369
120
  }
370
- return column;
371
121
  }
372
- assertPage(args) {
373
- for (const [name, value] of [["take", args.take], ["skip", args.skip]]) {
374
- if (value !== undefined && (!Number.isInteger(value) || value < 0)) {
375
- throw new Error(`${name} must be a non-negative integer`);
376
- }
122
+ mapPhysicalRow(row, shape, scalarSource = row) {
123
+ const metadata = pqs_schema_profile_js_1.pqsRelationMetadata[shape.relation];
124
+ const scalar = Object.fromEntries(shape.fields
125
+ .filter(({ name }) => Object.hasOwn(scalarSource, name) || Object.hasOwn(scalarSource, metadata.fields[name] ?? ""))
126
+ .map(({ name }) => [name, mapPhysicalValue(scalarSource[name] ?? scalarSource[metadata.fields[name] ?? ""], shape.relation, metadata, name)]));
127
+ const projected = Object.fromEntries(shape.json.map((projection) => [projection.name, mapJsonValue(row[projection.name], projection.as)]));
128
+ const included = Object.fromEntries(shape.includes.map((include) => [include.edge, this.mapIncludedPhysicalValue(row[include.edge], include)]));
129
+ return { ...scalar, ...projected, ...included };
130
+ }
131
+ mapIncludedPhysicalValue(value, include) {
132
+ if (include.cardinality === "many") {
133
+ if (value === null || value === undefined)
134
+ return [];
135
+ if (!Array.isArray(value))
136
+ throw new Error(`Invalid included ${include.target} rows`);
137
+ return value.map((entry) => this.mapIncludedPhysicalValue(entry, { ...include, cardinality: "one" }));
377
138
  }
378
- }
379
- mapPhysicalRow(row, metadata, fields, includes, json = {}) {
380
- const scalar = Object.fromEntries(fields
381
- .filter(([field]) => Object.hasOwn(row, field))
382
- .map(([field]) => [field, mapPhysicalValue(row[field], metadata, field)]));
383
- const related = Object.fromEntries(Object.entries(includes).map(([name, edge]) => [name, this.mapRelatedValue(row[name], edge.target, edge.options)]));
384
- const projected = Object.fromEntries(Object.entries(json).map(([name, as]) => [name, mapJsonValue(row[name], as)]));
385
- return { ...scalar, ...projected, ...related };
386
- }
387
- mapRelatedValue(value, relation, options) {
388
139
  if (value === null || value === undefined)
389
- return value ?? null;
390
- if (Array.isArray(value))
391
- return value.map((entry) => this.mapRelatedValue(entry, relation, options));
392
- if (typeof value !== "object")
393
- throw new Error(`Invalid included ${relation} row`);
394
- if (relation === "__contracts")
395
- return this.mapLogicalContractValue(value, options);
396
- const metadata = pqs_schema_profile_js_1.pqsRelationMetadata[relation];
397
- const row = value;
398
- const fields = this.selectedFields(relation, metadata, options.select);
399
- const nested = Object.fromEntries(Object.entries(options.include ?? {}).map(([name, option]) => {
400
- const edge = pqs_schema_profile_js_1.pqsRelationEdges[relation]?.[name];
401
- if (edge === undefined)
402
- throw new Error(`${name} is not a relation of ${relation}`);
403
- return [name, { target: edge.target, options: option === true ? {} : option }];
404
- }));
405
- const json = Object.fromEntries(Object.entries(options.select?.json ?? {}).map(([name, projection]) => [name, projection.as]));
406
- const normalized = Object.fromEntries(fields
407
- .filter(([field, column]) => Object.hasOwn(row, field) || Object.hasOwn(row, column))
408
- .map(([field, column]) => [field, row[field] ?? row[column]]));
409
- for (const name of Object.keys(nested))
410
- normalized[name] = row[name];
411
- for (const name of Object.keys(json))
412
- normalized[name] = row[name];
413
- return this.mapPhysicalRow(normalized, metadata, fields, nested, json);
414
- }
415
- mapLogicalContractValue(row, options) {
416
- const fields = options.select === undefined
417
- ? logicalContractFields
418
- : Object.entries(options.select).filter(([field, enabled]) => field !== "json" && enabled === true).map(([field]) => {
419
- if (!logicalContractFields.includes(field))
420
- throw new Error(`${field} is not a field of __contracts`);
421
- return field;
422
- });
423
- const scalar = Object.fromEntries(fields.filter((field) => Object.hasOwn(row, field)).map((field) => [field, row[field]]));
424
- const relations = Object.fromEntries(Object.entries(options.include ?? {}).map(([name, option]) => {
425
- const edge = pqs_schema_profile_js_1.pqsRelationEdges.__contracts?.[name];
426
- if (edge === undefined)
427
- throw new Error(`${name} is not a relation of __contracts`);
428
- return [name, this.mapRelatedValue(row[name], edge.target, option === true ? {} : option)];
429
- }));
430
- const json = Object.fromEntries(Object.entries(options.select?.json ?? {}).map(([name, projection]) => [name, mapJsonValue(row[name], projection.as)]));
431
- return { ...scalar, ...json, ...relations };
432
- }
433
- compileIncludes(relation, include, add, parentExpression = this.profile.relation(relation)) {
434
- const selections = [];
435
- const values = {};
436
- for (const [name, option] of Object.entries(include ?? {})) {
437
- const edge = pqs_schema_profile_js_1.pqsRelationEdges[relation]?.[name];
438
- if (edge === undefined)
439
- throw new Error(`${name} is not a relation of ${relation}`);
440
- const options = option === true ? {} : option;
441
- if (edge.cardinality === "many" && options.take === undefined)
442
- throw new Error(`${name} is a to-many relation and requires take`);
443
- if (options.take !== undefined && (!Number.isInteger(options.take) || options.take < 0))
444
- throw new Error(`${name}.take must be a non-negative integer`);
445
- const expression = this.compileIncludedExpression(name, edge.target, edge.sourceColumn, edge.targetColumn, edge.cardinality, options, add, parentExpression);
446
- selections.push(`${expression} as "${name}"`);
447
- values[name] = { target: edge.target, options };
448
- }
449
- return { selection: selections, values };
450
- }
451
- compileJsonSelections(relation, selections, add, tableAlias) {
452
- const selection = [];
453
- const fields = {};
454
- for (const [name, projection] of Object.entries(selections ?? {})) {
455
- if (!pqs_schema_profile_js_1.PqsSchemaProfileV1.jsonField(relation, projection.field))
456
- throw new Error(`${projection.field} is not a JSON field of ${relation}`);
457
- if (projection.path.length === 0 || projection.path.some((segment) => segment.length === 0))
458
- throw new Error(`${name}.path must be a non-empty JSON path`);
459
- const column = this.field(relation, pqs_schema_profile_js_1.pqsRelationMetadata[relation], projection.field);
460
- const text = `${tableAlias === undefined ? "" : `${tableAlias}.`}"${column}" #>> ${add(projection.path)}::text[]`;
461
- const expression = projection.as === "text" ? text : projection.as === "numeric" ? `(${text})::numeric::text` : projection.as === "boolean" ? `(${text})::boolean` : `(${text})::timestamptz`;
462
- selection.push(`${expression} as "${name}"`);
463
- fields[name] = projection.as;
464
- }
465
- return { selection, fields };
466
- }
467
- compileIncludedExpression(name, target, sourceColumn, targetColumn, cardinality, options, add, parentExpression) {
468
- const alias = `"${name}"`;
469
- const targetMetadata = pqs_schema_profile_js_1.pqsRelationMetadata[target];
470
- const fields = target === "__contracts" ? [] : this.selectedFields(target, targetMetadata, options.select);
471
- const json = target === "__contracts"
472
- ? this.compileLogicalContractJsonSelections(options.select?.json, add, alias)
473
- : this.compileJsonSelections(target, options.select?.json, add, alias).selection;
474
- const nested = this.compileIncludes(target, options.include, add, alias).selection;
475
- const scalarSelections = target === "__contracts"
476
- ? this.compileLogicalContractSelections(alias, options.select)
477
- : fields.map(([field, column]) => `'${field}', ${alias}."${column}"`);
478
- const object = `jsonb_build_object(${[...scalarSelections, ...[...json, ...nested].flatMap((selection) => {
479
- const match = /^(.*) as "([^"]+)"$/.exec(selection);
480
- return match === null ? [] : [`'${match[2]}', ${match[1]}`];
481
- })].join(", ")})`;
482
- const { where } = this.compileWhere(target, targetMetadata, options.where, add, alias);
483
- const condition = `${alias}."${targetColumn}" = ${parentExpression}."${sourceColumn}"`;
484
- const childWhere = where.length === 0 ? ` where ${condition}` : `${where} and ${condition}`;
485
- if (cardinality === "one")
486
- return `(select ${object} from ${this.profile.relation(target)} ${alias}${childWhere})`;
487
- const orderBy = this.compileOrderBy(target, targetMetadata, options.orderBy);
488
- return `(select coalesce(jsonb_agg("${name}_limited".value), '[]'::jsonb) from (select ${object} as value from ${this.profile.relation(target)} ${alias}${childWhere}${orderBy} limit ${add(options.take)}) "${name}_limited")`;
489
- }
490
- compileLogicalContractSelections(alias, select) {
491
- const selected = select === undefined
492
- ? logicalContractFields
493
- : Object.entries(select).filter(([field, enabled]) => field !== "json" && enabled === true).map(([field]) => field);
494
- if (selected.length === 0 && Object.keys(select?.json ?? {}).length === 0)
495
- throw new Error("select must include at least one field");
496
- const expressions = {
497
- contractId: `${alias}."contract_id"`,
498
- templateId: `jsonb_build_object('packageId', ${alias}."creation_package_id", 'moduleName', (select contract_type."module_name" from ${this.profile.relation("__contract_tpe")} contract_type where contract_type."pk" = ${alias}."tpe_pk"), 'entityName', (select contract_type."entity_name" from ${this.profile.relation("__contract_tpe")} contract_type where contract_type."pk" = ${alias}."tpe_pk"))`,
499
- packageId: `${alias}."creation_package_id"`,
500
- payload: `${alias}."payload"`,
501
- witnesses: `${alias}."witnesses"`,
502
- createdEventOffset: `${alias}."created_at_ix"::text`,
503
- createdAt: `(select created_transaction."effective_at" from ${this.profile.relation("__transactions")} created_transaction where created_transaction."ix" = ${alias}."created_at_ix")`,
504
- archivedEventOffset: `${alias}."archived_at_ix"::text`,
505
- archivedAt: `(select archived_transaction."effective_at" from ${this.profile.relation("__transactions")} archived_transaction where archived_transaction."ix" = ${alias}."archived_at_ix")`,
506
- active: `${alias}."archived_at_ix" is null`,
507
- };
508
- return selected.map((field) => {
509
- const expression = expressions[field];
510
- if (expression === undefined)
511
- throw new Error(`${field} is not a field of __contracts`);
512
- return `'${field}', ${expression}`;
513
- });
514
- }
515
- compileLogicalContractJsonSelections(selections, add, alias) {
516
- return Object.entries(selections ?? {}).map(([name, projection]) => {
517
- if (projection.field !== "payload")
518
- throw new Error(`${projection.field} is not a JSON field of __contracts`);
519
- if (projection.path.length === 0 || projection.path.some((segment) => segment.length === 0))
520
- throw new Error(`${name}.path must be a non-empty JSON path`);
521
- const text = `${alias}."payload" #>> ${add(projection.path)}::text[]`;
522
- const expression = projection.as === "text" ? text : projection.as === "numeric" ? `(${text})::numeric::text` : projection.as === "boolean" ? `(${text})::boolean` : `(${text})::timestamptz`;
523
- return `${expression} as "${name}"`;
524
- });
140
+ return null;
141
+ if (typeof value !== "object" || Array.isArray(value))
142
+ throw new Error(`Invalid included ${include.target} row`);
143
+ return this.mapPhysicalRow(value, include.shape);
525
144
  }
526
- async findContractsAsync(args) {
527
- const compiled = (0, pqs_sql_compiler_js_1.compileContractFindMany)(args, this.profile);
145
+ async findContractsAsync(query) {
146
+ const compiled = (0, pqs_sql_compiler_js_1.compileContractFindMany)(query, this.profile);
528
147
  try {
529
- const include = "include" in args ? args.include : undefined;
530
- const rows = (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => mapContractRow(row, include, "select" in args ? args.select?.json : undefined));
531
- const select = "select" in args ? args.select : undefined;
532
- if (select === undefined) {
533
- return rows;
534
- }
535
- const fields = Object.entries(select).filter(([field, enabled]) => field !== "json" && enabled === true).map(([field]) => field);
536
- const json = Object.keys(select.json ?? {});
537
- if (fields.length === 0 && json.length === 0) {
538
- throw new Error("select must include at least one field");
539
- }
540
- return rows.map((row) => Object.fromEntries([...fields.map((field) => [field, row[field]]), ...json.map((field) => [field, row[field]])]));
148
+ await this.ready;
149
+ return (await this.executor.query(compiled.text, compiled.values)).rows.map((row) => this.mapPhysicalRow(contractRootRow(row), compiled.resultShape, contractRootScalars(row)));
541
150
  }
542
151
  catch (cause) {
543
152
  throw this.wrap("contracts.findMany", cause);
544
153
  }
545
154
  }
546
- async aggregateContractsAsync(args) {
547
- if (!args.count && args.min === undefined && args.max === undefined && args.sum === undefined) {
548
- throw new Error("aggregate must request at least one result");
155
+ async countContractsAsync(query) {
156
+ const compiled = (0, pqs_sql_compiler_js_1.compileContractCount)(query, this.profile);
157
+ try {
158
+ await this.ready;
159
+ return Number((await this.executor.query(compiled.text, compiled.values)).rows[0]?.count ?? 0);
549
160
  }
550
- const rows = await this.findContractsAsync({ where: args.where });
551
- const result = {};
552
- if (args.count) {
553
- result.count = rows.length;
161
+ catch (cause) {
162
+ throw this.wrap("contracts.count", cause);
554
163
  }
555
- for (const [operation, fields] of [["min", args.min], ["max", args.max], ["sum", args.sum]]) {
556
- if (fields !== undefined) {
557
- result[operation] = Object.fromEntries(fields.map((field) => [field, aggregateNumeric(rows.map((row) => row[field]), operation)]));
164
+ }
165
+ async aggregateContractsAsync(normalized) {
166
+ const compiled = (0, pqs_sql_compiler_js_1.compileContractAggregate)(normalized, this.profile);
167
+ try {
168
+ await this.ready;
169
+ const row = (await this.executor.query(compiled.text, compiled.values)).rows[0] ?? {};
170
+ const result = {};
171
+ if (normalized.aggregates.count)
172
+ result.count = Number(row.count ?? 0);
173
+ for (const [operation, fields] of [["min", normalized.aggregates.min], ["max", normalized.aggregates.max], ["sum", normalized.aggregates.sum]]) {
174
+ if (fields.length > 0)
175
+ result[operation] = Object.fromEntries(fields.map((field) => [field, nullableString(row[`${operation}_${field}`])]));
558
176
  }
177
+ return result;
178
+ }
179
+ catch (cause) {
180
+ throw this.wrap("contracts.aggregate", cause);
559
181
  }
560
- return result;
561
182
  }
562
- async groupContractsAsync(args) {
563
- const compiled = (0, pqs_sql_compiler_js_1.compileContractGroupBy)(args, this.profile);
183
+ async groupContractsAsync(query) {
184
+ const compiled = (0, pqs_sql_compiler_js_1.compileContractGroupBy)(query, this.profile);
564
185
  try {
565
186
  await this.ready;
566
187
  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)])));
@@ -574,22 +195,39 @@ class PqsQueryClient {
574
195
  }
575
196
  }
576
197
  exports.PqsQueryClient = PqsQueryClient;
577
- function mapPhysicalValue(value, metadata, field) {
578
- if (value === null || value === undefined) {
198
+ function mapPhysicalValue(value, relation, metadata, field) {
199
+ if (value === null || value === undefined)
579
200
  return value ?? null;
580
- }
581
- else if (metadata.numericFields.includes(field)) {
201
+ if (relation === "__events" && field === "eventId" && typeof value === "object" && !Array.isArray(value)) {
202
+ const event = value;
203
+ if (event.offset !== undefined && event.node_id !== undefined)
204
+ return `${String(event.offset)}:${String(event.node_id)}`;
205
+ }
206
+ if (relation === "__events" && field === "type") {
207
+ if (value === "create")
208
+ return "created";
209
+ if (value === "exercise")
210
+ return "exercised";
211
+ }
212
+ if (relation === "__transactions" && field === "workflowId" && value === "")
213
+ return null;
214
+ if (relation === "__transactions" && field === "traceContext" && typeof value === "object" && !Array.isArray(value)) {
215
+ const trace = value;
216
+ const traceparent = trace.traceparent ?? trace.trace_parent;
217
+ const tracestate = trace.tracestate ?? trace.trace_state;
218
+ return Object.fromEntries([
219
+ ...(traceparent === undefined || traceparent === null || traceparent === "" ? [] : [["traceparent", String(traceparent)]]),
220
+ ...(tracestate === undefined || tracestate === null || tracestate === "" ? [] : [["tracestate", String(tracestate)]]),
221
+ ]);
222
+ }
223
+ if (metadata.numericFields.includes(field))
582
224
  return String(value);
583
- }
584
- else if (metadata.dateFields.includes(field)) {
225
+ if (metadata.dateFields.includes(field))
585
226
  return value instanceof Date ? value : new Date(String(value));
586
- }
587
- else if (metadata.binaryFields.includes(field)) {
227
+ if (metadata.binaryFields.includes(field))
588
228
  return value instanceof Uint8Array ? value : new Uint8Array(value);
589
- }
590
- else if (metadata.arrayFields.includes(field)) {
229
+ if (metadata.arrayFields.includes(field))
591
230
  return Array.isArray(value) ? value.map(String) : [];
592
- }
593
231
  return value;
594
232
  }
595
233
  function mapJsonValue(value, as) {
@@ -601,99 +239,30 @@ function mapJsonValue(value, as) {
601
239
  return value instanceof Date ? value : new Date(String(value));
602
240
  return String(value);
603
241
  }
604
- function mapProfileJsonRow(value, relation) {
605
- if (value === null || value === undefined)
606
- return null;
607
- if (typeof value !== "object" || Array.isArray(value))
608
- throw new Error(`Invalid included ${relation} row`);
609
- const row = value;
610
- const metadata = pqs_schema_profile_js_1.pqsRelationMetadata[relation];
611
- return Object.fromEntries(Object.entries(metadata.fields).map(([field, column]) => [field, mapPhysicalValue(row[field] ?? row[column], metadata, field)]));
612
- }
613
- function mapSelectedProfileJsonRow(value, relation) {
614
- if (value === null || value === undefined)
615
- return null;
616
- if (typeof value !== "object" || Array.isArray(value))
617
- throw new Error(`Invalid included ${relation} row`);
618
- const row = value;
619
- const metadata = pqs_schema_profile_js_1.pqsRelationMetadata[relation];
620
- return Object.fromEntries(Object.entries(metadata.fields)
621
- .filter(([field, column]) => Object.hasOwn(row, field) || Object.hasOwn(row, column))
622
- .map(([field, column]) => [field, mapPhysicalValue(row[field] ?? row[column], metadata, field)]));
623
- }
624
- function mapContractTypeJson(value) {
625
- const row = mapProfileJsonRow(value, "__contract_tpe");
626
- return row === null ? undefined : { pk: String(row.pk), payloadType: String(row.payloadType), aliases: stringArray(row.aliases), packageName: String(row.packageName), moduleName: String(row.moduleName), entityName: String(row.entityName), templateFqn: String(row.templateFqn) };
627
- }
628
- function mapTransactionJson(value) {
629
- const row = mapProfileJsonRow(value, "__transactions");
630
- return row === null ? undefined : { ix: String(row.ix), offset: String(row.offset), transactionId: nullableString(row.transactionId), effectiveAt: nullableDate(row.effectiveAt), workflowId: nullableString(row.workflowId), domainId: nullableString(row.domainId), traceContext: row.traceContext, externalTransactionHash: row.externalTransactionHash instanceof Uint8Array ? row.externalTransactionHash : null, paidTrafficCost: nullableString(row.paidTrafficCost) };
631
- }
632
- function mapEventJson(value) {
633
- const row = mapSelectedProfileJsonRow(value, "__events");
634
- return row ?? undefined;
635
- }
636
- function mapSelectedRelationJson(value, relation) {
637
- const row = mapSelectedProfileJsonRow(value, relation);
638
- return row ?? undefined;
639
- }
640
- function mapLogicalContractJson(value) {
641
- if (value === null || value === undefined)
642
- return undefined;
643
- if (typeof value !== "object" || Array.isArray(value))
644
- throw new Error("Invalid included __contracts row");
645
- return value;
646
- }
647
- function mapExerciseJson(value) {
648
- const raw = value;
649
- const row = mapSelectedProfileJsonRow(value, "__exercises");
650
- if (row === null)
651
- throw new Error("Included exercise cannot be null");
652
- const base = row;
653
- const knownFields = new Set(Object.entries(pqs_schema_profile_js_1.pqsRelationMetadata.__exercises.fields).flatMap(([field, column]) => [field, column]));
654
- const knownRelations = new Set(Object.keys(pqs_schema_profile_js_1.pqsRelationEdges.__exercises ?? {}));
655
- const projections = Object.fromEntries(Object.entries(raw).filter(([name]) => !knownFields.has(name) && !knownRelations.has(name)));
656
- return {
657
- ...base,
658
- ...projections,
659
- ...(raw.exerciseType === undefined ? {} : { exerciseType: mapSelectedRelationJson(raw.exerciseType, "__exercise_tpe") }),
660
- ...(raw.contractType === undefined ? {} : { contractType: mapSelectedRelationJson(raw.contractType, "__contract_tpe") }),
661
- ...(raw.event === undefined ? {} : { event: raw.event === null ? null : mapEventJson(raw.event) ?? null }),
662
- ...(raw.transaction === undefined ? {} : { transaction: raw.transaction === null ? null : mapTransactionJson(raw.transaction) ?? null }),
663
- ...(raw.package === undefined ? {} : { package: mapSelectedRelationJson(raw.package, "__packages") }),
664
- ...(raw.contract === undefined ? {} : { contract: mapLogicalContractJson(raw.contract) }),
242
+ function contractRootScalars(row) {
243
+ const scalars = {
244
+ contractId: row.contract_id,
245
+ packageId: row.package_id,
246
+ payload: row.payload,
247
+ witnesses: row.witnesses,
248
+ createdEventOffset: row.created_event_offset,
249
+ createdAt: row.created_at,
250
+ archivedEventOffset: row.archived_event_offset,
251
+ archivedAt: row.archived_at,
252
+ active: row.active,
665
253
  };
254
+ if (row.template_package_id !== undefined && row.template_module_name !== undefined && row.template_entity_name !== undefined) {
255
+ scalars.templateId = { packageId: row.template_package_id, moduleName: row.template_module_name, entityName: row.template_entity_name };
256
+ }
257
+ return scalars;
666
258
  }
667
- function mapContractRow(row, include, json) {
668
- const base = { 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 };
669
- const relations = {
670
- ...(include?.contractType === undefined ? {} : { contractType: mapContractTypeJson(row.contractType ?? row.contract_type) }),
671
- ...(include?.createdTransaction === undefined ? {} : { createdTransaction: mapTransactionJson(row.createdTransaction ?? row.created_transaction) }),
672
- ...(include?.archivedTransaction === undefined ? {} : { archivedTransaction: (row.archivedTransaction ?? row.archived_transaction) === null || (row.archivedTransaction ?? row.archived_transaction) === undefined ? null : mapTransactionJson(row.archivedTransaction ?? row.archived_transaction) ?? null }),
673
- ...(include?.exercises === undefined ? {} : { exercises: Array.isArray(row.exercises) ? row.exercises.map(mapExerciseJson) : [] }),
259
+ function contractRootRow(row) {
260
+ return {
261
+ ...row,
262
+ contractType: row.contractType ?? row.contract_type,
263
+ createdTransaction: row.createdTransaction ?? row.created_transaction,
264
+ archivedTransaction: row.archivedTransaction ?? row.archived_transaction,
674
265
  };
675
- const projections = Object.fromEntries(Object.entries(json ?? {}).map(([name, projection]) => [name, mapJsonValue(row[name], projection.as)]));
676
- return { ...base, ...relations, ...projections };
677
- }
678
- function nullableString(value) {
679
- return value === null || value === undefined ? null : String(value);
680
- }
681
- function nullableDate(value) {
682
- return value === null || value === undefined ? null : value instanceof Date ? value : new Date(String(value));
683
- }
684
- function stringArray(value) {
685
- return Array.isArray(value) ? value.map(String) : [];
686
- }
687
- function getPqsCode(cause) {
688
- return typeof cause === "object" && cause !== null && "code" in cause && typeof cause.code === "string" ? cause.code : undefined;
689
- }
690
- function aggregateNumeric(values, operation) {
691
- const numbers = values.filter((value) => value !== null).map(BigInt);
692
- if (numbers.length === 0) {
693
- return null;
694
- }
695
- else if (operation === "sum") {
696
- return numbers.reduce((total, value) => total + value, 0n).toString();
697
- }
698
- return numbers.reduce((result, value) => operation === "min" ? value < result ? value : result : value > result ? value : result).toString();
699
266
  }
267
+ function nullableString(value) { return value === null || value === undefined ? null : String(value); }
268
+ function getPqsCode(cause) { return typeof cause === "object" && cause !== null && "code" in cause && typeof cause.code === "string" ? cause.code : undefined; }