@causa/workspace-google 0.16.0 → 0.18.0-beta.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 +8 -0
- package/dist/configurations/schemas/google.yaml +37 -70
- package/dist/configurations/schemas/infrastructure.yaml +3 -5
- package/dist/configurations/schemas/service-container.yaml +7 -17
- package/dist/functions/emulator/start-firebase-storage.d.ts +1 -4
- package/dist/functions/emulator/start-firebase-storage.js +8 -11
- package/dist/functions/emulator/start-firestore.d.ts +1 -3
- package/dist/functions/emulator/start-firestore.js +8 -10
- package/dist/functions/emulator/start-identity-platform.d.ts +1 -4
- package/dist/functions/emulator/start-identity-platform.js +7 -10
- package/dist/functions/emulator/start-pubsub.call.d.ts +1 -2
- package/dist/functions/emulator/start-pubsub.call.js +2 -2
- package/dist/functions/emulator/start-pubsub.d.ts +1 -2
- package/dist/functions/emulator/start-pubsub.js +3 -3
- package/dist/functions/emulator/start-spanner.call.d.ts +1 -2
- package/dist/functions/emulator/start-spanner.call.js +2 -2
- package/dist/functions/emulator/start-spanner.d.ts +1 -2
- package/dist/functions/emulator/start-spanner.js +3 -3
- package/dist/functions/emulator/stop-firebase-storage.d.ts +1 -2
- package/dist/functions/emulator/stop-firebase-storage.js +5 -6
- package/dist/functions/emulator/stop-firestore.d.ts +1 -2
- package/dist/functions/emulator/stop-firestore.js +5 -6
- package/dist/functions/emulator/stop-identity-platform.d.ts +1 -2
- package/dist/functions/emulator/stop-identity-platform.js +5 -6
- package/dist/functions/emulator/stop-pubsub.d.ts +1 -2
- package/dist/functions/emulator/stop-pubsub.js +5 -6
- package/dist/functions/emulator/stop-spanner.d.ts +1 -2
- package/dist/functions/emulator/stop-spanner.js +5 -6
- package/dist/functions/event-topic/broker-create-topic-pubsub.call.d.ts +1 -2
- package/dist/functions/event-topic/broker-create-topic-pubsub.call.js +4 -4
- package/dist/functions/event-topic/broker-create-topic-pubsub.d.ts +2 -3
- package/dist/functions/event-topic/broker-create-topic-pubsub.js +7 -6
- package/dist/functions/event-topic/broker-create-trigger-cloud-run.call.d.ts +1 -2
- package/dist/functions/event-topic/broker-create-trigger-cloud-run.call.js +4 -4
- package/dist/functions/event-topic/broker-create-trigger-cloud-run.d.ts +2 -3
- package/dist/functions/event-topic/broker-create-trigger-cloud-run.js +8 -7
- package/dist/functions/event-topic/broker-delete-topic-pubsub.call.d.ts +1 -2
- package/dist/functions/event-topic/broker-delete-topic-pubsub.call.js +4 -4
- package/dist/functions/event-topic/broker-delete-topic-pubsub.d.ts +2 -3
- package/dist/functions/event-topic/broker-delete-topic-pubsub.js +7 -6
- package/dist/functions/event-topic/broker-delete-trigger-resource-cloud-run-invoker-role.call.d.ts +1 -2
- package/dist/functions/event-topic/broker-delete-trigger-resource-cloud-run-invoker-role.call.js +3 -3
- package/dist/functions/event-topic/broker-delete-trigger-resource-cloud-run-invoker-role.d.ts +2 -3
- package/dist/functions/event-topic/broker-delete-trigger-resource-cloud-run-invoker-role.js +7 -6
- package/dist/functions/event-topic/broker-delete-trigger-resource-pubsub-subscription.call.d.ts +1 -2
- package/dist/functions/event-topic/broker-delete-trigger-resource-pubsub-subscription.call.js +7 -4
- package/dist/functions/event-topic/broker-delete-trigger-resource-pubsub-subscription.d.ts +2 -3
- package/dist/functions/event-topic/broker-delete-trigger-resource-pubsub-subscription.js +7 -6
- package/dist/functions/event-topic/broker-delete-trigger-resource-service-account.call.d.ts +1 -2
- package/dist/functions/event-topic/broker-delete-trigger-resource-service-account.call.js +4 -4
- package/dist/functions/event-topic/broker-delete-trigger-resource-service-account.d.ts +2 -3
- package/dist/functions/event-topic/broker-delete-trigger-resource-service-account.js +7 -6
- package/dist/functions/event-topic/broker-get-topic-id-pubsub.d.ts +2 -3
- package/dist/functions/event-topic/broker-get-topic-id-pubsub.js +6 -6
- package/dist/functions/event-topic/broker-publish-events-google.call.d.ts +1 -2
- package/dist/functions/event-topic/broker-publish-events-google.call.js +6 -7
- package/dist/functions/event-topic/broker-publish-events-google.d.ts +2 -3
- package/dist/functions/event-topic/broker-publish-events-google.js +7 -6
- package/dist/functions/event-topic/create-backfill-source-bigquery.call.d.ts +1 -2
- package/dist/functions/event-topic/create-backfill-source-bigquery.call.js +4 -4
- package/dist/functions/event-topic/create-backfill-source-bigquery.d.ts +2 -3
- package/dist/functions/event-topic/create-backfill-source-bigquery.js +5 -5
- package/dist/functions/event-topic/index.d.ts +1 -0
- package/dist/functions/event-topic/index.js +1 -0
- package/dist/functions/event-topic/query-events-bigquery.call.d.ts +3 -0
- package/dist/functions/event-topic/query-events-bigquery.call.js +41 -0
- package/dist/functions/event-topic/query-events-bigquery.d.ts +9 -0
- package/dist/functions/event-topic/query-events-bigquery.js +17 -0
- package/dist/functions/google-app-check/generate-token.call.d.ts +1 -2
- package/dist/functions/google-app-check/generate-token.call.js +3 -3
- package/dist/functions/google-app-check/generate-token.d.ts +2 -2
- package/dist/functions/google-app-check/generate-token.js +3 -3
- package/dist/functions/google-firebase-storage/merge-rules.d.ts +2 -2
- package/dist/functions/google-firebase-storage/merge-rules.js +4 -4
- package/dist/functions/google-firestore/extract-database.d.ts +11 -0
- package/dist/functions/google-firestore/extract-database.js +44 -0
- package/dist/functions/google-firestore/index.d.ts +2 -0
- package/dist/functions/google-firestore/index.js +2 -0
- package/dist/functions/google-firestore/merge-rules.d.ts +2 -2
- package/dist/functions/google-firestore/merge-rules.js +4 -4
- package/dist/functions/google-firestore/query-records.call.d.ts +2 -0
- package/dist/functions/google-firestore/query-records.call.js +50 -0
- package/dist/functions/google-firestore/query-records.d.ts +17 -0
- package/dist/functions/google-firestore/query-records.js +22 -0
- package/dist/functions/google-identity-platform/generate-custom-token.call.d.ts +1 -2
- package/dist/functions/google-identity-platform/generate-custom-token.call.js +2 -2
- package/dist/functions/google-identity-platform/generate-custom-token.d.ts +2 -2
- package/dist/functions/google-identity-platform/generate-custom-token.js +3 -3
- package/dist/functions/google-identity-platform/generate-token.call.d.ts +1 -2
- package/dist/functions/google-identity-platform/generate-token.call.js +4 -4
- package/dist/functions/google-identity-platform/generate-token.d.ts +2 -2
- package/dist/functions/google-identity-platform/generate-token.js +3 -3
- package/dist/functions/google-pubsub/write-topics.d.ts +2 -3
- package/dist/functions/google-pubsub/write-topics.js +11 -12
- package/dist/functions/google-services/enable.call.d.ts +1 -2
- package/dist/functions/google-services/enable.call.js +3 -3
- package/dist/functions/google-services/enable.d.ts +2 -2
- package/dist/functions/google-services/enable.js +3 -3
- package/dist/functions/google-spanner/extract-database.d.ts +11 -0
- package/dist/functions/google-spanner/extract-database.js +25 -0
- package/dist/functions/google-spanner/index.d.ts +2 -0
- package/dist/functions/google-spanner/index.js +2 -0
- package/dist/functions/google-spanner/list-databases.d.ts +2 -2
- package/dist/functions/google-spanner/list-databases.js +7 -7
- package/dist/functions/google-spanner/query-records.call.d.ts +2 -0
- package/dist/functions/google-spanner/query-records.call.js +66 -0
- package/dist/functions/google-spanner/query-records.d.ts +22 -0
- package/dist/functions/google-spanner/query-records.js +27 -0
- package/dist/functions/google-spanner/write-databases.d.ts +2 -3
- package/dist/functions/google-spanner/write-databases.js +11 -12
- package/dist/functions/index.js +5 -4
- package/dist/functions/project/get-artefact-destination-cloud-functions.d.ts +2 -3
- package/dist/functions/project/get-artefact-destination-cloud-functions.js +5 -6
- package/dist/functions/project/get-artefact-destination-cloud-run.d.ts +2 -3
- package/dist/functions/project/get-artefact-destination-cloud-run.js +5 -6
- package/dist/functions/project/push-artefact-cloud-functions.call.d.ts +1 -2
- package/dist/functions/project/push-artefact-cloud-functions.call.js +5 -5
- package/dist/functions/project/push-artefact-cloud-functions.d.ts +2 -3
- package/dist/functions/project/push-artefact-cloud-functions.js +5 -5
- package/dist/functions/secret/fetch-access-token.call.d.ts +1 -2
- package/dist/functions/secret/fetch-access-token.call.js +4 -2
- package/dist/functions/secret/fetch-access-token.d.ts +2 -2
- package/dist/functions/secret/fetch-access-token.js +3 -3
- package/dist/functions/secret/fetch-secret-manager.call.d.ts +1 -2
- package/dist/functions/secret/fetch-secret-manager.call.js +3 -3
- package/dist/functions/secret/fetch-secret-manager.d.ts +2 -2
- package/dist/functions/secret/fetch-secret-manager.js +3 -3
- package/dist/functions/service-container/index.d.ts +1 -0
- package/dist/functions/service-container/index.js +1 -0
- package/dist/functions/service-container/query-logs-cloud-run.call.d.ts +3 -0
- package/dist/functions/service-container/query-logs-cloud-run.call.js +36 -0
- package/dist/functions/service-container/query-logs-cloud-run.d.ts +11 -0
- package/dist/functions/service-container/query-logs-cloud-run.js +18 -0
- package/dist/functions/typescript/get-decorator-renderer-google-firestore.d.ts +1 -2
- package/dist/functions/typescript/get-decorator-renderer-google-firestore.js +2 -3
- package/dist/functions/typescript/get-decorator-renderer-google-spanner.d.ts +1 -2
- package/dist/functions/typescript/get-decorator-renderer-google-spanner.js +2 -3
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/logging.d.ts +16 -0
- package/dist/services/logging.js +20 -0
- package/package.json +22 -20
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { WorkspaceContext } from '@causa/workspace';
|
|
2
1
|
import { EventTopicBrokerGetTopicId, } from '@causa/workspace-core';
|
|
3
2
|
/**
|
|
4
3
|
* Implements {@link EventTopicBrokerGetTopicId} for Pub/Sub.
|
|
5
4
|
* The returned topic ID is a full Pub/Sub topic ID, e.g. `projects/<projectId>/topics/<topicId>`.
|
|
6
5
|
*/
|
|
7
6
|
export class EventTopicBrokerGetTopicIdForPubSub extends EventTopicBrokerGetTopicId {
|
|
8
|
-
async _call(
|
|
9
|
-
const googleConf =
|
|
7
|
+
async _call() {
|
|
8
|
+
const googleConf = this._context.asConfiguration();
|
|
10
9
|
const projectId = googleConf.getOrThrow('google.project');
|
|
11
10
|
return `projects/${projectId}/topics/${this.eventTopic}`;
|
|
12
11
|
}
|
|
13
|
-
_supports(
|
|
14
|
-
return (
|
|
15
|
-
|
|
12
|
+
_supports() {
|
|
13
|
+
return (this._context
|
|
14
|
+
.asConfiguration()
|
|
15
|
+
.get('events.broker') === 'google.pubSub');
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import type { WorkspaceContext } from '@causa/workspace';
|
|
2
1
|
import type { EventTopicBrokerPublishEventsForGoogle } from './broker-publish-events-google.js';
|
|
3
|
-
export default function call(this: EventTopicBrokerPublishEventsForGoogle
|
|
2
|
+
export default function call(this: EventTopicBrokerPublishEventsForGoogle): Promise<void>;
|
|
@@ -18,28 +18,27 @@ const PUBLISH_OPTIONS = {
|
|
|
18
18
|
maxMilliseconds: 1000,
|
|
19
19
|
},
|
|
20
20
|
};
|
|
21
|
-
export default async function call(
|
|
22
|
-
const publisher =
|
|
21
|
+
export default async function call() {
|
|
22
|
+
const publisher = this._context
|
|
23
23
|
.service(PubSubService)
|
|
24
24
|
.pubSub.topic(this.topicId, PUBLISH_OPTIONS)
|
|
25
25
|
.flowControlled();
|
|
26
|
-
|
|
26
|
+
this._context.logger.info('📫 Publishing events.');
|
|
27
27
|
let numEvents = 0;
|
|
28
28
|
for await (const event of this.source()) {
|
|
29
29
|
numEvents += 1;
|
|
30
30
|
const wait = publisher.publish({
|
|
31
31
|
data: event.data,
|
|
32
32
|
attributes: event.attributes,
|
|
33
|
-
orderingKey: event.key,
|
|
34
33
|
});
|
|
35
34
|
if (wait) {
|
|
36
|
-
|
|
35
|
+
this._context.logger.debug('Waiting for the publisher to catch up before resuming publishing.');
|
|
37
36
|
await wait;
|
|
38
37
|
}
|
|
39
38
|
if (numEvents % PUBLISH_PROGRESS_LOG_INTERVAL === 0) {
|
|
40
|
-
|
|
39
|
+
this._context.logger.debug(`Published ${numEvents} events.`);
|
|
41
40
|
}
|
|
42
41
|
}
|
|
43
42
|
await publisher.all();
|
|
44
|
-
|
|
43
|
+
this._context.logger.info(`📫 Finished publishing ${numEvents} events.`);
|
|
45
44
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { WorkspaceContext } from '@causa/workspace';
|
|
2
1
|
import { EventTopicBrokerPublishEvents } from '@causa/workspace-core';
|
|
3
2
|
/**
|
|
4
3
|
* Implements {@link EventTopicBrokerPublishEvents} for a Google / GCP stack.
|
|
5
4
|
* The supported message broker is Pub/Sub.
|
|
6
5
|
*/
|
|
7
6
|
export declare class EventTopicBrokerPublishEventsForGoogle extends EventTopicBrokerPublishEvents {
|
|
8
|
-
_call(
|
|
9
|
-
_supports(
|
|
7
|
+
_call(): Promise<void>;
|
|
8
|
+
_supports(): boolean;
|
|
10
9
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { callDeferred
|
|
1
|
+
import { callDeferred } from '@causa/workspace';
|
|
2
2
|
import { EventTopicBrokerPublishEvents, } from '@causa/workspace-core';
|
|
3
3
|
/**
|
|
4
4
|
* Implements {@link EventTopicBrokerPublishEvents} for a Google / GCP stack.
|
|
5
5
|
* The supported message broker is Pub/Sub.
|
|
6
6
|
*/
|
|
7
7
|
export class EventTopicBrokerPublishEventsForGoogle extends EventTopicBrokerPublishEvents {
|
|
8
|
-
async _call(
|
|
9
|
-
return await callDeferred(this,
|
|
8
|
+
async _call() {
|
|
9
|
+
return await callDeferred(this, import.meta.url);
|
|
10
10
|
}
|
|
11
|
-
_supports(
|
|
12
|
-
return (
|
|
13
|
-
|
|
11
|
+
_supports() {
|
|
12
|
+
return (this._context
|
|
13
|
+
.asConfiguration()
|
|
14
|
+
.get('events.broker') === 'google.pubSub');
|
|
14
15
|
}
|
|
15
16
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { WorkspaceContext } from '@causa/workspace';
|
|
2
1
|
import type { BackfillEvent } from '@causa/workspace-core';
|
|
3
2
|
import { type EventTopicCreateBackfillSourceForBigQuery } from './create-backfill-source-bigquery.js';
|
|
4
|
-
export default function call(this: EventTopicCreateBackfillSourceForBigQuery
|
|
3
|
+
export default function call(this: EventTopicCreateBackfillSourceForBigQuery): Promise<AsyncIterable<BackfillEvent>>;
|
|
@@ -21,8 +21,8 @@ function resolveTableId(self, context) {
|
|
|
21
21
|
const tableName = self.eventTopic.replace(/[-\.]/g, '_');
|
|
22
22
|
return `${projectId}.${rawEventsDatasetId}.${tableName}`;
|
|
23
23
|
}
|
|
24
|
-
export default async function call(
|
|
25
|
-
const tableId = resolveTableId(this,
|
|
24
|
+
export default async function call() {
|
|
25
|
+
const tableId = resolveTableId(this, this._context);
|
|
26
26
|
let query = `
|
|
27
27
|
SELECT
|
|
28
28
|
data,
|
|
@@ -34,8 +34,8 @@ export default async function call(context) {
|
|
|
34
34
|
WHERE
|
|
35
35
|
(${this.filter})`;
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
const bigQuery =
|
|
37
|
+
this._context.logger.debug(`Creating BigQuery job from query '${query}'.`);
|
|
38
|
+
const bigQuery = this._context.service(BigQueryService).bigQuery;
|
|
39
39
|
const [job] = await bigQuery.createQueryJob(query);
|
|
40
40
|
return (async function* () {
|
|
41
41
|
for await (const row of job.getQueryResultsStream()) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { WorkspaceContext } from '@causa/workspace';
|
|
2
1
|
import { type BackfillEvent, EventTopicCreateBackfillSource } from '@causa/workspace-core';
|
|
3
2
|
/**
|
|
4
3
|
* The regular expression used to parse a `bq://<tableId>` source string.
|
|
@@ -15,6 +14,6 @@ export declare const BIGQUERY_SOURCE_REGEX: RegExp;
|
|
|
15
14
|
* The returned async iterable pages through the query results and yields each row as a {@link BackfillEvent}.
|
|
16
15
|
*/
|
|
17
16
|
export declare class EventTopicCreateBackfillSourceForBigQuery extends EventTopicCreateBackfillSource {
|
|
18
|
-
_call(
|
|
19
|
-
_supports(
|
|
17
|
+
_call(): Promise<AsyncIterable<BackfillEvent>>;
|
|
18
|
+
_supports(): boolean;
|
|
20
19
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { callDeferred
|
|
1
|
+
import { callDeferred } from '@causa/workspace';
|
|
2
2
|
import { EventTopicCreateBackfillSource, } from '@causa/workspace-core';
|
|
3
3
|
/**
|
|
4
4
|
* The regular expression used to parse a `bq://<tableId>` source string.
|
|
@@ -15,17 +15,17 @@ export const BIGQUERY_SOURCE_REGEX = /^bq:\/\/(?<tableId>.+)$/;
|
|
|
15
15
|
* The returned async iterable pages through the query results and yields each row as a {@link BackfillEvent}.
|
|
16
16
|
*/
|
|
17
17
|
export class EventTopicCreateBackfillSourceForBigQuery extends EventTopicCreateBackfillSource {
|
|
18
|
-
async _call(
|
|
19
|
-
return await callDeferred(this,
|
|
18
|
+
async _call() {
|
|
19
|
+
return await callDeferred(this, import.meta.url);
|
|
20
20
|
}
|
|
21
|
-
_supports(
|
|
21
|
+
_supports() {
|
|
22
22
|
if (this.source?.match(BIGQUERY_SOURCE_REGEX)) {
|
|
23
23
|
return true;
|
|
24
24
|
}
|
|
25
25
|
if (this.source) {
|
|
26
26
|
return false;
|
|
27
27
|
}
|
|
28
|
-
const conf =
|
|
28
|
+
const conf = this._context.asConfiguration();
|
|
29
29
|
return (conf.get('events.broker') === 'google.pubSub' &&
|
|
30
30
|
!!conf.get('google.pubSub.bigQueryStorage.rawEventsDatasetId'));
|
|
31
31
|
}
|
|
@@ -7,3 +7,4 @@ export { EventTopicBrokerDeleteTriggerResourceForServiceAccount } from './broker
|
|
|
7
7
|
export { EventTopicBrokerGetTopicIdForPubSub } from './broker-get-topic-id-pubsub.js';
|
|
8
8
|
export { EventTopicBrokerPublishEventsForGoogle } from './broker-publish-events-google.js';
|
|
9
9
|
export { EventTopicCreateBackfillSourceForBigQuery } from './create-backfill-source-bigquery.js';
|
|
10
|
+
export { EventTopicQueryEventsForBigQuery } from './query-events-bigquery.js';
|
|
@@ -7,3 +7,4 @@ export { EventTopicBrokerDeleteTriggerResourceForServiceAccount } from './broker
|
|
|
7
7
|
export { EventTopicBrokerGetTopicIdForPubSub } from './broker-get-topic-id-pubsub.js';
|
|
8
8
|
export { EventTopicBrokerPublishEventsForGoogle } from './broker-publish-events-google.js';
|
|
9
9
|
export { EventTopicCreateBackfillSourceForBigQuery } from './create-backfill-source-bigquery.js';
|
|
10
|
+
export { EventTopicQueryEventsForBigQuery } from './query-events-bigquery.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BigQueryService } from '../../services/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The default duration applied to `from` when it is not set, in milliseconds.
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_FROM_OFFSET = 60 * 60 * 1000;
|
|
6
|
+
/**
|
|
7
|
+
* The default value for `limit` when it is not set.
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_LIMIT = 1000;
|
|
10
|
+
export default async function call() {
|
|
11
|
+
const from = this.from ?? new Date(Date.now() - DEFAULT_FROM_OFFSET);
|
|
12
|
+
const limit = this.limit ?? DEFAULT_LIMIT;
|
|
13
|
+
const googleConf = this._context.asConfiguration();
|
|
14
|
+
const projectId = googleConf.getOrThrow('google.project');
|
|
15
|
+
const rawEventsDatasetId = googleConf.getOrThrow('google.pubSub.bigQueryStorage.rawEventsDatasetId');
|
|
16
|
+
const tableName = this.topic.replace(/[-\.]/g, '_');
|
|
17
|
+
const tableId = `${projectId}.${rawEventsDatasetId}.${tableName}`;
|
|
18
|
+
const conditions = [`publish_time >= @from`];
|
|
19
|
+
const params = { from: from.toISOString() };
|
|
20
|
+
if (this.to) {
|
|
21
|
+
conditions.push(`publish_time < @to`);
|
|
22
|
+
params.to = this.to.toISOString();
|
|
23
|
+
}
|
|
24
|
+
if (this.filter) {
|
|
25
|
+
conditions.push(`(${this.filter})`);
|
|
26
|
+
}
|
|
27
|
+
const query = `
|
|
28
|
+
SELECT publish_time, data, attributes
|
|
29
|
+
FROM \`${tableId}\`
|
|
30
|
+
WHERE ${conditions.join(' AND ')}
|
|
31
|
+
ORDER BY publish_time ASC
|
|
32
|
+
LIMIT ${limit}`;
|
|
33
|
+
this._context.logger.debug(`Querying BigQuery for events:\n${query}`);
|
|
34
|
+
const bigQuery = this._context.service(BigQueryService).bigQuery;
|
|
35
|
+
const [rows] = await bigQuery.query({ query, params });
|
|
36
|
+
return rows.map((row) => ({
|
|
37
|
+
timestamp: new Date(row.publish_time.value),
|
|
38
|
+
attributes: row.attributes ? JSON.parse(row.attributes) : {},
|
|
39
|
+
data: JSON.parse(row.data.toString('utf8')),
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EventTopicQueryEvents, type QueriedEvent } from '@causa/workspace-core';
|
|
2
|
+
/**
|
|
3
|
+
* Implements {@link EventTopicQueryEvents} for Pub/Sub topics whose events are stored in BigQuery via a BigQuery
|
|
4
|
+
* subscription. The events are read from the dataset configured at `google.pubSub.bigQueryStorage.rawEventsDatasetId`.
|
|
5
|
+
*/
|
|
6
|
+
export declare class EventTopicQueryEventsForBigQuery extends EventTopicQueryEvents {
|
|
7
|
+
_call(): Promise<QueriedEvent[]>;
|
|
8
|
+
_supports(): boolean;
|
|
9
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { callDeferred } from '@causa/workspace';
|
|
2
|
+
import { EventTopicQueryEvents, } from '@causa/workspace-core';
|
|
3
|
+
/**
|
|
4
|
+
* Implements {@link EventTopicQueryEvents} for Pub/Sub topics whose events are stored in BigQuery via a BigQuery
|
|
5
|
+
* subscription. The events are read from the dataset configured at `google.pubSub.bigQueryStorage.rawEventsDatasetId`.
|
|
6
|
+
*/
|
|
7
|
+
export class EventTopicQueryEventsForBigQuery extends EventTopicQueryEvents {
|
|
8
|
+
async _call() {
|
|
9
|
+
return await callDeferred(this, import.meta.url);
|
|
10
|
+
}
|
|
11
|
+
_supports() {
|
|
12
|
+
const conf = this._context.asConfiguration();
|
|
13
|
+
return (conf.get('events.broker') === 'google.pubSub' &&
|
|
14
|
+
conf.get('events.format') === 'json' &&
|
|
15
|
+
!!conf.get('google.pubSub.bigQueryStorage.rawEventsDatasetId'));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import type { WorkspaceContext } from '@causa/workspace';
|
|
2
1
|
import type { GoogleAppCheckGenerateToken } from './generate-token.js';
|
|
3
|
-
export default function call(this: GoogleAppCheckGenerateToken
|
|
2
|
+
export default function call(this: GoogleAppCheckGenerateToken): Promise<string>;
|
|
@@ -4,11 +4,11 @@ import { FirebaseAppService } from '../../services/firebase-app.js';
|
|
|
4
4
|
* The time to live of generated tokens, in seconds.
|
|
5
5
|
*/
|
|
6
6
|
const TOKEN_TTL = 3600;
|
|
7
|
-
export default async function call(
|
|
8
|
-
const firebaseAppService =
|
|
7
|
+
export default async function call() {
|
|
8
|
+
const firebaseAppService = this._context.service(FirebaseAppService);
|
|
9
9
|
const app = await firebaseAppService.getAdminAppForAdminServiceAccount();
|
|
10
10
|
const appId = this.app ?? (await firebaseAppService.getAppId());
|
|
11
|
-
|
|
11
|
+
this._context.logger.info(`🛂 Generating AppCheck token for Firebase application '${appId}'.`);
|
|
12
12
|
const appCheck = getAppCheck(app);
|
|
13
13
|
const { token } = await appCheck.createToken(appId, {
|
|
14
14
|
ttlMillis: TOKEN_TTL * 1000,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { WorkspaceFunction } from '@causa/workspace';
|
|
2
2
|
/**
|
|
3
3
|
* Generates a new AppCheck token.
|
|
4
4
|
*/
|
|
@@ -8,6 +8,6 @@ export declare class GoogleAppCheckGenerateToken extends WorkspaceFunction<Promi
|
|
|
8
8
|
* If `undefined`, a Firebase app ID will be found in the configuration or using the API.
|
|
9
9
|
*/
|
|
10
10
|
readonly app?: string;
|
|
11
|
-
_call(
|
|
11
|
+
_call(): Promise<string>;
|
|
12
12
|
_supports(): boolean;
|
|
13
13
|
}
|
|
@@ -8,7 +8,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
10
|
import { CliCommand, CliOption } from '@causa/cli';
|
|
11
|
-
import { callDeferred,
|
|
11
|
+
import { callDeferred, WorkspaceFunction } from '@causa/workspace';
|
|
12
12
|
import { AllowMissing } from '@causa/workspace/validation';
|
|
13
13
|
import { IsString } from 'class-validator';
|
|
14
14
|
import { appCheckCommandDefinition } from '../../cli/index.js';
|
|
@@ -21,8 +21,8 @@ let GoogleAppCheckGenerateToken = class GoogleAppCheckGenerateToken extends Work
|
|
|
21
21
|
* If `undefined`, a Firebase app ID will be found in the configuration or using the API.
|
|
22
22
|
*/
|
|
23
23
|
app;
|
|
24
|
-
async _call(
|
|
25
|
-
return await callDeferred(this,
|
|
24
|
+
async _call() {
|
|
25
|
+
return await callDeferred(this, import.meta.url);
|
|
26
26
|
}
|
|
27
27
|
_supports() {
|
|
28
28
|
return true;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { WorkspaceFunction } from '@causa/workspace';
|
|
2
2
|
import type { InfrastructureProcessor } from '@causa/workspace-core';
|
|
3
3
|
import type { GoogleConfiguration } from '../../configurations/index.js';
|
|
4
4
|
/**
|
|
@@ -27,7 +27,7 @@ type GoogleFirebaseStorageMergeRulesResult = {
|
|
|
27
27
|
*/
|
|
28
28
|
export declare class GoogleFirebaseStorageMergeRules extends WorkspaceFunction<Promise<GoogleFirebaseStorageMergeRulesResult>> implements InfrastructureProcessor {
|
|
29
29
|
readonly tearDown?: boolean;
|
|
30
|
-
_call(
|
|
30
|
+
_call(): Promise<GoogleFirebaseStorageMergeRulesResult>;
|
|
31
31
|
_supports(): boolean;
|
|
32
32
|
}
|
|
33
33
|
export {};
|
|
@@ -8,7 +8,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
10
|
import { CliCommand } from '@causa/cli';
|
|
11
|
-
import {
|
|
11
|
+
import { WorkspaceFunction } from '@causa/workspace';
|
|
12
12
|
import { AllowMissing } from '@causa/workspace/validation';
|
|
13
13
|
import { IsBoolean } from 'class-validator';
|
|
14
14
|
import { firebaseStorageCommandDefinition } from '../../cli/index.js';
|
|
@@ -29,11 +29,11 @@ const DEFAULT_FIREBASE_STORAGE_SECURITY_RULE_FILE = 'storage.rules';
|
|
|
29
29
|
*/
|
|
30
30
|
let GoogleFirebaseStorageMergeRules = class GoogleFirebaseStorageMergeRules extends WorkspaceFunction {
|
|
31
31
|
tearDown;
|
|
32
|
-
async _call(
|
|
32
|
+
async _call() {
|
|
33
33
|
if (this.tearDown) {
|
|
34
34
|
return { configuration: {}, securityRuleFile: null };
|
|
35
35
|
}
|
|
36
|
-
const googleConf =
|
|
36
|
+
const googleConf = this._context.asConfiguration();
|
|
37
37
|
let securityRuleFile = googleConf.get('google.firebaseStorage.securityRuleFile') ??
|
|
38
38
|
DEFAULT_FIREBASE_STORAGE_SECURITY_RULE_FILE;
|
|
39
39
|
const globs = googleConf.get('google.firebaseStorage.securityRuleFiles') ?? [];
|
|
@@ -44,7 +44,7 @@ service firebase.storage {
|
|
|
44
44
|
${rules}
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
`, securityRuleFile,
|
|
47
|
+
`, securityRuleFile, this._context);
|
|
48
48
|
return {
|
|
49
49
|
configuration: { google: { firebaseStorage: { securityRuleFile } } },
|
|
50
50
|
securityRuleFile,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ModelSchemaExtractDatabase, type SchemaDatabase } from '@causa/workspace-core';
|
|
2
|
+
/**
|
|
3
|
+
* Implements {@link ModelSchemaExtractDatabase} for Google Firestore.
|
|
4
|
+
* The schema is selected when it carries a `googleFirestoreCollection` Causa extension with a `path` array. The table
|
|
5
|
+
* label is the slash-joined formatted path (e.g. `users/{userId}/orders/{orderId}`), optionally prefixed by the
|
|
6
|
+
* extension's `name`. Property references in the path become the primary keys.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ModelSchemaExtractDatabaseForGoogleFirestore extends ModelSchemaExtractDatabase {
|
|
9
|
+
_call(): SchemaDatabase;
|
|
10
|
+
_supports(): boolean;
|
|
11
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ModelSchemaExtractDatabase, } from '@causa/workspace-core';
|
|
2
|
+
/**
|
|
3
|
+
* The name of the Causa extension marking an object schema as a Google Firestore collection.
|
|
4
|
+
*/
|
|
5
|
+
const GOOGLE_FIRESTORE_COLLECTION_EXTENSION = 'googleFirestoreCollection';
|
|
6
|
+
/**
|
|
7
|
+
* Implements {@link ModelSchemaExtractDatabase} for Google Firestore.
|
|
8
|
+
* The schema is selected when it carries a `googleFirestoreCollection` Causa extension with a `path` array. The table
|
|
9
|
+
* label is the slash-joined formatted path (e.g. `users/{userId}/orders/{orderId}`), optionally prefixed by the
|
|
10
|
+
* extension's `name`. Property references in the path become the primary keys.
|
|
11
|
+
*/
|
|
12
|
+
export class ModelSchemaExtractDatabaseForGoogleFirestore extends ModelSchemaExtractDatabase {
|
|
13
|
+
_call() {
|
|
14
|
+
const extension = this.schema.extensions[GOOGLE_FIRESTORE_COLLECTION_EXTENSION];
|
|
15
|
+
const primaryKeys = [];
|
|
16
|
+
const segments = extension.path.map((element) => {
|
|
17
|
+
if (typeof element === 'string') {
|
|
18
|
+
return element;
|
|
19
|
+
}
|
|
20
|
+
if (typeof element === 'object' &&
|
|
21
|
+
element !== null &&
|
|
22
|
+
'property' in element &&
|
|
23
|
+
typeof element.property === 'string') {
|
|
24
|
+
primaryKeys.push(element.property);
|
|
25
|
+
return `{${element.property}}`;
|
|
26
|
+
}
|
|
27
|
+
return '?';
|
|
28
|
+
});
|
|
29
|
+
if (typeof extension.name === 'string') {
|
|
30
|
+
segments.unshift(extension.name);
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
engine: 'google.firestore',
|
|
34
|
+
table: segments.join('/'),
|
|
35
|
+
primaryKeys,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
_supports() {
|
|
39
|
+
const extension = this.schema.extensions[GOOGLE_FIRESTORE_COLLECTION_EXTENSION];
|
|
40
|
+
return (typeof extension === 'object' &&
|
|
41
|
+
extension !== null &&
|
|
42
|
+
Array.isArray(extension.path));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { WorkspaceFunction } from '@causa/workspace';
|
|
2
2
|
import type { InfrastructureProcessor } from '@causa/workspace-core';
|
|
3
3
|
import type { GoogleConfiguration } from '../../configurations/index.js';
|
|
4
4
|
/**
|
|
@@ -27,7 +27,7 @@ type GoogleFirestoreMergeRulesResult = {
|
|
|
27
27
|
*/
|
|
28
28
|
export declare class GoogleFirestoreMergeRules extends WorkspaceFunction<Promise<GoogleFirestoreMergeRulesResult>> implements InfrastructureProcessor {
|
|
29
29
|
readonly tearDown?: boolean;
|
|
30
|
-
_call(
|
|
30
|
+
_call(): Promise<GoogleFirestoreMergeRulesResult>;
|
|
31
31
|
_supports(): boolean;
|
|
32
32
|
}
|
|
33
33
|
export {};
|
|
@@ -8,7 +8,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
10
|
import { CliCommand } from '@causa/cli';
|
|
11
|
-
import {
|
|
11
|
+
import { WorkspaceFunction } from '@causa/workspace';
|
|
12
12
|
import { AllowMissing } from '@causa/workspace/validation';
|
|
13
13
|
import { IsBoolean } from 'class-validator';
|
|
14
14
|
import { firestoreCommandDefinition } from '../../cli/index.js';
|
|
@@ -29,11 +29,11 @@ const DEFAULT_FIRESTORE_SECURITY_RULE_FILE = 'firestore.rules';
|
|
|
29
29
|
*/
|
|
30
30
|
let GoogleFirestoreMergeRules = class GoogleFirestoreMergeRules extends WorkspaceFunction {
|
|
31
31
|
tearDown;
|
|
32
|
-
async _call(
|
|
32
|
+
async _call() {
|
|
33
33
|
if (this.tearDown) {
|
|
34
34
|
return { configuration: {}, securityRuleFile: null };
|
|
35
35
|
}
|
|
36
|
-
const googleConf =
|
|
36
|
+
const googleConf = this._context.asConfiguration();
|
|
37
37
|
let securityRuleFile = googleConf.get('google.firestore.securityRuleFile') ??
|
|
38
38
|
DEFAULT_FIRESTORE_SECURITY_RULE_FILE;
|
|
39
39
|
const globs = googleConf.get('google.firestore.securityRuleFiles') ?? [];
|
|
@@ -44,7 +44,7 @@ service cloud.firestore {
|
|
|
44
44
|
${rules}
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
`, securityRuleFile,
|
|
47
|
+
`, securityRuleFile, this._context);
|
|
48
48
|
return {
|
|
49
49
|
configuration: { google: { firestore: { securityRuleFile } } },
|
|
50
50
|
securityRuleFile,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { deleteApp, initializeApp } from 'firebase-admin/app';
|
|
2
|
+
import { DocumentReference, GeoPoint, getFirestore, Timestamp, } from 'firebase-admin/firestore';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
export default async function call() {
|
|
5
|
+
if (!this.query) {
|
|
6
|
+
throw new Error(`The 'query' input is required for the 'google.firestore' engine.`);
|
|
7
|
+
}
|
|
8
|
+
const googleConf = this._context.asConfiguration();
|
|
9
|
+
const projectId = googleConf.getOrThrow('google.project');
|
|
10
|
+
const database = this.database ?? '(default)';
|
|
11
|
+
this._context.logger.debug(`🗃️ Fetching Firestore document '${this.query}' from database '${database}' in project '${projectId}'.`);
|
|
12
|
+
const app = initializeApp({ projectId }, randomUUID());
|
|
13
|
+
try {
|
|
14
|
+
const firestore = getFirestore(app, database);
|
|
15
|
+
const snapshot = await firestore.doc(this.query).get();
|
|
16
|
+
return snapshot.exists ? [toJson(snapshot.data())] : [];
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
await deleteApp(app);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Recursively converts Firestore-specific types to JSON-friendly equivalents:
|
|
24
|
+
* - {@link Timestamp} → {@link Date}
|
|
25
|
+
* - {@link GeoPoint} → `{ latitude, longitude }`
|
|
26
|
+
* - {@link DocumentReference} → its `path`
|
|
27
|
+
*
|
|
28
|
+
* Other values (including `Buffer`) are returned as-is.
|
|
29
|
+
*/
|
|
30
|
+
function toJson(value) {
|
|
31
|
+
if (value === null || typeof value !== 'object') {
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
if (value instanceof Timestamp) {
|
|
35
|
+
return value.toDate();
|
|
36
|
+
}
|
|
37
|
+
if (value instanceof GeoPoint) {
|
|
38
|
+
return { latitude: value.latitude, longitude: value.longitude };
|
|
39
|
+
}
|
|
40
|
+
if (value instanceof DocumentReference) {
|
|
41
|
+
return value.path;
|
|
42
|
+
}
|
|
43
|
+
if (Buffer.isBuffer(value)) {
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
return value.map(toJson);
|
|
48
|
+
}
|
|
49
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, toJson(v)]));
|
|
50
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DatabaseQueryRecords } from '@causa/workspace-core';
|
|
2
|
+
/**
|
|
3
|
+
* The engine identifier handled by this implementation.
|
|
4
|
+
*/
|
|
5
|
+
export declare const FIRESTORE_ENGINE = "google.firestore";
|
|
6
|
+
/**
|
|
7
|
+
* Implements {@link DatabaseQueryRecords} for Firestore.
|
|
8
|
+
*
|
|
9
|
+
* The `database` input is optional and defaults to the default Firestore database. The `query` input is the path to a
|
|
10
|
+
* single document (e.g. `users/abc`).
|
|
11
|
+
*
|
|
12
|
+
* Returns an array containing a single document's data, or an empty array if the document does not exist.
|
|
13
|
+
*/
|
|
14
|
+
export declare class DatabaseQueryRecordsForFirestore extends DatabaseQueryRecords {
|
|
15
|
+
_call(): Promise<any[]>;
|
|
16
|
+
_supports(): boolean;
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { callDeferred } from '@causa/workspace';
|
|
2
|
+
import { DatabaseQueryRecords } from '@causa/workspace-core';
|
|
3
|
+
/**
|
|
4
|
+
* The engine identifier handled by this implementation.
|
|
5
|
+
*/
|
|
6
|
+
export const FIRESTORE_ENGINE = 'google.firestore';
|
|
7
|
+
/**
|
|
8
|
+
* Implements {@link DatabaseQueryRecords} for Firestore.
|
|
9
|
+
*
|
|
10
|
+
* The `database` input is optional and defaults to the default Firestore database. The `query` input is the path to a
|
|
11
|
+
* single document (e.g. `users/abc`).
|
|
12
|
+
*
|
|
13
|
+
* Returns an array containing a single document's data, or an empty array if the document does not exist.
|
|
14
|
+
*/
|
|
15
|
+
export class DatabaseQueryRecordsForFirestore extends DatabaseQueryRecords {
|
|
16
|
+
async _call() {
|
|
17
|
+
return await callDeferred(this, import.meta.url);
|
|
18
|
+
}
|
|
19
|
+
_supports() {
|
|
20
|
+
return this.engine === FIRESTORE_ENGINE;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import type { WorkspaceContext } from '@causa/workspace';
|
|
2
1
|
import type { GoogleIdentityPlatformGenerateCustomToken } from './generate-custom-token.js';
|
|
3
|
-
export default function call(this: GoogleIdentityPlatformGenerateCustomToken
|
|
2
|
+
export default function call(this: GoogleIdentityPlatformGenerateCustomToken): Promise<string>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getAuth } from 'firebase-admin/auth';
|
|
2
2
|
import { FirebaseAppService } from '../../services/firebase-app.js';
|
|
3
|
-
export default async function call(
|
|
4
|
-
const adminApp = await
|
|
3
|
+
export default async function call() {
|
|
4
|
+
const adminApp = await this._context
|
|
5
5
|
.service(FirebaseAppService)
|
|
6
6
|
.getAdminAppForAdminServiceAccount();
|
|
7
7
|
return await getAuth(adminApp).createCustomToken(this.user, this.claims);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { WorkspaceFunction } from '@causa/workspace';
|
|
2
2
|
/**
|
|
3
3
|
* Generates a custom token that can be used to sign in to Identity Platform as a given user.
|
|
4
4
|
* Optionally, custom claims can be set in the token.
|
|
@@ -15,6 +15,6 @@ export declare class GoogleIdentityPlatformGenerateCustomToken extends Workspace
|
|
|
15
15
|
* A dictionary of custom claims to add to the token.
|
|
16
16
|
*/
|
|
17
17
|
readonly claims?: Record<string, any>;
|
|
18
|
-
_call(
|
|
18
|
+
_call(): Promise<string>;
|
|
19
19
|
_supports(): boolean;
|
|
20
20
|
}
|