@causa/runtime-google 1.5.1 → 1.5.3
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 +6 -7
- package/dist/spanner/healthcheck.d.ts +5 -4
- package/dist/spanner/healthcheck.js +12 -10
- package/package.json +5 -5
|
@@ -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
|
}
|
|
@@ -293,15 +293,15 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
293
293
|
? optionsOrStatement
|
|
294
294
|
: {};
|
|
295
295
|
const sqlStatement = statement ?? optionsOrStatement;
|
|
296
|
-
const { entityType, requestOptions } = options;
|
|
296
|
+
const { entityType, requestOptions, transaction } = options;
|
|
297
297
|
let snapshot;
|
|
298
298
|
try {
|
|
299
|
-
let
|
|
300
|
-
if (!
|
|
299
|
+
let txn = transaction;
|
|
300
|
+
if (!txn) {
|
|
301
301
|
[snapshot] = await this.database.getSnapshot();
|
|
302
|
-
|
|
302
|
+
txn = snapshot;
|
|
303
303
|
}
|
|
304
|
-
const stream =
|
|
304
|
+
const stream = txn.runStream({
|
|
305
305
|
...sqlStatement,
|
|
306
306
|
requestOptions,
|
|
307
307
|
json: true,
|
|
@@ -316,8 +316,7 @@ let SpannerEntityManager = class SpannerEntityManager {
|
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
catch (error) {
|
|
319
|
-
|
|
320
|
-
throw !snapshot ? error : (convertSpannerToEntityError(error) ?? error);
|
|
319
|
+
throw convertSpannerToEntityError(error) ?? error;
|
|
321
320
|
}
|
|
322
321
|
finally {
|
|
323
322
|
snapshot?.end();
|
|
@@ -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.3",
|
|
4
4
|
"description": "An extension to the Causa runtime SDK (`@causa/runtime`), providing Google-specific features.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,10 +32,10 @@
|
|
|
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
37
|
"@google-cloud/pubsub": "^5.2.1",
|
|
38
|
-
"@google-cloud/spanner": "^8.
|
|
38
|
+
"@google-cloud/spanner": "^8.4.0",
|
|
39
39
|
"@google-cloud/tasks": "^6.2.1",
|
|
40
40
|
"@grpc/grpc-js": "^1.14.3",
|
|
41
41
|
"@nestjs/common": "^11.1.11",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"firebase-admin": "^13.6.0",
|
|
50
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": {
|
|
@@ -59,7 +59,7 @@
|
|
|
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",
|