@causa/runtime-google 1.5.0 → 1.5.2
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/firestore/healthcheck.d.ts +5 -4
- package/dist/firestore/healthcheck.js +12 -12
- package/dist/pubsub/healthcheck.d.ts +5 -4
- package/dist/pubsub/healthcheck.js +17 -16
- package/dist/spanner/conversion.js +25 -1
- package/dist/spanner/entity-manager.js +12 -2
- package/dist/spanner/healthcheck.d.ts +5 -4
- package/dist/spanner/healthcheck.js +12 -10
- package/package.json +18 -18
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { BaseHealthIndicatorService } from '@causa/runtime/nestjs';
|
|
2
|
-
import { type HealthIndicatorResult } from '@nestjs/terminus';
|
|
1
|
+
import { BaseHealthIndicatorService, type HealthChecker } from '@causa/runtime/nestjs';
|
|
2
|
+
import { HealthIndicatorService, type HealthIndicatorResult } from '@nestjs/terminus';
|
|
3
3
|
import { Firestore } from 'firebase-admin/firestore';
|
|
4
4
|
/**
|
|
5
5
|
* A service testing the availability of the Firestore service.
|
|
6
6
|
*/
|
|
7
|
-
export declare class FirestoreHealthIndicator extends BaseHealthIndicatorService {
|
|
7
|
+
export declare class FirestoreHealthIndicator extends BaseHealthIndicatorService implements HealthChecker {
|
|
8
8
|
private readonly firestore;
|
|
9
|
-
|
|
9
|
+
private readonly healthIndicatorService;
|
|
10
|
+
constructor(firestore: Firestore, healthIndicatorService: HealthIndicatorService);
|
|
10
11
|
check(): Promise<HealthIndicatorResult>;
|
|
11
12
|
}
|
|
@@ -7,9 +7,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
-
import {
|
|
10
|
+
import { orFallbackFn, tryMap } from '@causa/runtime';
|
|
11
|
+
import { BaseHealthIndicatorService, } from '@causa/runtime/nestjs';
|
|
11
12
|
import { Injectable } from '@nestjs/common';
|
|
12
|
-
import {
|
|
13
|
+
import { HealthIndicatorService, } from '@nestjs/terminus';
|
|
13
14
|
import { Firestore } from 'firebase-admin/firestore';
|
|
14
15
|
/**
|
|
15
16
|
* The key used to identify the Firestore health indicator.
|
|
@@ -20,24 +21,23 @@ const FIRESTORE_HEALTH_KEY = 'google.firestore';
|
|
|
20
21
|
*/
|
|
21
22
|
let FirestoreHealthIndicator = class FirestoreHealthIndicator extends BaseHealthIndicatorService {
|
|
22
23
|
firestore;
|
|
23
|
-
|
|
24
|
+
healthIndicatorService;
|
|
25
|
+
constructor(firestore, healthIndicatorService) {
|
|
24
26
|
super();
|
|
25
27
|
this.firestore = firestore;
|
|
28
|
+
this.healthIndicatorService = healthIndicatorService;
|
|
26
29
|
}
|
|
27
30
|
async check() {
|
|
28
|
-
|
|
31
|
+
const check = this.healthIndicatorService.check(FIRESTORE_HEALTH_KEY);
|
|
32
|
+
return await tryMap(async () => {
|
|
29
33
|
await this.firestore.listCollections();
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
throw new HealthCheckError('Failed to check health by listing Firestore collections.', this.getStatus(FIRESTORE_HEALTH_KEY, false, {
|
|
34
|
-
error: error.message,
|
|
35
|
-
}));
|
|
36
|
-
}
|
|
34
|
+
return check.up();
|
|
35
|
+
}, orFallbackFn((error) => check.down({ error: error.message })));
|
|
37
36
|
}
|
|
38
37
|
};
|
|
39
38
|
FirestoreHealthIndicator = __decorate([
|
|
40
39
|
Injectable(),
|
|
41
|
-
__metadata("design:paramtypes", [Firestore
|
|
40
|
+
__metadata("design:paramtypes", [Firestore,
|
|
41
|
+
HealthIndicatorService])
|
|
42
42
|
], FirestoreHealthIndicator);
|
|
43
43
|
export { FirestoreHealthIndicator };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { BaseHealthIndicatorService } from '@causa/runtime/nestjs';
|
|
1
|
+
import { BaseHealthIndicatorService, type HealthChecker } from '@causa/runtime/nestjs';
|
|
2
2
|
import { PubSub } from '@google-cloud/pubsub';
|
|
3
|
-
import { type HealthIndicatorResult } from '@nestjs/terminus';
|
|
3
|
+
import { HealthIndicatorService, type HealthIndicatorResult } from '@nestjs/terminus';
|
|
4
4
|
/**
|
|
5
5
|
* A service testing the availability of the Pub/Sub service.
|
|
6
6
|
*/
|
|
7
|
-
export declare class PubSubHealthIndicator extends BaseHealthIndicatorService {
|
|
7
|
+
export declare class PubSubHealthIndicator extends BaseHealthIndicatorService implements HealthChecker {
|
|
8
8
|
private readonly pubSub;
|
|
9
|
-
|
|
9
|
+
private readonly healthIndicatorService;
|
|
10
|
+
constructor(pubSub: PubSub, healthIndicatorService: HealthIndicatorService);
|
|
10
11
|
check(): Promise<HealthIndicatorResult>;
|
|
11
12
|
}
|
|
@@ -7,11 +7,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
-
import {
|
|
10
|
+
import { orFallbackFn, tryMap } from '@causa/runtime';
|
|
11
|
+
import { BaseHealthIndicatorService, } from '@causa/runtime/nestjs';
|
|
11
12
|
import { PubSub } from '@google-cloud/pubsub';
|
|
12
13
|
import { status } from '@grpc/grpc-js';
|
|
13
14
|
import { Injectable } from '@nestjs/common';
|
|
14
|
-
import {
|
|
15
|
+
import { HealthIndicatorService, } from '@nestjs/terminus';
|
|
15
16
|
/**
|
|
16
17
|
* The key used to identify the Pub/Sub health indicator.
|
|
17
18
|
*/
|
|
@@ -21,30 +22,30 @@ const PUBSUB_HEALTH_KEY = 'google.pubSub';
|
|
|
21
22
|
*/
|
|
22
23
|
let PubSubHealthIndicator = class PubSubHealthIndicator extends BaseHealthIndicatorService {
|
|
23
24
|
pubSub;
|
|
24
|
-
|
|
25
|
+
healthIndicatorService;
|
|
26
|
+
constructor(pubSub, healthIndicatorService) {
|
|
25
27
|
super();
|
|
26
28
|
this.pubSub = pubSub;
|
|
29
|
+
this.healthIndicatorService = healthIndicatorService;
|
|
27
30
|
}
|
|
28
31
|
async check() {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
32
|
+
const check = this.healthIndicatorService.check(PUBSUB_HEALTH_KEY);
|
|
33
|
+
return await tryMap(async () => {
|
|
34
|
+
await this.pubSub.getTopics({ autoPaginate: false, pageSize: 1 });
|
|
35
|
+
return check.up();
|
|
36
|
+
}, orFallbackFn((error) => {
|
|
36
37
|
// Permission denied errors are treated as healthy, as they indicate that the service could successfully connect
|
|
37
38
|
// to the Pub/Sub service (which is probably healthy), but was not allowed to list topics (which is usually not
|
|
38
39
|
// the case for publishers).
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
return this.getStatus(PUBSUB_HEALTH_KEY, true);
|
|
40
|
+
return error.code === status.PERMISSION_DENIED
|
|
41
|
+
? check.up()
|
|
42
|
+
: check.down({ error: error.message });
|
|
43
|
+
}));
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
PubSubHealthIndicator = __decorate([
|
|
47
47
|
Injectable(),
|
|
48
|
-
__metadata("design:paramtypes", [PubSub
|
|
48
|
+
__metadata("design:paramtypes", [PubSub,
|
|
49
|
+
HealthIndicatorService])
|
|
49
50
|
], PubSubHealthIndicator);
|
|
50
51
|
export { PubSubHealthIndicator };
|
|
@@ -57,6 +57,25 @@ function spannerValueToJavaScript(value, columnMetadata) {
|
|
|
57
57
|
}
|
|
58
58
|
return value;
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Converts a number, bigint, or string value to a Spanner `Int`, throwing if the value is not a safe integer.
|
|
62
|
+
*
|
|
63
|
+
* @param value The value to convert.
|
|
64
|
+
* @returns The Spanner `Int` value.
|
|
65
|
+
*/
|
|
66
|
+
function toSafeSpannerInt(value) {
|
|
67
|
+
const valueType = typeof value;
|
|
68
|
+
if (valueType !== 'number' &&
|
|
69
|
+
valueType !== 'string' &&
|
|
70
|
+
valueType !== 'bigint') {
|
|
71
|
+
throw new TypeError(`Expected a number, bigint, or string, but received ${valueType}.`);
|
|
72
|
+
}
|
|
73
|
+
const num = valueType !== 'number' ? Number(value) : value;
|
|
74
|
+
if (!Number.isSafeInteger(num)) {
|
|
75
|
+
throw new RangeError('Value is not a safe integer for column marked as integer.');
|
|
76
|
+
}
|
|
77
|
+
return new Int(value.toString());
|
|
78
|
+
}
|
|
60
79
|
/**
|
|
61
80
|
* Converts a value such that it is safe to pass to the Spanner client.
|
|
62
81
|
* Numeric values and arrays of numeric values are wrapped using Spanner classes.
|
|
@@ -70,11 +89,16 @@ function makeSpannerValue(value, metadata) {
|
|
|
70
89
|
if (value === undefined || value === null) {
|
|
71
90
|
return value;
|
|
72
91
|
}
|
|
73
|
-
if (metadata.isBigInt
|
|
92
|
+
if (metadata.isBigInt) {
|
|
74
93
|
return Array.isArray(value)
|
|
75
94
|
? value.map((v) => new Int(v.toString()))
|
|
76
95
|
: new Int(value.toString());
|
|
77
96
|
}
|
|
97
|
+
if (metadata.isInt) {
|
|
98
|
+
return Array.isArray(value)
|
|
99
|
+
? value.map(toSafeSpannerInt)
|
|
100
|
+
: toSafeSpannerInt(value);
|
|
101
|
+
}
|
|
78
102
|
if (metadata.isJson) {
|
|
79
103
|
return JSON.stringify(value);
|
|
80
104
|
}
|
|
@@ -294,8 +294,14 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
294
294
|
: {};
|
|
295
295
|
const sqlStatement = statement ?? optionsOrStatement;
|
|
296
296
|
const { entityType, requestOptions, transaction } = options;
|
|
297
|
+
let snapshot;
|
|
297
298
|
try {
|
|
298
|
-
|
|
299
|
+
let txn = transaction;
|
|
300
|
+
if (!txn) {
|
|
301
|
+
[snapshot] = await this.database.getSnapshot();
|
|
302
|
+
txn = snapshot;
|
|
303
|
+
}
|
|
304
|
+
const stream = txn.runStream({
|
|
299
305
|
...sqlStatement,
|
|
300
306
|
requestOptions,
|
|
301
307
|
json: true,
|
|
@@ -310,9 +316,13 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
310
316
|
}
|
|
311
317
|
}
|
|
312
318
|
catch (error) {
|
|
313
|
-
// If running in a transaction, the error will be caught by `snapshot()` or `transaction()`.
|
|
319
|
+
// If running in a provided transaction, the error will be caught by `snapshot()` or `transaction()`.
|
|
320
|
+
// Otherwise, the error should be converted.
|
|
314
321
|
throw transaction ? error : (convertSpannerToEntityError(error) ?? error);
|
|
315
322
|
}
|
|
323
|
+
finally {
|
|
324
|
+
snapshot?.end();
|
|
325
|
+
}
|
|
316
326
|
}
|
|
317
327
|
/**
|
|
318
328
|
* Runs the given SQL statement in the database, returning an async iterable of batches of results.
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { BaseHealthIndicatorService } from '@causa/runtime/nestjs';
|
|
1
|
+
import { BaseHealthIndicatorService, type HealthChecker } from '@causa/runtime/nestjs';
|
|
2
2
|
import { Database } from '@google-cloud/spanner';
|
|
3
|
-
import { type HealthIndicatorResult } from '@nestjs/terminus';
|
|
3
|
+
import { HealthIndicatorService, type HealthIndicatorResult } from '@nestjs/terminus';
|
|
4
4
|
/**
|
|
5
5
|
* A service testing the availability of the Spanner service.
|
|
6
6
|
*/
|
|
7
|
-
export declare class SpannerHealthIndicator extends BaseHealthIndicatorService {
|
|
7
|
+
export declare class SpannerHealthIndicator extends BaseHealthIndicatorService implements HealthChecker {
|
|
8
8
|
private readonly database;
|
|
9
|
-
|
|
9
|
+
private readonly healthIndicatorService;
|
|
10
|
+
constructor(database: Database, healthIndicatorService: HealthIndicatorService);
|
|
10
11
|
check(): Promise<HealthIndicatorResult>;
|
|
11
12
|
}
|
|
@@ -7,10 +7,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
-
import {
|
|
10
|
+
import { orFallbackFn, tryMap } from '@causa/runtime';
|
|
11
|
+
import { BaseHealthIndicatorService, } from '@causa/runtime/nestjs';
|
|
11
12
|
import { Database } from '@google-cloud/spanner';
|
|
12
13
|
import { Injectable } from '@nestjs/common';
|
|
13
|
-
import {
|
|
14
|
+
import { HealthIndicatorService, } from '@nestjs/terminus';
|
|
14
15
|
/**
|
|
15
16
|
* The key used to identify the Spanner health indicator.
|
|
16
17
|
*/
|
|
@@ -20,22 +21,23 @@ const SPANNER_HEALTH_KEY = 'google.spanner';
|
|
|
20
21
|
*/
|
|
21
22
|
let SpannerHealthIndicator = class SpannerHealthIndicator extends BaseHealthIndicatorService {
|
|
22
23
|
database;
|
|
23
|
-
|
|
24
|
+
healthIndicatorService;
|
|
25
|
+
constructor(database, healthIndicatorService) {
|
|
24
26
|
super();
|
|
25
27
|
this.database = database;
|
|
28
|
+
this.healthIndicatorService = healthIndicatorService;
|
|
26
29
|
}
|
|
27
30
|
async check() {
|
|
28
|
-
|
|
31
|
+
const check = this.healthIndicatorService.check(SPANNER_HEALTH_KEY);
|
|
32
|
+
return await tryMap(async () => {
|
|
29
33
|
await this.database.run('SELECT 1');
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
throw new HealthCheckError('Failed to check health by running Spanner query.', this.getStatus(SPANNER_HEALTH_KEY, false, { error: error.message }));
|
|
34
|
-
}
|
|
34
|
+
return check.up();
|
|
35
|
+
}, orFallbackFn((error) => check.down({ error: error.message })));
|
|
35
36
|
}
|
|
36
37
|
};
|
|
37
38
|
SpannerHealthIndicator = __decorate([
|
|
38
39
|
Injectable(),
|
|
39
|
-
__metadata("design:paramtypes", [Database
|
|
40
|
+
__metadata("design:paramtypes", [Database,
|
|
41
|
+
HealthIndicatorService])
|
|
40
42
|
], SpannerHealthIndicator);
|
|
41
43
|
export { SpannerHealthIndicator };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@causa/runtime-google",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.2",
|
|
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.5.0",
|
|
36
36
|
"@google-cloud/precise-date": "^5.0.0",
|
|
37
|
-
"@google-cloud/pubsub": "^5.2.
|
|
38
|
-
"@google-cloud/spanner": "^8.
|
|
37
|
+
"@google-cloud/pubsub": "^5.2.1",
|
|
38
|
+
"@google-cloud/spanner": "^8.4.0",
|
|
39
39
|
"@google-cloud/tasks": "^6.2.1",
|
|
40
|
-
"@grpc/grpc-js": "^1.14.
|
|
41
|
-
"@nestjs/common": "^11.1.
|
|
40
|
+
"@grpc/grpc-js": "^1.14.3",
|
|
41
|
+
"@nestjs/common": "^11.1.11",
|
|
42
42
|
"@nestjs/config": "^4.0.2",
|
|
43
|
-
"@nestjs/core": "^11.1.
|
|
43
|
+
"@nestjs/core": "^11.1.11",
|
|
44
44
|
"@nestjs/passport": "^11.0.5",
|
|
45
45
|
"@nestjs/terminus": "^11.0.0",
|
|
46
46
|
"class-transformer": "^0.5.1",
|
|
47
|
-
"class-validator": "^0.14.
|
|
48
|
-
"express": "^5.1
|
|
47
|
+
"class-validator": "^0.14.3",
|
|
48
|
+
"express": "^5.2.1",
|
|
49
49
|
"firebase-admin": "^13.6.0",
|
|
50
|
-
"jsonwebtoken": "^9.0.
|
|
50
|
+
"jsonwebtoken": "^9.0.3",
|
|
51
51
|
"passport-http-bearer": "^1.0.1",
|
|
52
|
-
"pino": "^
|
|
52
|
+
"pino": "^10.1.1",
|
|
53
53
|
"reflect-metadata": "^0.2.2"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@nestjs/testing": "^11.1.
|
|
57
|
-
"@swc/core": "^1.15.
|
|
56
|
+
"@nestjs/testing": "^11.1.11",
|
|
57
|
+
"@swc/core": "^1.15.8",
|
|
58
58
|
"@swc/jest": "^0.2.39",
|
|
59
59
|
"@tsconfig/node20": "^20.1.8",
|
|
60
60
|
"@types/jest": "^30.0.0",
|
|
61
61
|
"@types/jsonwebtoken": "^9.0.10",
|
|
62
|
-
"@types/node": "^20.19.
|
|
62
|
+
"@types/node": "^20.19.28",
|
|
63
63
|
"@types/passport-http-bearer": "^1.0.42",
|
|
64
64
|
"@types/supertest": "^6.0.3",
|
|
65
65
|
"@types/uuid": "^11.0.0",
|
|
66
66
|
"dotenv": "^17.2.3",
|
|
67
|
-
"eslint": "^9.39.
|
|
67
|
+
"eslint": "^9.39.2",
|
|
68
68
|
"eslint-config-prettier": "^10.1.8",
|
|
69
69
|
"eslint-plugin-prettier": "^5.5.4",
|
|
70
70
|
"jest": "^30.2.0",
|
|
71
71
|
"jest-extended": "^7.0.0",
|
|
72
|
-
"pino-pretty": "^13.1.
|
|
72
|
+
"pino-pretty": "^13.1.3",
|
|
73
73
|
"rimraf": "^6.1.2",
|
|
74
|
-
"supertest": "^7.
|
|
74
|
+
"supertest": "^7.2.2",
|
|
75
75
|
"typescript": "^5.9.3",
|
|
76
|
-
"typescript-eslint": "^8.
|
|
76
|
+
"typescript-eslint": "^8.52.0",
|
|
77
77
|
"uuid": "^13.0.0"
|
|
78
78
|
}
|
|
79
79
|
}
|