@causa/runtime-google 0.34.0 → 0.35.1

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.
@@ -7,6 +7,7 @@ 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
+ var AppCheckGuard_1;
10
11
  import { Logger, UnauthenticatedError } from '@causa/runtime/nestjs';
11
12
  import { Injectable, } from '@nestjs/common';
12
13
  import { Reflector } from '@nestjs/core';
@@ -16,7 +17,7 @@ import { APP_CHECK_DISABLED_METADATA_KEY } from './app-check-disabled.decorator.
16
17
  * A NestJS guard that verifies the App Check token in the request.
17
18
  * The token is expected to be in the `X-Firebase-AppCheck` header.
18
19
  */
19
- let AppCheckGuard = class AppCheckGuard {
20
+ let AppCheckGuard = AppCheckGuard_1 = class AppCheckGuard {
20
21
  appCheck;
21
22
  reflector;
22
23
  logger;
@@ -24,6 +25,7 @@ let AppCheckGuard = class AppCheckGuard {
24
25
  this.appCheck = appCheck;
25
26
  this.reflector = reflector;
26
27
  this.logger = logger;
28
+ this.logger.setContext(AppCheckGuard_1.name);
27
29
  }
28
30
  async canActivate(context) {
29
31
  const isDisabled = this.reflector.getAllAndOverride(APP_CHECK_DISABLED_METADATA_KEY, [context.getHandler(), context.getClass()]);
@@ -45,7 +47,7 @@ let AppCheckGuard = class AppCheckGuard {
45
47
  }
46
48
  }
47
49
  };
48
- AppCheckGuard = __decorate([
50
+ AppCheckGuard = AppCheckGuard_1 = __decorate([
49
51
  Injectable(),
50
52
  __metadata("design:paramtypes", [AppCheck,
51
53
  Reflector,
@@ -7,6 +7,7 @@ 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
+ var IdentityPlatformStrategy_1;
10
11
  import { Logger, UnauthenticatedError } from '@causa/runtime/nestjs';
11
12
  import { Injectable } from '@nestjs/common';
12
13
  import { ConfigService } from '@nestjs/config';
@@ -19,7 +20,7 @@ import { Strategy } from 'passport-http-bearer';
19
20
  * The `IDENTITY_PLATFORM_STRATEGY_CHECK_REVOKED_TOKEN` configuration key can be set to `true` to also check whether the
20
21
  * token was revoked. This implies a call to the Identity Platform, which will increase latency.
21
22
  */
22
- let IdentityPlatformStrategy = class IdentityPlatformStrategy extends PassportStrategy(Strategy) {
23
+ let IdentityPlatformStrategy = IdentityPlatformStrategy_1 = class IdentityPlatformStrategy extends PassportStrategy(Strategy) {
23
24
  auth;
24
25
  configService;
25
26
  logger;
@@ -32,6 +33,7 @@ let IdentityPlatformStrategy = class IdentityPlatformStrategy extends PassportSt
32
33
  this.auth = auth;
33
34
  this.configService = configService;
34
35
  this.logger = logger;
36
+ this.logger.setContext(IdentityPlatformStrategy_1.name);
35
37
  this.checkRevoked = this.configService.get('IDENTITY_PLATFORM_STRATEGY_CHECK_REVOKED_TOKEN', false);
36
38
  }
37
39
  async validate(token) {
@@ -56,7 +58,7 @@ let IdentityPlatformStrategy = class IdentityPlatformStrategy extends PassportSt
56
58
  return user;
57
59
  }
58
60
  };
59
- IdentityPlatformStrategy = __decorate([
61
+ IdentityPlatformStrategy = IdentityPlatformStrategy_1 = __decorate([
60
62
  Injectable(),
61
63
  __metadata("design:paramtypes", [Auth,
62
64
  ConfigService,
@@ -1,7 +1,7 @@
1
1
  import { type EventPublisher, type ObjectSerializer, type PreparedEvent, type PublishOptions } from '@causa/runtime';
2
+ import { Logger } from '@causa/runtime/nestjs';
2
3
  import { PubSub, type PublishOptions as TopicPublishOptions } from '@google-cloud/pubsub';
3
4
  import type { OnApplicationShutdown } from '@nestjs/common';
4
- import type { Logger } from 'pino';
5
5
  /**
6
6
  * Options for the {@link PubSubPublisher}.
7
7
  */
@@ -32,16 +32,12 @@ export type PubSubPublisherOptions = {
32
32
  * This inherits and overrides the {@link PubSubPublisherOptions.publishOptions} for a given topic.
33
33
  */
34
34
  topicPublishOptions?: Record<string, TopicPublishOptions>;
35
- /**
36
- * The logger to use.
37
- * Defaults to {@link getDefaultLogger}.
38
- */
39
- logger?: Logger;
40
35
  };
41
36
  /**
42
37
  * An implementation of the {@link EventPublisher} using Google Pub/Sub as the broker.
43
38
  */
44
39
  export declare class PubSubPublisher implements EventPublisher, OnApplicationShutdown {
40
+ private readonly logger;
45
41
  /**
46
42
  * The {@link PubSub} client to use.
47
43
  */
@@ -59,10 +55,6 @@ export declare class PubSubPublisher implements EventPublisher, OnApplicationShu
59
55
  * A cache of Pub/Sub {@link Topic}s to which messages can be published.
60
56
  */
61
57
  private readonly topicCache;
62
- /**
63
- * The logger to use.
64
- */
65
- readonly logger: Logger;
66
58
  /**
67
59
  * The options to use when publishing messages.
68
60
  * This is used to instantiate the Pub/Sub {@link Topic}s.
@@ -77,9 +69,10 @@ export declare class PubSubPublisher implements EventPublisher, OnApplicationShu
77
69
  /**
78
70
  * Creates a new {@link PubSubPublisher}.
79
71
  *
72
+ * @param logger The logger to use.
80
73
  * @param options Options for the publisher.
81
74
  */
82
- constructor(options?: PubSubPublisherOptions);
75
+ constructor(logger: Logger, options?: PubSubPublisherOptions);
83
76
  /**
84
77
  * Returns the Pub/Sub {@link Topic} to which messages can be published for a given event topic.
85
78
  * If the topic has not been used before, it will be created using the {@link PubSubPublisher.publishOptions}.
@@ -1,4 +1,5 @@
1
- import { JsonObjectSerializer, getDefaultLogger, } from '@causa/runtime';
1
+ import { JsonObjectSerializer, } from '@causa/runtime';
2
+ import { Logger } from '@causa/runtime/nestjs';
2
3
  import { PubSub, Topic, } from '@google-cloud/pubsub';
3
4
  import { getConfigurationKeyForTopic } from './configuration.js';
4
5
  import { PubSubTopicNotConfiguredError } from './errors.js';
@@ -14,6 +15,7 @@ const DEFAULT_PUBLISH_OPTIONS = {
14
15
  * An implementation of the {@link EventPublisher} using Google Pub/Sub as the broker.
15
16
  */
16
17
  export class PubSubPublisher {
18
+ logger;
17
19
  /**
18
20
  * The {@link PubSub} client to use.
19
21
  */
@@ -31,10 +33,6 @@ export class PubSubPublisher {
31
33
  * A cache of Pub/Sub {@link Topic}s to which messages can be published.
32
34
  */
33
35
  topicCache = {};
34
- /**
35
- * The logger to use.
36
- */
37
- logger;
38
36
  /**
39
37
  * The options to use when publishing messages.
40
38
  * This is used to instantiate the Pub/Sub {@link Topic}s.
@@ -49,16 +47,18 @@ export class PubSubPublisher {
49
47
  /**
50
48
  * Creates a new {@link PubSubPublisher}.
51
49
  *
50
+ * @param logger The logger to use.
52
51
  * @param options Options for the publisher.
53
52
  */
54
- constructor(options = {}) {
53
+ constructor(logger, options = {}) {
54
+ this.logger = logger;
55
+ this.logger.setContext(PubSubPublisher.name);
55
56
  this.pubSub = options.pubSub ?? new PubSub();
56
57
  this.serializer = options.serializer ?? new JsonObjectSerializer();
57
58
  this.getConfiguration =
58
59
  options.configurationGetter ?? ((key) => process.env[key]);
59
60
  this.publishOptions = options.publishOptions ?? DEFAULT_PUBLISH_OPTIONS;
60
61
  this.topicPublishOptions = options.topicPublishOptions ?? {};
61
- this.logger = options.logger ?? getDefaultLogger();
62
62
  }
63
63
  /**
64
64
  * Returns the Pub/Sub {@link Topic} to which messages can be published for a given event topic.
@@ -28,11 +28,10 @@ export class PubSubPublisherModule {
28
28
  },
29
29
  {
30
30
  provide: PubSubPublisher,
31
- useFactory: (pubSub, configurationGetter, { logger }) => new PubSubPublisher({
31
+ useFactory: (pubSub, configurationGetter, logger) => new PubSubPublisher(logger, {
32
32
  ...options,
33
33
  pubSub,
34
34
  configurationGetter,
35
- logger,
36
35
  }),
37
36
  inject: [
38
37
  PubSub,
@@ -7,6 +7,7 @@ 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
+ var FirestorePubSubTransactionRunner_1;
10
11
  import { BufferEventTransaction, TransactionRunner } from '@causa/runtime';
11
12
  import { Logger } from '@causa/runtime/nestjs';
12
13
  import { Firestore } from '@google-cloud/firestore';
@@ -22,7 +23,7 @@ import { FirestorePubSubTransaction } from './transaction.js';
22
23
  * This runner and the transaction use the {@link FirestoreStateTransaction}, which handles soft-deleted documents. All
23
24
  * entities that are written to the state should be decorated with the `SoftDeletedFirestoreCollection` decorator.
24
25
  */
25
- let FirestorePubSubTransactionRunner = class FirestorePubSubTransactionRunner extends TransactionRunner {
26
+ let FirestorePubSubTransactionRunner = FirestorePubSubTransactionRunner_1 = class FirestorePubSubTransactionRunner extends TransactionRunner {
26
27
  firestore;
27
28
  pubSubPublisher;
28
29
  collectionResolver;
@@ -33,6 +34,7 @@ let FirestorePubSubTransactionRunner = class FirestorePubSubTransactionRunner ex
33
34
  this.pubSubPublisher = pubSubPublisher;
34
35
  this.collectionResolver = collectionResolver;
35
36
  this.logger = logger;
37
+ this.logger.setContext(FirestorePubSubTransactionRunner_1.name);
36
38
  }
37
39
  async run(runFn) {
38
40
  this.logger.info('Creating a Firestore Pub/Sub transaction.');
@@ -49,7 +51,7 @@ let FirestorePubSubTransactionRunner = class FirestorePubSubTransactionRunner ex
49
51
  return [result];
50
52
  }
51
53
  };
52
- FirestorePubSubTransactionRunner = __decorate([
54
+ FirestorePubSubTransactionRunner = FirestorePubSubTransactionRunner_1 = __decorate([
53
55
  Injectable(),
54
56
  __metadata("design:paramtypes", [Firestore,
55
57
  PubSubPublisher, Object, Logger])
@@ -12,7 +12,7 @@ import type { EventAttributes, OutboxEvent } from '@causa/runtime';
12
12
  * attributes JSON NOT NULL,
13
13
  * leaseExpiration TIMESTAMP,
14
14
  * -- 20 is the number of shards.
15
- * shard INT64 NOT NULL AS (MOD(ABS(FARM_FINGERPRINT(id)), 20)),
15
+ * shard INT64 AS (MOD(ABS(FARM_FINGERPRINT(id)), 20)),
16
16
  * ) PRIMARY KEY (id);
17
17
  * CREATE INDEX OutboxEventsByShardAndLeaseExpiration ON OutboxEvent(shard, leaseExpiration)
18
18
  * ```
@@ -21,7 +21,7 @@ import { SpannerColumn, SpannerTable } from '../../spanner/index.js';
21
21
  * attributes JSON NOT NULL,
22
22
  * leaseExpiration TIMESTAMP,
23
23
  * -- 20 is the number of shards.
24
- * shard INT64 NOT NULL AS (MOD(ABS(FARM_FINGERPRINT(id)), 20)),
24
+ * shard INT64 AS (MOD(ABS(FARM_FINGERPRINT(id)), 20)),
25
25
  * ) PRIMARY KEY (id);
26
26
  * CREATE INDEX OutboxEventsByShardAndLeaseExpiration ON OutboxEvent(shard, leaseExpiration)
27
27
  * ```
@@ -1,5 +1,6 @@
1
1
  import { EVENT_PUBLISHER_INJECTION_NAME, Logger } from '@causa/runtime/nestjs';
2
2
  import { ConfigService } from '@nestjs/config';
3
+ import { PubSubPublisher } from '../../pubsub/index.js';
3
4
  import { SpannerEntityManager } from '../../spanner/index.js';
4
5
  import { SpannerOutboxEvent } from './event.js';
5
6
  import { SpannerOutboxTransactionRunner } from './runner.js';
@@ -7,11 +8,12 @@ import { SpannerOutboxSender, } from './sender.js';
7
8
  /**
8
9
  * Combines options passed to the module with the configuration (from the environment).
9
10
  *
10
- * @param options Options passed to the module.
11
+ * @param defaultOptions Options inferred by the module itself.
12
+ * @param customOptions Options passed to the module by the caller.
11
13
  * @param config The {@link ConfigService} to use.
12
14
  * @returns The parsed {@link SpannerOutboxSenderOptions}.
13
15
  */
14
- function parseSenderOptions(options, config) {
16
+ function parseSenderOptions(defaultOptions, customOptions, config) {
15
17
  function validateIntOrUndefined(name) {
16
18
  const strValue = config.get(name);
17
19
  if (strValue === undefined) {
@@ -34,7 +36,7 @@ function parseSenderOptions(options, config) {
34
36
  const sharding = shardingColumn && shardingCount
35
37
  ? { column: shardingColumn, count: shardingCount }
36
38
  : undefined;
37
- const envOptions = {
39
+ const envOptionsWithUndefined = {
38
40
  batchSize,
39
41
  pollingInterval,
40
42
  idColumn,
@@ -43,8 +45,15 @@ function parseSenderOptions(options, config) {
43
45
  sharding,
44
46
  leaseDuration,
45
47
  };
46
- return { ...envOptions, ...options };
48
+ const envOptions = Object.fromEntries(Object.entries(envOptionsWithUndefined).filter(([, v]) => v !== undefined));
49
+ return { ...defaultOptions, ...envOptions, ...customOptions };
47
50
  }
51
+ /**
52
+ * The default lease duration, in milliseconds, when the publisher is Pub/Sub.
53
+ * Pub/Sub has a default retry/timeout of 60 seconds. This ensures the lease is long enough and the event doesn't get
54
+ * picked up by another instance.
55
+ */
56
+ const DEFAULT_PUBSUB_LEASE_DURATION = 70000;
48
57
  /**
49
58
  * The module providing the {@link SpannerOutboxTransactionRunner}.
50
59
  * This assumes the `SpannerModule` and an {@link EventPublisher} are available (as well as the `LoggerModule`).
@@ -69,7 +78,10 @@ export class SpannerOutboxTransactionModule {
69
78
  {
70
79
  provide: SpannerOutboxSender,
71
80
  useFactory: (entityManager, publisher, logger, config) => {
72
- const options = parseSenderOptions(senderOptions, config);
81
+ const defaultOptions = publisher instanceof PubSubPublisher
82
+ ? { leaseDuration: DEFAULT_PUBSUB_LEASE_DURATION }
83
+ : {};
84
+ const options = parseSenderOptions(defaultOptions, senderOptions, config);
73
85
  return new SpannerOutboxSender(entityManager, outboxEventType, publisher, logger, options);
74
86
  },
75
87
  inject: [
@@ -7,6 +7,7 @@ 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
+ var SpannerPubSubTransactionRunner_1;
10
11
  import { BufferEventTransaction, TransactionRunner } from '@causa/runtime';
11
12
  import { Logger } from '@causa/runtime/nestjs';
12
13
  import { Injectable } from '@nestjs/common';
@@ -19,7 +20,7 @@ import { throwRetryableInTransactionIfNeeded } from '../spanner-utils.js';
19
20
  * A {@link TransactionRunner} that uses Spanner for state and Pub/Sub for events.
20
21
  * A Spanner transaction is used as the main transaction. If it succeeds, events are published to Pub/Sub outside of it.
21
22
  */
22
- let SpannerPubSubTransactionRunner = class SpannerPubSubTransactionRunner extends TransactionRunner {
23
+ let SpannerPubSubTransactionRunner = SpannerPubSubTransactionRunner_1 = class SpannerPubSubTransactionRunner extends TransactionRunner {
23
24
  entityManager;
24
25
  publisher;
25
26
  logger;
@@ -35,6 +36,7 @@ let SpannerPubSubTransactionRunner = class SpannerPubSubTransactionRunner extend
35
36
  this.entityManager = entityManager;
36
37
  this.publisher = publisher;
37
38
  this.logger = logger;
39
+ this.logger.setContext(SpannerPubSubTransactionRunner_1.name);
38
40
  }
39
41
  async run(runFn) {
40
42
  this.logger.info('Creating a Spanner Pub/Sub transaction.');
@@ -58,7 +60,7 @@ let SpannerPubSubTransactionRunner = class SpannerPubSubTransactionRunner extend
58
60
  return [result];
59
61
  }
60
62
  };
61
- SpannerPubSubTransactionRunner = __decorate([
63
+ SpannerPubSubTransactionRunner = SpannerPubSubTransactionRunner_1 = __decorate([
62
64
  Injectable(),
63
65
  __metadata("design:paramtypes", [SpannerEntityManager,
64
66
  PubSubPublisher,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@causa/runtime-google",
3
- "version": "0.34.0",
3
+ "version": "0.35.1",
4
4
  "description": "An extension to the Causa runtime SDK (`@causa/runtime`), providing Google-specific features.",
5
5
  "repository": "github:causa-io/runtime-typescript-google",
6
6
  "license": "ISC",
@@ -29,15 +29,15 @@
29
29
  "test:cov": "npm run test -- --coverage"
30
30
  },
31
31
  "dependencies": {
32
- "@causa/runtime": ">= 0.24.0 < 1.0.0",
32
+ "@causa/runtime": ">= 0.24.1 < 1.0.0",
33
33
  "@google-cloud/precise-date": "^4.0.0",
34
34
  "@google-cloud/pubsub": "^4.9.0",
35
35
  "@google-cloud/spanner": "^7.16.0",
36
36
  "@google-cloud/tasks": "^5.5.1",
37
37
  "@grpc/grpc-js": "^1.12.2",
38
- "@nestjs/common": "^10.4.11",
38
+ "@nestjs/common": "^10.4.12",
39
39
  "@nestjs/config": "^3.3.0",
40
- "@nestjs/core": "^10.4.11",
40
+ "@nestjs/core": "^10.4.12",
41
41
  "@nestjs/passport": "^10.0.3",
42
42
  "@nestjs/terminus": "^10.2.3",
43
43
  "class-transformer": "^0.5.1",
@@ -51,18 +51,18 @@
51
51
  "reflect-metadata": "^0.2.2"
52
52
  },
53
53
  "devDependencies": {
54
- "@nestjs/testing": "^10.4.11",
54
+ "@nestjs/testing": "^10.4.12",
55
55
  "@swc/core": "^1.9.3",
56
56
  "@swc/jest": "^0.2.37",
57
57
  "@tsconfig/node22": "^22.0.0",
58
58
  "@types/jest": "^29.5.14",
59
59
  "@types/jsonwebtoken": "^9.0.7",
60
- "@types/node": "^22.10.0",
60
+ "@types/node": "^22.10.1",
61
61
  "@types/passport-http-bearer": "^1.0.41",
62
62
  "@types/supertest": "^6.0.2",
63
63
  "@types/uuid": "^10.0.0",
64
64
  "dotenv": "^16.4.5",
65
- "eslint": "^9.15.0",
65
+ "eslint": "^9.16.0",
66
66
  "eslint-config-prettier": "^9.1.0",
67
67
  "eslint-plugin-prettier": "^5.2.1",
68
68
  "jest": "^29.7.0",