@distrohelena/canton-typescript-sdk 0.1.16 → 0.1.17
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.
- package/dist/client/external-party-activation-client.js +34 -20
- package/dist/client/external-party-activation-response.d.ts +1 -1
- package/dist/core/transports/transport.interface.d.ts +16 -22
- package/dist/debugger/replay/ledger-replay-environment-builder.js +1 -1
- package/dist/index.d.ts +1 -19
- package/dist/index.js +0 -18
- package/dist/protobuf/index.d.ts +4075 -0
- package/dist/query/grpc/grpc-contract-query-client.d.ts +4 -3
- package/dist/query/grpc/grpc-contract-query-client.js +12 -4
- package/dist/query/model-types.d.ts +232 -14
- package/dist/query/model-types.js +2 -2
- package/dist/query/pqs/pqs-query-client.d.ts +14 -3
- package/dist/query/pqs/pqs-query-client.js +381 -25
- package/dist/query/pqs/pqs-relational-sql-compiler.d.ts +23 -0
- package/dist/query/pqs/pqs-relational-sql-compiler.js +146 -0
- package/dist/query/pqs/pqs-schema-profile.d.ts +10 -0
- package/dist/query/pqs/pqs-schema-profile.js +46 -0
- package/dist/query/pqs/pqs-sql-compiler.d.ts +2 -1
- package/dist/query/pqs/pqs-sql-compiler.js +212 -10
- package/dist/query/query-client.d.ts +20 -16
- package/dist/services/party-management/decentralized-party-lifecycle.js +96 -18
- package/dist/services/party-management/party-management-service-client.d.ts +2 -2
- package/dist/services/party-management/party-management-service-client.js +34 -9
- package/dist/services/topology-manager-write/topology-manager-write-service-client.d.ts +5 -16
- package/dist/transports/grpc/grpc-channel-factory.js +12 -7
- package/dist/transports/grpc/grpc-transport.d.ts +9 -9
- package/dist/transports/grpc/grpc-transport.js +12 -13
- package/dist/transports/grpc/mappers/topology-common-mapper.d.ts +5 -1
- package/dist/transports/grpc/mappers/topology-common-mapper.js +17 -0
- package/dist/transports/json/json-transport.d.ts +18 -16
- package/package.json +1 -1
- package/dist/core/types/requests/add-topology-transactions-request.d.ts +0 -16
- package/dist/core/types/requests/add-topology-transactions-request.js +0 -12
- package/dist/core/types/requests/allocate-external-party-request.d.ts +0 -18
- package/dist/core/types/requests/allocate-external-party-request.js +0 -16
- package/dist/core/types/requests/authorize-topology-transactions-request.d.ts +0 -37
- package/dist/core/types/requests/authorize-topology-transactions-request.js +0 -35
- package/dist/core/types/requests/generate-external-party-topology-request.d.ts +0 -19
- package/dist/core/types/requests/generate-external-party-topology-request.js +0 -21
- package/dist/core/types/requests/generate-topology-transactions-request.d.ts +0 -26
- package/dist/core/types/requests/generate-topology-transactions-request.js +0 -22
- package/dist/core/types/requests/import-topology-snapshot-request.d.ts +0 -12
- package/dist/core/types/requests/import-topology-snapshot-request.js +0 -10
- package/dist/core/types/requests/import-topology-snapshot-v2-request.d.ts +0 -12
- package/dist/core/types/requests/import-topology-snapshot-v2-request.js +0 -10
- package/dist/core/types/requests/sign-topology-transactions-request.d.ts +0 -15
- package/dist/core/types/requests/sign-topology-transactions-request.js +0 -12
- package/dist/core/types/responses/add-topology-transactions-response.d.ts +0 -3
- package/dist/core/types/responses/add-topology-transactions-response.js +0 -5
- package/dist/core/types/responses/allocate-external-party-response.d.ts +0 -6
- package/dist/core/types/responses/allocate-external-party-response.js +0 -6
- package/dist/core/types/responses/authorize-topology-transactions-response.d.ts +0 -7
- package/dist/core/types/responses/authorize-topology-transactions-response.js +0 -6
- package/dist/core/types/responses/generate-external-party-topology-response.d.ts +0 -12
- package/dist/core/types/responses/generate-external-party-topology-response.js +0 -12
- package/dist/core/types/responses/generate-topology-transactions-response.d.ts +0 -7
- package/dist/core/types/responses/generate-topology-transactions-response.js +0 -6
- package/dist/core/types/responses/import-topology-snapshot-response.d.ts +0 -3
- package/dist/core/types/responses/import-topology-snapshot-response.js +0 -5
- package/dist/core/types/responses/import-topology-snapshot-v2-response.d.ts +0 -3
- package/dist/core/types/responses/import-topology-snapshot-v2-response.js +0 -5
- package/dist/core/types/responses/sign-topology-transactions-response.d.ts +0 -7
- package/dist/core/types/responses/sign-topology-transactions-response.js +0 -6
- package/dist/transports/grpc/mappers/external-party-management-mapper.d.ts +0 -9
- package/dist/transports/grpc/mappers/external-party-management-mapper.js +0 -126
- package/dist/transports/grpc/mappers/topology-manager-write-mapper.d.ts +0 -25
- package/dist/transports/grpc/mappers/topology-manager-write-mapper.js +0 -475
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { PqsSchemaProfileV1, pqsRelationMetadata } from "./pqs-schema-profile.js";
|
|
2
|
+
import { pqsRelationEdges } from "./pqs-schema-profile.js";
|
|
3
|
+
export function compilePqsRelationFindMany(relation, args, profile) {
|
|
4
|
+
assertPage(args);
|
|
5
|
+
const metadata = pqsRelationMetadata[relation];
|
|
6
|
+
const values = [];
|
|
7
|
+
const add = (value) => {
|
|
8
|
+
values.push(value);
|
|
9
|
+
return `$${values.length}`;
|
|
10
|
+
};
|
|
11
|
+
const fields = selectedFields(relation, metadata, args.select);
|
|
12
|
+
const where = compileWhere(relation, metadata, args.where, add);
|
|
13
|
+
const orderBy = compileOrderBy(relation, metadata, args.orderBy);
|
|
14
|
+
const limit = args.take === undefined ? "" : ` limit ${add(args.take)}`;
|
|
15
|
+
const offset = args.skip === undefined ? "" : ` offset ${add(args.skip)}`;
|
|
16
|
+
return {
|
|
17
|
+
text: `select ${fields.map(([field, column]) => `"${column}" as "${field}"`).join(", ")} from ${profile.relation(relation)}${where}${orderBy}${limit}${offset}`,
|
|
18
|
+
values,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function compilePqsRelationGroupBy(relation, args, profile, parameterOffset = 0) {
|
|
22
|
+
if (args.by.length === 0 || (!args.aggregate.count && !args.aggregate.min && !args.aggregate.max && !args.aggregate.sum))
|
|
23
|
+
throw new Error("groupBy requires a key and aggregate");
|
|
24
|
+
const metadata = pqsRelationMetadata[relation];
|
|
25
|
+
const root = relation === "__events" ? "event" : "root";
|
|
26
|
+
const joins = [];
|
|
27
|
+
const expressions = [];
|
|
28
|
+
const selected = [];
|
|
29
|
+
const values = [];
|
|
30
|
+
const add = (value) => { values.push(value); return `$${parameterOffset + values.length}`; };
|
|
31
|
+
for (const key of args.by) {
|
|
32
|
+
if (typeof key === "string") {
|
|
33
|
+
const column = field(relation, metadata, key);
|
|
34
|
+
const expression = metadata.arrayFields.includes(key)
|
|
35
|
+
? `"${key}".value`
|
|
36
|
+
: `"${root}"."${column}"`;
|
|
37
|
+
if (metadata.arrayFields.includes(key))
|
|
38
|
+
joins.push(`cross join lateral unnest("${root}"."${column}") as "${key}"(value)`);
|
|
39
|
+
expressions.push(expression);
|
|
40
|
+
selected.push(`${expression} as "${key}"`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (key === null || typeof key !== "object")
|
|
44
|
+
throw new Error("invalid group key");
|
|
45
|
+
const [edgeName, nested] = Object.entries(key)[0] ?? [];
|
|
46
|
+
if (nested !== null && typeof nested === "object" && "name" in nested && "path" in nested && "as" in nested) {
|
|
47
|
+
const projection = nested;
|
|
48
|
+
if (typeof projection.name !== "string" || !Array.isArray(projection.path) || !projection.path.every((segment) => typeof segment === "string" && segment.length > 0) || !["text", "numeric", "boolean", "timestamp"].includes(String(projection.as)) || !PqsSchemaProfileV1.jsonField(relation, edgeName))
|
|
49
|
+
throw new Error("invalid profiled JSON group key");
|
|
50
|
+
const column = field(relation, metadata, edgeName);
|
|
51
|
+
const text = `"${root}"."${column}" #>> ${add(projection.path)}::text[]`;
|
|
52
|
+
const expression = projection.as === "text" ? text : projection.as === "numeric" ? `(${text})::numeric` : projection.as === "boolean" ? `(${text})::boolean` : `(${text})::timestamptz`;
|
|
53
|
+
expressions.push(expression);
|
|
54
|
+
selected.push(`${expression} as "${projection.name}"`);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (nested !== null && typeof nested === "object" && "bucket" in nested && PqsSchemaProfileV1.bucketField(relation, edgeName)) {
|
|
58
|
+
const bucket = nested.bucket;
|
|
59
|
+
if (typeof bucket !== "string" || !["hour", "day", "week", "month"].includes(bucket))
|
|
60
|
+
throw new Error("invalid profiled time bucket");
|
|
61
|
+
const column = field(relation, metadata, edgeName);
|
|
62
|
+
const expression = `date_trunc('${bucket}', "${root}"."${column}")`;
|
|
63
|
+
expressions.push(expression);
|
|
64
|
+
selected.push(`${expression} as "${edgeName}_${bucket}"`);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const edge = pqsRelationEdges[relation]?.[edgeName];
|
|
68
|
+
if (edge === undefined || edge.cardinality !== "one" || nested === null || typeof nested !== "object")
|
|
69
|
+
throw new Error("group key must follow a profiled to-one edge");
|
|
70
|
+
const [fieldName, bucketValue] = Object.entries(nested)[0] ?? [];
|
|
71
|
+
const bucket = bucketValue !== null && typeof bucketValue === "object" ? bucketValue.bucket : undefined;
|
|
72
|
+
if (typeof bucket !== "string" || !["hour", "day", "week", "month"].includes(bucket) || !PqsSchemaProfileV1.bucketField(edge.target, fieldName))
|
|
73
|
+
throw new Error("invalid profiled time bucket");
|
|
74
|
+
const targetColumn = field(edge.target, pqsRelationMetadata[edge.target], fieldName);
|
|
75
|
+
joins.push(`join ${profile.relation(edge.target)} "${edgeName}" on "${edgeName}"."${edge.targetColumn}" = "${root}"."${edge.sourceColumn}"`);
|
|
76
|
+
const expression = `date_trunc('${bucket}', "${edgeName}"."${targetColumn}")`;
|
|
77
|
+
expressions.push(expression);
|
|
78
|
+
selected.push(`${expression} as "${edgeName}_${fieldName}_${bucket}"`);
|
|
79
|
+
}
|
|
80
|
+
if (args.aggregate.count)
|
|
81
|
+
selected.push("count(*)::text as count");
|
|
82
|
+
for (const [operation, fields] of [["min", args.aggregate.min], ["max", args.aggregate.max], ["sum", args.aggregate.sum]])
|
|
83
|
+
for (const name of fields ?? []) {
|
|
84
|
+
if (!metadata.numericFields.includes(name))
|
|
85
|
+
throw new Error(`${name} is not a numeric aggregate field of ${relation}`);
|
|
86
|
+
selected.push(`${operation}("${root}"."${field(relation, metadata, name)}")::text as "${operation}_${name}"`);
|
|
87
|
+
}
|
|
88
|
+
return { text: `select ${selected.join(", ")} from ${profile.relation(relation)} "${root}" ${joins.join(" ")} group by ${expressions.join(", ")}`, values };
|
|
89
|
+
}
|
|
90
|
+
function selectedFields(relation, metadata, select) {
|
|
91
|
+
const fields = select === undefined
|
|
92
|
+
? Object.entries(metadata.fields)
|
|
93
|
+
: Object.entries(select).filter(([, enabled]) => enabled).map(([name]) => [name, field(relation, metadata, name)]);
|
|
94
|
+
if (fields.length === 0)
|
|
95
|
+
throw new Error("select must include at least one field");
|
|
96
|
+
return fields;
|
|
97
|
+
}
|
|
98
|
+
function compileWhere(relation, metadata, where, add) {
|
|
99
|
+
const conditions = [];
|
|
100
|
+
for (const [name, value] of Object.entries(where ?? {})) {
|
|
101
|
+
const column = field(relation, metadata, name);
|
|
102
|
+
if (value === null || Array.isArray(value) || typeof value !== "object")
|
|
103
|
+
throw new Error(`${name} must be a filter`);
|
|
104
|
+
const filter = value;
|
|
105
|
+
for (const [operator, operand] of Object.entries(filter)) {
|
|
106
|
+
if (operator === "equals")
|
|
107
|
+
conditions.push(`"${column}" = ${add(operand)}`);
|
|
108
|
+
else if (operator === "in" && Array.isArray(operand))
|
|
109
|
+
conditions.push(operand.length === 0 ? "false" : `"${column}" = any(${add(operand)})`);
|
|
110
|
+
else if (operator === "is" && operand === null)
|
|
111
|
+
conditions.push(`"${column}" is null`);
|
|
112
|
+
else if (operator === "isNot" && operand === null)
|
|
113
|
+
conditions.push(`"${column}" is not null`);
|
|
114
|
+
else if (["lt", "lte", "gt", "gte", "like", "ilike"].includes(operator)) {
|
|
115
|
+
const sql = { lt: "<", lte: "<=", gt: ">", gte: ">=", like: "like", ilike: "ilike" }[operator];
|
|
116
|
+
conditions.push(`"${column}" ${sql} ${add(operand)}`);
|
|
117
|
+
}
|
|
118
|
+
else
|
|
119
|
+
throw new Error(`${operator} is not supported for ${name}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return conditions.length === 0 ? "" : ` where ${conditions.join(" and ")}`;
|
|
123
|
+
}
|
|
124
|
+
function compileOrderBy(relation, metadata, orderBy) {
|
|
125
|
+
if (orderBy === undefined)
|
|
126
|
+
return "";
|
|
127
|
+
const requested = orderBy.flatMap((entry) => Object.entries(entry));
|
|
128
|
+
if (requested.length === 0 || requested.some(([, direction]) => direction !== "asc" && direction !== "desc"))
|
|
129
|
+
throw new Error("orderBy must be a non-empty list of one-field entries");
|
|
130
|
+
const ordered = requested.map(([name, direction]) => [field(relation, metadata, name), direction]);
|
|
131
|
+
const stableKey = metadata.uniqueKeys[0]?.[0];
|
|
132
|
+
if (stableKey !== undefined && !ordered.some(([column]) => column === metadata.fields[stableKey]))
|
|
133
|
+
ordered.push([metadata.fields[stableKey], "asc"]);
|
|
134
|
+
return ` order by ${ordered.map(([column, direction]) => `"${column}" ${direction}`).join(", ")}`;
|
|
135
|
+
}
|
|
136
|
+
function field(relation, metadata, name) {
|
|
137
|
+
const column = metadata.fields[name];
|
|
138
|
+
if (column === undefined)
|
|
139
|
+
throw new Error(`${name} is not a field of ${relation}`);
|
|
140
|
+
return column;
|
|
141
|
+
}
|
|
142
|
+
function assertPage(args) {
|
|
143
|
+
for (const [name, value] of [["take", args.take], ["skip", args.skip]])
|
|
144
|
+
if (value !== undefined && (!Number.isInteger(value) || value < 0))
|
|
145
|
+
throw new Error(`${name} must be a non-negative integer`);
|
|
146
|
+
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
export declare const requiredPqsRelations: readonly ["__contracts", "__contract_tpe", "__events", "__exercises", "__exercise_tpe", "__packages", "__transactions", "__watermark"];
|
|
2
2
|
export type PqsRelation = (typeof requiredPqsRelations)[number];
|
|
3
|
+
export interface PqsRelationEdge {
|
|
4
|
+
readonly target: PqsRelation;
|
|
5
|
+
readonly sourceColumn: string;
|
|
6
|
+
readonly targetColumn: string;
|
|
7
|
+
readonly cardinality: "one" | "many";
|
|
8
|
+
readonly nullable: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare const pqsRelationEdges: Readonly<Partial<Record<PqsRelation, Readonly<Record<string, PqsRelationEdge>>>>>;
|
|
3
11
|
export interface PqsRelationMetadata {
|
|
4
12
|
readonly fields: Readonly<Record<string, string>>;
|
|
5
13
|
readonly uniqueKeys: readonly (readonly string[])[];
|
|
@@ -15,6 +23,8 @@ export declare class PqsSchemaProfileV1 {
|
|
|
15
23
|
readonly schema: string;
|
|
16
24
|
constructor(schema?: string);
|
|
17
25
|
relation(relation: PqsRelation): string;
|
|
26
|
+
static jsonField(relation: PqsRelation, field: string): boolean;
|
|
27
|
+
static bucketField(relation: PqsRelation, field: string): boolean;
|
|
18
28
|
}
|
|
19
29
|
export interface PqsSchemaClient {
|
|
20
30
|
query(query: string, values: readonly unknown[]): Promise<{
|
|
@@ -10,6 +10,46 @@ export const requiredPqsRelations = [
|
|
|
10
10
|
"__transactions",
|
|
11
11
|
"__watermark",
|
|
12
12
|
];
|
|
13
|
+
export const pqsRelationEdges = {
|
|
14
|
+
__contracts: {
|
|
15
|
+
contractType: { target: "__contract_tpe", sourceColumn: "tpe_pk", targetColumn: "pk", cardinality: "one", nullable: false },
|
|
16
|
+
createdTransaction: { target: "__transactions", sourceColumn: "created_at_ix", targetColumn: "ix", cardinality: "one", nullable: false },
|
|
17
|
+
archivedTransaction: { target: "__transactions", sourceColumn: "archived_at_ix", targetColumn: "ix", cardinality: "one", nullable: true },
|
|
18
|
+
exercises: { target: "__exercises", sourceColumn: "contract_id", targetColumn: "contract_id", cardinality: "many", nullable: false },
|
|
19
|
+
},
|
|
20
|
+
__contract_tpe: {
|
|
21
|
+
contracts: { target: "__contracts", sourceColumn: "pk", targetColumn: "tpe_pk", cardinality: "many", nullable: false },
|
|
22
|
+
exercises: { target: "__exercises", sourceColumn: "pk", targetColumn: "contract_tpe_pk", cardinality: "many", nullable: false },
|
|
23
|
+
},
|
|
24
|
+
__events: {
|
|
25
|
+
transaction: { target: "__transactions", sourceColumn: "tx_ix", targetColumn: "ix", cardinality: "one", nullable: false },
|
|
26
|
+
exercises: { target: "__exercises", sourceColumn: "pk", targetColumn: "exercise_event_pk", cardinality: "many", nullable: false },
|
|
27
|
+
},
|
|
28
|
+
__exercises: {
|
|
29
|
+
exerciseType: { target: "__exercise_tpe", sourceColumn: "tpe_pk", targetColumn: "pk", cardinality: "one", nullable: false },
|
|
30
|
+
contractType: { target: "__contract_tpe", sourceColumn: "contract_tpe_pk", targetColumn: "pk", cardinality: "one", nullable: false },
|
|
31
|
+
event: { target: "__events", sourceColumn: "exercise_event_pk", targetColumn: "pk", cardinality: "one", nullable: true },
|
|
32
|
+
transaction: { target: "__transactions", sourceColumn: "exercised_at_ix", targetColumn: "ix", cardinality: "one", nullable: true },
|
|
33
|
+
package: { target: "__packages", sourceColumn: "package_pk", targetColumn: "pk", cardinality: "one", nullable: false },
|
|
34
|
+
contract: { target: "__contracts", sourceColumn: "contract_id", targetColumn: "contract_id", cardinality: "one", nullable: false },
|
|
35
|
+
},
|
|
36
|
+
__exercise_tpe: { exercises: { target: "__exercises", sourceColumn: "pk", targetColumn: "tpe_pk", cardinality: "many", nullable: false } },
|
|
37
|
+
__packages: { exercises: { target: "__exercises", sourceColumn: "pk", targetColumn: "package_pk", cardinality: "many", nullable: false } },
|
|
38
|
+
__transactions: {
|
|
39
|
+
events: { target: "__events", sourceColumn: "ix", targetColumn: "tx_ix", cardinality: "many", nullable: false },
|
|
40
|
+
createdContracts: { target: "__contracts", sourceColumn: "ix", targetColumn: "created_at_ix", cardinality: "many", nullable: false },
|
|
41
|
+
archivedContracts: { target: "__contracts", sourceColumn: "ix", targetColumn: "archived_at_ix", cardinality: "many", nullable: false },
|
|
42
|
+
exercises: { target: "__exercises", sourceColumn: "ix", targetColumn: "exercised_at_ix", cardinality: "many", nullable: false },
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const pqsJsonFields = {
|
|
46
|
+
__contracts: ["payload"],
|
|
47
|
+
__exercises: ["argument", "result"],
|
|
48
|
+
__transactions: ["traceContext"],
|
|
49
|
+
};
|
|
50
|
+
const pqsBucketFields = {
|
|
51
|
+
__transactions: ["effectiveAt"],
|
|
52
|
+
};
|
|
13
53
|
export const pqsRelationMetadata = {
|
|
14
54
|
__contracts: { fields: {}, uniqueKeys: [["contractId"]], numericFields: ["createdEventOffset", "archivedEventOffset"], arrayFields: ["witnesses"], dateFields: ["createdAt", "archivedAt"], binaryFields: [] },
|
|
15
55
|
__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: [] },
|
|
@@ -99,6 +139,12 @@ export class PqsSchemaProfileV1 {
|
|
|
99
139
|
relation(relation) {
|
|
100
140
|
return `${quoteIdentifier(this.schema)}.${quoteIdentifier(relation)}`;
|
|
101
141
|
}
|
|
142
|
+
static jsonField(relation, field) {
|
|
143
|
+
return pqsJsonFields[relation]?.includes(field) ?? false;
|
|
144
|
+
}
|
|
145
|
+
static bucketField(relation, field) {
|
|
146
|
+
return pqsBucketFields[relation]?.includes(field) ?? false;
|
|
147
|
+
}
|
|
102
148
|
}
|
|
103
149
|
export async function validatePqsSchemaAsync(client, profile) {
|
|
104
150
|
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]);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { ContractFindManyArgs } from "../model-types.js";
|
|
1
|
+
import { ContractFindManyArgs, ContractGroupByArgs } from "../model-types.js";
|
|
2
2
|
import { PqsSchemaProfileV1 } from "./pqs-schema-profile.js";
|
|
3
3
|
export interface CompiledPqsQuery {
|
|
4
4
|
readonly text: string;
|
|
5
5
|
readonly values: readonly unknown[];
|
|
6
6
|
}
|
|
7
7
|
export declare function compileContractFindMany(args: ContractFindManyArgs, profile: PqsSchemaProfileV1): CompiledPqsQuery;
|
|
8
|
+
export declare function compileContractGroupBy(args: ContractGroupByArgs, profile: PqsSchemaProfileV1): CompiledPqsQuery;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { assertQueryPageArgs, } from "../model-types.js";
|
|
2
|
+
import { PqsSchemaProfileV1 } from "./pqs-schema-profile.js";
|
|
3
|
+
import { pqsRelationEdges, pqsRelationMetadata } from "./pqs-schema-profile.js";
|
|
2
4
|
export function compileContractFindMany(args, profile) {
|
|
3
5
|
assertQueryPageArgs(args);
|
|
4
6
|
const values = [];
|
|
@@ -7,7 +9,7 @@ export function compileContractFindMany(args, profile) {
|
|
|
7
9
|
return `$${values.length}`;
|
|
8
10
|
};
|
|
9
11
|
const conditions = [];
|
|
10
|
-
const where = args.where === undefined ? undefined : compileWhere(args.where, addValue);
|
|
12
|
+
const where = args.where === undefined ? undefined : compileWhere(args.where, addValue, profile);
|
|
11
13
|
if (where !== undefined)
|
|
12
14
|
conditions.push(where);
|
|
13
15
|
if (args.parties !== undefined) {
|
|
@@ -17,6 +19,16 @@ export function compileContractFindMany(args, profile) {
|
|
|
17
19
|
const whereSql = conditions.length === 0 ? "" : `where ${conditions.join(" and ")}`;
|
|
18
20
|
const limitSql = args.take === undefined ? "" : `limit ${addValue(args.take)}`;
|
|
19
21
|
const offsetSql = args.skip === undefined ? "" : `offset ${addValue(args.skip)}`;
|
|
22
|
+
const included = compileProfileIncludes("__contracts", "contract_row", args.include, profile, addValue);
|
|
23
|
+
const jsonProjection = Object.entries(args.select?.json ?? {}).map(([name, projection]) => {
|
|
24
|
+
if (projection.field !== "payload")
|
|
25
|
+
throw new Error(`${projection.field} is not a JSON field of contracts`);
|
|
26
|
+
if (projection.path.length === 0 || projection.path.some((segment) => segment.length === 0))
|
|
27
|
+
throw new Error(`${name}.path must be a non-empty JSON path`);
|
|
28
|
+
const text = `contract_row.payload #>> ${addValue(projection.path)}::text[]`;
|
|
29
|
+
const expression = projection.as === "text" ? text : projection.as === "numeric" ? `(${text})::numeric::text` : projection.as === "boolean" ? `(${text})::boolean` : `(${text})::timestamptz`;
|
|
30
|
+
return `${expression} as "${name}"`;
|
|
31
|
+
});
|
|
20
32
|
return {
|
|
21
33
|
text: `select
|
|
22
34
|
contract_row.contract_id as contract_id,
|
|
@@ -30,7 +42,7 @@ export function compileContractFindMany(args, profile) {
|
|
|
30
42
|
contract_row.archived_at_ix is null as active,
|
|
31
43
|
contract_row.creation_package_id as template_package_id,
|
|
32
44
|
contract_tpe_row.module_name as template_module_name,
|
|
33
|
-
contract_tpe_row.entity_name as template_entity_name
|
|
45
|
+
contract_tpe_row.entity_name as template_entity_name${[...included, ...jsonProjection].length === 0 ? "" : `,\n ${[...included, ...jsonProjection].join(",\n ")}`}
|
|
34
46
|
from ${profile.relation("__contracts")} contract_row
|
|
35
47
|
join ${profile.relation("__contract_tpe")} contract_tpe_row on contract_tpe_row.pk = contract_row.tpe_pk
|
|
36
48
|
left join ${profile.relation("__transactions")} created_tx on created_tx.ix = contract_row.created_at_ix
|
|
@@ -42,18 +54,135 @@ ${offsetSql}`,
|
|
|
42
54
|
values,
|
|
43
55
|
};
|
|
44
56
|
}
|
|
45
|
-
function
|
|
57
|
+
function compileProfileIncludes(source, parentAlias, include, profile, addValue) {
|
|
58
|
+
const selected = [];
|
|
59
|
+
for (const [name, option] of Object.entries(include ?? {})) {
|
|
60
|
+
const edge = pqsRelationEdges[source]?.[name];
|
|
61
|
+
if (edge === undefined)
|
|
62
|
+
throw new Error(`${name} is not a relation of ${source}`);
|
|
63
|
+
const settings = option === true ? {} : option;
|
|
64
|
+
if (settings === null || typeof settings !== "object" || Array.isArray(settings))
|
|
65
|
+
throw new Error(`${name} must be an include option`);
|
|
66
|
+
const options = settings;
|
|
67
|
+
if (edge.cardinality === "many" && (typeof options.take !== "number" || !Number.isInteger(options.take) || options.take < 0))
|
|
68
|
+
throw new Error(`${name} is a to-many relation and requires a non-negative take`);
|
|
69
|
+
const alias = `"${name}"`;
|
|
70
|
+
const nested = compileProfileIncludes(edge.target, alias, options.include, profile, addValue);
|
|
71
|
+
const metadata = pqsRelationMetadata[edge.target];
|
|
72
|
+
const requested = options.select === undefined
|
|
73
|
+
? Object.entries(metadata.fields)
|
|
74
|
+
: Object.entries(options.select).filter(([field, enabled]) => field !== "json" && enabled === true).map(([field]) => [field, metadata.fields[field]]);
|
|
75
|
+
const json = options.select?.json ?? {};
|
|
76
|
+
const jsonSelections = Object.entries(json).map(([projectionName, projection]) => {
|
|
77
|
+
if (!PqsSchemaProfileV1.jsonField(edge.target, projection.field))
|
|
78
|
+
throw new Error(`${projection.field} is not a JSON field of ${edge.target}`);
|
|
79
|
+
if (projection.path.length === 0 || projection.path.some((segment) => segment.length === 0))
|
|
80
|
+
throw new Error(`${projectionName}.path must be a non-empty JSON path`);
|
|
81
|
+
const column = metadata.fields[projection.field];
|
|
82
|
+
if (column === undefined)
|
|
83
|
+
throw new Error(`${projection.field} is not a field of ${edge.target}`);
|
|
84
|
+
const text = `${alias}."${column}" #>> ${addValue(projection.path)}::text[]`;
|
|
85
|
+
const expression = projection.as === "text" ? text : projection.as === "numeric" ? `(${text})::numeric::text` : projection.as === "boolean" ? `(${text})::boolean` : `(${text})::timestamptz`;
|
|
86
|
+
return [`'${projectionName}'`, expression];
|
|
87
|
+
});
|
|
88
|
+
if (requested.length === 0 && jsonSelections.length === 0)
|
|
89
|
+
throw new Error(`Nested ${name}.select must include at least one field`);
|
|
90
|
+
if (requested.some(([, column]) => column === undefined))
|
|
91
|
+
throw new Error(`Nested ${name}.select references an unknown field`);
|
|
92
|
+
const fields = requested.flatMap(([field, column]) => [`'${field}'`, `${alias}."${column}"`]);
|
|
93
|
+
const nestedFields = nested.flatMap((selection) => {
|
|
94
|
+
const match = /^(.*) as "([^"]+)"$/.exec(selection);
|
|
95
|
+
return match === null ? [] : [`'${match[2]}'`, match[1]];
|
|
96
|
+
});
|
|
97
|
+
const object = `jsonb_build_object(${[...fields, ...jsonSelections.flat(), ...nestedFields].join(", ")})`;
|
|
98
|
+
const relationFilter = options.where === undefined ? "true" : compilePhysicalWhere(edge.target, options.where, alias, profile, addValue);
|
|
99
|
+
const condition = `${alias}."${edge.targetColumn}" = ${parentAlias}."${edge.sourceColumn}" and (${relationFilter})`;
|
|
100
|
+
const orderBy = compilePhysicalOrderBy(edge.target, options.orderBy, alias);
|
|
101
|
+
const expression = edge.cardinality === "one"
|
|
102
|
+
? `(select ${object} from ${profile.relation(edge.target)} ${alias} where ${condition})`
|
|
103
|
+
: `(select coalesce(jsonb_agg("${name}_limited".value), '[]'::jsonb) from (select ${object} as value from ${profile.relation(edge.target)} ${alias} where ${condition}${orderBy} limit ${addValue(options.take)}) "${name}_limited")`;
|
|
104
|
+
selected.push(`${expression} as "${name}"`);
|
|
105
|
+
}
|
|
106
|
+
return selected;
|
|
107
|
+
}
|
|
108
|
+
function compilePhysicalOrderBy(relation, orderBy, alias) {
|
|
109
|
+
if (orderBy === undefined)
|
|
110
|
+
return "";
|
|
111
|
+
if (!Array.isArray(orderBy) || orderBy.length === 0)
|
|
112
|
+
throw new Error("Nested orderBy must be a non-empty list");
|
|
113
|
+
const metadata = pqsRelationMetadata[relation];
|
|
114
|
+
const entries = orderBy.flatMap((entry) => entry !== null && typeof entry === "object" ? Object.entries(entry) : []);
|
|
115
|
+
if (entries.length !== orderBy.length || entries.some(([, direction]) => direction !== "asc" && direction !== "desc"))
|
|
116
|
+
throw new Error("Nested orderBy entries must have one valid direction");
|
|
117
|
+
return ` order by ${entries.map(([field, direction]) => {
|
|
118
|
+
const column = metadata.fields[field];
|
|
119
|
+
if (column === undefined)
|
|
120
|
+
throw new Error(`${field} is not a field of ${relation}`);
|
|
121
|
+
return `${alias}."${column}" ${direction}`;
|
|
122
|
+
}).join(", ")}`;
|
|
123
|
+
}
|
|
124
|
+
export function compileContractGroupBy(args, profile) {
|
|
125
|
+
if (args.by.length === 0 || (!args.aggregate.count && !args.aggregate.min && !args.aggregate.max && !args.aggregate.sum))
|
|
126
|
+
throw new Error("groupBy requires keys and an aggregate");
|
|
127
|
+
const values = [];
|
|
128
|
+
const add = (value) => { values.push(value); return `$${values.length}`; };
|
|
129
|
+
const where = args.where === undefined ? undefined : compileWhere(args.where, add, profile);
|
|
130
|
+
const fields = {
|
|
131
|
+
contractId: "contract_row.contract_id",
|
|
132
|
+
createdEventOffset: "contract_row.created_at_ix",
|
|
133
|
+
archivedEventOffset: "contract_row.archived_at_ix",
|
|
134
|
+
};
|
|
135
|
+
const expressions = [];
|
|
136
|
+
const select = [];
|
|
137
|
+
let unnestWitnesses = false;
|
|
138
|
+
for (const key of args.by) {
|
|
139
|
+
if (key === "witnesses") {
|
|
140
|
+
unnestWitnesses = true;
|
|
141
|
+
expressions.push("witness.value");
|
|
142
|
+
select.push("witness.value as \"witnesses\"");
|
|
143
|
+
}
|
|
144
|
+
else if (typeof key === "string") {
|
|
145
|
+
const expression = fields[key];
|
|
146
|
+
if (expression === undefined)
|
|
147
|
+
throw new Error(`${key} is not a contract group key`);
|
|
148
|
+
expressions.push(expression);
|
|
149
|
+
select.push(`${expression} as "${key}"`);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
const payload = key.payload;
|
|
153
|
+
if (payload.path.length === 0 || payload.path.some((segment) => segment.length === 0))
|
|
154
|
+
throw new Error("payload group path must be non-empty");
|
|
155
|
+
const base = `contract_row.payload #>> ${add(payload.path)}::text[]`;
|
|
156
|
+
const cast = payload.as === "text" ? base : `(${base})::${payload.as === "numeric" ? "numeric" : payload.as === "boolean" ? "boolean" : "timestamptz"}`;
|
|
157
|
+
expressions.push(cast);
|
|
158
|
+
select.push(`${cast} as "${payload.name}"`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (args.aggregate.count)
|
|
162
|
+
select.push("count(*)::text as count");
|
|
163
|
+
for (const [operation, requested] of [["min", args.aggregate.min], ["max", args.aggregate.max], ["sum", args.aggregate.sum]]) {
|
|
164
|
+
for (const name of requested ?? []) {
|
|
165
|
+
const expression = fields[name];
|
|
166
|
+
select.push(`${operation}(${expression})::text as "${operation}_${name}"`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
text: `select ${select.join(", ")} from ${profile.relation("__contracts")} contract_row${unnestWitnesses ? " cross join lateral unnest(contract_row.witnesses) as witness(value)" : ""}${where === undefined ? "" : ` where ${where}`} group by ${expressions.join(", ")}`,
|
|
171
|
+
values,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function compileWhere(where, addValue, profile) {
|
|
46
175
|
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
176
|
const parts = [];
|
|
48
177
|
for (const [key, value] of Object.entries(where)) {
|
|
49
178
|
if (key === "and" || key === "or") {
|
|
50
179
|
if (!Array.isArray(value))
|
|
51
180
|
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} `)})`);
|
|
181
|
+
parts.push(value.length === 0 ? key === "and" ? "true" : "false" : `(${value.map((child) => compileWhere(child, addValue, profile)).join(` ${key} `)})`);
|
|
53
182
|
continue;
|
|
54
183
|
}
|
|
55
184
|
if (key === "not") {
|
|
56
|
-
parts.push(`not (${compileWhere(value, addValue)})`);
|
|
185
|
+
parts.push(`not (${compileWhere(value, addValue, profile)})`);
|
|
57
186
|
continue;
|
|
58
187
|
}
|
|
59
188
|
if (key === "active") {
|
|
@@ -94,6 +223,11 @@ function compileWhere(where, addValue) {
|
|
|
94
223
|
}
|
|
95
224
|
continue;
|
|
96
225
|
}
|
|
226
|
+
const edge = pqsRelationEdges.__contracts?.[key];
|
|
227
|
+
if (edge !== undefined) {
|
|
228
|
+
parts.push(compilePhysicalRelationPredicate(edge.target, key, edge.targetColumn, edge.sourceColumn, edge.cardinality, value, "contract_row", profile, addValue));
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
97
231
|
const column = columns[key];
|
|
98
232
|
if (column === undefined || value === null || typeof value !== "object")
|
|
99
233
|
throw new Error(`${key} is not a supported contract filter`);
|
|
@@ -113,6 +247,75 @@ function compileWhere(where, addValue) {
|
|
|
113
247
|
}
|
|
114
248
|
return parts.length === 0 ? "true" : parts.join(" and ");
|
|
115
249
|
}
|
|
250
|
+
function compilePhysicalRelationPredicate(target, edgeName, targetColumn, sourceColumn, cardinality, value, parentAlias, profile, addValue) {
|
|
251
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
252
|
+
throw new Error(`${edgeName} must be a relation filter`);
|
|
253
|
+
const relation = value;
|
|
254
|
+
const alias = `"${edgeName}"`;
|
|
255
|
+
const join = `${alias}."${targetColumn}" = ${parentAlias}."${sourceColumn}"`;
|
|
256
|
+
if (cardinality === "one") {
|
|
257
|
+
const predicate = compilePhysicalWhere(target, relation, alias, profile, addValue);
|
|
258
|
+
return `exists (select 1 from ${profile.relation(target)} ${alias} where ${join} and (${predicate}))`;
|
|
259
|
+
}
|
|
260
|
+
const operators = ["some", "none", "every"].filter((name) => relation[name] !== undefined);
|
|
261
|
+
if (operators.length !== 1)
|
|
262
|
+
throw new Error(`${edgeName} requires exactly one of some, none, or every`);
|
|
263
|
+
const predicate = compilePhysicalWhere(target, relation[operators[0]], alias, profile, addValue);
|
|
264
|
+
const base = `select 1 from ${profile.relation(target)} ${alias} where ${join} and (${predicate})`;
|
|
265
|
+
return operators[0] === "some" ? `exists (${base})` : operators[0] === "none" ? `not exists (${base})` : `not exists (select 1 from ${profile.relation(target)} ${alias} where ${join} and not (${predicate}))`;
|
|
266
|
+
}
|
|
267
|
+
function compilePhysicalWhere(relation, expression, alias, profile, addValue) {
|
|
268
|
+
if (expression === null || typeof expression !== "object" || Array.isArray(expression))
|
|
269
|
+
throw new Error(`${relation} relation predicate must be an expression`);
|
|
270
|
+
const metadata = pqsRelationMetadata[relation];
|
|
271
|
+
const conditions = [];
|
|
272
|
+
for (const [field, value] of Object.entries(expression)) {
|
|
273
|
+
if (field === "and" || field === "or") {
|
|
274
|
+
if (!Array.isArray(value))
|
|
275
|
+
throw new Error(`${field} must be an array`);
|
|
276
|
+
conditions.push(value.length === 0 ? field === "and" ? "true" : "false" : `(${value.map((child) => compilePhysicalWhere(relation, child, alias, profile, addValue)).join(` ${field} `)})`);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (field === "not") {
|
|
280
|
+
conditions.push(`not (${compilePhysicalWhere(relation, value, alias, profile, addValue)})`);
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
const edge = pqsRelationEdges[relation]?.[field];
|
|
284
|
+
if (edge !== undefined) {
|
|
285
|
+
conditions.push(compilePhysicalRelationPredicate(edge.target, field, edge.targetColumn, edge.sourceColumn, edge.cardinality, value, alias, profile, addValue));
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const column = metadata.fields[field];
|
|
289
|
+
if (column === undefined || value === null || typeof value !== "object" || Array.isArray(value))
|
|
290
|
+
throw new Error(`${field} is not a field of ${relation}`);
|
|
291
|
+
const filter = value;
|
|
292
|
+
const text = PqsSchemaProfileV1.jsonField(relation, field) && Array.isArray(filter.path) ? `${alias}."${column}" #>> ${addValue(filter.path)}::text[]` : `${alias}."${column}"`;
|
|
293
|
+
if (Array.isArray(filter.path) && (filter.path.length === 0 || filter.path.some((segment) => typeof segment !== "string" || segment.length === 0)))
|
|
294
|
+
throw new Error(`${field}.path must be a non-empty JSON path`);
|
|
295
|
+
if (filter.is === null)
|
|
296
|
+
conditions.push(`${text} is null`);
|
|
297
|
+
if (filter.isNot === null)
|
|
298
|
+
conditions.push(`${text} is not null`);
|
|
299
|
+
if (filter.equals !== undefined)
|
|
300
|
+
conditions.push(`${text} = ${addValue(filter.equals)}`);
|
|
301
|
+
if (filter.in !== undefined) {
|
|
302
|
+
if (!Array.isArray(filter.in))
|
|
303
|
+
throw new Error(`${field}.in must be an array`);
|
|
304
|
+
conditions.push(filter.in.length === 0 ? "false" : `${text} = any(${addValue(filter.in)})`);
|
|
305
|
+
}
|
|
306
|
+
if (filter.has !== undefined) {
|
|
307
|
+
if (!metadata.arrayFields.includes(field))
|
|
308
|
+
throw new Error(`${field} is not an array field of ${relation}`);
|
|
309
|
+
conditions.push(`${addValue(filter.has)} = any(${alias}."${column}")`);
|
|
310
|
+
}
|
|
311
|
+
for (const [operator, operand] of Object.entries(filter)) {
|
|
312
|
+
const sql = { lt: "<", lte: "<=", gt: ">", gte: ">=", like: "like", ilike: "ilike" }[operator];
|
|
313
|
+
if (sql !== undefined)
|
|
314
|
+
conditions.push(`${text} ${sql} ${addValue(operand)}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return conditions.length === 0 ? "true" : conditions.join(" and ");
|
|
318
|
+
}
|
|
116
319
|
function compileOrderBy(orderBy) {
|
|
117
320
|
if (orderBy === undefined) {
|
|
118
321
|
return "order by contract_row.contract_id asc";
|
|
@@ -124,10 +327,9 @@ function compileOrderBy(orderBy) {
|
|
|
124
327
|
archivedEventOffset: "contract_row.archived_at_ix",
|
|
125
328
|
archivedAt: "archived_tx.effective_at",
|
|
126
329
|
};
|
|
127
|
-
const entries = Object.entries(
|
|
128
|
-
if (entries.
|
|
129
|
-
throw new Error("orderBy must
|
|
330
|
+
const entries = orderBy.flatMap((entry) => Object.entries(entry));
|
|
331
|
+
if (entries.some(([field, direction]) => fields[field] === undefined || (direction !== "asc" && direction !== "desc"))) {
|
|
332
|
+
throw new Error("orderBy must contain valid one-field entries");
|
|
130
333
|
}
|
|
131
|
-
|
|
132
|
-
return `order by ${fields[field]} ${direction}`;
|
|
334
|
+
return `order by ${entries.map(([field, direction]) => `${fields[field]} ${direction}`).join(", ")}`;
|
|
133
335
|
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { QuerySource } from "./query-source.js";
|
|
2
|
-
import { ContractTypeOrderBy,
|
|
3
|
-
export interface FindManyArgs<TWhere, TSelect, TOrderBy> {
|
|
2
|
+
import { ContractTypeOrderBy, ContractTypeResult, ContractTypeSelect, ContractTypeUnique, ContractTypeWhere, ContractTypeGroupByArgs, ContractTypeGroupRow, ContractCountArgs, ContractFindManyArgs, ContractFindUniqueArgs, ContractGroupByArgs, ContractGroupRow, ContractResult, EventOrderBy, EventResult, EventGroupByArgs, EventGroupRow, EventSelect, EventUnique, EventWhere, ExerciseOrderBy, ExerciseResult, ExerciseSelect, ExerciseTypeOrderBy, ExerciseTypeResult, ExerciseTypeSelect, ExerciseTypeUnique, ExerciseTypeWhere, ExerciseTypeGroupByArgs, ExerciseTypeGroupRow, ExerciseWhere, ExerciseGroupByArgs, ExerciseGroupRow, PackageOrderBy, PackageResult, PackageSelect, PackageUnique, PackageWhere, PackageGroupByArgs, PackageGroupRow, TransactionOrderBy, TransactionResult, TransactionSelect, TransactionUnique, TransactionWhere, TransactionGroupByArgs, TransactionGroupRow, WatermarkOrderBy, WatermarkRow, WatermarkSelect, WatermarkUnique, WatermarkWhere, WatermarkGroupByArgs, WatermarkGroupRow, ContractTypeInclude, EventInclude, ExerciseInclude, ExerciseTypeInclude, PackageInclude, TransactionInclude, JsonProjectionResult } from "./model-types.js";
|
|
3
|
+
export interface FindManyArgs<TWhere, TSelect, TOrderBy, TInclude = never> {
|
|
4
4
|
readonly where?: TWhere;
|
|
5
5
|
readonly select?: TSelect;
|
|
6
6
|
readonly orderBy?: TOrderBy;
|
|
7
7
|
readonly skip?: number;
|
|
8
8
|
readonly take?: number;
|
|
9
|
+
readonly include?: TInclude;
|
|
9
10
|
}
|
|
10
|
-
export interface QueryDelegate<TRow, TWhere, TSelect, TOrderBy, TUnique> {
|
|
11
|
-
findMany
|
|
12
|
-
findUnique
|
|
11
|
+
export interface QueryDelegate<TRow, TWhere, TSelect, TOrderBy, TUnique, TInclude = never, TGroupBy = never, TGroupRow = never> {
|
|
12
|
+
findMany<TArgs extends FindManyArgs<TWhere, TSelect, TOrderBy, TInclude>>(args?: TArgs): Promise<readonly (TRow & JsonProjectionResult<TArgs>)[]>;
|
|
13
|
+
findUnique<TArgs extends {
|
|
13
14
|
readonly where: TUnique;
|
|
14
15
|
readonly select?: TSelect;
|
|
15
|
-
|
|
16
|
+
readonly include?: TInclude;
|
|
17
|
+
}>(args: TArgs): Promise<(TRow & JsonProjectionResult<TArgs>) | undefined>;
|
|
16
18
|
count(args?: {
|
|
17
19
|
readonly where?: TWhere;
|
|
18
20
|
}): Promise<number>;
|
|
@@ -28,14 +30,15 @@ export interface QueryDelegate<TRow, TWhere, TSelect, TOrderBy, TUnique> {
|
|
|
28
30
|
readonly max?: Readonly<Record<string, string | null>>;
|
|
29
31
|
readonly sum?: Readonly<Record<string, string | null>>;
|
|
30
32
|
}>;
|
|
33
|
+
groupBy(args: TGroupBy): Promise<readonly TGroupRow[]>;
|
|
31
34
|
}
|
|
32
|
-
export type QueryCollectionDelegate<TRow, TWhere, TSelect, TOrderBy> = Omit<QueryDelegate<TRow, TWhere, TSelect, TOrderBy, never>, "findUnique">;
|
|
35
|
+
export type QueryCollectionDelegate<TRow, TWhere, TSelect, TOrderBy, TInclude = never, TGroupBy = never, TGroupRow = never> = Omit<QueryDelegate<TRow, TWhere, TSelect, TOrderBy, never, TInclude, TGroupBy, TGroupRow>, "findUnique">;
|
|
33
36
|
export interface QueryClient {
|
|
34
37
|
readonly source: QuerySource;
|
|
35
38
|
$queryRaw<TRow>(sql: string, values?: readonly unknown[]): Promise<readonly TRow[]>;
|
|
36
39
|
readonly contracts: {
|
|
37
|
-
findMany(args?:
|
|
38
|
-
findUnique(args:
|
|
40
|
+
findMany<TArgs extends ContractFindManyArgs>(args?: TArgs): Promise<readonly (ContractResult & JsonProjectionResult<TArgs>)[]>;
|
|
41
|
+
findUnique<TArgs extends ContractFindUniqueArgs>(args: TArgs): Promise<(ContractResult & JsonProjectionResult<TArgs>) | undefined>;
|
|
39
42
|
count(args?: ContractCountArgs): Promise<number>;
|
|
40
43
|
aggregate(args: {
|
|
41
44
|
readonly where?: ContractCountArgs["where"];
|
|
@@ -49,13 +52,14 @@ export interface QueryClient {
|
|
|
49
52
|
readonly max?: Readonly<Partial<Record<ContractNumericField, string | null>>>;
|
|
50
53
|
readonly sum?: Readonly<Partial<Record<ContractNumericField, string | null>>>;
|
|
51
54
|
}>;
|
|
55
|
+
groupBy(args: ContractGroupByArgs): Promise<readonly ContractGroupRow[]>;
|
|
52
56
|
};
|
|
53
|
-
readonly contractTypes: QueryDelegate<
|
|
54
|
-
readonly events: QueryDelegate<
|
|
55
|
-
readonly exercises: QueryCollectionDelegate<
|
|
56
|
-
readonly exerciseTypes: QueryDelegate<
|
|
57
|
-
readonly packages: QueryDelegate<
|
|
58
|
-
readonly transactions: QueryDelegate<
|
|
59
|
-
readonly watermark: QueryDelegate<WatermarkRow, WatermarkWhere, WatermarkSelect, WatermarkOrderBy, WatermarkUnique>;
|
|
57
|
+
readonly contractTypes: QueryDelegate<ContractTypeResult, ContractTypeWhere, ContractTypeSelect, ContractTypeOrderBy, ContractTypeUnique, ContractTypeInclude, ContractTypeGroupByArgs, ContractTypeGroupRow>;
|
|
58
|
+
readonly events: QueryDelegate<EventResult, EventWhere, EventSelect, EventOrderBy, EventUnique, EventInclude, EventGroupByArgs, EventGroupRow>;
|
|
59
|
+
readonly exercises: QueryCollectionDelegate<ExerciseResult, ExerciseWhere, ExerciseSelect, ExerciseOrderBy, ExerciseInclude, ExerciseGroupByArgs, ExerciseGroupRow>;
|
|
60
|
+
readonly exerciseTypes: QueryDelegate<ExerciseTypeResult, ExerciseTypeWhere, ExerciseTypeSelect, ExerciseTypeOrderBy, ExerciseTypeUnique, ExerciseTypeInclude, ExerciseTypeGroupByArgs, ExerciseTypeGroupRow>;
|
|
61
|
+
readonly packages: QueryDelegate<PackageResult, PackageWhere, PackageSelect, PackageOrderBy, PackageUnique, PackageInclude, PackageGroupByArgs, PackageGroupRow>;
|
|
62
|
+
readonly transactions: QueryDelegate<TransactionResult, TransactionWhere, TransactionSelect, TransactionOrderBy, TransactionUnique, TransactionInclude, TransactionGroupByArgs, TransactionGroupRow>;
|
|
63
|
+
readonly watermark: QueryDelegate<WatermarkRow, WatermarkWhere, WatermarkSelect, WatermarkOrderBy, WatermarkUnique, never, WatermarkGroupByArgs, WatermarkGroupRow>;
|
|
60
64
|
}
|
|
61
65
|
export type ContractNumericField = "createdEventOffset" | "archivedEventOffset";
|