mirror of
https://github.com/jambonz/jambonz-api-server.git
synced 2026-01-25 02:08:24 +00:00
feat google storage (#207)
* feat google storage * feat google storage * add google storage writablestream * add google storage writablestream * add google storage writablestream * add metadata to google storage * add metadata to google storage * add metadata to google storage * add tags to google storage * fix * fix * fix * fix
This commit is contained in:
41
lib/record/google-storage.js
Normal file
41
lib/record/google-storage.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
const { Storage } = require('@google-cloud/storage');
|
||||||
|
const { Writable } = require('stream');
|
||||||
|
|
||||||
|
class GoogleStorageUploadStream extends Writable {
|
||||||
|
|
||||||
|
constructor(logger, opts) {
|
||||||
|
super(opts);
|
||||||
|
this.logger = logger;
|
||||||
|
this.metadata = opts.metadata;
|
||||||
|
|
||||||
|
const storage = new Storage(opts.bucketCredential);
|
||||||
|
this.gcsFile = storage.bucket(opts.bucketName).file(opts.Key);
|
||||||
|
this.writeStream = this.gcsFile.createWriteStream();
|
||||||
|
|
||||||
|
this.writeStream.on('error', (err) => this.logger.error(err));
|
||||||
|
this.writeStream.on('finish', () => {
|
||||||
|
this.logger.info('google storage Upload completed.');
|
||||||
|
this._addMetadata();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_write(chunk, encoding, callback) {
|
||||||
|
this.writeStream.write(chunk, encoding, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
_final(callback) {
|
||||||
|
this.writeStream.end();
|
||||||
|
this.writeStream.once('finish', callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _addMetadata() {
|
||||||
|
try {
|
||||||
|
await this.gcsFile.setMetadata({metadata: this.metadata});
|
||||||
|
this.logger.info('Google storage Upload and metadata setting completed.');
|
||||||
|
} catch (err) {
|
||||||
|
this.logger.error(err, 'Google storage An error occurred while setting metadata');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = GoogleStorageUploadStream;
|
||||||
@@ -1,17 +1,6 @@
|
|||||||
|
|
||||||
const path = require('node:path');
|
async function record(logger, socket) {
|
||||||
async function record(logger, socket, url) {
|
return require('./upload')(logger, socket);
|
||||||
const p = path.basename(url);
|
|
||||||
const idx = p.lastIndexOf('/');
|
|
||||||
const vendor = p.substring(idx + 1);
|
|
||||||
switch (vendor) {
|
|
||||||
case 'aws_s3':
|
|
||||||
return require('./s3')(logger, socket);
|
|
||||||
default:
|
|
||||||
logger.info(`unknown bucket vendor: ${vendor}`);
|
|
||||||
socket.send(`unknown bucket vendor: ${vendor}`);
|
|
||||||
socket.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = record;
|
module.exports = record;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const Account = require('../models/account');
|
const Account = require('../models/account');
|
||||||
const Websocket = require('ws');
|
const Websocket = require('ws');
|
||||||
const PCMToMP3Encoder = require('./encoder');
|
const PCMToMP3Encoder = require('./encoder');
|
||||||
const S3MultipartUploadStream = require('./s3-multipart-upload-stream');
|
|
||||||
const wav = require('wav');
|
const wav = require('wav');
|
||||||
|
const { getUploader } = require('./utils');
|
||||||
|
|
||||||
async function upload(logger, socket) {
|
async function upload(logger, socket) {
|
||||||
|
|
||||||
@@ -43,19 +43,11 @@ async function upload(logger, socket) {
|
|||||||
Key += `/${day.getDate().toString().padStart(2, '0')}/${callSid}.${account[0].record_format}`;
|
Key += `/${day.getDate().toString().padStart(2, '0')}/${callSid}.${account[0].record_format}`;
|
||||||
|
|
||||||
// Uploader
|
// Uploader
|
||||||
const uploaderOpts = {
|
const uploadStream = getUploader(Key, metadata, obj, logger);
|
||||||
bucketName: obj.name,
|
if (!uploadStream) {
|
||||||
Key,
|
logger.info('There is no available record uploader, close the socket.');
|
||||||
metadata,
|
socket.close();
|
||||||
bucketCredential: {
|
}
|
||||||
credentials: {
|
|
||||||
accessKeyId: obj.access_key_id,
|
|
||||||
secretAccessKey: obj.secret_access_key,
|
|
||||||
},
|
|
||||||
region: obj.region || 'us-east-1'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const uploadStream = new S3MultipartUploadStream(logger, uploaderOpts);
|
|
||||||
|
|
||||||
/**encoder */
|
/**encoder */
|
||||||
let encoder;
|
let encoder;
|
||||||
40
lib/record/utils.js
Normal file
40
lib/record/utils.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
const GoogleStorageUploadStream = require('./google-storage');
|
||||||
|
const S3MultipartUploadStream = require('./s3-multipart-upload-stream');
|
||||||
|
|
||||||
|
const getUploader = (Key, metadata, bucket_credential, logger) => {
|
||||||
|
const uploaderOpts = {
|
||||||
|
bucketName: bucket_credential.name,
|
||||||
|
Key,
|
||||||
|
metadata
|
||||||
|
};
|
||||||
|
switch (bucket_credential.vendor) {
|
||||||
|
case 'aws_s3':
|
||||||
|
uploaderOpts.bucketCredential = {
|
||||||
|
credentials: {
|
||||||
|
accessKeyId: bucket_credential.access_key_id,
|
||||||
|
secretAccessKey: bucket_credential.secret_access_key,
|
||||||
|
},
|
||||||
|
region: bucket_credential.region || 'us-east-1'
|
||||||
|
};
|
||||||
|
return new S3MultipartUploadStream(logger, uploaderOpts);
|
||||||
|
case 'google':
|
||||||
|
const serviceKey = JSON.parse(bucket_credential.service_key);
|
||||||
|
uploaderOpts.bucketCredential = {
|
||||||
|
projectId: serviceKey.project_id,
|
||||||
|
credentials: {
|
||||||
|
client_email: serviceKey.client_email,
|
||||||
|
private_key: serviceKey.private_key
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return new GoogleStorageUploadStream(logger, uploaderOpts);
|
||||||
|
|
||||||
|
default:
|
||||||
|
logger.error(`unknown bucket vendor: ${bucket_credential.vendor}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getUploader
|
||||||
|
};
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
const router = require('express').Router();
|
const router = require('express').Router();
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const request = require('request');
|
const request = require('request');
|
||||||
const {DbErrorBadRequest, DbErrorForbidden, DbErrorUnprocessableRequest, DbError} = require('../../utils/errors');
|
const {DbErrorBadRequest, DbErrorForbidden, DbErrorUnprocessableRequest} = require('../../utils/errors');
|
||||||
const Account = require('../../models/account');
|
const Account = require('../../models/account');
|
||||||
const Application = require('../../models/application');
|
const Application = require('../../models/application');
|
||||||
const Webhook = require('../../models/webhook');
|
const Webhook = require('../../models/webhook');
|
||||||
@@ -23,8 +23,8 @@ const {
|
|||||||
} = require('./utils');
|
} = require('./utils');
|
||||||
const short = require('short-uuid');
|
const short = require('short-uuid');
|
||||||
const VoipCarrier = require('../../models/voip-carrier');
|
const VoipCarrier = require('../../models/voip-carrier');
|
||||||
const { encrypt, decrypt } = require('../../utils/encrypt-decrypt');
|
const { encrypt } = require('../../utils/encrypt-decrypt');
|
||||||
const { testAwsS3 } = require('../../utils/storage-utils');
|
const { testAwsS3, testGoogleStorage } = require('../../utils/storage-utils');
|
||||||
const translator = short();
|
const translator = short();
|
||||||
|
|
||||||
let idx = 0;
|
let idx = 0;
|
||||||
@@ -541,7 +541,8 @@ function encryptBucketCredential(obj) {
|
|||||||
name,
|
name,
|
||||||
access_key_id,
|
access_key_id,
|
||||||
secret_access_key,
|
secret_access_key,
|
||||||
tags
|
tags,
|
||||||
|
service_key
|
||||||
} = obj.bucket_credential;
|
} = obj.bucket_credential;
|
||||||
|
|
||||||
switch (vendor) {
|
switch (vendor) {
|
||||||
@@ -554,6 +555,11 @@ function encryptBucketCredential(obj) {
|
|||||||
secret_access_key, tags});
|
secret_access_key, tags});
|
||||||
obj.bucket_credential = encrypt(awsData);
|
obj.bucket_credential = encrypt(awsData);
|
||||||
break;
|
break;
|
||||||
|
case 'google':
|
||||||
|
assert(service_key, 'invalid aws S3 bucket credential: service_key is required');
|
||||||
|
const googleData = JSON.stringify({vendor, name, service_key, tags});
|
||||||
|
obj.bucket_credential = encrypt(googleData);
|
||||||
|
break;
|
||||||
case 'none':
|
case 'none':
|
||||||
obj.bucket_credential = null;
|
obj.bucket_credential = null;
|
||||||
break;
|
break;
|
||||||
@@ -708,35 +714,20 @@ router.post('/:sid/BucketCredentialTest', async(req, res) => {
|
|||||||
try {
|
try {
|
||||||
const account_sid = parseAccountSid(req);
|
const account_sid = parseAccountSid(req);
|
||||||
await validateRequest(req, account_sid);
|
await validateRequest(req, account_sid);
|
||||||
let {vendor, name, region, access_key_id, secret_access_key} = req.body;
|
const {vendor, name, region, access_key_id, secret_access_key, service_key} = req.body;
|
||||||
const ret = {
|
const ret = {
|
||||||
status: 'not tested'
|
status: 'not tested'
|
||||||
};
|
};
|
||||||
|
|
||||||
if (secret_access_key.endsWith('XXXXXX')) {
|
|
||||||
// this is when the password already saved in account
|
|
||||||
const service_provider_sid = req.user.hasServiceProviderAuth ? req.user.service_provider_sid : null;
|
|
||||||
const results = await Account.retrieve(account_sid, service_provider_sid);
|
|
||||||
if (results.length === 0) throw new DbError('Invalid Account Sid');
|
|
||||||
const {bucket_credential} = results[0];
|
|
||||||
if (bucket_credential) {
|
|
||||||
const o = JSON.parse(decrypt(bucket_credential));
|
|
||||||
vendor = o.vendor;
|
|
||||||
switch (vendor) {
|
|
||||||
case 'aws_s3':
|
|
||||||
name = o.name;
|
|
||||||
region = o.region;
|
|
||||||
access_key_id = o.access_key_id;
|
|
||||||
secret_access_key = o.secret_access_key;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (vendor) {
|
switch (vendor) {
|
||||||
case 'aws_s3':
|
case 'aws_s3':
|
||||||
await testAwsS3(logger, {vendor, name, region, access_key_id, secret_access_key});
|
await testAwsS3(logger, {vendor, name, region, access_key_id, secret_access_key});
|
||||||
ret.status = 'ok';
|
ret.status = 'ok';
|
||||||
break;
|
break;
|
||||||
|
case 'google':
|
||||||
|
await testGoogleStorage(logger, {vendor, name, service_key});
|
||||||
|
ret.status = 'ok';
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new DbErrorBadRequest(`Does not support test for ${vendor}`);
|
throw new DbErrorBadRequest(`Does not support test for ${vendor}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const {DbErrorBadRequest} = require('../../utils/errors');
|
|||||||
const {getHomerApiKey, getHomerSipTrace, getHomerPcap} = require('../../utils/homer-utils');
|
const {getHomerApiKey, getHomerSipTrace, getHomerPcap} = require('../../utils/homer-utils');
|
||||||
const {getJaegerTrace} = require('../../utils/jaeger-utils');
|
const {getJaegerTrace} = require('../../utils/jaeger-utils');
|
||||||
const Account = require('../../models/account');
|
const Account = require('../../models/account');
|
||||||
const { getS3Object } = require('../../utils/storage-utils');
|
const { getS3Object, getGoogleStorageObject } = require('../../utils/storage-utils');
|
||||||
|
|
||||||
const parseAccountSid = (url) => {
|
const parseAccountSid = (url) => {
|
||||||
const arr = /Accounts\/([^\/]*)/.exec(url);
|
const arr = /Accounts\/([^\/]*)/.exec(url);
|
||||||
@@ -124,22 +124,26 @@ router.get('/:call_sid/record/:year/:month/:day/:format', async(req, res) => {
|
|||||||
const r = await Account.retrieve(account_sid);
|
const r = await Account.retrieve(account_sid);
|
||||||
if (r.length === 0 || !r[0].bucket_credential) return res.sendStatus(404);
|
if (r.length === 0 || !r[0].bucket_credential) return res.sendStatus(404);
|
||||||
const {bucket_credential} = r[0];
|
const {bucket_credential} = r[0];
|
||||||
|
const getOptions = {
|
||||||
|
...bucket_credential,
|
||||||
|
key: `${year}/${month}/${day}/${call_sid}.${format || 'mp3'}`
|
||||||
|
};
|
||||||
|
let stream;
|
||||||
switch (bucket_credential.vendor) {
|
switch (bucket_credential.vendor) {
|
||||||
case 'aws_s3':
|
case 'aws_s3':
|
||||||
const getS3Options = {
|
stream = await getS3Object(logger, getOptions);
|
||||||
...bucket_credential,
|
break;
|
||||||
key: `${year}/${month}/${day}/${call_sid}.${format || 'mp3'}`
|
case 'google':
|
||||||
};
|
stream = await getGoogleStorageObject(logger, getOptions);
|
||||||
const stream = await getS3Object(logger, getS3Options);
|
|
||||||
res.set({
|
|
||||||
'Content-Type': `audio/${format || 'mp3'}`
|
|
||||||
});
|
|
||||||
stream.pipe(res);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.error(`There is no handler for fetching record from ${bucket_credential.vendor}`);
|
logger.error(`There is no handler for fetching record from ${bucket_credential.vendor}`);
|
||||||
return res.sendStatus(500);
|
return res.sendStatus(500);
|
||||||
}
|
}
|
||||||
|
res.set({
|
||||||
|
'Content-Type': `audio/${format || 'mp3'}`
|
||||||
|
});
|
||||||
|
stream.pipe(res);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error({err}, ` error retrieving recording ${call_sid}`);
|
logger.error({err}, ` error retrieving recording ${call_sid}`);
|
||||||
res.sendStatus(404);
|
res.sendStatus(404);
|
||||||
|
|||||||
1
lib/utils/jambonz-sample.text
Normal file
1
lib/utils/jambonz-sample.text
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello From Jambonz. This file was created because Record all call bucket credential test.
|
||||||
@@ -1,4 +1,42 @@
|
|||||||
const { S3Client, PutObjectCommand, GetObjectCommand } = require('@aws-sdk/client-s3');
|
const { S3Client, PutObjectCommand, GetObjectCommand } = require('@aws-sdk/client-s3');
|
||||||
|
const {Storage} = require('@google-cloud/storage');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
function testGoogleStorage(logger, opts) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const serviceKey = JSON.parse(opts.service_key);
|
||||||
|
const storage = new Storage({
|
||||||
|
projectId: serviceKey.project_id,
|
||||||
|
credentials: {
|
||||||
|
client_email: serviceKey.client_email,
|
||||||
|
private_key: serviceKey.private_key
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const blob = storage.bucket(opts.name).file('jambonz-sample.text');
|
||||||
|
|
||||||
|
fs.createReadStream(`${__dirname}/jambonz-sample.text`)
|
||||||
|
.pipe(blob.createWriteStream())
|
||||||
|
.on('error', (err) => reject(err))
|
||||||
|
.on('finish', () => resolve());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getGoogleStorageObject(logger, opts) {
|
||||||
|
const serviceKey = JSON.parse(opts.service_key);
|
||||||
|
const storage = new Storage({
|
||||||
|
projectId: serviceKey.project_id,
|
||||||
|
credentials: {
|
||||||
|
client_email: serviceKey.client_email,
|
||||||
|
private_key: serviceKey.private_key
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const bucket = storage.bucket(opts.name);
|
||||||
|
const file = bucket.file(opts.key);
|
||||||
|
|
||||||
|
return file.createReadStream();
|
||||||
|
}
|
||||||
|
|
||||||
async function testAwsS3(logger, opts) {
|
async function testAwsS3(logger, opts) {
|
||||||
const s3 = new S3Client({
|
const s3 = new S3Client({
|
||||||
@@ -38,5 +76,7 @@ async function getS3Object(logger, opts) {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
testAwsS3,
|
testAwsS3,
|
||||||
getS3Object
|
getS3Object,
|
||||||
|
testGoogleStorage,
|
||||||
|
getGoogleStorageObject
|
||||||
};
|
};
|
||||||
|
|||||||
167
package-lock.json
generated
167
package-lock.json
generated
@@ -13,6 +13,7 @@
|
|||||||
"@aws-sdk/client-transcribe": "^3.363.0",
|
"@aws-sdk/client-transcribe": "^3.363.0",
|
||||||
"@deepgram/sdk": "^1.21.0",
|
"@deepgram/sdk": "^1.21.0",
|
||||||
"@google-cloud/speech": "^5.2.0",
|
"@google-cloud/speech": "^5.2.0",
|
||||||
|
"@google-cloud/storage": "^6.12.0",
|
||||||
"@jambonz/db-helpers": "^0.9.0",
|
"@jambonz/db-helpers": "^0.9.0",
|
||||||
"@jambonz/lamejs": "^1.2.2",
|
"@jambonz/lamejs": "^1.2.2",
|
||||||
"@jambonz/realtimedb-helpers": "^0.8.6",
|
"@jambonz/realtimedb-helpers": "^0.8.6",
|
||||||
@@ -1520,6 +1521,18 @@
|
|||||||
"node": ">=12.0.0"
|
"node": ">=12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@google-cloud/paginator": {
|
||||||
|
"version": "3.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.7.tgz",
|
||||||
|
"integrity": "sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"arrify": "^2.0.0",
|
||||||
|
"extend": "^3.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@google-cloud/projectify": {
|
"node_modules/@google-cloud/projectify": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz",
|
||||||
@@ -1560,6 +1573,59 @@
|
|||||||
"uuid": "dist/bin/uuid"
|
"uuid": "dist/bin/uuid"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@google-cloud/storage": {
|
||||||
|
"version": "6.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.12.0.tgz",
|
||||||
|
"integrity": "sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@google-cloud/paginator": "^3.0.7",
|
||||||
|
"@google-cloud/projectify": "^3.0.0",
|
||||||
|
"@google-cloud/promisify": "^3.0.0",
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
|
"async-retry": "^1.3.3",
|
||||||
|
"compressible": "^2.0.12",
|
||||||
|
"duplexify": "^4.0.0",
|
||||||
|
"ent": "^2.2.0",
|
||||||
|
"extend": "^3.0.2",
|
||||||
|
"fast-xml-parser": "^4.2.2",
|
||||||
|
"gaxios": "^5.0.0",
|
||||||
|
"google-auth-library": "^8.0.1",
|
||||||
|
"mime": "^3.0.0",
|
||||||
|
"mime-types": "^2.0.8",
|
||||||
|
"p-limit": "^3.0.1",
|
||||||
|
"retry-request": "^5.0.0",
|
||||||
|
"teeny-request": "^8.0.0",
|
||||||
|
"uuid": "^8.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@google-cloud/storage/node_modules/mime": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
|
||||||
|
"bin": {
|
||||||
|
"mime": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@google-cloud/storage/node_modules/p-limit": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"yocto-queue": "^0.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@google-cloud/text-to-speech": {
|
"node_modules/@google-cloud/text-to-speech": {
|
||||||
"version": "4.2.2",
|
"version": "4.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@google-cloud/text-to-speech/-/text-to-speech-4.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@google-cloud/text-to-speech/-/text-to-speech-4.2.2.tgz",
|
||||||
@@ -3034,6 +3100,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
||||||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/async-retry": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==",
|
||||||
|
"dependencies": {
|
||||||
|
"retry": "0.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/asynckit": {
|
"node_modules/asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
@@ -3509,6 +3583,17 @@
|
|||||||
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
|
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/compressible": {
|
||||||
|
"version": "2.0.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
|
||||||
|
"integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": ">= 1.43.0 < 2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/concat-map": {
|
"node_modules/concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
@@ -8101,6 +8186,14 @@
|
|||||||
"through": "~2.3.4"
|
"through": "~2.3.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/retry": {
|
||||||
|
"version": "0.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
|
||||||
|
"integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/retry-axios": {
|
"node_modules/retry-axios": {
|
||||||
"version": "2.6.0",
|
"version": "2.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-2.6.0.tgz",
|
||||||
@@ -9504,7 +9597,6 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
},
|
},
|
||||||
@@ -10741,6 +10833,15 @@
|
|||||||
"teeny-request": "^8.0.0"
|
"teeny-request": "^8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@google-cloud/paginator": {
|
||||||
|
"version": "3.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.7.tgz",
|
||||||
|
"integrity": "sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ==",
|
||||||
|
"requires": {
|
||||||
|
"arrify": "^2.0.0",
|
||||||
|
"extend": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@google-cloud/projectify": {
|
"@google-cloud/projectify": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz",
|
||||||
@@ -10771,6 +10872,46 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@google-cloud/storage": {
|
||||||
|
"version": "6.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.12.0.tgz",
|
||||||
|
"integrity": "sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw==",
|
||||||
|
"requires": {
|
||||||
|
"@google-cloud/paginator": "^3.0.7",
|
||||||
|
"@google-cloud/projectify": "^3.0.0",
|
||||||
|
"@google-cloud/promisify": "^3.0.0",
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
|
"async-retry": "^1.3.3",
|
||||||
|
"compressible": "^2.0.12",
|
||||||
|
"duplexify": "^4.0.0",
|
||||||
|
"ent": "^2.2.0",
|
||||||
|
"extend": "^3.0.2",
|
||||||
|
"fast-xml-parser": "^4.2.2",
|
||||||
|
"gaxios": "^5.0.0",
|
||||||
|
"google-auth-library": "^8.0.1",
|
||||||
|
"mime": "^3.0.0",
|
||||||
|
"mime-types": "^2.0.8",
|
||||||
|
"p-limit": "^3.0.1",
|
||||||
|
"retry-request": "^5.0.0",
|
||||||
|
"teeny-request": "^8.0.0",
|
||||||
|
"uuid": "^8.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"mime": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="
|
||||||
|
},
|
||||||
|
"p-limit": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||||
|
"requires": {
|
||||||
|
"yocto-queue": "^0.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@google-cloud/text-to-speech": {
|
"@google-cloud/text-to-speech": {
|
||||||
"version": "4.2.2",
|
"version": "4.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@google-cloud/text-to-speech/-/text-to-speech-4.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@google-cloud/text-to-speech/-/text-to-speech-4.2.2.tgz",
|
||||||
@@ -11997,6 +12138,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
||||||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
||||||
},
|
},
|
||||||
|
"async-retry": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==",
|
||||||
|
"requires": {
|
||||||
|
"retry": "0.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"asynckit": {
|
"asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
@@ -12345,6 +12494,14 @@
|
|||||||
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
|
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"compressible": {
|
||||||
|
"version": "2.0.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
|
||||||
|
"integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
|
||||||
|
"requires": {
|
||||||
|
"mime-db": ">= 1.43.0 < 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
@@ -15774,6 +15931,11 @@
|
|||||||
"through": "~2.3.4"
|
"through": "~2.3.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"retry": {
|
||||||
|
"version": "0.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
|
||||||
|
"integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="
|
||||||
|
},
|
||||||
"retry-axios": {
|
"retry-axios": {
|
||||||
"version": "2.6.0",
|
"version": "2.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-2.6.0.tgz",
|
||||||
@@ -16828,8 +16990,7 @@
|
|||||||
"yocto-queue": {
|
"yocto-queue": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,8 @@
|
|||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"yamljs": "^0.3.0",
|
"yamljs": "^0.3.0",
|
||||||
"ws": "^8.12.1",
|
"ws": "^8.12.1",
|
||||||
"wav": "^1.0.2"
|
"wav": "^1.0.2",
|
||||||
|
"@google-cloud/storage" : "^6.12.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.39.0",
|
"eslint": "^8.39.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user