@framers/agentos-ext-google-cloud-stt 0.3.0 → 0.3.2
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/SKILL.md +3 -3
- package/dist/GoogleCloudSTTProvider.d.ts +10 -10
- package/dist/GoogleCloudSTTProvider.d.ts.map +1 -1
- package/dist/GoogleCloudSTTProvider.js +52 -25
- package/dist/GoogleCloudSTTProvider.js.map +1 -1
- package/manifest.json +1 -1
- package/package.json +2 -2
- package/src/GoogleCloudSTTProvider.ts +56 -25
package/SKILL.md
CHANGED
|
@@ -11,14 +11,14 @@ Batch speech-to-text recognition using Google Cloud Speech-to-Text V1 API.
|
|
|
11
11
|
## Setup
|
|
12
12
|
|
|
13
13
|
Provide credentials via the `GOOGLE_CLOUD_STT_CREDENTIALS` secret. Accepts either:
|
|
14
|
-
-
|
|
15
|
-
- A
|
|
14
|
+
- The service-account key itself, as JSON (any value that starts with `{`)
|
|
15
|
+
- A path to a service-account JSON key file (any other value)
|
|
16
16
|
|
|
17
17
|
Leave the secret unset to use Google's Application Default Credentials (`GOOGLE_APPLICATION_CREDENTIALS`, `gcloud auth application-default login`, or the metadata server on Google Cloud).
|
|
18
18
|
|
|
19
19
|
## Features
|
|
20
20
|
|
|
21
|
-
- WAV and FLAC files (Google reads the encoding and sample rate from the header) and raw LINEAR16 PCM
|
|
21
|
+
- WAV and FLAC files (detected from the bytes; Google reads the encoding and sample rate from the header) and raw LINEAR16 PCM, whatever MIME type the caller declares
|
|
22
22
|
- Configurable language code (BCP-47)
|
|
23
23
|
- Returns the AgentOS `SpeechTranscriptionResult`: `text` (each stretch's most likely transcript, in order), mean `confidence`, `isFinal`, and `segments` with timing when Google reports end times
|
|
24
24
|
- Batch only (`supportsStreaming: false`)
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* @file GoogleCloudSTTProvider.ts
|
|
3
3
|
* @description Batch speech-to-text provider backed by Google Cloud Speech-to-Text V1 API.
|
|
4
4
|
*
|
|
5
|
-
* Credentials are resolved from the constructor argument:
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
5
|
+
* Credentials are resolved from the constructor argument (see `clientOptionsFor`):
|
|
6
|
+
* - An empty string leaves the client on Application Default Credentials.
|
|
7
|
+
* - A string that starts with `{` is an inline service-account key, passed as `credentials`.
|
|
8
|
+
* - Any other string is a path to a service-account key file, passed as `keyFilename`.
|
|
9
9
|
*
|
|
10
10
|
* @module google-cloud-stt
|
|
11
11
|
*/
|
|
@@ -60,9 +60,9 @@ export interface AudioData {
|
|
|
60
60
|
data: Buffer;
|
|
61
61
|
/** Sample rate in Hz. Raw PCM defaults to 16000; a WAV or FLAC header supplies its own. */
|
|
62
62
|
sampleRate?: number;
|
|
63
|
-
/** MIME type, such as `'audio/wav'
|
|
63
|
+
/** MIME type, such as `'audio/wav'`. Informational: the bytes decide the encoding. */
|
|
64
64
|
mimeType?: string;
|
|
65
|
-
/** Container format, such as `'wav'
|
|
65
|
+
/** Container format, such as `'wav'`. Informational: the bytes decide the encoding. */
|
|
66
66
|
format?: string;
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
@@ -86,10 +86,10 @@ export declare class GoogleCloudSTTProvider {
|
|
|
86
86
|
/**
|
|
87
87
|
* Create a new {@link GoogleCloudSTTProvider}.
|
|
88
88
|
*
|
|
89
|
-
* @param credentials -
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
89
|
+
* @param credentials - The service-account key as JSON (a string that starts
|
|
90
|
+
* with `{`), a path to its key file, or an empty string, which leaves the
|
|
91
|
+
* client on Google's Application Default Credentials.
|
|
92
|
+
* @throws When `credentials` starts with `{` but is not valid JSON.
|
|
93
93
|
*/
|
|
94
94
|
constructor(credentials: string);
|
|
95
95
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoogleCloudSTTProvider.d.ts","sourceRoot":"","sources":["../src/GoogleCloudSTTProvider.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AAOH;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;IACjB,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,QAAQ,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACxC,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,
|
|
1
|
+
{"version":3,"file":"GoogleCloudSTTProvider.d.ts","sourceRoot":"","sources":["../src/GoogleCloudSTTProvider.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AAOH;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;IACjB,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,QAAQ,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACxC,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgED;;;;;;GAMG;AACH,qBAAa,sBAAsB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,sBAAsB;IAEjC,oCAAoC;IACpC,QAAQ,CAAC,WAAW,iCAAiC;IAErD,6DAA6D;IAC7D,QAAQ,CAAC,iBAAiB,SAAS;IAEnC,wCAAwC;IACxC,OAAO,CAAC,OAAO,CAA6B;IAE5C,4FAA4F;IAC5F,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;IAEzD;;;;;;;OAOG;gBACS,WAAW,EAAE,MAAM;IAY/B;;;;;OAKG;YACW,UAAU;IAaxB;;;;OAIG;IACH,eAAe,IAAI,MAAM;IAIzB;;;;;;;;;;OAUG;IACG,UAAU,CACd,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,yBAAyB,CAAC;CA0CtC"}
|
|
@@ -3,25 +3,35 @@
|
|
|
3
3
|
* @file GoogleCloudSTTProvider.ts
|
|
4
4
|
* @description Batch speech-to-text provider backed by Google Cloud Speech-to-Text V1 API.
|
|
5
5
|
*
|
|
6
|
-
* Credentials are resolved from the constructor argument:
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
6
|
+
* Credentials are resolved from the constructor argument (see `clientOptionsFor`):
|
|
7
|
+
* - An empty string leaves the client on Application Default Credentials.
|
|
8
|
+
* - A string that starts with `{` is an inline service-account key, passed as `credentials`.
|
|
9
|
+
* - Any other string is a path to a service-account key file, passed as `keyFilename`.
|
|
10
10
|
*
|
|
11
11
|
* @module google-cloud-stt
|
|
12
12
|
*/
|
|
13
|
+
/** True when the bytes start with a RIFF/WAVE header. */
|
|
14
|
+
function hasWavHeader(data) {
|
|
15
|
+
return data.length >= 12 && data.toString('latin1', 0, 4) === 'RIFF' && data.toString('latin1', 8, 12) === 'WAVE';
|
|
16
|
+
}
|
|
17
|
+
/** True when the bytes start with the FLAC stream marker. */
|
|
18
|
+
function hasFlacHeader(data) {
|
|
19
|
+
return data.length >= 4 && data.toString('latin1', 0, 4) === 'fLaC';
|
|
20
|
+
}
|
|
13
21
|
/**
|
|
14
22
|
* The encoding fields of the recognition config for this audio.
|
|
15
23
|
*
|
|
16
24
|
* WAV and FLAC files carry a header that states the encoding and sample rate.
|
|
17
25
|
* Google reads both from it and rejects a request whose stated values disagree
|
|
18
|
-
* (google.cloud.speech.v1 `RecognitionConfig`), so for those
|
|
26
|
+
* (google.cloud.speech.v1 `RecognitionConfig`), so for those files the
|
|
19
27
|
* encoding is left out and the sample rate is sent only when the caller gives
|
|
20
28
|
* one. Anything else is sent as raw LINEAR16 PCM.
|
|
29
|
+
*
|
|
30
|
+
* The bytes decide, not the declared type: AgentOS's speech adapter labels
|
|
31
|
+
* every buffer `audio/wav`, headerless PCM included.
|
|
21
32
|
*/
|
|
22
33
|
function encodingFor(audio) {
|
|
23
|
-
|
|
24
|
-
if (declared.includes('wav') || declared.includes('flac')) {
|
|
34
|
+
if (hasWavHeader(audio.data) || hasFlacHeader(audio.data)) {
|
|
25
35
|
return audio.sampleRate ? { sampleRateHertz: audio.sampleRate } : {};
|
|
26
36
|
}
|
|
27
37
|
return { encoding: 'LINEAR16', sampleRateHertz: audio.sampleRate ?? 16000 };
|
|
@@ -33,6 +43,32 @@ function durationSeconds(duration) {
|
|
|
33
43
|
const seconds = Number(duration.seconds ?? 0) + Number(duration.nanos ?? 0) / 1e9;
|
|
34
44
|
return Number.isFinite(seconds) ? seconds : undefined;
|
|
35
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Client options for a credentials string, decided by its content:
|
|
48
|
+
* - empty or blank: none, so the client finds Application Default Credentials;
|
|
49
|
+
* - starting with `{`: an inline service-account key, passed as `credentials`;
|
|
50
|
+
* - anything else: a path to a key file, passed as `keyFilename`.
|
|
51
|
+
*
|
|
52
|
+
* Every real key holds `/` (its https URLs) and `\` (the `\n` escapes in
|
|
53
|
+
* `private_key`), so those characters cannot tell a key from a path.
|
|
54
|
+
*
|
|
55
|
+
* @throws When the string starts with `{` but is not valid JSON. The message
|
|
56
|
+
* names GOOGLE_CLOUD_STT_CREDENTIALS and quotes none of the value.
|
|
57
|
+
*/
|
|
58
|
+
function clientOptionsFor(credentials) {
|
|
59
|
+
const text = credentials.trim();
|
|
60
|
+
if (!text)
|
|
61
|
+
return {};
|
|
62
|
+
if (!text.startsWith('{'))
|
|
63
|
+
return { keyFilename: text };
|
|
64
|
+
try {
|
|
65
|
+
return { credentials: JSON.parse(text) };
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// JSON.parse's message quotes the text near the error, and here that text is key material.
|
|
69
|
+
throw new Error('GOOGLE_CLOUD_STT_CREDENTIALS starts with "{" but is not valid JSON: give the whole service-account key, or a path to its file.');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
36
72
|
/**
|
|
37
73
|
* Google Cloud Speech-to-Text batch provider.
|
|
38
74
|
*
|
|
@@ -54,26 +90,17 @@ export class GoogleCloudSTTProvider {
|
|
|
54
90
|
/**
|
|
55
91
|
* Create a new {@link GoogleCloudSTTProvider}.
|
|
56
92
|
*
|
|
57
|
-
* @param credentials -
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
93
|
+
* @param credentials - The service-account key as JSON (a string that starts
|
|
94
|
+
* with `{`), a path to its key file, or an empty string, which leaves the
|
|
95
|
+
* client on Google's Application Default Credentials.
|
|
96
|
+
* @throws When `credentials` starts with `{` but is not valid JSON.
|
|
61
97
|
*/
|
|
62
98
|
constructor(credentials) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
else if (credentials.includes('/') || credentials.includes('\\')) {
|
|
70
|
-
// Treat as a file path.
|
|
71
|
-
this._clientOptions = { keyFilename: credentials };
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
// Treat as an inline JSON credentials object.
|
|
75
|
-
this._clientOptions = { credentials: JSON.parse(credentials) };
|
|
76
|
-
}
|
|
99
|
+
// An empty string gives no options: the Google client finds Application
|
|
100
|
+
// Default Credentials (GOOGLE_APPLICATION_CREDENTIALS, gcloud, or the
|
|
101
|
+
// metadata server) when it is first used, so the pack still loads without
|
|
102
|
+
// a configured secret.
|
|
103
|
+
this._clientOptions = clientOptionsFor(credentials);
|
|
77
104
|
}
|
|
78
105
|
// ---------------------------------------------------------------------------
|
|
79
106
|
// Private helpers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoogleCloudSTTProvider.js","sourceRoot":"","sources":["../src/GoogleCloudSTTProvider.ts"],"names":[],"mappings":"AAAA,cAAc;AACd;;;;;;;;;;GAUG;AAmEH
|
|
1
|
+
{"version":3,"file":"GoogleCloudSTTProvider.js","sourceRoot":"","sources":["../src/GoogleCloudSTTProvider.ts"],"names":[],"mappings":"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"}
|
package/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@framers/agentos-ext-google-cloud-stt",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Batch speech-to-text via Google Cloud Speech-to-Text API for AgentOS voice pipeline",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"@google-cloud/speech": "^6.0.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@framers/agentos": "^0.12.
|
|
25
|
+
"@framers/agentos": "^0.12.8",
|
|
26
26
|
"@google-cloud/speech": "^6.0.0",
|
|
27
27
|
"typescript": "^5.5.0",
|
|
28
28
|
"vitest": "^3.2.7"
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* @file GoogleCloudSTTProvider.ts
|
|
4
4
|
* @description Batch speech-to-text provider backed by Google Cloud Speech-to-Text V1 API.
|
|
5
5
|
*
|
|
6
|
-
* Credentials are resolved from the constructor argument:
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
6
|
+
* Credentials are resolved from the constructor argument (see `clientOptionsFor`):
|
|
7
|
+
* - An empty string leaves the client on Application Default Credentials.
|
|
8
|
+
* - A string that starts with `{` is an inline service-account key, passed as `credentials`.
|
|
9
|
+
* - Any other string is a path to a service-account key file, passed as `keyFilename`.
|
|
10
10
|
*
|
|
11
11
|
* @module google-cloud-stt
|
|
12
12
|
*/
|
|
@@ -70,24 +70,36 @@ export interface AudioData {
|
|
|
70
70
|
data: Buffer;
|
|
71
71
|
/** Sample rate in Hz. Raw PCM defaults to 16000; a WAV or FLAC header supplies its own. */
|
|
72
72
|
sampleRate?: number;
|
|
73
|
-
/** MIME type, such as `'audio/wav'
|
|
73
|
+
/** MIME type, such as `'audio/wav'`. Informational: the bytes decide the encoding. */
|
|
74
74
|
mimeType?: string;
|
|
75
|
-
/** Container format, such as `'wav'
|
|
75
|
+
/** Container format, such as `'wav'`. Informational: the bytes decide the encoding. */
|
|
76
76
|
format?: string;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
/** True when the bytes start with a RIFF/WAVE header. */
|
|
80
|
+
function hasWavHeader(data: Buffer): boolean {
|
|
81
|
+
return data.length >= 12 && data.toString('latin1', 0, 4) === 'RIFF' && data.toString('latin1', 8, 12) === 'WAVE';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** True when the bytes start with the FLAC stream marker. */
|
|
85
|
+
function hasFlacHeader(data: Buffer): boolean {
|
|
86
|
+
return data.length >= 4 && data.toString('latin1', 0, 4) === 'fLaC';
|
|
87
|
+
}
|
|
88
|
+
|
|
79
89
|
/**
|
|
80
90
|
* The encoding fields of the recognition config for this audio.
|
|
81
91
|
*
|
|
82
92
|
* WAV and FLAC files carry a header that states the encoding and sample rate.
|
|
83
93
|
* Google reads both from it and rejects a request whose stated values disagree
|
|
84
|
-
* (google.cloud.speech.v1 `RecognitionConfig`), so for those
|
|
94
|
+
* (google.cloud.speech.v1 `RecognitionConfig`), so for those files the
|
|
85
95
|
* encoding is left out and the sample rate is sent only when the caller gives
|
|
86
96
|
* one. Anything else is sent as raw LINEAR16 PCM.
|
|
97
|
+
*
|
|
98
|
+
* The bytes decide, not the declared type: AgentOS's speech adapter labels
|
|
99
|
+
* every buffer `audio/wav`, headerless PCM included.
|
|
87
100
|
*/
|
|
88
101
|
function encodingFor(audio: AudioData): { encoding?: string; sampleRateHertz?: number } {
|
|
89
|
-
|
|
90
|
-
if (declared.includes('wav') || declared.includes('flac')) {
|
|
102
|
+
if (hasWavHeader(audio.data) || hasFlacHeader(audio.data)) {
|
|
91
103
|
return audio.sampleRate ? { sampleRateHertz: audio.sampleRate } : {};
|
|
92
104
|
}
|
|
93
105
|
return { encoding: 'LINEAR16', sampleRateHertz: audio.sampleRate ?? 16000 };
|
|
@@ -100,6 +112,32 @@ function durationSeconds(duration: { seconds?: unknown; nanos?: unknown } | null
|
|
|
100
112
|
return Number.isFinite(seconds) ? seconds : undefined;
|
|
101
113
|
}
|
|
102
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Client options for a credentials string, decided by its content:
|
|
117
|
+
* - empty or blank: none, so the client finds Application Default Credentials;
|
|
118
|
+
* - starting with `{`: an inline service-account key, passed as `credentials`;
|
|
119
|
+
* - anything else: a path to a key file, passed as `keyFilename`.
|
|
120
|
+
*
|
|
121
|
+
* Every real key holds `/` (its https URLs) and `\` (the `\n` escapes in
|
|
122
|
+
* `private_key`), so those characters cannot tell a key from a path.
|
|
123
|
+
*
|
|
124
|
+
* @throws When the string starts with `{` but is not valid JSON. The message
|
|
125
|
+
* names GOOGLE_CLOUD_STT_CREDENTIALS and quotes none of the value.
|
|
126
|
+
*/
|
|
127
|
+
function clientOptionsFor(credentials: string): Record<string, unknown> {
|
|
128
|
+
const text = credentials.trim();
|
|
129
|
+
if (!text) return {};
|
|
130
|
+
if (!text.startsWith('{')) return { keyFilename: text };
|
|
131
|
+
try {
|
|
132
|
+
return { credentials: JSON.parse(text) as Record<string, unknown> };
|
|
133
|
+
} catch {
|
|
134
|
+
// JSON.parse's message quotes the text near the error, and here that text is key material.
|
|
135
|
+
throw new Error(
|
|
136
|
+
'GOOGLE_CLOUD_STT_CREDENTIALS starts with "{" but is not valid JSON: give the whole service-account key, or a path to its file.',
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
103
141
|
/**
|
|
104
142
|
* Google Cloud Speech-to-Text batch provider.
|
|
105
143
|
*
|
|
@@ -126,24 +164,17 @@ export class GoogleCloudSTTProvider {
|
|
|
126
164
|
/**
|
|
127
165
|
* Create a new {@link GoogleCloudSTTProvider}.
|
|
128
166
|
*
|
|
129
|
-
* @param credentials -
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
167
|
+
* @param credentials - The service-account key as JSON (a string that starts
|
|
168
|
+
* with `{`), a path to its key file, or an empty string, which leaves the
|
|
169
|
+
* client on Google's Application Default Credentials.
|
|
170
|
+
* @throws When `credentials` starts with `{` but is not valid JSON.
|
|
133
171
|
*/
|
|
134
172
|
constructor(credentials: string) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
} else if (credentials.includes('/') || credentials.includes('\\')) {
|
|
141
|
-
// Treat as a file path.
|
|
142
|
-
this._clientOptions = { keyFilename: credentials };
|
|
143
|
-
} else {
|
|
144
|
-
// Treat as an inline JSON credentials object.
|
|
145
|
-
this._clientOptions = { credentials: JSON.parse(credentials) as Record<string, unknown> };
|
|
146
|
-
}
|
|
173
|
+
// An empty string gives no options: the Google client finds Application
|
|
174
|
+
// Default Credentials (GOOGLE_APPLICATION_CREDENTIALS, gcloud, or the
|
|
175
|
+
// metadata server) when it is first used, so the pack still loads without
|
|
176
|
+
// a configured secret.
|
|
177
|
+
this._clientOptions = clientOptionsFor(credentials);
|
|
147
178
|
}
|
|
148
179
|
|
|
149
180
|
// ---------------------------------------------------------------------------
|