@causa/runtime-google 1.1.0 → 1.2.0
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.
|
@@ -114,6 +114,8 @@ export declare class SpannerEntityManager {
|
|
|
114
114
|
/**
|
|
115
115
|
* Returns the (quoted) name of the table for the given entity type.
|
|
116
116
|
*
|
|
117
|
+
* @deprecated Use {@link sqlTable} instead.
|
|
118
|
+
*
|
|
117
119
|
* @param entityTypeOrTable The type of entity, or the unquoted table name.
|
|
118
120
|
* @param options Options when constructing the table name (e.g. the index to use).
|
|
119
121
|
* @returns The name of the table, quoted with backticks.
|
|
@@ -130,6 +132,25 @@ export declare class SpannerEntityManager {
|
|
|
130
132
|
*/
|
|
131
133
|
disableQueryNullFilteredIndexEmulatorCheck?: boolean;
|
|
132
134
|
}): string;
|
|
135
|
+
/**
|
|
136
|
+
* Returns the (quoted) name of the table for the given entity type.
|
|
137
|
+
*
|
|
138
|
+
* @param entityTypeOrTable The type of entity, or the unquoted table name.
|
|
139
|
+
* @param options Options when constructing the table name (e.g. the index to use).
|
|
140
|
+
* @returns The name of the table, quoted with backticks.
|
|
141
|
+
*/
|
|
142
|
+
sqlTable(entityTypeOrTable: Type | string, options?: {
|
|
143
|
+
/**
|
|
144
|
+
* Sets a table hint to indicate which index to use when querying the table.
|
|
145
|
+
* The value will be quoted with backticks.
|
|
146
|
+
*/
|
|
147
|
+
index?: string;
|
|
148
|
+
/**
|
|
149
|
+
* Sets a table hint to disable the check that prevents queries from using null-filtered indexes.
|
|
150
|
+
* This is useful when using the emulator, which does not support null-filtered indexes.
|
|
151
|
+
*/
|
|
152
|
+
disableQueryNullFilteredIndexEmulatorCheck?: boolean;
|
|
153
|
+
}): string;
|
|
133
154
|
/**
|
|
134
155
|
* Returns the (quoted) list of columns for the given entity type or list of columns.
|
|
135
156
|
*
|
|
@@ -139,7 +160,16 @@ export declare class SpannerEntityManager {
|
|
|
139
160
|
* @param entityTypeOrColumns The type of entity, or the unquoted list of columns.
|
|
140
161
|
* @returns The list of columns, quoted with backticks and joined.
|
|
141
162
|
*/
|
|
142
|
-
sqlColumns(entityTypeOrColumns: Type | string[]
|
|
163
|
+
sqlColumns<T = unknown>(entityTypeOrColumns: Type<T> | string[], options?: {
|
|
164
|
+
/**
|
|
165
|
+
* If `entityTypeOrColumns` is a type, only the columns for the given properties will be included.
|
|
166
|
+
*/
|
|
167
|
+
forProperties?: T extends object ? (keyof T & string)[] : never;
|
|
168
|
+
/**
|
|
169
|
+
* The alias with which to prefix each column.
|
|
170
|
+
*/
|
|
171
|
+
alias?: string;
|
|
172
|
+
}): string;
|
|
143
173
|
/**
|
|
144
174
|
* Fetches a single row from the database using its key (either primary or for a secondary index).
|
|
145
175
|
*
|
|
@@ -73,11 +73,23 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
73
73
|
/**
|
|
74
74
|
* Returns the (quoted) name of the table for the given entity type.
|
|
75
75
|
*
|
|
76
|
+
* @deprecated Use {@link sqlTable} instead.
|
|
77
|
+
*
|
|
76
78
|
* @param entityTypeOrTable The type of entity, or the unquoted table name.
|
|
77
79
|
* @param options Options when constructing the table name (e.g. the index to use).
|
|
78
80
|
* @returns The name of the table, quoted with backticks.
|
|
79
81
|
*/
|
|
80
82
|
sqlTableName(entityTypeOrTable, options = {}) {
|
|
83
|
+
return this.sqlTable(entityTypeOrTable, options);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Returns the (quoted) name of the table for the given entity type.
|
|
87
|
+
*
|
|
88
|
+
* @param entityTypeOrTable The type of entity, or the unquoted table name.
|
|
89
|
+
* @param options Options when constructing the table name (e.g. the index to use).
|
|
90
|
+
* @returns The name of the table, quoted with backticks.
|
|
91
|
+
*/
|
|
92
|
+
sqlTable(entityTypeOrTable, options = {}) {
|
|
81
93
|
const tableHints = {};
|
|
82
94
|
if (options.index) {
|
|
83
95
|
tableHints.FORCE_INDEX = `\`${options.index}\``;
|
|
@@ -89,9 +101,10 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
89
101
|
const tableHintsString = Object.entries(tableHints)
|
|
90
102
|
.map(([k, v]) => `${k}=${v}`)
|
|
91
103
|
.join(',');
|
|
92
|
-
const
|
|
93
|
-
?
|
|
94
|
-
: this.tableCache.getMetadata(entityTypeOrTable).
|
|
104
|
+
const tableName = typeof entityTypeOrTable === 'string'
|
|
105
|
+
? entityTypeOrTable
|
|
106
|
+
: this.tableCache.getMetadata(entityTypeOrTable).tableName;
|
|
107
|
+
const quotedTableName = `\`${tableName}\``;
|
|
95
108
|
return tableHintsString.length > 0
|
|
96
109
|
? `${quotedTableName}@{${tableHintsString}}`
|
|
97
110
|
: quotedTableName;
|
|
@@ -105,11 +118,22 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
105
118
|
* @param entityTypeOrColumns The type of entity, or the unquoted list of columns.
|
|
106
119
|
* @returns The list of columns, quoted with backticks and joined.
|
|
107
120
|
*/
|
|
108
|
-
sqlColumns(entityTypeOrColumns) {
|
|
121
|
+
sqlColumns(entityTypeOrColumns, options = {}) {
|
|
122
|
+
let columns;
|
|
109
123
|
if (Array.isArray(entityTypeOrColumns)) {
|
|
110
|
-
|
|
124
|
+
columns = entityTypeOrColumns;
|
|
111
125
|
}
|
|
112
|
-
|
|
126
|
+
else {
|
|
127
|
+
const { columnNames } = this.tableCache.getMetadata(entityTypeOrColumns);
|
|
128
|
+
columns = options.forProperties
|
|
129
|
+
? options.forProperties.map((p) => columnNames[p])
|
|
130
|
+
: Object.values(columnNames);
|
|
131
|
+
}
|
|
132
|
+
columns = columns.map((c) => `\`${c}\``);
|
|
133
|
+
if (options.alias) {
|
|
134
|
+
columns = columns.map((c) => `\`${options.alias}\`.${c}`);
|
|
135
|
+
}
|
|
136
|
+
return columns.join(', ');
|
|
113
137
|
}
|
|
114
138
|
/**
|
|
115
139
|
* Fetches a single row from the database using its key (either primary or for a secondary index).
|
|
@@ -131,8 +155,9 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
131
155
|
if (!Array.isArray(key)) {
|
|
132
156
|
key = [key];
|
|
133
157
|
}
|
|
134
|
-
const { tableName,
|
|
135
|
-
const columns = options.columns ??
|
|
158
|
+
const { tableName, columnNames, primaryKeyColumns, softDeleteColumn } = this.tableCache.getMetadata(entityType);
|
|
159
|
+
const columns = options.columns ??
|
|
160
|
+
(options.index ? primaryKeyColumns : Object.values(columnNames));
|
|
136
161
|
return await this.snapshot({ transaction: options.transaction }, async (transaction) => {
|
|
137
162
|
const [rows] = await transaction.read(tableName, {
|
|
138
163
|
keys: [key],
|
|
@@ -266,10 +291,8 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
266
291
|
* @param options The options to use when running the operation.
|
|
267
292
|
*/
|
|
268
293
|
async clear(entityType, options = {}) {
|
|
269
|
-
const {
|
|
270
|
-
await this.transaction(options, (transaction) => transaction.runUpdate({
|
|
271
|
-
sql: `DELETE FROM ${quotedTableName} WHERE TRUE`,
|
|
272
|
-
}));
|
|
294
|
+
const { tableName } = this.tableCache.getMetadata(entityType);
|
|
295
|
+
await this.transaction(options, (transaction) => transaction.runUpdate(`DELETE FROM \`${tableName}\` WHERE TRUE`));
|
|
273
296
|
}
|
|
274
297
|
async query(optionsOrStatement, statement) {
|
|
275
298
|
const options = statement
|
|
@@ -7,22 +7,14 @@ export type CachedSpannerTableMetadata = {
|
|
|
7
7
|
* The name of the table.
|
|
8
8
|
*/
|
|
9
9
|
tableName: string;
|
|
10
|
-
/**
|
|
11
|
-
* The name of the table, quoted with backticks for use in queries.
|
|
12
|
-
*/
|
|
13
|
-
quotedTableName: string;
|
|
14
10
|
/**
|
|
15
11
|
* The (ordered) list of columns that are part of the primary key.
|
|
16
12
|
*/
|
|
17
13
|
primaryKeyColumns: string[];
|
|
18
14
|
/**
|
|
19
|
-
*
|
|
20
|
-
*/
|
|
21
|
-
columns: string[];
|
|
22
|
-
/**
|
|
23
|
-
* The list of all columns in the table, quoted with backticks and joined for use in queries.
|
|
15
|
+
* A map from class property names to Spanner column names.
|
|
24
16
|
*/
|
|
25
|
-
|
|
17
|
+
columnNames: Record<string, string>;
|
|
26
18
|
/**
|
|
27
19
|
* The name of the column used to mark soft deletes, if any.
|
|
28
20
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getSpannerColumnsMetadata } from './column.decorator.js';
|
|
2
2
|
import { InvalidEntityDefinitionError } from './errors.js';
|
|
3
3
|
import { getSpannerTableMetadataFromType } from './table.decorator.js';
|
|
4
4
|
/**
|
|
@@ -21,7 +21,6 @@ export class SpannerTableCache {
|
|
|
21
21
|
throw new InvalidEntityDefinitionError(entityType);
|
|
22
22
|
}
|
|
23
23
|
const tableName = tableMetadata.name;
|
|
24
|
-
const quotedTableName = `\`${tableName}\``;
|
|
25
24
|
const primaryKeyColumns = tableMetadata.primaryKey;
|
|
26
25
|
const columnsMetadata = getSpannerColumnsMetadata(entityType);
|
|
27
26
|
const softDeleteColumns = Object.values(columnsMetadata).filter((metadata) => metadata.softDelete);
|
|
@@ -29,15 +28,12 @@ export class SpannerTableCache {
|
|
|
29
28
|
throw new InvalidEntityDefinitionError(entityType, `Only one column can be marked as soft delete.`);
|
|
30
29
|
}
|
|
31
30
|
const softDeleteColumn = softDeleteColumns[0]?.name ?? null;
|
|
32
|
-
const
|
|
33
|
-
const quotedColumns = columns.map((c) => `\`${c}\``).join(', ');
|
|
31
|
+
const columnNames = Object.fromEntries(Object.entries(columnsMetadata).map(([prop, { name }]) => [prop, name]));
|
|
34
32
|
return {
|
|
35
33
|
tableName,
|
|
36
|
-
quotedTableName,
|
|
37
34
|
primaryKeyColumns,
|
|
38
|
-
columns,
|
|
39
|
-
quotedColumns,
|
|
40
35
|
softDeleteColumn,
|
|
36
|
+
columnNames,
|
|
41
37
|
};
|
|
42
38
|
}
|
|
43
39
|
/**
|
|
@@ -99,8 +99,10 @@ export class SpannerOutboxSender extends OutboxEventSender {
|
|
|
99
99
|
* @returns The SQL queries used to fetch and update events in the outbox.
|
|
100
100
|
*/
|
|
101
101
|
buildSql() {
|
|
102
|
-
const table = this.entityManager.
|
|
103
|
-
const tableWithIndex = this.entityManager.
|
|
102
|
+
const table = this.entityManager.sqlTable(this.outboxEventType);
|
|
103
|
+
const tableWithIndex = this.entityManager.sqlTable(this.outboxEventType, {
|
|
104
|
+
index: this.index,
|
|
105
|
+
});
|
|
104
106
|
const noLeaseFilter = `\`${this.leaseExpirationColumn}\` IS NULL OR \`${this.leaseExpirationColumn}\` < @currentTime`;
|
|
105
107
|
let fetchFilter = noLeaseFilter;
|
|
106
108
|
if (this.sharding) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@causa/runtime-google",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "An extension to the Causa runtime SDK (`@causa/runtime`), providing Google-specific features.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,48 +32,48 @@
|
|
|
32
32
|
"test:cov": "npm run test -- --coverage"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@causa/runtime": "^1.
|
|
35
|
+
"@causa/runtime": "^1.1.0",
|
|
36
36
|
"@google-cloud/precise-date": "^5.0.0",
|
|
37
|
-
"@google-cloud/pubsub": "^5.
|
|
38
|
-
"@google-cloud/spanner": "^8.1
|
|
37
|
+
"@google-cloud/pubsub": "^5.2.0",
|
|
38
|
+
"@google-cloud/spanner": "^8.2.1",
|
|
39
39
|
"@google-cloud/tasks": "^6.2.0",
|
|
40
|
-
"@grpc/grpc-js": "^1.
|
|
41
|
-
"@nestjs/common": "^11.1.
|
|
40
|
+
"@grpc/grpc-js": "^1.14.0",
|
|
41
|
+
"@nestjs/common": "^11.1.6",
|
|
42
42
|
"@nestjs/config": "^4.0.2",
|
|
43
|
-
"@nestjs/core": "^11.1.
|
|
43
|
+
"@nestjs/core": "^11.1.6",
|
|
44
44
|
"@nestjs/passport": "^11.0.5",
|
|
45
45
|
"@nestjs/terminus": "^11.0.0",
|
|
46
46
|
"class-transformer": "^0.5.1",
|
|
47
47
|
"class-validator": "^0.14.2",
|
|
48
48
|
"express": "^5.1.0",
|
|
49
|
-
"firebase-admin": "^13.
|
|
49
|
+
"firebase-admin": "^13.5.0",
|
|
50
50
|
"jsonwebtoken": "^9.0.2",
|
|
51
51
|
"passport-http-bearer": "^1.0.1",
|
|
52
|
-
"pino": "^9.
|
|
52
|
+
"pino": "^9.12.0",
|
|
53
53
|
"reflect-metadata": "^0.2.2"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@nestjs/testing": "^11.1.
|
|
57
|
-
"@swc/core": "^1.13.
|
|
56
|
+
"@nestjs/testing": "^11.1.6",
|
|
57
|
+
"@swc/core": "^1.13.5",
|
|
58
58
|
"@swc/jest": "^0.2.39",
|
|
59
59
|
"@tsconfig/node22": "^22.0.2",
|
|
60
60
|
"@types/jest": "^30.0.0",
|
|
61
61
|
"@types/jsonwebtoken": "^9.0.10",
|
|
62
|
-
"@types/node": "^22.
|
|
63
|
-
"@types/passport-http-bearer": "^1.0.
|
|
62
|
+
"@types/node": "^22.18.8",
|
|
63
|
+
"@types/passport-http-bearer": "^1.0.42",
|
|
64
64
|
"@types/supertest": "^6.0.3",
|
|
65
|
-
"@types/uuid": "^
|
|
66
|
-
"dotenv": "^17.2.
|
|
67
|
-
"eslint": "^9.
|
|
65
|
+
"@types/uuid": "^11.0.0",
|
|
66
|
+
"dotenv": "^17.2.3",
|
|
67
|
+
"eslint": "^9.36.0",
|
|
68
68
|
"eslint-config-prettier": "^10.1.8",
|
|
69
|
-
"eslint-plugin-prettier": "^5.5.
|
|
70
|
-
"jest": "^30.0
|
|
69
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
70
|
+
"jest": "^30.2.0",
|
|
71
71
|
"jest-extended": "^6.0.0",
|
|
72
72
|
"pino-pretty": "^13.1.1",
|
|
73
73
|
"rimraf": "^6.0.1",
|
|
74
74
|
"supertest": "^7.1.4",
|
|
75
|
-
"typescript": "^5.9.
|
|
76
|
-
"typescript-eslint": "^8.
|
|
77
|
-
"uuid": "^
|
|
75
|
+
"typescript": "^5.9.3",
|
|
76
|
+
"typescript-eslint": "^8.45.0",
|
|
77
|
+
"uuid": "^13.0.0"
|
|
78
78
|
}
|
|
79
79
|
}
|