@causa/runtime-google 0.40.0 → 1.0.0-rc.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.
- package/README.md +7 -14
- package/dist/app-check/testing.d.ts +7 -3
- package/dist/app-check/testing.js +9 -6
- package/dist/firebase/testing.d.ts +7 -4
- package/dist/firebase/testing.js +12 -7
- package/dist/firestore/testing.d.ts +32 -17
- package/dist/firestore/testing.js +45 -29
- package/dist/identity-platform/testing.d.ts +21 -6
- package/dist/identity-platform/testing.js +34 -9
- package/dist/pubsub/publisher.module.d.ts +1 -1
- package/dist/pubsub/{testing/fixture.d.ts → testing.d.ts} +64 -48
- package/dist/pubsub/{testing/fixture.js → testing.js} +106 -73
- package/dist/spanner/column.decorator.d.ts +1 -11
- package/dist/spanner/column.decorator.js +2 -7
- package/dist/spanner/conversion.d.ts +5 -18
- package/dist/spanner/conversion.js +45 -125
- package/dist/spanner/entity-manager.d.ts +19 -23
- package/dist/spanner/entity-manager.js +26 -60
- package/dist/spanner/table-cache.js +0 -3
- package/dist/spanner/testing.d.ts +37 -18
- package/dist/spanner/testing.js +75 -10
- package/dist/spanner/types.d.ts +0 -6
- package/dist/testing.d.ts +36 -2
- package/dist/testing.js +33 -2
- package/dist/transaction/firestore-pubsub/index.d.ts +3 -2
- package/dist/transaction/firestore-pubsub/index.js +2 -1
- package/dist/transaction/firestore-pubsub/nestjs-collection-resolver.d.ts +1 -1
- package/dist/transaction/firestore-pubsub/nestjs-collection-resolver.js +0 -1
- package/dist/transaction/firestore-pubsub/readonly-state-transaction.d.ts +37 -0
- package/dist/transaction/firestore-pubsub/readonly-state-transaction.js +46 -0
- package/dist/transaction/firestore-pubsub/runner.d.ts +6 -4
- package/dist/transaction/firestore-pubsub/runner.js +16 -7
- package/dist/transaction/firestore-pubsub/state-transaction.d.ts +11 -49
- package/dist/transaction/firestore-pubsub/state-transaction.js +19 -42
- package/dist/transaction/firestore-pubsub/transaction.d.ts +15 -3
- package/dist/transaction/firestore-pubsub/transaction.js +21 -3
- package/dist/transaction/firestore-pubsub/types.d.ts +36 -0
- package/dist/transaction/firestore-pubsub/types.js +1 -0
- package/dist/transaction/index.d.ts +0 -3
- package/dist/transaction/index.js +0 -3
- package/dist/transaction/spanner-outbox/index.d.ts +3 -1
- package/dist/transaction/spanner-outbox/index.js +3 -0
- package/dist/transaction/spanner-outbox/readonly-transaction.d.ts +22 -0
- package/dist/transaction/spanner-outbox/readonly-transaction.js +25 -0
- package/dist/transaction/spanner-outbox/runner.d.ts +7 -18
- package/dist/transaction/spanner-outbox/runner.js +13 -6
- package/dist/transaction/{spanner-utils.js → spanner-outbox/spanner-utils.js} +1 -1
- package/dist/transaction/spanner-outbox/state-transaction.d.ts +20 -0
- package/dist/transaction/spanner-outbox/state-transaction.js +34 -0
- package/dist/transaction/spanner-outbox/transaction.d.ts +28 -0
- package/dist/transaction/spanner-outbox/transaction.js +38 -0
- package/package.json +24 -21
- package/dist/pubsub/testing/index.d.ts +0 -4
- package/dist/pubsub/testing/index.js +0 -2
- package/dist/pubsub/testing/requester.d.ts +0 -50
- package/dist/pubsub/testing/requester.js +0 -53
- package/dist/testing/google-app-fixture.d.ts +0 -191
- package/dist/testing/google-app-fixture.js +0 -200
- package/dist/testing/index.d.ts +0 -1
- package/dist/testing/index.js +0 -1
- package/dist/transaction/spanner-pubsub/index.d.ts +0 -2
- package/dist/transaction/spanner-pubsub/index.js +0 -2
- package/dist/transaction/spanner-pubsub/module.d.ts +0 -14
- package/dist/transaction/spanner-pubsub/module.js +0 -21
- package/dist/transaction/spanner-pubsub/runner.d.ts +0 -23
- package/dist/transaction/spanner-pubsub/runner.js +0 -69
- package/dist/transaction/spanner-state-transaction.d.ts +0 -20
- package/dist/transaction/spanner-state-transaction.js +0 -35
- package/dist/transaction/spanner-transaction.d.ts +0 -16
- package/dist/transaction/spanner-transaction.js +0 -20
- /package/dist/transaction/{spanner-utils.d.ts → spanner-outbox/spanner-utils.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ The `FirebaseModule` is a NestJS module which exports various Firebase services
|
|
|
52
52
|
|
|
53
53
|
Outside of a NestJS context, `getDefaultFirebaseApp()` can be used to retrieve a consistently initialized singleton app.
|
|
54
54
|
|
|
55
|
-
For testing, `
|
|
55
|
+
For testing, the `FirebaseFixture` can be used, which ensures the default Firebase application is used across tests and avoids lifecycle issues (repeatedly creating and tearing down new applications).
|
|
56
56
|
|
|
57
57
|
### Firestore
|
|
58
58
|
|
|
@@ -60,7 +60,7 @@ The `makeFirestoreDataConverter` is a utility that returns a `FirestoreDataConve
|
|
|
60
60
|
|
|
61
61
|
The `FirestoreCollectionsModule` builds upon the `FirebaseModule` and provides Firestore collections for the listed document types. In services, the `@InjectFirestoreCollection` decorator can be used to retrieve a Firestore collection, prepared with the aforementioned converter.
|
|
62
62
|
|
|
63
|
-
Testing utilities are also provided
|
|
63
|
+
Testing utilities are also provided with `FirestoreFixture`. It replaces injected collections with temporary ones, to ensure separate collections are used for each test suite and avoid conflicts. Also, collections are cleared between tests.
|
|
64
64
|
|
|
65
65
|
### NestJS health checks
|
|
66
66
|
|
|
@@ -86,9 +86,7 @@ For services being triggered by Pub/Sub messages, the `PubSubEventHandlerModule`
|
|
|
86
86
|
|
|
87
87
|
The `PubSubHealthIndicator` is a `HealthIndicator` which can be used in a health check controller, such as the `GoogleHealthcheckModule`. It attempts to list topics using the Pub/Sub client to check connectivity to the Pub/Sub API.
|
|
88
88
|
|
|
89
|
-
To test publishers, the `PubSubFixture` handles the creation and deletion of temporary topics.
|
|
90
|
-
|
|
91
|
-
To test event handlers, the `makePubSubRequester()` utility returns a function which can be used to make HTTP requests in the same way a Pub/Sub push subscription would.
|
|
89
|
+
To test publishers, the `PubSubFixture` handles the creation and deletion of temporary topics, and provides `expect*` utilities to check for published messages. To test event handlers, it also provides the `makeRequester()` utility, which returns a function that can be used to make HTTP requests in the same way a Pub/Sub push subscription would.
|
|
92
90
|
|
|
93
91
|
### Spanner
|
|
94
92
|
|
|
@@ -98,25 +96,20 @@ The `SpannerModule` provides a `Database` instance configured using the `SPANNER
|
|
|
98
96
|
|
|
99
97
|
The `SpannerHealthIndicator` is a `HealthIndicator` which can be used in a health check controller, such as the `GoogleHealthcheckModule`. It runs a dummy `SELECT 1` query against the database to check connectivity.
|
|
100
98
|
|
|
101
|
-
For testing, the `createDatabase` utility creates a temporary database, copying the DDL from the configured database (set with the `SPANNER_DATABASE` environment variable). `
|
|
99
|
+
For testing, the `createDatabase` utility creates a temporary database, copying the DDL from the configured database (set with the `SPANNER_DATABASE` environment variable). The `SpannerFixture` uses this mechanism, and also clears the specified tables between tests.
|
|
102
100
|
|
|
103
101
|
### GCP-based Causa transaction runners
|
|
104
102
|
|
|
105
103
|
This package provides the following `TransactionRunner`s:
|
|
106
104
|
|
|
107
|
-
- `SpannerPubSubTransactionRunner`
|
|
108
105
|
- `FirestorePubSubTransactionRunner`
|
|
109
106
|
- `SpannerOutboxTransactionRunner`
|
|
110
107
|
|
|
111
|
-
The
|
|
112
|
-
|
|
113
|
-
The `SpannerPubSubTransactionRunner` uses a Spanner transaction as the underlying transaction for the `SpannerTransaction`, while the `FirestorePubSubTransactionRunner` uses a Firestore transaction for the `FirestorePubSubTransaction`. Both state transactions implement the `FindReplaceStateTransaction` interface, and therefore the runners can be used with the `VersionedEntityManager`.
|
|
114
|
-
|
|
115
|
-
One feature sets the `FirestorePubSubTransactionRunner` and its `FirestoreStateTransaction` apart: the handling of deleted entities using a separate, "soft-deleted document collection". Entities with a non-null `deletedAt` property are moved to a collection suffixed with `$deleted`, and an `_expirationDate` field is added to them. A TTL is expected to be set on this field. The `@SoftDeletedFirestoreCollection` decorator must be added to document classes that are meant to be handled using the `FirestorePubSubTransactionRunner`.
|
|
108
|
+
The `FirestorePubSubTransactionRunner` uses a Firestore transaction as the underlying state transaction for the `FirestorePubSubTransaction`. One feature sets the `FirestorePubSubTransactionRunner` and its `FirestoreStateTransaction` apart: the handling of deleted entities using a separate, "soft-deleted document collection". Entities with a non-null `deletedAt` property are moved to a collection suffixed with `$deleted`, and an `_expirationDate` field is added to them. A TTL is expected to be set on this field. The `@SoftDeletedFirestoreCollection` decorator must be added to document classes that are meant to be handled using the `FirestorePubSubTransactionRunner`.
|
|
116
109
|
|
|
117
110
|
> [!CAUTION]
|
|
118
111
|
>
|
|
119
|
-
> `
|
|
112
|
+
> `FirestorePubSubTransactionRunner` does not provide atomic guarantees between the state and the events being committed. This could result in events being lost, as they are published once the state transaction successfully committed. Prefer the `SpannerOutboxTransactionRunner` when applicable.
|
|
120
113
|
|
|
121
114
|
`SpannerOutboxTransactionRunner` implements the outbox pattern (from the base runtime's `OutboxTransactionRunner`), and uses the default injected `EventPublisher` (which can be the `PubSubPublisher`, if the corresponding module is imported). It requires an outbox table to be created in each database using the runner. See the documentation of the `SpannerOutboxEvent` for more information.
|
|
122
115
|
|
|
@@ -126,4 +119,4 @@ The `@IsValidFirestoreId` validation decorator checks that a property is a strin
|
|
|
126
119
|
|
|
127
120
|
### More testing utilities
|
|
128
121
|
|
|
129
|
-
|
|
122
|
+
To include all fixtures provided in this package as part of an `AppFixture`, use the `createGoogleFixtures` function, which is a convenience method to create the fixtures with sensible defaults. This will also automatically provide a `VersionedEntityFixture` configured with the `SpannerOutboxTransactionRunner`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { NestJsModuleOverrider } from '@causa/runtime/nestjs/testing';
|
|
1
|
+
import type { Fixture, NestJsModuleOverrider } from '@causa/runtime/nestjs/testing';
|
|
2
2
|
/**
|
|
3
|
-
* A {@link
|
|
3
|
+
* A {@link Fixture} that disables the {@link AppCheckGuard}.
|
|
4
4
|
*
|
|
5
5
|
* If used as an app-level guard, the {@link AppCheckGuard} should be defined as a provider first, and the app guard
|
|
6
6
|
* should reuse the existing instance:
|
|
@@ -9,4 +9,8 @@ import type { NestJsModuleOverrider } from '@causa/runtime/nestjs/testing';
|
|
|
9
9
|
* { provide: APP_GUARD, useExisting: AppCheckGuard }
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
|
-
export declare
|
|
12
|
+
export declare class AppCheckFixture implements Fixture {
|
|
13
|
+
init(): Promise<NestJsModuleOverrider>;
|
|
14
|
+
clear(): Promise<void>;
|
|
15
|
+
delete(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AppCheckGuard } from './guard.js';
|
|
2
2
|
/**
|
|
3
|
-
* A {@link
|
|
3
|
+
* A {@link Fixture} that disables the {@link AppCheckGuard}.
|
|
4
4
|
*
|
|
5
5
|
* If used as an app-level guard, the {@link AppCheckGuard} should be defined as a provider first, and the app guard
|
|
6
6
|
* should reuse the existing instance:
|
|
@@ -9,8 +9,11 @@ import { AppCheckGuard } from './guard.js';
|
|
|
9
9
|
* { provide: APP_GUARD, useExisting: AppCheckGuard }
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
12
|
+
export class AppCheckFixture {
|
|
13
|
+
async init() {
|
|
14
|
+
const mockGuard = { canActivate: () => true };
|
|
15
|
+
return (builder) => builder.overrideProvider(AppCheckGuard).useValue(mockGuard);
|
|
16
|
+
}
|
|
17
|
+
async clear() { }
|
|
18
|
+
async delete() { }
|
|
19
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type { NestJsModuleOverrider } from '@causa/runtime/nestjs/testing';
|
|
1
|
+
import type { Fixture, NestJsModuleOverrider } from '@causa/runtime/nestjs/testing';
|
|
2
2
|
/**
|
|
3
|
-
* A {@link
|
|
4
|
-
* application upon shutdown.
|
|
3
|
+
* A {@link Fixture} that reuses the default Firebase application and prevents its deletion upon shutdown.
|
|
5
4
|
*/
|
|
6
|
-
export declare
|
|
5
|
+
export declare class FirebaseFixture implements Fixture {
|
|
6
|
+
init(): Promise<NestJsModuleOverrider>;
|
|
7
|
+
clear(): Promise<void>;
|
|
8
|
+
delete(): Promise<void>;
|
|
9
|
+
}
|
package/dist/firebase/testing.js
CHANGED
|
@@ -2,11 +2,16 @@ import { getDefaultFirebaseApp } from './app.js';
|
|
|
2
2
|
import { FIREBASE_APP_TOKEN } from './inject-firebase-app.decorator.js';
|
|
3
3
|
import { FirebaseLifecycleService } from './lifecycle.service.js';
|
|
4
4
|
/**
|
|
5
|
-
* A {@link
|
|
6
|
-
* application upon shutdown.
|
|
5
|
+
* A {@link Fixture} that reuses the default Firebase application and prevents its deletion upon shutdown.
|
|
7
6
|
*/
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
export class FirebaseFixture {
|
|
8
|
+
async init() {
|
|
9
|
+
return (builder) => builder
|
|
10
|
+
.overrideProvider(FIREBASE_APP_TOKEN)
|
|
11
|
+
.useValue(getDefaultFirebaseApp())
|
|
12
|
+
.overrideProvider(FirebaseLifecycleService)
|
|
13
|
+
.useValue({});
|
|
14
|
+
}
|
|
15
|
+
async clear() { }
|
|
16
|
+
async delete() { }
|
|
17
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { NestJsModuleOverrider } from '@causa/runtime/nestjs/testing';
|
|
2
|
-
import type {
|
|
1
|
+
import type { AppFixture, Fixture, NestJsModuleOverrider } from '@causa/runtime/nestjs/testing';
|
|
2
|
+
import type { Type } from '@nestjs/common';
|
|
3
3
|
import { CollectionReference, Firestore } from 'firebase-admin/firestore';
|
|
4
4
|
/**
|
|
5
5
|
* Creates a new collection prefixed with a random ID.
|
|
@@ -17,19 +17,34 @@ export declare function createFirestoreTemporaryCollection<T>(firestore: Firesto
|
|
|
17
17
|
*/
|
|
18
18
|
export declare function clearFirestoreCollection(collectionRef: CollectionReference): Promise<void>;
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* @param documentTypes The types of documents corresponding to Firestore collections, for which collections should be
|
|
23
|
-
* overridden.
|
|
24
|
-
* @returns The {@link NestJsModuleOverrider} that can be used to override the Firestore collections.
|
|
25
|
-
*/
|
|
26
|
-
export declare function overrideFirestoreCollections(...documentTypes: Type[]): NestJsModuleOverrider;
|
|
27
|
-
/**
|
|
28
|
-
* Returns the {@link CollectionReference} of the Firestore collection corresponding to the given class.
|
|
29
|
-
* Retrieving it from the module or application ensures the "mocked" collection is used.
|
|
30
|
-
*
|
|
31
|
-
* @param context The NestJS module or application from which the Firestore collection should be retrieved.
|
|
32
|
-
* @param documentType The type of document stored in the collection.
|
|
33
|
-
* @returns The {@link CollectionReference} of the Firestore collection.
|
|
20
|
+
* A {@link Fixture} that replaces Firestore collections with temporary collections, and clears them when requested.
|
|
34
21
|
*/
|
|
35
|
-
export declare
|
|
22
|
+
export declare class FirestoreFixture implements Fixture {
|
|
23
|
+
/**
|
|
24
|
+
* The types of documents that should be stored in temporary collections and cleared.
|
|
25
|
+
*/
|
|
26
|
+
readonly types: Type[];
|
|
27
|
+
/**
|
|
28
|
+
* The parent {@link AppFixture}.
|
|
29
|
+
*/
|
|
30
|
+
private appFixture;
|
|
31
|
+
constructor(
|
|
32
|
+
/**
|
|
33
|
+
* The types of documents that should be stored in temporary collections and cleared.
|
|
34
|
+
*/
|
|
35
|
+
types: Type[]);
|
|
36
|
+
init(appFixture: AppFixture): Promise<NestJsModuleOverrider>;
|
|
37
|
+
clear(): Promise<void>;
|
|
38
|
+
delete(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* The underlying {@link Firestore} instance used by this fixture.
|
|
41
|
+
*/
|
|
42
|
+
get firestore(): Firestore;
|
|
43
|
+
/**
|
|
44
|
+
* Returns the (temporary) collection for the given document type.
|
|
45
|
+
*
|
|
46
|
+
* @param documentType The type of the document.
|
|
47
|
+
* @returns The {@link CollectionReference} for the given document type.
|
|
48
|
+
*/
|
|
49
|
+
collection<T>(documentType: Type<T>): CollectionReference<T>;
|
|
50
|
+
}
|
|
@@ -26,37 +26,53 @@ export function createFirestoreTemporaryCollection(firestore, documentType) {
|
|
|
26
26
|
export async function clearFirestoreCollection(collectionRef) {
|
|
27
27
|
const batch = collectionRef.firestore.batch();
|
|
28
28
|
const documents = await collectionRef.listDocuments();
|
|
29
|
-
documents.forEach((
|
|
29
|
+
documents.forEach((d) => batch.delete(d));
|
|
30
30
|
await batch.commit();
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* @param documentTypes The types of documents corresponding to Firestore collections, for which collections should be
|
|
36
|
-
* overridden.
|
|
37
|
-
* @returns The {@link NestJsModuleOverrider} that can be used to override the Firestore collections.
|
|
38
|
-
*/
|
|
39
|
-
export function overrideFirestoreCollections(...documentTypes) {
|
|
40
|
-
return (builder) => {
|
|
41
|
-
documentTypes.forEach((documentType) => {
|
|
42
|
-
builder = builder
|
|
43
|
-
.overrideProvider(getFirestoreCollectionInjectionName(documentType))
|
|
44
|
-
.useFactory({
|
|
45
|
-
factory: (firestore) => createFirestoreTemporaryCollection(firestore, documentType),
|
|
46
|
-
inject: [Firestore],
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
return builder;
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Returns the {@link CollectionReference} of the Firestore collection corresponding to the given class.
|
|
54
|
-
* Retrieving it from the module or application ensures the "mocked" collection is used.
|
|
55
|
-
*
|
|
56
|
-
* @param context The NestJS module or application from which the Firestore collection should be retrieved.
|
|
57
|
-
* @param documentType The type of document stored in the collection.
|
|
58
|
-
* @returns The {@link CollectionReference} of the Firestore collection.
|
|
33
|
+
* A {@link Fixture} that replaces Firestore collections with temporary collections, and clears them when requested.
|
|
59
34
|
*/
|
|
60
|
-
export
|
|
61
|
-
|
|
35
|
+
export class FirestoreFixture {
|
|
36
|
+
types;
|
|
37
|
+
/**
|
|
38
|
+
* The parent {@link AppFixture}.
|
|
39
|
+
*/
|
|
40
|
+
appFixture;
|
|
41
|
+
constructor(
|
|
42
|
+
/**
|
|
43
|
+
* The types of documents that should be stored in temporary collections and cleared.
|
|
44
|
+
*/
|
|
45
|
+
types) {
|
|
46
|
+
this.types = types;
|
|
47
|
+
}
|
|
48
|
+
async init(appFixture) {
|
|
49
|
+
this.appFixture = appFixture;
|
|
50
|
+
return (builder) => this.types.reduce((builder, t) => builder
|
|
51
|
+
.overrideProvider(getFirestoreCollectionInjectionName(t))
|
|
52
|
+
.useFactory({
|
|
53
|
+
factory: (f) => createFirestoreTemporaryCollection(f, t),
|
|
54
|
+
inject: [Firestore],
|
|
55
|
+
}), builder);
|
|
56
|
+
}
|
|
57
|
+
async clear() {
|
|
58
|
+
await Promise.all(this.types.map((t) => clearFirestoreCollection(this.collection(t))));
|
|
59
|
+
}
|
|
60
|
+
async delete() {
|
|
61
|
+
this.appFixture = undefined;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The underlying {@link Firestore} instance used by this fixture.
|
|
65
|
+
*/
|
|
66
|
+
get firestore() {
|
|
67
|
+
return this.appFixture.get(Firestore);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns the (temporary) collection for the given document type.
|
|
71
|
+
*
|
|
72
|
+
* @param documentType The type of the document.
|
|
73
|
+
* @returns The {@link CollectionReference} for the given document type.
|
|
74
|
+
*/
|
|
75
|
+
collection(documentType) {
|
|
76
|
+
return this.appFixture.get(getFirestoreCollectionInjectionName(documentType));
|
|
77
|
+
}
|
|
62
78
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { User } from '@causa/runtime';
|
|
2
|
+
import type { AppFixture, Fixture } from '@causa/runtime/nestjs/testing';
|
|
2
3
|
import { Auth } from 'firebase-admin/auth';
|
|
3
4
|
import jwt from 'jsonwebtoken';
|
|
4
5
|
/**
|
|
5
|
-
* A
|
|
6
|
+
* A {@link Fixture} to create and delete Identity Platform users in the emulator.
|
|
6
7
|
* It also creates an ID token for them.
|
|
7
8
|
*/
|
|
8
|
-
export declare class AuthUsersFixture {
|
|
9
|
+
export declare class AuthUsersFixture implements Fixture {
|
|
9
10
|
/**
|
|
10
|
-
* The
|
|
11
|
+
* The parent {@link AppFixture}.
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
+
private appFixture;
|
|
13
14
|
/**
|
|
14
15
|
* The list of created users.
|
|
15
16
|
*/
|
|
@@ -18,10 +19,21 @@ export declare class AuthUsersFixture {
|
|
|
18
19
|
* The base payload required to form a JWT.
|
|
19
20
|
*/
|
|
20
21
|
private readonly jwtBasePayload;
|
|
22
|
+
/**
|
|
23
|
+
* The Firebase Auth client to use.
|
|
24
|
+
* This is lazily initialized when the `auth` property is accessed, which avoids trying to fetch it during
|
|
25
|
+
* {@link AuthUsersFixture.init} and / or {@link AuthUsersFixture.delete}.
|
|
26
|
+
*/
|
|
27
|
+
private lazyAuth?;
|
|
21
28
|
/**
|
|
22
29
|
* Creates a new {@link AuthUsersFixture}.
|
|
23
30
|
*/
|
|
24
31
|
constructor();
|
|
32
|
+
init(appFixture: AppFixture): Promise<undefined>;
|
|
33
|
+
/**
|
|
34
|
+
* The Firebase Auth client to use.
|
|
35
|
+
*/
|
|
36
|
+
get auth(): Auth;
|
|
25
37
|
/**
|
|
26
38
|
* Creates a new user if it doesn't already exist, and generates a corresponding JWT.
|
|
27
39
|
*
|
|
@@ -33,8 +45,11 @@ export declare class AuthUsersFixture {
|
|
|
33
45
|
user: User;
|
|
34
46
|
token: string;
|
|
35
47
|
}>;
|
|
48
|
+
clear(): Promise<void>;
|
|
36
49
|
/**
|
|
37
|
-
* Deletes users created by this fixture
|
|
50
|
+
* Deletes all users created by this fixture.
|
|
51
|
+
* This does not delete the fixture itself.
|
|
38
52
|
*/
|
|
39
|
-
|
|
53
|
+
deleteUsers(): Promise<void>;
|
|
54
|
+
delete(): Promise<void>;
|
|
40
55
|
}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { Auth
|
|
1
|
+
import { Auth } from 'firebase-admin/auth';
|
|
2
2
|
import jwt from 'jsonwebtoken';
|
|
3
3
|
import * as uuid from 'uuid';
|
|
4
|
-
import { getDefaultFirebaseApp } from '../firebase/index.js';
|
|
5
4
|
/**
|
|
6
|
-
* A
|
|
5
|
+
* A {@link Fixture} to create and delete Identity Platform users in the emulator.
|
|
7
6
|
* It also creates an ID token for them.
|
|
8
7
|
*/
|
|
9
8
|
export class AuthUsersFixture {
|
|
10
9
|
/**
|
|
11
|
-
* The
|
|
10
|
+
* The parent {@link AppFixture}.
|
|
12
11
|
*/
|
|
13
|
-
|
|
12
|
+
appFixture;
|
|
14
13
|
/**
|
|
15
14
|
* The list of created users.
|
|
16
15
|
*/
|
|
@@ -19,17 +18,34 @@ export class AuthUsersFixture {
|
|
|
19
18
|
* The base payload required to form a JWT.
|
|
20
19
|
*/
|
|
21
20
|
jwtBasePayload;
|
|
21
|
+
/**
|
|
22
|
+
* The Firebase Auth client to use.
|
|
23
|
+
* This is lazily initialized when the `auth` property is accessed, which avoids trying to fetch it during
|
|
24
|
+
* {@link AuthUsersFixture.init} and / or {@link AuthUsersFixture.delete}.
|
|
25
|
+
*/
|
|
26
|
+
lazyAuth;
|
|
22
27
|
/**
|
|
23
28
|
* Creates a new {@link AuthUsersFixture}.
|
|
24
29
|
*/
|
|
25
30
|
constructor() {
|
|
26
|
-
this.auth = getAuth(getDefaultFirebaseApp());
|
|
27
31
|
const projectId = process.env.GOOGLE_CLOUD_PROJECT ?? '';
|
|
28
32
|
this.jwtBasePayload = {
|
|
29
33
|
aud: projectId,
|
|
30
34
|
iss: `https://securetoken.google.com/${projectId}`,
|
|
31
35
|
};
|
|
32
36
|
}
|
|
37
|
+
async init(appFixture) {
|
|
38
|
+
this.appFixture = appFixture;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The Firebase Auth client to use.
|
|
42
|
+
*/
|
|
43
|
+
get auth() {
|
|
44
|
+
if (!this.lazyAuth) {
|
|
45
|
+
this.lazyAuth = this.appFixture.get(Auth);
|
|
46
|
+
}
|
|
47
|
+
return this.lazyAuth;
|
|
48
|
+
}
|
|
33
49
|
/**
|
|
34
50
|
* Creates a new user if it doesn't already exist, and generates a corresponding JWT.
|
|
35
51
|
*
|
|
@@ -52,11 +68,20 @@ export class AuthUsersFixture {
|
|
|
52
68
|
const token = jwt.sign({ ...this.jwtBasePayload, sub: user.id, ...customClaims }, null, { ...tokenOptions, algorithm: 'none' });
|
|
53
69
|
return { user, token };
|
|
54
70
|
}
|
|
71
|
+
async clear() { }
|
|
55
72
|
/**
|
|
56
|
-
* Deletes users created by this fixture
|
|
73
|
+
* Deletes all users created by this fixture.
|
|
74
|
+
* This does not delete the fixture itself.
|
|
57
75
|
*/
|
|
58
|
-
async
|
|
59
|
-
|
|
76
|
+
async deleteUsers() {
|
|
77
|
+
if (this.users.length === 0) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
await this.auth.deleteUsers(this.users.map(({ id }) => id));
|
|
60
81
|
this.users.length = 0;
|
|
61
82
|
}
|
|
83
|
+
async delete() {
|
|
84
|
+
await this.deleteUsers();
|
|
85
|
+
this.appFixture = undefined;
|
|
86
|
+
}
|
|
62
87
|
}
|
|
@@ -14,5 +14,5 @@ export declare class PubSubPublisherModule {
|
|
|
14
14
|
* @param options Options for the {@link PubSubPublisher}.
|
|
15
15
|
* @returns The module.
|
|
16
16
|
*/
|
|
17
|
-
static forRoot(options?:
|
|
17
|
+
static forRoot(options?: Omit<PubSubPublisherOptions, 'pubSub' | 'configurationGetter'>): DynamicModule;
|
|
18
18
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ObjectSerializer } from '@causa/runtime';
|
|
2
|
-
import type { NestJsModuleOverrider } from '@causa/runtime/nestjs/testing';
|
|
2
|
+
import type { AppFixture, EventFixture, Fixture, NestJsModuleOverrider } from '@causa/runtime/nestjs/testing';
|
|
3
3
|
import { PubSub, Subscription, Topic } from '@google-cloud/pubsub';
|
|
4
|
-
import type
|
|
4
|
+
import { type Type } from '@nestjs/common';
|
|
5
5
|
/**
|
|
6
6
|
* A received Pub/Sub message that was deserialized.
|
|
7
7
|
*/
|
|
@@ -20,27 +20,51 @@ export type ReceivedPubSubEvent = {
|
|
|
20
20
|
event: any;
|
|
21
21
|
};
|
|
22
22
|
/**
|
|
23
|
-
* Options for the {@link PubSubFixture.
|
|
23
|
+
* Options for the {@link PubSubFixture.expectMessage} method.
|
|
24
24
|
*/
|
|
25
|
-
type
|
|
25
|
+
export type ExpectMessageOptions = {
|
|
26
26
|
/**
|
|
27
27
|
* The maximum time (in milliseconds) to wait for a message before giving up.
|
|
28
28
|
* Defaults to `2000`.
|
|
29
29
|
*/
|
|
30
30
|
timeout?: number;
|
|
31
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* Options when making a request to an endpoint handling Pub/Sub events using an {@link EventRequester}.
|
|
34
|
+
*/
|
|
35
|
+
export type EventRequesterOptions = {
|
|
36
|
+
/**
|
|
37
|
+
* The attributes to add to the Pub/Sub message.
|
|
38
|
+
* Using `undefined` values allows removing the attributes set by default.
|
|
39
|
+
*/
|
|
40
|
+
attributes?: Record<string, string | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* The expected status code when making the request.
|
|
43
|
+
* Default is `200`.
|
|
44
|
+
*/
|
|
45
|
+
expectedStatus?: number;
|
|
46
|
+
/**
|
|
47
|
+
* The time to set as the publication time of the Pub/Sub message.
|
|
48
|
+
*/
|
|
49
|
+
publishTime?: Date;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* A function that makes a query to an endpoint handling Pub/Sub events and tests the response.
|
|
53
|
+
*/
|
|
54
|
+
export type EventRequester = (event: object, options?: EventRequesterOptions) => Promise<void>;
|
|
32
55
|
/**
|
|
33
56
|
* A utility class managing temporary Pub/Sub topics and listening to messages published to them.
|
|
34
57
|
*/
|
|
35
|
-
export declare class PubSubFixture {
|
|
58
|
+
export declare class PubSubFixture implements Fixture, EventFixture {
|
|
59
|
+
private readonly topicsAndTypes;
|
|
36
60
|
/**
|
|
37
|
-
* The
|
|
61
|
+
* The parent {@link AppFixture}.
|
|
38
62
|
*/
|
|
39
|
-
|
|
63
|
+
private appFixture;
|
|
40
64
|
/**
|
|
41
|
-
*
|
|
65
|
+
* The Pub/Sub client to use.
|
|
42
66
|
*/
|
|
43
|
-
|
|
67
|
+
readonly pubSub: PubSub;
|
|
44
68
|
/**
|
|
45
69
|
* The (de)serializer to use for Pub/Sub messages.
|
|
46
70
|
*/
|
|
@@ -49,7 +73,7 @@ export declare class PubSubFixture {
|
|
|
49
73
|
* The dictionary of monitored temporary topics.
|
|
50
74
|
* The key is the name of the event topic (not broker-specific).
|
|
51
75
|
*/
|
|
52
|
-
readonly
|
|
76
|
+
readonly topics: Record<string, {
|
|
53
77
|
/**
|
|
54
78
|
* The created temporary Pub/Sub topic.
|
|
55
79
|
*/
|
|
@@ -66,13 +90,10 @@ export declare class PubSubFixture {
|
|
|
66
90
|
/**
|
|
67
91
|
* Creates a new {@link PubSubFixture}.
|
|
68
92
|
*
|
|
93
|
+
* @param topicsAndTypes The dictionary of topics to test and their event types.
|
|
69
94
|
* @param options Options for the fixture.
|
|
70
95
|
*/
|
|
71
|
-
constructor(options?: {
|
|
72
|
-
/**
|
|
73
|
-
* The Pub/Sub client to use.
|
|
74
|
-
*/
|
|
75
|
-
pubSub?: PubSub;
|
|
96
|
+
constructor(topicsAndTypes: Record<string, Type>, options?: {
|
|
76
97
|
/**
|
|
77
98
|
* The (de)serializer to use for Pub/Sub messages.
|
|
78
99
|
*/
|
|
@@ -81,44 +102,46 @@ export declare class PubSubFixture {
|
|
|
81
102
|
/**
|
|
82
103
|
* Creates a new temporary topic and starts listening to messages published to it.
|
|
83
104
|
*
|
|
84
|
-
* @param
|
|
105
|
+
* @param sourceTopic The original name of the topic, i.e. the one used in production.
|
|
85
106
|
* @param eventType The type of the event published to the topic, used for deserialization.
|
|
86
107
|
* @returns The configuration key and value for the created temporary topic.
|
|
87
108
|
*/
|
|
88
|
-
create
|
|
89
|
-
|
|
90
|
-
* Creates several temporary topics and returns the configuration (environment variables) for the
|
|
91
|
-
*
|
|
92
|
-
* @param topicsAndTypes A dictionary of topics and their corresponding event types.
|
|
93
|
-
* @returns The configuration for Pub/Sub topics, with the IDs of the created topics.
|
|
94
|
-
*/
|
|
95
|
-
createMany(topicsAndTypes: Record<string, Type>): Promise<Record<string, string>>;
|
|
109
|
+
private create;
|
|
110
|
+
init(appFixture: AppFixture): Promise<NestJsModuleOverrider>;
|
|
96
111
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
112
|
+
* Creates an {@link EventRequester} for an endpoint handling Pub/Sub messages.
|
|
113
|
+
* If the `event` passed to the {@link EventRequester} conforms to the `Event` interface (if it has `producedAt`,
|
|
114
|
+
* `name` and / or `id` properties), the default attributes are set in the Pub/Sub message. Default attributes can be
|
|
115
|
+
* overridden (or removed by passing `undefined`) using {@link EventRequesterOptions.attributes}.
|
|
99
116
|
*
|
|
100
|
-
* @param
|
|
101
|
-
* @
|
|
117
|
+
* @param endpoint The endpoint to query.
|
|
118
|
+
* @param options Options when creating the requester.
|
|
119
|
+
* @returns The {@link EventRequester}.
|
|
102
120
|
*/
|
|
103
|
-
|
|
121
|
+
makeRequester(endpoint: string, options?: {
|
|
122
|
+
/**
|
|
123
|
+
* The default expected status code when making a request.
|
|
124
|
+
*/
|
|
125
|
+
expectedStatus?: number;
|
|
126
|
+
}): EventRequester;
|
|
104
127
|
/**
|
|
105
128
|
* Checks that the given message has been published to the specified topic.
|
|
106
129
|
*
|
|
107
|
-
* @param
|
|
130
|
+
* @param topic The original name of the event topic.
|
|
108
131
|
* @param expectedMessage The message expected to have been published.
|
|
109
132
|
* This can be an `expect` expression, e.g. `expect.objectContaining({})`.
|
|
110
133
|
* @param options Options for the expectation.
|
|
111
134
|
*/
|
|
112
|
-
|
|
135
|
+
expectMessage(topic: string, expectedMessage: any, options?: ExpectMessageOptions): Promise<void>;
|
|
113
136
|
/**
|
|
114
|
-
* Uses {@link PubSubFixture.
|
|
137
|
+
* Uses {@link PubSubFixture.expectMessage} to check that the given event has been published to the specified
|
|
115
138
|
* topic. The `expectedEvent` is the payload of the message, i.e. the `event` property.
|
|
116
139
|
*
|
|
117
|
-
* @param
|
|
140
|
+
* @param topic The original name of the event topic.
|
|
118
141
|
* @param expectedEvent The event expected to have been published.
|
|
119
142
|
* @param options Options for the expectation.
|
|
120
143
|
*/
|
|
121
|
-
|
|
144
|
+
expectEvent(topic: string, expectedEvent: any, options?: ExpectMessageOptions & {
|
|
122
145
|
/**
|
|
123
146
|
* The attributes expected to have been published with the event.
|
|
124
147
|
* This may contain only a subset of the attributes.
|
|
@@ -130,29 +153,22 @@ export declare class PubSubFixture {
|
|
|
130
153
|
* By default, because publishing (and receiving) the messages is asynchronous, a small delay is added before checking
|
|
131
154
|
* that no message has been received. This delay can be removed or increased by passing the `delay` option.
|
|
132
155
|
*
|
|
133
|
-
* @param
|
|
156
|
+
* @param topic The original name of the topic, i.e. the one used in production.
|
|
134
157
|
* @param options Options for the expectation.
|
|
135
158
|
*/
|
|
136
|
-
|
|
159
|
+
expectNoMessage(topic: string, options?: {
|
|
137
160
|
/**
|
|
138
161
|
* The delay (in milliseconds) before checking that no message has been received.
|
|
139
162
|
*/
|
|
140
163
|
delay?: number;
|
|
141
164
|
}): Promise<void>;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
*/
|
|
145
|
-
clear(): void;
|
|
165
|
+
expectNoEvent(topic: string): Promise<void>;
|
|
166
|
+
clear(): Promise<void>;
|
|
146
167
|
/**
|
|
147
168
|
* Deletes the temporary topic for the corresponding "production" topic.
|
|
148
169
|
*
|
|
149
|
-
* @param
|
|
150
|
-
*/
|
|
151
|
-
delete(sourceTopicName: string): Promise<void>;
|
|
152
|
-
/**
|
|
153
|
-
* Deletes all previously created temporary topics.
|
|
154
|
-
* If the Pub/Sub client was managed by the fixture (it wasn't passed as an option), it is also closed.
|
|
170
|
+
* @param topic The original name of the topic, i.e. the one used in production.
|
|
155
171
|
*/
|
|
156
|
-
|
|
172
|
+
deleteTopic(topic: string): Promise<void>;
|
|
173
|
+
delete(): Promise<void>;
|
|
157
174
|
}
|
|
158
|
-
export {};
|