@causa/runtime-google 0.39.1 → 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/module.d.ts +14 -2
- package/dist/firebase/module.js +45 -16
- 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 +37 -34
- 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
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import type { VersionedEntity } from '@causa/runtime';
|
|
2
|
-
import { type MakeTestAppFactoryOptions } from '@causa/runtime/nestjs/testing';
|
|
3
|
-
import { Database, Spanner } from '@google-cloud/spanner';
|
|
4
|
-
import type { INestApplication, NestApplicationOptions, Type } from '@nestjs/common';
|
|
5
|
-
import { CollectionReference } from 'firebase-admin/firestore';
|
|
6
|
-
import { Test } from 'supertest';
|
|
7
|
-
import TestAgent from 'supertest/lib/agent.js';
|
|
8
|
-
import { AuthUsersFixture } from '../identity-platform/testing.js';
|
|
9
|
-
import { type EventRequester, PubSubFixture } from '../pubsub/testing/index.js';
|
|
10
|
-
import { SpannerEntityManager, type SpannerKey } from '../spanner/index.js';
|
|
11
|
-
/**
|
|
12
|
-
* Describes an entity to fetch using the {@link SpannerEntityManager}.
|
|
13
|
-
* Used by expect methods in {@link GoogleAppFixture}.
|
|
14
|
-
*/
|
|
15
|
-
type EntityToFetch<T extends object> = {
|
|
16
|
-
/**
|
|
17
|
-
* The type of entity to fetch.
|
|
18
|
-
*/
|
|
19
|
-
type: Type<T>;
|
|
20
|
-
/**
|
|
21
|
-
* The ID of the entity to fetch.
|
|
22
|
-
*/
|
|
23
|
-
id: string | SpannerKey;
|
|
24
|
-
/**
|
|
25
|
-
* Whether to include soft-deleted results when fetching the entity.
|
|
26
|
-
* See {@link SpannerEntityManager.findOneByKeyOrFail} options.
|
|
27
|
-
*/
|
|
28
|
-
includeSoftDeletes?: boolean;
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* Describes tests to run on a versioned entity stored in Spanner.
|
|
32
|
-
*/
|
|
33
|
-
type VersionedEntityTests<T extends object> = {
|
|
34
|
-
/**
|
|
35
|
-
* The expected entity after mutation.
|
|
36
|
-
* It is checked against the actual entity in the database using `toEqual`, which means it can contain matchers.
|
|
37
|
-
* A function can be provided to generate the expected entity from the actual entity.
|
|
38
|
-
*/
|
|
39
|
-
expectedEntity: ((actual: T) => T) | T;
|
|
40
|
-
/**
|
|
41
|
-
* If set, checks that an event has been published to the corresponding Pub/Sub topic with the entity as `data`.
|
|
42
|
-
*/
|
|
43
|
-
expectedEvent?: {
|
|
44
|
-
/**
|
|
45
|
-
* The name of the topic.
|
|
46
|
-
*/
|
|
47
|
-
topic: string;
|
|
48
|
-
/**
|
|
49
|
-
* The `name` of the expected published event.
|
|
50
|
-
*/
|
|
51
|
-
name: string;
|
|
52
|
-
/**
|
|
53
|
-
* Attributes expected to have been set on the published event.
|
|
54
|
-
*/
|
|
55
|
-
attributes?: Record<string, string>;
|
|
56
|
-
};
|
|
57
|
-
/**
|
|
58
|
-
* If set, the passed object is checked to be equal to a "plain object" (e.g. with `Date`s converted to `string`s)
|
|
59
|
-
* version of the fetched entity.
|
|
60
|
-
* This can contain a parsed HTTP response body which is expected to return the entity.
|
|
61
|
-
*
|
|
62
|
-
* {@link serializeAsJavaScriptObject} is used to serialize the fetched entity.
|
|
63
|
-
*/
|
|
64
|
-
matchesHttpResponse?: object;
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* A fixture for testing a NestJS application that uses Google Cloud Platform services.
|
|
68
|
-
*
|
|
69
|
-
* It manages the setup and teardown of resources in GCP emulators, and provides utilities for testing versioned
|
|
70
|
-
* entities.
|
|
71
|
-
*/
|
|
72
|
-
export declare class GoogleAppFixture {
|
|
73
|
-
readonly app: INestApplication;
|
|
74
|
-
readonly spanner: Spanner;
|
|
75
|
-
readonly database: Database;
|
|
76
|
-
readonly entityManager: SpannerEntityManager;
|
|
77
|
-
readonly pubSub: PubSubFixture;
|
|
78
|
-
readonly users: AuthUsersFixture;
|
|
79
|
-
readonly request: TestAgent<Test>;
|
|
80
|
-
readonly pubSubRequest: EventRequester;
|
|
81
|
-
readonly entities: Type[];
|
|
82
|
-
readonly firestoreDocuments: Type[];
|
|
83
|
-
/**
|
|
84
|
-
* Creates a new {@link GoogleAppFixture} instance.
|
|
85
|
-
*
|
|
86
|
-
* @param app The NestJS application.
|
|
87
|
-
* @param spanner The {@link Spanner} client managed by the fixture.
|
|
88
|
-
* @param database The temporary Spanner database.
|
|
89
|
-
* @param entityManager The {@link SpannerEntityManager} for the temporary database.
|
|
90
|
-
* @param pubSub The {@link PubSubFixture} managing temporary topics.
|
|
91
|
-
* @param users The {@link AuthUsersFixture}.
|
|
92
|
-
* @param request The {@link SuperTest} instance for the NestJS application.
|
|
93
|
-
* @param pubSubRequest The {@link EventRequester} to make requests to Pub/Sub push endpoints in the application.
|
|
94
|
-
* @param entities The entities to clear from the database when calling {@link GoogleAppFixture.clear}.
|
|
95
|
-
* @param firestoreDocuments The Firestore documents to clear when calling {@link GoogleAppFixture.clear}.
|
|
96
|
-
*/
|
|
97
|
-
private constructor();
|
|
98
|
-
/**
|
|
99
|
-
* Returns the temporary Firestore collection (as set up by the fixture) for a given document type.
|
|
100
|
-
*
|
|
101
|
-
* @param document The type of document to get the collection for.
|
|
102
|
-
* @returns The Firestore collection.
|
|
103
|
-
*/
|
|
104
|
-
firestoreCollection<T>(document: Type<T>): CollectionReference<T>;
|
|
105
|
-
/**
|
|
106
|
-
* Runs a test on a versioned entity, checking that it has been mutated as expected.
|
|
107
|
-
* Optionally, checks that an event has been published to the corresponding Pub/Sub topic.
|
|
108
|
-
* Also, a serialized version of the entity (e.g. an HTTP response) can be checked against the expected entity.
|
|
109
|
-
*
|
|
110
|
-
* @param entity Describes the entity to fetch using the {@link SpannerEntityManager}.
|
|
111
|
-
* @param tests The tests to run on the entity and its event.
|
|
112
|
-
* @returns The entity fetched from the database.
|
|
113
|
-
*/
|
|
114
|
-
expectMutatedVersionedEntity<T extends Pick<VersionedEntity, 'updatedAt'>>(entity: EntityToFetch<T>, tests: VersionedEntityTests<T>): Promise<T>;
|
|
115
|
-
/**
|
|
116
|
-
* Ensures the specified entity has not been mutated.
|
|
117
|
-
* Optionally, checks that no event has been published to the corresponding Pub/Sub topic.
|
|
118
|
-
* Also, a serialized version of the entity (e.g. an HTTP response) can be checked against the expected entity.
|
|
119
|
-
*
|
|
120
|
-
* @param entity Describes the entity to fetch using the {@link SpannerEntityManager}.
|
|
121
|
-
* @param tests The tests to run on the entity.
|
|
122
|
-
*/
|
|
123
|
-
expectNonMutatedVersionedEntity<T extends Pick<VersionedEntity, 'updatedAt'>>(entity: EntityToFetch<T>, tests: Omit<VersionedEntityTests<T>, 'expectedEvent'> & {
|
|
124
|
-
expectedEntity: object;
|
|
125
|
-
/**
|
|
126
|
-
* If set, checks that no event has been published to the corresponding Pub/Sub topic.
|
|
127
|
-
*/
|
|
128
|
-
expectNoEventInTopic?: string;
|
|
129
|
-
}): Promise<void>;
|
|
130
|
-
/**
|
|
131
|
-
* Clears all entities from the test database.
|
|
132
|
-
*
|
|
133
|
-
* The tables to clear should be specified in the `entities` property of the options passed to
|
|
134
|
-
* {@link GoogleAppFixture.create}.
|
|
135
|
-
*/
|
|
136
|
-
clearSpanner(): Promise<void>;
|
|
137
|
-
/**
|
|
138
|
-
* Clears all documents from the test Firestore collections.
|
|
139
|
-
*
|
|
140
|
-
* The collections to clear should be specified in the `firestoreDocuments` property of the options passed to
|
|
141
|
-
* {@link GoogleAppFixture.create}.
|
|
142
|
-
*/
|
|
143
|
-
clearFirestore(): Promise<void>;
|
|
144
|
-
/**
|
|
145
|
-
* Clears all entities from the test database and all documents from the test Firestore collections.
|
|
146
|
-
* Also clears all messages read from the test Pub/Sub topics up to now.
|
|
147
|
-
*
|
|
148
|
-
* This does **not** delete Identity Platform users, which are only deleted when calling {
|
|
149
|
-
* @link GoogleAppFixture.delete}.
|
|
150
|
-
*/
|
|
151
|
-
clear(): Promise<void>;
|
|
152
|
-
/**
|
|
153
|
-
* Deletes all resources created by the fixture.
|
|
154
|
-
*/
|
|
155
|
-
delete(): Promise<void>;
|
|
156
|
-
/**
|
|
157
|
-
* Creates a NestJS application using the specified module, and sets up the fixture.
|
|
158
|
-
*
|
|
159
|
-
* @param appModule The NestJS module to create the application from.
|
|
160
|
-
* @param options Options when creating the GCP resources for the fixture.
|
|
161
|
-
* @returns The {@link GoogleAppFixture}.
|
|
162
|
-
*/
|
|
163
|
-
static create(appModule: any, options?: {
|
|
164
|
-
/**
|
|
165
|
-
* Temporary Pub/Sub topics to create using the {@link PubSubFixture}.
|
|
166
|
-
*/
|
|
167
|
-
pubSubTopics?: Record<string, Type>;
|
|
168
|
-
/**
|
|
169
|
-
* Temporary Firestore collections to create and to clear during teardown.
|
|
170
|
-
*/
|
|
171
|
-
firestoreDocuments?: Type[];
|
|
172
|
-
/**
|
|
173
|
-
* Spanner entities to clear during teardown.
|
|
174
|
-
*/
|
|
175
|
-
entities?: Type[];
|
|
176
|
-
/**
|
|
177
|
-
* Options for the {@link makeTestAppFactory} function.
|
|
178
|
-
*/
|
|
179
|
-
appFactoryOptions?: MakeTestAppFactoryOptions;
|
|
180
|
-
/**
|
|
181
|
-
* Options passed to the NestJS application factory.
|
|
182
|
-
*/
|
|
183
|
-
nestApplicationOptions?: NestApplicationOptions;
|
|
184
|
-
/**
|
|
185
|
-
* Whether the `AppCheckGuard` should be disabled.
|
|
186
|
-
* Defaults to `true`.
|
|
187
|
-
*/
|
|
188
|
-
disableAppCheck?: boolean;
|
|
189
|
-
}): Promise<GoogleAppFixture>;
|
|
190
|
-
}
|
|
191
|
-
export {};
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { createApp } from '@causa/runtime/nestjs';
|
|
2
|
-
import { makeTestAppFactory, } from '@causa/runtime/nestjs/testing';
|
|
3
|
-
import { serializeAsJavaScriptObject } from '@causa/runtime/testing';
|
|
4
|
-
import { Database, Spanner } from '@google-cloud/spanner';
|
|
5
|
-
import { CollectionReference } from 'firebase-admin/firestore';
|
|
6
|
-
import supertest, { Test } from 'supertest';
|
|
7
|
-
import TestAgent from 'supertest/lib/agent.js';
|
|
8
|
-
import { overrideAppCheck } from '../app-check/testing.js';
|
|
9
|
-
import { overrideFirebaseApp } from '../firebase/testing.js';
|
|
10
|
-
import { clearFirestoreCollection, getFirestoreCollectionFromModule, overrideFirestoreCollections, } from '../firestore/testing.js';
|
|
11
|
-
import { AuthUsersFixture } from '../identity-platform/testing.js';
|
|
12
|
-
import { PubSubFixture, makePubSubRequester, } from '../pubsub/testing/index.js';
|
|
13
|
-
import { SpannerEntityManager } from '../spanner/index.js';
|
|
14
|
-
import { createDatabase, overrideDatabase } from '../spanner/testing.js';
|
|
15
|
-
/**
|
|
16
|
-
* A fixture for testing a NestJS application that uses Google Cloud Platform services.
|
|
17
|
-
*
|
|
18
|
-
* It manages the setup and teardown of resources in GCP emulators, and provides utilities for testing versioned
|
|
19
|
-
* entities.
|
|
20
|
-
*/
|
|
21
|
-
export class GoogleAppFixture {
|
|
22
|
-
app;
|
|
23
|
-
spanner;
|
|
24
|
-
database;
|
|
25
|
-
entityManager;
|
|
26
|
-
pubSub;
|
|
27
|
-
users;
|
|
28
|
-
request;
|
|
29
|
-
pubSubRequest;
|
|
30
|
-
entities;
|
|
31
|
-
firestoreDocuments;
|
|
32
|
-
/**
|
|
33
|
-
* Creates a new {@link GoogleAppFixture} instance.
|
|
34
|
-
*
|
|
35
|
-
* @param app The NestJS application.
|
|
36
|
-
* @param spanner The {@link Spanner} client managed by the fixture.
|
|
37
|
-
* @param database The temporary Spanner database.
|
|
38
|
-
* @param entityManager The {@link SpannerEntityManager} for the temporary database.
|
|
39
|
-
* @param pubSub The {@link PubSubFixture} managing temporary topics.
|
|
40
|
-
* @param users The {@link AuthUsersFixture}.
|
|
41
|
-
* @param request The {@link SuperTest} instance for the NestJS application.
|
|
42
|
-
* @param pubSubRequest The {@link EventRequester} to make requests to Pub/Sub push endpoints in the application.
|
|
43
|
-
* @param entities The entities to clear from the database when calling {@link GoogleAppFixture.clear}.
|
|
44
|
-
* @param firestoreDocuments The Firestore documents to clear when calling {@link GoogleAppFixture.clear}.
|
|
45
|
-
*/
|
|
46
|
-
constructor(app, spanner, database, entityManager, pubSub, users, request, pubSubRequest, entities, firestoreDocuments) {
|
|
47
|
-
this.app = app;
|
|
48
|
-
this.spanner = spanner;
|
|
49
|
-
this.database = database;
|
|
50
|
-
this.entityManager = entityManager;
|
|
51
|
-
this.pubSub = pubSub;
|
|
52
|
-
this.users = users;
|
|
53
|
-
this.request = request;
|
|
54
|
-
this.pubSubRequest = pubSubRequest;
|
|
55
|
-
this.entities = entities;
|
|
56
|
-
this.firestoreDocuments = firestoreDocuments;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Returns the temporary Firestore collection (as set up by the fixture) for a given document type.
|
|
60
|
-
*
|
|
61
|
-
* @param document The type of document to get the collection for.
|
|
62
|
-
* @returns The Firestore collection.
|
|
63
|
-
*/
|
|
64
|
-
firestoreCollection(document) {
|
|
65
|
-
return getFirestoreCollectionFromModule(this.app, document);
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Runs a test on a versioned entity, checking that it has been mutated as expected.
|
|
69
|
-
* Optionally, checks that an event has been published to the corresponding Pub/Sub topic.
|
|
70
|
-
* Also, a serialized version of the entity (e.g. an HTTP response) can be checked against the expected entity.
|
|
71
|
-
*
|
|
72
|
-
* @param entity Describes the entity to fetch using the {@link SpannerEntityManager}.
|
|
73
|
-
* @param tests The tests to run on the entity and its event.
|
|
74
|
-
* @returns The entity fetched from the database.
|
|
75
|
-
*/
|
|
76
|
-
async expectMutatedVersionedEntity(entity, tests) {
|
|
77
|
-
const storedEntity = await this.entityManager.findOneByKeyOrFail(entity.type, entity.id, { includeSoftDeletes: entity.includeSoftDeletes });
|
|
78
|
-
const expectedEntity = typeof tests.expectedEntity === 'function'
|
|
79
|
-
? tests.expectedEntity(storedEntity)
|
|
80
|
-
: tests.expectedEntity;
|
|
81
|
-
expect(storedEntity).toEqual(expectedEntity);
|
|
82
|
-
const { expectedEvent } = tests;
|
|
83
|
-
if (expectedEvent) {
|
|
84
|
-
await this.pubSub.expectEventInTopic(expectedEvent.topic, {
|
|
85
|
-
id: expect.any(String),
|
|
86
|
-
name: expectedEvent.name,
|
|
87
|
-
producedAt: storedEntity.updatedAt,
|
|
88
|
-
data: storedEntity,
|
|
89
|
-
}, { attributes: expectedEvent.attributes });
|
|
90
|
-
}
|
|
91
|
-
if (tests.matchesHttpResponse) {
|
|
92
|
-
const expectedResponse = await serializeAsJavaScriptObject(storedEntity);
|
|
93
|
-
expect(tests.matchesHttpResponse).toEqual(expectedResponse);
|
|
94
|
-
}
|
|
95
|
-
return storedEntity;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Ensures the specified entity has not been mutated.
|
|
99
|
-
* Optionally, checks that no event has been published to the corresponding Pub/Sub topic.
|
|
100
|
-
* Also, a serialized version of the entity (e.g. an HTTP response) can be checked against the expected entity.
|
|
101
|
-
*
|
|
102
|
-
* @param entity Describes the entity to fetch using the {@link SpannerEntityManager}.
|
|
103
|
-
* @param tests The tests to run on the entity.
|
|
104
|
-
*/
|
|
105
|
-
async expectNonMutatedVersionedEntity(entity, tests) {
|
|
106
|
-
const storedEntity = await this.entityManager.findOneByKeyOrFail(entity.type, entity.id, { includeSoftDeletes: entity.includeSoftDeletes });
|
|
107
|
-
expect(storedEntity).toEqual(tests.expectedEntity);
|
|
108
|
-
if (tests.expectNoEventInTopic) {
|
|
109
|
-
await this.pubSub.expectNoMessageInTopic(tests.expectNoEventInTopic);
|
|
110
|
-
}
|
|
111
|
-
if (tests.matchesHttpResponse) {
|
|
112
|
-
const expectedResponse = await serializeAsJavaScriptObject(storedEntity);
|
|
113
|
-
expect(tests.matchesHttpResponse).toEqual(expectedResponse);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Clears all entities from the test database.
|
|
118
|
-
*
|
|
119
|
-
* The tables to clear should be specified in the `entities` property of the options passed to
|
|
120
|
-
* {@link GoogleAppFixture.create}.
|
|
121
|
-
*/
|
|
122
|
-
async clearSpanner() {
|
|
123
|
-
await this.entityManager.transaction(async (transaction) => {
|
|
124
|
-
for (const entity of this.entities) {
|
|
125
|
-
await this.entityManager.clear(entity, { transaction });
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Clears all documents from the test Firestore collections.
|
|
131
|
-
*
|
|
132
|
-
* The collections to clear should be specified in the `firestoreDocuments` property of the options passed to
|
|
133
|
-
* {@link GoogleAppFixture.create}.
|
|
134
|
-
*/
|
|
135
|
-
async clearFirestore() {
|
|
136
|
-
await Promise.all(this.firestoreDocuments.map((d) => clearFirestoreCollection(this.firestoreCollection(d))));
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Clears all entities from the test database and all documents from the test Firestore collections.
|
|
140
|
-
* Also clears all messages read from the test Pub/Sub topics up to now.
|
|
141
|
-
*
|
|
142
|
-
* This does **not** delete Identity Platform users, which are only deleted when calling {
|
|
143
|
-
* @link GoogleAppFixture.delete}.
|
|
144
|
-
*/
|
|
145
|
-
async clear() {
|
|
146
|
-
this.pubSub.clear();
|
|
147
|
-
await Promise.all([this.clearSpanner(), this.clearFirestore()]);
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Deletes all resources created by the fixture.
|
|
151
|
-
*/
|
|
152
|
-
async delete() {
|
|
153
|
-
await this.app.close();
|
|
154
|
-
await Promise.all([
|
|
155
|
-
this.users.deleteAll(),
|
|
156
|
-
this.pubSub.deleteAll(),
|
|
157
|
-
this.database.delete(),
|
|
158
|
-
]);
|
|
159
|
-
this.spanner.close();
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Creates a NestJS application using the specified module, and sets up the fixture.
|
|
163
|
-
*
|
|
164
|
-
* @param appModule The NestJS module to create the application from.
|
|
165
|
-
* @param options Options when creating the GCP resources for the fixture.
|
|
166
|
-
* @returns The {@link GoogleAppFixture}.
|
|
167
|
-
*/
|
|
168
|
-
static async create(appModule, options = {}) {
|
|
169
|
-
const entities = options.entities ?? [];
|
|
170
|
-
const firestoreDocuments = options.firestoreDocuments ?? [];
|
|
171
|
-
const disableAppCheck = options.disableAppCheck ?? true;
|
|
172
|
-
const spanner = new Spanner();
|
|
173
|
-
const database = await createDatabase({ spanner });
|
|
174
|
-
const entityManager = new SpannerEntityManager(database);
|
|
175
|
-
const pubSubFixture = new PubSubFixture();
|
|
176
|
-
const overridePubSub = await pubSubFixture.createWithOverrider(options.pubSubTopics ?? {});
|
|
177
|
-
const usersFixture = new AuthUsersFixture();
|
|
178
|
-
const appFactoryOptions = options.appFactoryOptions ?? {};
|
|
179
|
-
const additionalOverrides = appFactoryOptions.overrides && !Array.isArray(appFactoryOptions.overrides)
|
|
180
|
-
? [appFactoryOptions.overrides]
|
|
181
|
-
: (appFactoryOptions.overrides ?? []);
|
|
182
|
-
const app = await createApp(appModule, {
|
|
183
|
-
nestApplicationOptions: options.nestApplicationOptions,
|
|
184
|
-
appFactory: makeTestAppFactory({
|
|
185
|
-
...appFactoryOptions,
|
|
186
|
-
overrides: [
|
|
187
|
-
overrideDatabase(database),
|
|
188
|
-
overridePubSub,
|
|
189
|
-
overrideFirebaseApp,
|
|
190
|
-
overrideFirestoreCollections(...firestoreDocuments),
|
|
191
|
-
...(disableAppCheck ? [overrideAppCheck] : []),
|
|
192
|
-
...additionalOverrides,
|
|
193
|
-
],
|
|
194
|
-
}),
|
|
195
|
-
});
|
|
196
|
-
const request = supertest(app.getHttpServer());
|
|
197
|
-
const pubSubRequest = makePubSubRequester(app);
|
|
198
|
-
return new GoogleAppFixture(app, spanner, database, entityManager, pubSubFixture, usersFixture, request, pubSubRequest, entities, firestoreDocuments);
|
|
199
|
-
}
|
|
200
|
-
}
|
package/dist/testing/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { GoogleAppFixture } from './google-app-fixture.js';
|
package/dist/testing/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { GoogleAppFixture } from './google-app-fixture.js';
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { DynamicModule } from '@nestjs/common';
|
|
2
|
-
/**
|
|
3
|
-
* The module exposing the {@link SpannerPubSubTransactionRunner}.
|
|
4
|
-
* This modules assumes that the `SpannerModule` and `PubSubPublisherModule` are available.
|
|
5
|
-
*/
|
|
6
|
-
export declare class SpannerPubSubTransactionModule {
|
|
7
|
-
/**
|
|
8
|
-
* Create a global module that provides the {@link SpannerPubSubTransactionRunner}.
|
|
9
|
-
* This modules assumes that the `SpannerModule` and `PubSubPublisherModule` are available.
|
|
10
|
-
*
|
|
11
|
-
* @returns The module.
|
|
12
|
-
*/
|
|
13
|
-
static forRoot(): DynamicModule;
|
|
14
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { SpannerPubSubTransactionRunner } from './runner.js';
|
|
2
|
-
/**
|
|
3
|
-
* The module exposing the {@link SpannerPubSubTransactionRunner}.
|
|
4
|
-
* This modules assumes that the `SpannerModule` and `PubSubPublisherModule` are available.
|
|
5
|
-
*/
|
|
6
|
-
export class SpannerPubSubTransactionModule {
|
|
7
|
-
/**
|
|
8
|
-
* Create a global module that provides the {@link SpannerPubSubTransactionRunner}.
|
|
9
|
-
* This modules assumes that the `SpannerModule` and `PubSubPublisherModule` are available.
|
|
10
|
-
*
|
|
11
|
-
* @returns The module.
|
|
12
|
-
*/
|
|
13
|
-
static forRoot() {
|
|
14
|
-
return {
|
|
15
|
-
module: SpannerPubSubTransactionModule,
|
|
16
|
-
global: true,
|
|
17
|
-
providers: [SpannerPubSubTransactionRunner],
|
|
18
|
-
exports: [SpannerPubSubTransactionRunner],
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { TransactionRunner } from '@causa/runtime';
|
|
2
|
-
import { Logger } from '@causa/runtime/nestjs';
|
|
3
|
-
import { PubSubPublisher } from '../../pubsub/index.js';
|
|
4
|
-
import { SpannerEntityManager } from '../../spanner/index.js';
|
|
5
|
-
import { SpannerTransaction } from '../spanner-transaction.js';
|
|
6
|
-
/**
|
|
7
|
-
* A {@link TransactionRunner} that uses Spanner for state and Pub/Sub for events.
|
|
8
|
-
* A Spanner transaction is used as the main transaction. If it succeeds, events are published to Pub/Sub outside of it.
|
|
9
|
-
*/
|
|
10
|
-
export declare class SpannerPubSubTransactionRunner extends TransactionRunner<SpannerTransaction> {
|
|
11
|
-
readonly entityManager: SpannerEntityManager;
|
|
12
|
-
readonly publisher: PubSubPublisher;
|
|
13
|
-
private readonly logger;
|
|
14
|
-
/**
|
|
15
|
-
* Creates a new {@link SpannerPubSubTransactionRunner}.
|
|
16
|
-
*
|
|
17
|
-
* @param entityManager The {@link SpannerEntityManager} to use for the transaction.
|
|
18
|
-
* @param publisher The {@link PubSubPublisher} to use for the transaction.
|
|
19
|
-
* @param logger The {@link Logger} to use.
|
|
20
|
-
*/
|
|
21
|
-
constructor(entityManager: SpannerEntityManager, publisher: PubSubPublisher, logger: Logger);
|
|
22
|
-
run<T>(runFn: (transaction: SpannerTransaction) => Promise<T>): Promise<[T]>;
|
|
23
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
};
|
|
10
|
-
var SpannerPubSubTransactionRunner_1;
|
|
11
|
-
import { BufferEventTransaction, TransactionRunner } from '@causa/runtime';
|
|
12
|
-
import { Logger } from '@causa/runtime/nestjs';
|
|
13
|
-
import { Injectable } from '@nestjs/common';
|
|
14
|
-
import { PubSubPublisher } from '../../pubsub/index.js';
|
|
15
|
-
import { SpannerEntityManager } from '../../spanner/index.js';
|
|
16
|
-
import { SpannerStateTransaction } from '../spanner-state-transaction.js';
|
|
17
|
-
import { SpannerTransaction } from '../spanner-transaction.js';
|
|
18
|
-
import { throwRetryableInTransactionIfNeeded } from '../spanner-utils.js';
|
|
19
|
-
/**
|
|
20
|
-
* A {@link TransactionRunner} that uses Spanner for state and Pub/Sub for events.
|
|
21
|
-
* A Spanner transaction is used as the main transaction. If it succeeds, events are published to Pub/Sub outside of it.
|
|
22
|
-
*/
|
|
23
|
-
let SpannerPubSubTransactionRunner = SpannerPubSubTransactionRunner_1 = class SpannerPubSubTransactionRunner extends TransactionRunner {
|
|
24
|
-
entityManager;
|
|
25
|
-
publisher;
|
|
26
|
-
logger;
|
|
27
|
-
/**
|
|
28
|
-
* Creates a new {@link SpannerPubSubTransactionRunner}.
|
|
29
|
-
*
|
|
30
|
-
* @param entityManager The {@link SpannerEntityManager} to use for the transaction.
|
|
31
|
-
* @param publisher The {@link PubSubPublisher} to use for the transaction.
|
|
32
|
-
* @param logger The {@link Logger} to use.
|
|
33
|
-
*/
|
|
34
|
-
constructor(entityManager, publisher, logger) {
|
|
35
|
-
super();
|
|
36
|
-
this.entityManager = entityManager;
|
|
37
|
-
this.publisher = publisher;
|
|
38
|
-
this.logger = logger;
|
|
39
|
-
this.logger.setContext(SpannerPubSubTransactionRunner_1.name);
|
|
40
|
-
}
|
|
41
|
-
async run(runFn) {
|
|
42
|
-
this.logger.info('Creating a Spanner Pub/Sub transaction.');
|
|
43
|
-
const { result, eventTransaction } = await this.entityManager.transaction(async (dbTransaction) => {
|
|
44
|
-
const stateTransaction = new SpannerStateTransaction(this.entityManager, dbTransaction);
|
|
45
|
-
// This must be inside the Spanner transaction because staged messages should be cleared when the transaction is retried.
|
|
46
|
-
const eventTransaction = new BufferEventTransaction(this.publisher);
|
|
47
|
-
const transaction = new SpannerTransaction(stateTransaction, eventTransaction);
|
|
48
|
-
try {
|
|
49
|
-
const result = await runFn(transaction);
|
|
50
|
-
this.logger.info('Committing the Spanner transaction.');
|
|
51
|
-
return { result, eventTransaction };
|
|
52
|
-
}
|
|
53
|
-
catch (error) {
|
|
54
|
-
await throwRetryableInTransactionIfNeeded(error);
|
|
55
|
-
throw error;
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
this.logger.info('Publishing Pub/Sub events.');
|
|
59
|
-
await eventTransaction.commit();
|
|
60
|
-
return [result];
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
SpannerPubSubTransactionRunner = SpannerPubSubTransactionRunner_1 = __decorate([
|
|
64
|
-
Injectable(),
|
|
65
|
-
__metadata("design:paramtypes", [SpannerEntityManager,
|
|
66
|
-
PubSubPublisher,
|
|
67
|
-
Logger])
|
|
68
|
-
], SpannerPubSubTransactionRunner);
|
|
69
|
-
export { SpannerPubSubTransactionRunner };
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { FindReplaceStateTransaction } from '@causa/runtime';
|
|
2
|
-
import type { Type } from '@nestjs/common';
|
|
3
|
-
import { SpannerEntityManager, type SpannerReadWriteTransaction } from '../spanner/index.js';
|
|
4
|
-
/**
|
|
5
|
-
* A {@link FindReplaceStateTransaction} that uses Spanner for state storage.
|
|
6
|
-
*/
|
|
7
|
-
export declare class SpannerStateTransaction implements FindReplaceStateTransaction {
|
|
8
|
-
readonly entityManager: SpannerEntityManager;
|
|
9
|
-
readonly transaction: SpannerReadWriteTransaction;
|
|
10
|
-
/**
|
|
11
|
-
* Creates a new {@link SpannerStateTransaction}.
|
|
12
|
-
*
|
|
13
|
-
* @param entityManager The {@link SpannerEntityManager} to use to access entities in the state.
|
|
14
|
-
* @param transaction The {@link SpannerReadWriteTransaction} to use for the transaction.
|
|
15
|
-
*/
|
|
16
|
-
constructor(entityManager: SpannerEntityManager, transaction: SpannerReadWriteTransaction);
|
|
17
|
-
replace<T extends object>(entity: T): Promise<void>;
|
|
18
|
-
deleteWithSameKeyAs<T extends object>(type: Type<T>, key: Partial<T>): Promise<void>;
|
|
19
|
-
findOneWithSameKeyAs<T extends object>(type: Type<T>, entity: Partial<T>): Promise<T | undefined>;
|
|
20
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { SpannerEntityManager, } from '../spanner/index.js';
|
|
2
|
-
/**
|
|
3
|
-
* A {@link FindReplaceStateTransaction} that uses Spanner for state storage.
|
|
4
|
-
*/
|
|
5
|
-
export class SpannerStateTransaction {
|
|
6
|
-
entityManager;
|
|
7
|
-
transaction;
|
|
8
|
-
/**
|
|
9
|
-
* Creates a new {@link SpannerStateTransaction}.
|
|
10
|
-
*
|
|
11
|
-
* @param entityManager The {@link SpannerEntityManager} to use to access entities in the state.
|
|
12
|
-
* @param transaction The {@link SpannerReadWriteTransaction} to use for the transaction.
|
|
13
|
-
*/
|
|
14
|
-
constructor(entityManager, transaction) {
|
|
15
|
-
this.entityManager = entityManager;
|
|
16
|
-
this.transaction = transaction;
|
|
17
|
-
}
|
|
18
|
-
async replace(entity) {
|
|
19
|
-
await this.entityManager.replace(entity, { transaction: this.transaction });
|
|
20
|
-
}
|
|
21
|
-
async deleteWithSameKeyAs(type, key) {
|
|
22
|
-
const primaryKey = this.entityManager.getPrimaryKey(key, type);
|
|
23
|
-
await this.entityManager.delete(type, primaryKey, {
|
|
24
|
-
transaction: this.transaction,
|
|
25
|
-
includeSoftDeletes: true,
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
async findOneWithSameKeyAs(type, entity) {
|
|
29
|
-
const primaryKey = this.entityManager.getPrimaryKey(entity, type);
|
|
30
|
-
return await this.entityManager.findOneByKey(type, primaryKey, {
|
|
31
|
-
transaction: this.transaction,
|
|
32
|
-
includeSoftDeletes: true,
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { type EventTransaction, Transaction } from '@causa/runtime';
|
|
2
|
-
import { SpannerEntityManager, type SpannerReadWriteTransaction } from '../spanner/index.js';
|
|
3
|
-
import { SpannerStateTransaction } from './spanner-state-transaction.js';
|
|
4
|
-
/**
|
|
5
|
-
* A {@link Transaction} that uses Spanner for state storage, and any available {@link EventTransaction} implementation.
|
|
6
|
-
*/
|
|
7
|
-
export declare class SpannerTransaction<ET extends EventTransaction = EventTransaction> extends Transaction<SpannerStateTransaction, ET> {
|
|
8
|
-
/**
|
|
9
|
-
* The underlying {@link SpannerTransaction} used by the state transaction.
|
|
10
|
-
*/
|
|
11
|
-
get spannerTransaction(): SpannerReadWriteTransaction;
|
|
12
|
-
/**
|
|
13
|
-
* The underlying {@link SpannerEntityManager} used by the state transaction.
|
|
14
|
-
*/
|
|
15
|
-
get entityManager(): SpannerEntityManager;
|
|
16
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Transaction } from '@causa/runtime';
|
|
2
|
-
import { SpannerEntityManager, } from '../spanner/index.js';
|
|
3
|
-
import { SpannerStateTransaction } from './spanner-state-transaction.js';
|
|
4
|
-
/**
|
|
5
|
-
* A {@link Transaction} that uses Spanner for state storage, and any available {@link EventTransaction} implementation.
|
|
6
|
-
*/
|
|
7
|
-
export class SpannerTransaction extends Transaction {
|
|
8
|
-
/**
|
|
9
|
-
* The underlying {@link SpannerTransaction} used by the state transaction.
|
|
10
|
-
*/
|
|
11
|
-
get spannerTransaction() {
|
|
12
|
-
return this.stateTransaction.transaction;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* The underlying {@link SpannerEntityManager} used by the state transaction.
|
|
16
|
-
*/
|
|
17
|
-
get entityManager() {
|
|
18
|
-
return this.stateTransaction.entityManager;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
File without changes
|