@causa/workspace-google 0.5.0 → 0.7.0
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 +34 -0
- package/dist/code-generation/google-spanner-renderer.d.ts +11 -0
- package/dist/code-generation/google-spanner-renderer.js +94 -0
- package/dist/code-generation/index.d.ts +1 -0
- package/dist/code-generation/index.js +1 -0
- package/dist/functions/emulator/start-spanner.d.ts +8 -0
- package/dist/functions/emulator/start-spanner.js +26 -11
- package/dist/functions/google-app-check/generate-token.js +2 -1
- package/dist/functions/google-firebase-storage/merge-rules.js +2 -1
- package/dist/functions/google-firestore/merge-rules.js +2 -1
- package/dist/functions/google-identity-platform/generate-token.js +2 -1
- package/dist/functions/google-services/enable.js +2 -1
- package/dist/functions/index.js +3 -2
- package/dist/functions/secret/fetch-access-token.d.ts +18 -0
- package/dist/functions/secret/fetch-access-token.js +30 -0
- package/dist/functions/secret/index.d.ts +1 -0
- package/dist/functions/secret/index.js +1 -0
- package/dist/functions/typescript/get-decorator-renderer-google-spanner.d.ts +10 -0
- package/dist/functions/typescript/get-decorator-renderer-google-spanner.js +21 -0
- package/dist/functions/typescript/index.d.ts +1 -0
- package/dist/functions/typescript/index.js +1 -0
- package/dist/services/google-apis.d.ts +3 -2
- package/dist/services/google-apis.js +3 -2
- package/package.json +35 -32
package/README.md
CHANGED
|
@@ -57,6 +57,40 @@ secrets:
|
|
|
57
57
|
|
|
58
58
|
When the GCP project is not specified in the secret ID, it is inferred from `google.secretManager.project`, or `google.project` (in this order). This allows defining the GCP project a single time if needed.
|
|
59
59
|
|
|
60
|
+
A second secret backend, `google.accessToken`, does not fetch secrets from a source but rather returns a GCP access token, which can be used to access Google services:
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
secrets:
|
|
64
|
+
gcpAccessToken:
|
|
65
|
+
backend: google.accessToken
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Code generation
|
|
69
|
+
|
|
70
|
+
This module implements the `google.spanner` TypeScript decorator renderer, which can be used to add `@SpannerTable` and `@SpannerColumn` decorators to classes generated from events. Below is an example of how to enable it for a JSONSchema object:
|
|
71
|
+
|
|
72
|
+
```yaml
|
|
73
|
+
title: MyClass
|
|
74
|
+
type: object
|
|
75
|
+
additionalProperties: false
|
|
76
|
+
causa:
|
|
77
|
+
# This must be set for the decorators to be added to both the class and its properties.
|
|
78
|
+
# The content of the object will be passed as the argument to the `@SpannerTable` decorator.
|
|
79
|
+
tsGoogleSpannerTable:
|
|
80
|
+
primaryKey: [id]
|
|
81
|
+
properties:
|
|
82
|
+
id:
|
|
83
|
+
type: string
|
|
84
|
+
format: uuid
|
|
85
|
+
# In most cases, the property-level `tsGoogleSpannerColumn` attribute does not need to be set. The decorator configuration will be automatically inferred.
|
|
86
|
+
# If needed, the content of `tsGoogleSpannerColumn` will be passed as the argument to the `@SpannerColumn` decorator.
|
|
87
|
+
# causa:
|
|
88
|
+
# tsGoogleSpannerColumn:
|
|
89
|
+
# isJson: false
|
|
90
|
+
myProperty:
|
|
91
|
+
type: string
|
|
92
|
+
```
|
|
93
|
+
|
|
60
94
|
## 🔨 Custom `google` commands
|
|
61
95
|
|
|
62
96
|
This modules adds a new command to the CLI: `cs google`. Here is the list of subcommands that are exposed.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ClassContext, ClassPropertyContext, TypeScriptDecorator, TypeScriptDecoratorsRenderer } from '@causa/workspace-typescript';
|
|
2
|
+
/**
|
|
3
|
+
* A {@link TypeScriptDecoratorsRenderer} that adds Google Spanner decorators from the Causa Google runtime.
|
|
4
|
+
*
|
|
5
|
+
* If an object schema is marked with the `tsGoogleSpannerTable` attribute, the `@SpannerTable` decorator is added to
|
|
6
|
+
* the class, and `@SpannerColumn` decorators are added to all its properties.
|
|
7
|
+
*/
|
|
8
|
+
export declare class GoogleSpannerRenderer extends TypeScriptDecoratorsRenderer {
|
|
9
|
+
decoratorsForClass(context: ClassContext): TypeScriptDecorator[];
|
|
10
|
+
decoratorsForProperty(context: ClassPropertyContext): TypeScriptDecorator[];
|
|
11
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { TypeScriptDecoratorsRenderer, getSingleType, typeScriptSourceForObject, } from '@causa/workspace-typescript';
|
|
2
|
+
import { panic } from 'quicktype-core';
|
|
3
|
+
/**
|
|
4
|
+
* The name of the Causa attribute that should be present for a class to be decorated with Google Spanner decorators.
|
|
5
|
+
*/
|
|
6
|
+
const GOOGLE_SPANNER_TABLE_ATTRIBUTE = 'tsGoogleSpannerTable';
|
|
7
|
+
/**
|
|
8
|
+
* The name of the Causa attribute that can be present on a class to only generate `@SpannerColumn` decorators for its
|
|
9
|
+
* properties, but not a `@SpannerTable` decorator for the class itself.
|
|
10
|
+
*/
|
|
11
|
+
const GOOGLE_SPANNER_NESTED_TYPE_ATTRIBUTE = 'tsGoogleSpannerNestedType';
|
|
12
|
+
/**
|
|
13
|
+
* The name of the optional Causa attribute that can be present on an object property schema to specify options for the
|
|
14
|
+
* `@SpannerColumn` decorator.
|
|
15
|
+
*/
|
|
16
|
+
const GOOGLE_SPANNER_COLUMN_ATTRIBUTE = 'tsGoogleSpannerColumn';
|
|
17
|
+
/**
|
|
18
|
+
* The name of the `decoratorOptions` key that can be used to specify the name of the property that should be used as
|
|
19
|
+
* the soft deletion column.
|
|
20
|
+
*/
|
|
21
|
+
const GOOGLE_SPANNER_SOFT_DELETION_COLUMN_OPTION = 'googleSpannerSoftDeletionColumn';
|
|
22
|
+
/**
|
|
23
|
+
* The name of the Causa module for the TypeScript Google runtime.
|
|
24
|
+
*/
|
|
25
|
+
const CAUSA_GOOGLE_MODULE = '@causa/runtime-google';
|
|
26
|
+
/**
|
|
27
|
+
* The list of options that can be passed to the `@SpannerColumn` decorator and that indicates that the JSONSchema
|
|
28
|
+
* specifies the type of the column. In this case, the renderer should not infer any type information.
|
|
29
|
+
*/
|
|
30
|
+
const TYPE_INFO_COLUMN_ATTRIBUTE_NAMES = [
|
|
31
|
+
'nestedType',
|
|
32
|
+
'nullifyNested',
|
|
33
|
+
'isBigInt',
|
|
34
|
+
'isInt',
|
|
35
|
+
'isPreciseDate',
|
|
36
|
+
'isJson',
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* A {@link TypeScriptDecoratorsRenderer} that adds Google Spanner decorators from the Causa Google runtime.
|
|
40
|
+
*
|
|
41
|
+
* If an object schema is marked with the `tsGoogleSpannerTable` attribute, the `@SpannerTable` decorator is added to
|
|
42
|
+
* the class, and `@SpannerColumn` decorators are added to all its properties.
|
|
43
|
+
*/
|
|
44
|
+
export class GoogleSpannerRenderer extends TypeScriptDecoratorsRenderer {
|
|
45
|
+
decoratorsForClass(context) {
|
|
46
|
+
const tableAttribute = context.objectAttributes[GOOGLE_SPANNER_TABLE_ATTRIBUTE];
|
|
47
|
+
if (!tableAttribute) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
if (typeof tableAttribute !== 'object' ||
|
|
51
|
+
!('primaryKey' in tableAttribute) ||
|
|
52
|
+
!Array.isArray(tableAttribute.primaryKey)) {
|
|
53
|
+
panic(`Invalid ${GOOGLE_SPANNER_TABLE_ATTRIBUTE} attribute on ${context.classType.getNames()}`);
|
|
54
|
+
}
|
|
55
|
+
const optionsSource = typeScriptSourceForObject(tableAttribute);
|
|
56
|
+
const decorators = [];
|
|
57
|
+
this.addDecoratorToList(decorators, context, 'SpannerTable', CAUSA_GOOGLE_MODULE, ['@SpannerTable(', optionsSource, ')']);
|
|
58
|
+
return decorators;
|
|
59
|
+
}
|
|
60
|
+
decoratorsForProperty(context) {
|
|
61
|
+
if (!context.objectAttributes[GOOGLE_SPANNER_TABLE_ATTRIBUTE] &&
|
|
62
|
+
!context.objectAttributes[GOOGLE_SPANNER_NESTED_TYPE_ATTRIBUTE]) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
const rawColumnAttributes = context.propertyAttributes[GOOGLE_SPANNER_COLUMN_ATTRIBUTE] ?? {};
|
|
66
|
+
const columnAttributes = typeof rawColumnAttributes === 'object' ? rawColumnAttributes : {};
|
|
67
|
+
const softDeletionColumn = this.decoratorOptions[GOOGLE_SPANNER_SOFT_DELETION_COLUMN_OPTION];
|
|
68
|
+
if (softDeletionColumn && context.jsonName === softDeletionColumn) {
|
|
69
|
+
columnAttributes.softDelete = true;
|
|
70
|
+
}
|
|
71
|
+
if (!context.propertyAttributes.tsType) {
|
|
72
|
+
const singleTypeInfo = getSingleType(context.property.type);
|
|
73
|
+
const schemaOverridesTypeInfo = TYPE_INFO_COLUMN_ATTRIBUTE_NAMES.some((name) => name in columnAttributes);
|
|
74
|
+
if (!schemaOverridesTypeInfo && singleTypeInfo) {
|
|
75
|
+
switch (singleTypeInfo.type.kind) {
|
|
76
|
+
case 'class':
|
|
77
|
+
case 'object':
|
|
78
|
+
case 'map':
|
|
79
|
+
columnAttributes.isJson = true;
|
|
80
|
+
break;
|
|
81
|
+
case 'integer':
|
|
82
|
+
columnAttributes.isInt = true;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const optionsSource = typeScriptSourceForObject(columnAttributes, {
|
|
88
|
+
encoder: (key, value) => key === 'nestedType' ? value : JSON.stringify(value),
|
|
89
|
+
});
|
|
90
|
+
const decorators = [];
|
|
91
|
+
this.addDecoratorToList(decorators, context, 'SpannerColumn', CAUSA_GOOGLE_MODULE, ['@SpannerColumn(', optionsSource, ')']);
|
|
92
|
+
return decorators;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { GoogleSpannerRenderer } from './google-spanner-renderer.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { GoogleSpannerRenderer } from './google-spanner-renderer.js';
|
|
@@ -22,9 +22,17 @@ export declare class EmulatorStartForSpanner extends EmulatorStart {
|
|
|
22
22
|
* @returns The configuration for the Spanner emulator.
|
|
23
23
|
*/
|
|
24
24
|
private startSpannerEmulator;
|
|
25
|
+
/**
|
|
26
|
+
* Creates the Spanner instance and databases within the emulator.
|
|
27
|
+
*
|
|
28
|
+
* @param context The {@link WorkspaceContext}.
|
|
29
|
+
* @returns The configuration for the created instance and databases.
|
|
30
|
+
*/
|
|
31
|
+
private initializeEmulator;
|
|
25
32
|
/**
|
|
26
33
|
* Creates a local instance within the Spanner emulator.
|
|
27
34
|
*
|
|
35
|
+
* @param spanner The {@link Spanner} client.
|
|
28
36
|
* @param context The {@link WorkspaceContext}.
|
|
29
37
|
* @returns The created Spanner {@link Instance} and the corresponding client configuration.
|
|
30
38
|
*/
|
|
@@ -27,10 +27,9 @@ export class EmulatorStartForSpanner extends EmulatorStart {
|
|
|
27
27
|
return {};
|
|
28
28
|
}
|
|
29
29
|
const emulatorConf = await this.startSpannerEmulator(context);
|
|
30
|
-
const
|
|
31
|
-
const databaseConf = await this.createDatabases(instance, context);
|
|
30
|
+
const instanceAndDatabaseConf = await this.initializeEmulator(context);
|
|
32
31
|
context.logger.info('🗃️ Successfully initialized Spanner emulator.');
|
|
33
|
-
return { ...emulatorConf, ...
|
|
32
|
+
return { ...emulatorConf, ...instanceAndDatabaseConf };
|
|
34
33
|
}
|
|
35
34
|
/**
|
|
36
35
|
* Starts the Spanner emulator.
|
|
@@ -61,22 +60,35 @@ export class EmulatorStartForSpanner extends EmulatorStart {
|
|
|
61
60
|
};
|
|
62
61
|
}
|
|
63
62
|
/**
|
|
64
|
-
* Creates
|
|
63
|
+
* Creates the Spanner instance and databases within the emulator.
|
|
65
64
|
*
|
|
66
65
|
* @param context The {@link WorkspaceContext}.
|
|
67
|
-
* @returns The
|
|
66
|
+
* @returns The configuration for the created instance and databases.
|
|
68
67
|
*/
|
|
69
|
-
async
|
|
70
|
-
const instanceName = context
|
|
71
|
-
.asConfiguration()
|
|
72
|
-
.get('google.spanner.emulator.instanceName') ?? 'local';
|
|
73
|
-
context.logger.info(`🗃️ Creating Spanner emulator instance '${instanceName}'.`);
|
|
68
|
+
async initializeEmulator(context) {
|
|
74
69
|
const spanner = new Spanner({
|
|
75
70
|
servicePath: '127.0.0.1',
|
|
76
71
|
port: SPANNER_GRPC_PORT,
|
|
77
72
|
projectId: getLocalGcpProject(context),
|
|
78
73
|
sslCreds: credentials.createInsecure(),
|
|
79
74
|
});
|
|
75
|
+
const { instance, instanceConf } = await this.createInstance(spanner, context);
|
|
76
|
+
const databaseConf = await this.createDatabases(instance, context);
|
|
77
|
+
spanner.close();
|
|
78
|
+
return { ...instanceConf, ...databaseConf };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Creates a local instance within the Spanner emulator.
|
|
82
|
+
*
|
|
83
|
+
* @param spanner The {@link Spanner} client.
|
|
84
|
+
* @param context The {@link WorkspaceContext}.
|
|
85
|
+
* @returns The created Spanner {@link Instance} and the corresponding client configuration.
|
|
86
|
+
*/
|
|
87
|
+
async createInstance(spanner, context) {
|
|
88
|
+
const instanceName = context
|
|
89
|
+
.asConfiguration()
|
|
90
|
+
.get('google.spanner.emulator.instanceName') ?? 'local';
|
|
91
|
+
context.logger.info(`🗃️ Creating Spanner emulator instance '${instanceName}'.`);
|
|
80
92
|
const [instance, operation] = await spanner.createInstance(instanceName, {
|
|
81
93
|
config: 'emulator-config',
|
|
82
94
|
displayName: instanceName,
|
|
@@ -98,8 +110,11 @@ export class EmulatorStartForSpanner extends EmulatorStart {
|
|
|
98
110
|
context.logger.info(`🗃️ Creating Spanner emulator database '${database.id}'.`);
|
|
99
111
|
// Discarding `DROP TABLE` statements as the emulator does not seem to handle them properly.
|
|
100
112
|
const ddls = database.ddls.filter((statement) => !statement.toUpperCase().startsWith('DROP TABLE'));
|
|
101
|
-
const operation =
|
|
113
|
+
const [db, operation] = await instance.createDatabase(database.id, {
|
|
114
|
+
schema: ddls,
|
|
115
|
+
});
|
|
102
116
|
await operation.promise();
|
|
117
|
+
await db.close();
|
|
103
118
|
}));
|
|
104
119
|
return databases.length === 0
|
|
105
120
|
? {}
|
|
@@ -21,7 +21,7 @@ const TOKEN_TTL = 3600;
|
|
|
21
21
|
/**
|
|
22
22
|
* Generates a new AppCheck token.
|
|
23
23
|
*/
|
|
24
|
-
|
|
24
|
+
let GoogleAppCheckGenerateToken = class GoogleAppCheckGenerateToken extends WorkspaceFunction {
|
|
25
25
|
/**
|
|
26
26
|
* The ID of the Firebase app for which the token will be generated.
|
|
27
27
|
* If `undefined`, a Firebase app ID will be found in the configuration or using the API.
|
|
@@ -64,3 +64,4 @@ If the Firebase app ID is not specified, it will:
|
|
|
64
64
|
outputFn: (token) => console.log(token),
|
|
65
65
|
})
|
|
66
66
|
], GoogleAppCheckGenerateToken);
|
|
67
|
+
export { GoogleAppCheckGenerateToken };
|
|
@@ -27,7 +27,7 @@ const DEFAULT_FIREBASE_STORAGE_SECURITY_RULE_FILE = 'storage.rules';
|
|
|
27
27
|
* Returns a configuration with `google.firebaseStorage.securityRuleFile` set, such that the function can be used as a
|
|
28
28
|
* processor.
|
|
29
29
|
*/
|
|
30
|
-
|
|
30
|
+
let GoogleFirebaseStorageMergeRules = class GoogleFirebaseStorageMergeRules extends WorkspaceFunction {
|
|
31
31
|
tearDown;
|
|
32
32
|
async _call(context) {
|
|
33
33
|
if (this.tearDown) {
|
|
@@ -69,3 +69,4 @@ Input files are looked for in the workspace using the globs defined in google.fi
|
|
|
69
69
|
outputFn: ({ securityRuleFile }) => console.log(securityRuleFile),
|
|
70
70
|
})
|
|
71
71
|
], GoogleFirebaseStorageMergeRules);
|
|
72
|
+
export { GoogleFirebaseStorageMergeRules };
|
|
@@ -27,7 +27,7 @@ const DEFAULT_FIRESTORE_SECURITY_RULE_FILE = 'firestore.rules';
|
|
|
27
27
|
* Returns a configuration with `google.firestore.securityRuleFile` set, such that the function can be used as a
|
|
28
28
|
* processor.
|
|
29
29
|
*/
|
|
30
|
-
|
|
30
|
+
let GoogleFirestoreMergeRules = class GoogleFirestoreMergeRules extends WorkspaceFunction {
|
|
31
31
|
tearDown;
|
|
32
32
|
async _call(context) {
|
|
33
33
|
if (this.tearDown) {
|
|
@@ -69,3 +69,4 @@ Input files are looked for in the workspace using the globs defined in google.fi
|
|
|
69
69
|
outputFn: ({ securityRuleFile }) => console.log(securityRuleFile),
|
|
70
70
|
})
|
|
71
71
|
], GoogleFirestoreMergeRules);
|
|
72
|
+
export { GoogleFirestoreMergeRules };
|
|
@@ -21,7 +21,7 @@ import { GoogleIdentityPlatformGenerateCustomToken } from './generate-custom-tok
|
|
|
21
21
|
* For this function to succeed, the `google.project` should be set, which usually means setting the environment in the
|
|
22
22
|
* context. Also `google.firebase` children can be used to configure (and speed up) how tokens are generated.
|
|
23
23
|
*/
|
|
24
|
-
|
|
24
|
+
let GoogleIdentityPlatformGenerateToken = class GoogleIdentityPlatformGenerateToken extends WorkspaceFunction {
|
|
25
25
|
/**
|
|
26
26
|
* The ID of the user for which the token will be generated.
|
|
27
27
|
*/
|
|
@@ -71,3 +71,4 @@ Optional custom claims can be included in the signed token.`,
|
|
|
71
71
|
outputFn: (token) => console.log(token),
|
|
72
72
|
})
|
|
73
73
|
], GoogleIdentityPlatformGenerateToken);
|
|
74
|
+
export { GoogleIdentityPlatformGenerateToken };
|
|
@@ -20,7 +20,7 @@ const MAX_SERVICE_BATCH = 20;
|
|
|
20
20
|
/**
|
|
21
21
|
* Enables GCP services defined in `google.services` for the GCP project defined in `google.project`.
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
let GoogleServicesEnable = class GoogleServicesEnable extends WorkspaceFunction {
|
|
24
24
|
tearDown;
|
|
25
25
|
async _call(context) {
|
|
26
26
|
if (this.tearDown) {
|
|
@@ -72,3 +72,4 @@ They will be enabled in the 'google.project' GCP project.`,
|
|
|
72
72
|
outputFn: ({ services }) => console.log(services.join('\n')),
|
|
73
73
|
})
|
|
74
74
|
], GoogleServicesEnable);
|
|
75
|
+
export { GoogleServicesEnable };
|
package/dist/functions/index.js
CHANGED
|
@@ -8,7 +8,8 @@ import { GooglePubSubWriteTopics } from './google-pubsub/index.js';
|
|
|
8
8
|
import { GoogleServicesEnable } from './google-services/index.js';
|
|
9
9
|
import { GoogleSpannerListDatabases, GoogleSpannerWriteDatabases, } from './google-spanner/index.js';
|
|
10
10
|
import { ProjectGetArtefactDestinationForCloudFunctions, ProjectGetArtefactDestinationForCloudRun, ProjectPushArtefactForCloudFunctions, } from './project/index.js';
|
|
11
|
-
import { SecretFetchForGoogleSecretManager } from './secret/index.js';
|
|
11
|
+
import { SecretFetchForGoogleAccessToken, SecretFetchForGoogleSecretManager, } from './secret/index.js';
|
|
12
|
+
import { TypeScriptGetDecoratorRendererForGoogleSpanner } from './typescript/index.js';
|
|
12
13
|
export function registerFunctions(context) {
|
|
13
|
-
context.registerFunctionImplementations(EmulatorStartForFirebaseStorage, EmulatorStartForFirestore, EmulatorStartForIdentityPlatform, EmulatorStartForPubSub, EmulatorStartForSpanner, EmulatorStopForFirebaseStorage, EmulatorStopForFirestore, EmulatorStopForIdentityPlatform, EmulatorStopForPubSub, EmulatorStopForSpanner, EventTopicBrokerCreateTopicForPubSub, EventTopicBrokerCreateTriggerForCloudRun, EventTopicBrokerDeleteTopicForPubSub, EventTopicBrokerDeleteTriggerResourceForCloudRunInvokerRole, EventTopicBrokerDeleteTriggerResourceForPubSubSubscription, EventTopicBrokerDeleteTriggerResourceForServiceAccount, EventTopicBrokerGetTopicIdForPubSub, EventTopicBrokerPublishEventsForGoogle, GoogleAppCheckGenerateToken, GoogleFirebaseStorageMergeRules, GoogleFirestoreMergeRules, GoogleIdentityPlatformGenerateCustomToken, GoogleIdentityPlatformGenerateToken, GooglePubSubWriteTopics, GoogleServicesEnable, GoogleSpannerListDatabases, GoogleSpannerWriteDatabases, ProjectGetArtefactDestinationForCloudFunctions, ProjectGetArtefactDestinationForCloudRun, ProjectPushArtefactForCloudFunctions, SecretFetchForGoogleSecretManager);
|
|
14
|
+
context.registerFunctionImplementations(EmulatorStartForFirebaseStorage, EmulatorStartForFirestore, EmulatorStartForIdentityPlatform, EmulatorStartForPubSub, EmulatorStartForSpanner, EmulatorStopForFirebaseStorage, EmulatorStopForFirestore, EmulatorStopForIdentityPlatform, EmulatorStopForPubSub, EmulatorStopForSpanner, EventTopicBrokerCreateTopicForPubSub, EventTopicBrokerCreateTriggerForCloudRun, EventTopicBrokerDeleteTopicForPubSub, EventTopicBrokerDeleteTriggerResourceForCloudRunInvokerRole, EventTopicBrokerDeleteTriggerResourceForPubSubSubscription, EventTopicBrokerDeleteTriggerResourceForServiceAccount, EventTopicBrokerGetTopicIdForPubSub, EventTopicBrokerPublishEventsForGoogle, GoogleAppCheckGenerateToken, GoogleFirebaseStorageMergeRules, GoogleFirestoreMergeRules, GoogleIdentityPlatformGenerateCustomToken, GoogleIdentityPlatformGenerateToken, GooglePubSubWriteTopics, GoogleServicesEnable, GoogleSpannerListDatabases, GoogleSpannerWriteDatabases, ProjectGetArtefactDestinationForCloudFunctions, ProjectGetArtefactDestinationForCloudRun, ProjectPushArtefactForCloudFunctions, SecretFetchForGoogleAccessToken, SecretFetchForGoogleSecretManager, TypeScriptGetDecoratorRendererForGoogleSpanner);
|
|
14
15
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SecretFetch, WorkspaceContext } from '@causa/workspace';
|
|
2
|
+
/**
|
|
3
|
+
* An error thrown when the auth client does not return a token.
|
|
4
|
+
*/
|
|
5
|
+
export declare class AuthClientResponseError extends Error {
|
|
6
|
+
constructor();
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Implements {@link SecretFetch} to retrieve a Google access token.
|
|
10
|
+
* This backend does not require any configuration, as it does not fetch a specific secret and can only return a single
|
|
11
|
+
* value. A Google access token can be used to authenticate with other Google services. The returned token is configured
|
|
12
|
+
* with the current user (or service account)'s credentials, and for the configured GCP project (if any).
|
|
13
|
+
* The backend ID is `google.accessToken`.
|
|
14
|
+
*/
|
|
15
|
+
export declare class SecretFetchForGoogleAccessToken extends SecretFetch {
|
|
16
|
+
_call(context: WorkspaceContext): Promise<string>;
|
|
17
|
+
_supports(): boolean;
|
|
18
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SecretFetch } from '@causa/workspace';
|
|
2
|
+
import { GoogleApisService } from '../../services/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* An error thrown when the auth client does not return a token.
|
|
5
|
+
*/
|
|
6
|
+
export class AuthClientResponseError extends Error {
|
|
7
|
+
constructor() {
|
|
8
|
+
super('Failed to retrieve the Google access token from the auth client response.');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Implements {@link SecretFetch} to retrieve a Google access token.
|
|
13
|
+
* This backend does not require any configuration, as it does not fetch a specific secret and can only return a single
|
|
14
|
+
* value. A Google access token can be used to authenticate with other Google services. The returned token is configured
|
|
15
|
+
* with the current user (or service account)'s credentials, and for the configured GCP project (if any).
|
|
16
|
+
* The backend ID is `google.accessToken`.
|
|
17
|
+
*/
|
|
18
|
+
export class SecretFetchForGoogleAccessToken extends SecretFetch {
|
|
19
|
+
async _call(context) {
|
|
20
|
+
const authClient = await context.service(GoogleApisService).getAuthClient();
|
|
21
|
+
const { token } = await authClient.getAccessToken();
|
|
22
|
+
if (!token) {
|
|
23
|
+
throw new AuthClientResponseError();
|
|
24
|
+
}
|
|
25
|
+
return token;
|
|
26
|
+
}
|
|
27
|
+
_supports() {
|
|
28
|
+
return this.backend === 'google.accessToken';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { WorkspaceContext } from '@causa/workspace';
|
|
2
|
+
import { TypeScriptDecoratorsRenderer, TypeScriptGetDecoratorRenderer } from '@causa/workspace-typescript';
|
|
3
|
+
/**
|
|
4
|
+
* Implements {@link TypeScriptGetDecoratorRenderer} for the {@link GoogleSpannerRenderer}.
|
|
5
|
+
* The configuration name for the renderer is `google.spanner`.
|
|
6
|
+
*/
|
|
7
|
+
export declare class TypeScriptGetDecoratorRendererForGoogleSpanner extends TypeScriptGetDecoratorRenderer {
|
|
8
|
+
_call(): new (...args: any[]) => TypeScriptDecoratorsRenderer;
|
|
9
|
+
_supports(context: WorkspaceContext): boolean;
|
|
10
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { TypeScriptGetDecoratorRenderer, } from '@causa/workspace-typescript';
|
|
2
|
+
import { GoogleSpannerRenderer } from '../../code-generation/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Implements {@link TypeScriptGetDecoratorRenderer} for the {@link GoogleSpannerRenderer}.
|
|
5
|
+
* The configuration name for the renderer is `google.spanner`.
|
|
6
|
+
*/
|
|
7
|
+
export class TypeScriptGetDecoratorRendererForGoogleSpanner extends TypeScriptGetDecoratorRenderer {
|
|
8
|
+
_call() {
|
|
9
|
+
return GoogleSpannerRenderer;
|
|
10
|
+
}
|
|
11
|
+
_supports(context) {
|
|
12
|
+
if (context.get('project.language') !== 'typescript') {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
const decoratorRenderers = context
|
|
16
|
+
.asConfiguration()
|
|
17
|
+
.get('typescript.codeGeneration.decoratorRenderers') ?? [];
|
|
18
|
+
return (decoratorRenderers.length === 0 ||
|
|
19
|
+
decoratorRenderers.includes('google.spanner'));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { TypeScriptGetDecoratorRendererForGoogleSpanner } from './get-decorator-renderer-google-spanner.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { TypeScriptGetDecoratorRendererForGoogleSpanner } from './get-decorator-renderer-google-spanner.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { WorkspaceContext } from '@causa/workspace';
|
|
2
|
+
import { AuthClient } from 'google-auth-library';
|
|
2
3
|
import { GoogleApis } from 'googleapis';
|
|
3
4
|
import { ApiClient, OptionsOfApiClient } from './google-apis.types.js';
|
|
4
5
|
/**
|
|
@@ -9,7 +10,7 @@ export declare class GoogleApisService {
|
|
|
9
10
|
/**
|
|
10
11
|
* The GCP project ID read from the {@link WorkspaceContext} configuration.
|
|
11
12
|
*/
|
|
12
|
-
readonly projectId: string;
|
|
13
|
+
readonly projectId: string | undefined;
|
|
13
14
|
constructor(context: WorkspaceContext);
|
|
14
15
|
/**
|
|
15
16
|
* The promise returning the `JSONClient` configured with the {@link GoogleApisService.projectId}.
|
|
@@ -20,7 +21,7 @@ export declare class GoogleApisService {
|
|
|
20
21
|
*
|
|
21
22
|
* @returns The auth client.
|
|
22
23
|
*/
|
|
23
|
-
getAuthClient(): Promise<
|
|
24
|
+
getAuthClient(): Promise<AuthClient>;
|
|
24
25
|
/**
|
|
25
26
|
* Creates a new client for one of Google's APIs.
|
|
26
27
|
* Authentication is automatically configured.
|
|
@@ -9,8 +9,9 @@ export class GoogleApisService {
|
|
|
9
9
|
*/
|
|
10
10
|
projectId;
|
|
11
11
|
constructor(context) {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
this.projectId = context
|
|
13
|
+
.asConfiguration()
|
|
14
|
+
.get('google.project');
|
|
14
15
|
}
|
|
15
16
|
/**
|
|
16
17
|
* The promise returning the `JSONClient` configured with the {@link GoogleApisService.projectId}.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@causa/workspace-google",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "The Causa workspace module providing many functionalities related to GCP and its services.",
|
|
5
5
|
"repository": "github:causa-io/workspace-module-google",
|
|
6
6
|
"license": "ISC",
|
|
@@ -29,43 +29,46 @@
|
|
|
29
29
|
"test:cov": "npm run test -- --coverage"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@causa/cli": ">= 0.4.
|
|
33
|
-
"@causa/workspace": ">= 0.12.
|
|
34
|
-
"@causa/workspace-core": ">= 0.
|
|
35
|
-
"@
|
|
36
|
-
"@google-cloud/
|
|
37
|
-
"@google-cloud/
|
|
38
|
-
"@google-cloud/
|
|
39
|
-
"@google-cloud/
|
|
40
|
-
"@google-cloud/
|
|
41
|
-
"@google-cloud/
|
|
42
|
-
"@google-cloud/
|
|
43
|
-
"@google-cloud/
|
|
44
|
-
"@google-cloud/
|
|
45
|
-
"@
|
|
32
|
+
"@causa/cli": ">= 0.4.1 < 1.0.0",
|
|
33
|
+
"@causa/workspace": ">= 0.12.1 < 1.0.0",
|
|
34
|
+
"@causa/workspace-core": ">= 0.19.1 < 1.0.0",
|
|
35
|
+
"@causa/workspace-typescript": ">= 0.7.0",
|
|
36
|
+
"@google-cloud/apikeys": "^1.0.1",
|
|
37
|
+
"@google-cloud/bigquery": "^7.3.0",
|
|
38
|
+
"@google-cloud/iam-credentials": "^3.0.1",
|
|
39
|
+
"@google-cloud/pubsub": "^4.0.6",
|
|
40
|
+
"@google-cloud/resource-manager": "^5.0.1",
|
|
41
|
+
"@google-cloud/run": "^1.0.2",
|
|
42
|
+
"@google-cloud/secret-manager": "^5.0.1",
|
|
43
|
+
"@google-cloud/service-usage": "^3.1.0",
|
|
44
|
+
"@google-cloud/spanner": "^7.0.0",
|
|
45
|
+
"@google-cloud/storage": "^7.5.0",
|
|
46
|
+
"@grpc/grpc-js": "^1.9.9",
|
|
46
47
|
"class-validator": "^0.14.0",
|
|
47
|
-
"firebase": "^10.
|
|
48
|
-
"firebase-admin": "^11.
|
|
48
|
+
"firebase": "^10.5.2",
|
|
49
|
+
"firebase-admin": "^11.11.0",
|
|
49
50
|
"globby": "^13.2.2",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
51
|
+
"google-auth-library": "^9.2.0",
|
|
52
|
+
"googleapis": "^128.0.0",
|
|
53
|
+
"pino": "^8.16.1",
|
|
54
|
+
"quicktype-core": "^23.0.77",
|
|
55
|
+
"uuid": "^9.0.1"
|
|
53
56
|
},
|
|
54
57
|
"devDependencies": {
|
|
55
|
-
"@tsconfig/node18": "^18.2.
|
|
56
|
-
"@types/jest": "^29.5.
|
|
57
|
-
"@types/node": "^18.
|
|
58
|
-
"@types/uuid": "^9.0.
|
|
59
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
58
|
+
"@tsconfig/node18": "^18.2.2",
|
|
59
|
+
"@types/jest": "^29.5.7",
|
|
60
|
+
"@types/node": "^18.18.8",
|
|
61
|
+
"@types/uuid": "^9.0.6",
|
|
62
|
+
"@typescript-eslint/eslint-plugin": "^6.9.1",
|
|
60
63
|
"copyfiles": "^2.4.1",
|
|
61
|
-
"eslint": "^8.
|
|
62
|
-
"eslint-config-prettier": "^
|
|
63
|
-
"eslint-plugin-prettier": "^5.0.
|
|
64
|
-
"jest": "^29.
|
|
65
|
-
"jest-extended": "^4.0.
|
|
66
|
-
"rimraf": "^5.0.
|
|
64
|
+
"eslint": "^8.52.0",
|
|
65
|
+
"eslint-config-prettier": "^9.0.0",
|
|
66
|
+
"eslint-plugin-prettier": "^5.0.1",
|
|
67
|
+
"jest": "^29.7.0",
|
|
68
|
+
"jest-extended": "^4.0.2",
|
|
69
|
+
"rimraf": "^5.0.5",
|
|
67
70
|
"ts-jest": "^29.1.1",
|
|
68
71
|
"ts-node": "^10.9.1",
|
|
69
|
-
"typescript": "^5.
|
|
72
|
+
"typescript": "^5.2.2"
|
|
70
73
|
}
|
|
71
74
|
}
|