firebase-tools 11.20.0 → 11.22.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/lib/bin/firebase.js +1 -1
- package/lib/commands/appdistribution-distribute.js +3 -0
- package/lib/commands/ext-configure.js +2 -1
- package/lib/commands/ext-install.js +2 -2
- package/lib/deploy/extensions/planner.js +16 -9
- package/lib/deploy/extensions/tasks.js +6 -0
- package/lib/deploy/functions/prepareFunctionsUpload.js +13 -2
- package/lib/deploy/functions/runtimes/discovery/index.js +1 -1
- package/lib/deploy/functions/runtimes/index.js +5 -3
- package/lib/deploy/functions/runtimes/node/index.js +71 -26
- package/lib/deploy/functions/runtimes/node/versioning.js +4 -2
- package/lib/deploy/functions/runtimes/python/index.js +119 -0
- package/lib/emulator/auth/apiSpec.js +4 -0
- package/lib/emulator/auth/operations.js +3 -3
- package/lib/emulator/controller.js +5 -5
- package/lib/emulator/downloadableEmulators.js +3 -3
- package/lib/emulator/extensionsEmulator.js +3 -2
- package/lib/emulator/functionsEmulator.js +107 -72
- package/lib/emulator/functionsRuntimeWorker.js +4 -14
- package/lib/emulator/storage/apis/firebase.js +1 -0
- package/lib/emulator/storage/rules/manager.js +1 -1
- package/lib/emulator/storage/server.js +1 -1
- package/lib/emulator/storage/upload.js +3 -3
- package/lib/extensions/askUserForParam.js +32 -1
- package/lib/extensions/emulator/optionsHelper.js +3 -3
- package/lib/extensions/emulator/specHelper.js +17 -16
- package/lib/extensions/extensionsApi.js +16 -3
- package/lib/extensions/paramHelper.js +6 -1
- package/lib/firestore/checkDatabaseType.js +3 -3
- package/lib/frameworks/index.js +9 -8
- package/lib/frameworks/next/index.js +6 -4
- package/lib/frameworks/nuxt/index.js +18 -26
- package/lib/frameworks/nuxt/interfaces.js +2 -0
- package/lib/frameworks/nuxt/utils.js +13 -0
- package/lib/frameworks/nuxt2/index.js +91 -0
- package/lib/functional.js +10 -3
- package/lib/functions/env.js +1 -1
- package/lib/functions/python.js +21 -0
- package/lib/init/features/firestore/index.js +1 -3
- package/lib/serve/functions.js +1 -3
- package/npm-shrinkwrap.json +1805 -1171
- package/package.json +3 -3
- package/lib/deploy/functions/runtimes/golang/gomod.js +0 -74
- package/lib/deploy/functions/runtimes/golang/index.js +0 -106
- package/lib/init/features/functions/golang.js +0 -57
- package/templates/init/functions/golang/_gitignore +0 -12
- package/templates/init/functions/golang/functions.go +0 -38
|
@@ -52,7 +52,7 @@ async function build(dir) {
|
|
|
52
52
|
throw e;
|
|
53
53
|
});
|
|
54
54
|
const reasonsForBackend = [];
|
|
55
|
-
const { distDir } = await getConfig(dir);
|
|
55
|
+
const { distDir, trailingSlash } = await getConfig(dir);
|
|
56
56
|
if (await (0, utils_1.isUsingMiddleware)((0, path_1.join)(dir, distDir), false)) {
|
|
57
57
|
reasonsForBackend.push("middleware");
|
|
58
58
|
}
|
|
@@ -96,7 +96,9 @@ async function build(dir) {
|
|
|
96
96
|
source: (0, utils_1.cleanEscapedChars)(source),
|
|
97
97
|
headers,
|
|
98
98
|
}));
|
|
99
|
-
const isEveryRedirectSupported = nextJsRedirects
|
|
99
|
+
const isEveryRedirectSupported = nextJsRedirects
|
|
100
|
+
.filter((it) => !it.internal)
|
|
101
|
+
.every(utils_1.isRedirectSupportedByHosting);
|
|
100
102
|
if (!isEveryRedirectSupported) {
|
|
101
103
|
reasonsForBackend.push("advanced redirects");
|
|
102
104
|
}
|
|
@@ -134,7 +136,7 @@ async function build(dir) {
|
|
|
134
136
|
}
|
|
135
137
|
console.log("");
|
|
136
138
|
}
|
|
137
|
-
return { wantsBackend, headers, redirects, rewrites };
|
|
139
|
+
return { wantsBackend, headers, redirects, rewrites, trailingSlash };
|
|
138
140
|
}
|
|
139
141
|
exports.build = build;
|
|
140
142
|
async function init(setup) {
|
|
@@ -284,5 +286,5 @@ async function getConfig(dir) {
|
|
|
284
286
|
}
|
|
285
287
|
}
|
|
286
288
|
}
|
|
287
|
-
return Object.assign({ distDir: ".next" }, config);
|
|
289
|
+
return Object.assign({ distDir: ".next", trailingSlash: false }, config);
|
|
288
290
|
}
|
|
@@ -10,30 +10,34 @@ const utils_1 = require("../utils");
|
|
|
10
10
|
exports.name = "Nuxt";
|
|
11
11
|
exports.support = "experimental";
|
|
12
12
|
exports.type = 4;
|
|
13
|
+
const utils_2 = require("./utils");
|
|
13
14
|
const DEFAULT_BUILD_SCRIPT = ["nuxt build"];
|
|
14
15
|
async function discover(dir) {
|
|
15
16
|
if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "package.json"))))
|
|
16
17
|
return;
|
|
17
|
-
const nuxtDependency = (0, __1.findDependency)("nuxt", {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
18
|
+
const nuxtDependency = (0, __1.findDependency)("nuxt", {
|
|
19
|
+
cwd: dir,
|
|
20
|
+
depth: 0,
|
|
21
|
+
omitDev: false,
|
|
22
|
+
});
|
|
23
|
+
const version = nuxtDependency === null || nuxtDependency === void 0 ? void 0 : nuxtDependency.version;
|
|
24
|
+
const anyConfigFileExists = await (0, utils_2.nuxtConfigFilesExist)(dir);
|
|
23
25
|
if (!anyConfigFileExists && !nuxtDependency)
|
|
24
26
|
return;
|
|
25
|
-
|
|
27
|
+
if (version && (0, semver_1.gte)(version, "3.0.0-0"))
|
|
28
|
+
return { mayWantBackend: true };
|
|
29
|
+
return;
|
|
26
30
|
}
|
|
27
31
|
exports.discover = discover;
|
|
28
32
|
async function build(root) {
|
|
29
33
|
const { buildNuxt } = await (0, __1.relativeRequire)(root, "@nuxt/kit");
|
|
30
|
-
const nuxtApp = await
|
|
34
|
+
const nuxtApp = await getNuxt3App(root);
|
|
31
35
|
await (0, utils_1.warnIfCustomBuildScript)(root, exports.name, DEFAULT_BUILD_SCRIPT);
|
|
32
36
|
await buildNuxt(nuxtApp);
|
|
33
37
|
return { wantsBackend: true };
|
|
34
38
|
}
|
|
35
39
|
exports.build = build;
|
|
36
|
-
async function
|
|
40
|
+
async function getNuxt3App(cwd) {
|
|
37
41
|
const { loadNuxt } = await (0, __1.relativeRequire)(cwd, "@nuxt/kit");
|
|
38
42
|
return await loadNuxt({
|
|
39
43
|
cwd,
|
|
@@ -42,29 +46,17 @@ async function getNuxtApp(cwd) {
|
|
|
42
46
|
},
|
|
43
47
|
});
|
|
44
48
|
}
|
|
45
|
-
function isNuxt3(cwd) {
|
|
46
|
-
const { version } = (0, __1.findDependency)("nuxt", { cwd, depth: 0, omitDev: false });
|
|
47
|
-
return (0, semver_1.gte)(version, "3.0.0-0");
|
|
48
|
-
}
|
|
49
49
|
async function ɵcodegenPublicDirectory(root, dest) {
|
|
50
|
-
const
|
|
51
|
-
const distPath = isNuxt3(root) ? (0, path_1.join)(root, ".output", "public") : app.options.generate.dir;
|
|
50
|
+
const distPath = (0, path_1.join)(root, ".output", "public");
|
|
52
51
|
await (0, fs_extra_1.copy)(distPath, dest);
|
|
53
52
|
}
|
|
54
53
|
exports.ɵcodegenPublicDirectory = ɵcodegenPublicDirectory;
|
|
55
54
|
async function ɵcodegenFunctionsDirectory(sourceDir, destDir) {
|
|
56
55
|
const packageJsonBuffer = await (0, promises_1.readFile)((0, path_1.join)(sourceDir, "package.json"));
|
|
57
56
|
const packageJson = JSON.parse(packageJsonBuffer.toString());
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return { packageJson: Object.assign(Object.assign({}, packageJson), outputPackageJson), frameworksEntry: "nuxt3" };
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
const { options: { buildDir }, } = await getNuxtApp(sourceDir);
|
|
66
|
-
await (0, fs_extra_1.copy)(buildDir, (0, path_1.join)(destDir, (0, path_1.basename)(buildDir)));
|
|
67
|
-
return { packageJson };
|
|
68
|
-
}
|
|
57
|
+
const outputPackageJsonBuffer = await (0, promises_1.readFile)((0, path_1.join)(sourceDir, ".output", "server", "package.json"));
|
|
58
|
+
const outputPackageJson = JSON.parse(outputPackageJsonBuffer.toString());
|
|
59
|
+
await (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, ".output", "server"), destDir);
|
|
60
|
+
return { packageJson: Object.assign(Object.assign({}, packageJson), outputPackageJson), frameworksEntry: "nuxt3" };
|
|
69
61
|
}
|
|
70
62
|
exports.ɵcodegenFunctionsDirectory = ɵcodegenFunctionsDirectory;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.nuxtConfigFilesExist = void 0;
|
|
4
|
+
const fs_extra_1 = require("fs-extra");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
async function nuxtConfigFilesExist(dir) {
|
|
7
|
+
const configFilesExist = await Promise.all([
|
|
8
|
+
(0, fs_extra_1.pathExists)((0, path_1.join)(dir, "nuxt.config.js")),
|
|
9
|
+
(0, fs_extra_1.pathExists)((0, path_1.join)(dir, "nuxt.config.ts")),
|
|
10
|
+
]);
|
|
11
|
+
return configFilesExist.some((it) => it);
|
|
12
|
+
}
|
|
13
|
+
exports.nuxtConfigFilesExist = nuxtConfigFilesExist;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ɵcodegenFunctionsDirectory = exports.ɵcodegenPublicDirectory = exports.build = exports.discover = exports.type = exports.support = exports.name = void 0;
|
|
4
|
+
const fs_extra_1 = require("fs-extra");
|
|
5
|
+
const promises_1 = require("fs/promises");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const semver_1 = require("semver");
|
|
8
|
+
const __1 = require("..");
|
|
9
|
+
const utils_1 = require("../nuxt/utils");
|
|
10
|
+
exports.name = "Nuxt";
|
|
11
|
+
exports.support = "experimental";
|
|
12
|
+
exports.type = 2;
|
|
13
|
+
async function discover(dir) {
|
|
14
|
+
if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "package.json"))))
|
|
15
|
+
return;
|
|
16
|
+
const nuxtDependency = (0, __1.findDependency)("nuxt", {
|
|
17
|
+
cwd: dir,
|
|
18
|
+
depth: 0,
|
|
19
|
+
omitDev: false,
|
|
20
|
+
});
|
|
21
|
+
const version = nuxtDependency === null || nuxtDependency === void 0 ? void 0 : nuxtDependency.version;
|
|
22
|
+
const anyConfigFileExists = await (0, utils_1.nuxtConfigFilesExist)(dir);
|
|
23
|
+
if (!anyConfigFileExists && !nuxtDependency)
|
|
24
|
+
return;
|
|
25
|
+
if (version && (0, semver_1.lt)(version, "3.0.0-0"))
|
|
26
|
+
return { mayWantBackend: true };
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
exports.discover = discover;
|
|
30
|
+
async function getNuxtApp(cwd) {
|
|
31
|
+
return await (0, __1.relativeRequire)(cwd, "nuxt/dist/nuxt.js");
|
|
32
|
+
}
|
|
33
|
+
async function build(root) {
|
|
34
|
+
const nuxt = await getNuxtApp(root);
|
|
35
|
+
const nuxtApp = await nuxt.loadNuxt({
|
|
36
|
+
for: "build",
|
|
37
|
+
rootDir: root,
|
|
38
|
+
});
|
|
39
|
+
const { options: { ssr, target }, } = await nuxt.build(nuxtApp);
|
|
40
|
+
if (ssr === true && target === "server") {
|
|
41
|
+
return { wantsBackend: true };
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
if (ssr === false && target === "static") {
|
|
45
|
+
console.log("Firebase: Nuxt 2: Static target is not supported with `ssr: false`. Please use `target: 'server'` in your `nuxt.config.js` file.");
|
|
46
|
+
console.log("Firebase: Nuxt 2: Bundling only for client side.\n");
|
|
47
|
+
}
|
|
48
|
+
await buildAndGenerate(nuxt, root);
|
|
49
|
+
return { wantsBackend: false };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.build = build;
|
|
53
|
+
async function buildAndGenerate(nuxt, root) {
|
|
54
|
+
const nuxtApp = await nuxt.loadNuxt({
|
|
55
|
+
for: "start",
|
|
56
|
+
rootDir: root,
|
|
57
|
+
});
|
|
58
|
+
const builder = await nuxt.getBuilder(nuxtApp);
|
|
59
|
+
const generator = new nuxt.Generator(nuxtApp, builder);
|
|
60
|
+
await generator.generate({ build: false, init: true });
|
|
61
|
+
}
|
|
62
|
+
async function ɵcodegenPublicDirectory(root, dest) {
|
|
63
|
+
var _a, _b;
|
|
64
|
+
const nuxt = await getNuxtApp(root);
|
|
65
|
+
const nuxtConfig = await nuxt.loadNuxtConfig();
|
|
66
|
+
const { ssr, target } = nuxtConfig;
|
|
67
|
+
if (!(ssr === true && target === "server")) {
|
|
68
|
+
const source = ((_a = nuxtConfig === null || nuxtConfig === void 0 ? void 0 : nuxtConfig.generate) === null || _a === void 0 ? void 0 : _a.dir) !== undefined
|
|
69
|
+
? (0, path_1.join)(root, (_b = nuxtConfig === null || nuxtConfig === void 0 ? void 0 : nuxtConfig.generate) === null || _b === void 0 ? void 0 : _b.dir)
|
|
70
|
+
: (0, path_1.join)(root, "dist");
|
|
71
|
+
await (0, fs_extra_1.copy)(source, dest);
|
|
72
|
+
}
|
|
73
|
+
const staticPath = (0, path_1.join)(root, "static");
|
|
74
|
+
if (await (0, fs_extra_1.pathExists)(staticPath)) {
|
|
75
|
+
await (0, fs_extra_1.copy)(staticPath, dest);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.ɵcodegenPublicDirectory = ɵcodegenPublicDirectory;
|
|
79
|
+
async function ɵcodegenFunctionsDirectory(sourceDir, destDir) {
|
|
80
|
+
const packageJsonBuffer = await (0, promises_1.readFile)((0, path_1.join)(sourceDir, "package.json"));
|
|
81
|
+
const packageJson = JSON.parse(packageJsonBuffer.toString());
|
|
82
|
+
const nuxt = await getNuxtApp(sourceDir);
|
|
83
|
+
const nuxtConfig = await nuxt.loadNuxtConfig();
|
|
84
|
+
await (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, ".nuxt"), (0, path_1.join)(destDir, ".nuxt"));
|
|
85
|
+
if (!nuxtConfig.ssr) {
|
|
86
|
+
const nuxtConfigFile = nuxtConfig._nuxtConfigFile.split("/").pop();
|
|
87
|
+
await (0, fs_extra_1.copy)(nuxtConfig._nuxtConfigFile, (0, path_1.join)(destDir, nuxtConfigFile));
|
|
88
|
+
}
|
|
89
|
+
return { packageJson: Object.assign({}, packageJson), frameworksEntry: "nuxt" };
|
|
90
|
+
}
|
|
91
|
+
exports.ɵcodegenFunctionsDirectory = ɵcodegenFunctionsDirectory;
|
package/lib/functional.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.nullsafeVisitor = exports.mapObject = exports.partition = exports.assertExhaustive = exports.zipIn = exports.zip = exports.reduceFlat = exports.flatten = exports.flattenArray = exports.flattenObject = void 0;
|
|
3
|
+
exports.nullsafeVisitor = exports.mapObject = exports.partitionRecord = exports.partition = exports.assertExhaustive = exports.zipIn = exports.zip = exports.reduceFlat = exports.flatten = exports.flattenArray = exports.flattenObject = void 0;
|
|
4
4
|
function* flattenObject(obj) {
|
|
5
5
|
function* helper(path, obj) {
|
|
6
6
|
for (const [k, v] of Object.entries(obj)) {
|
|
@@ -56,13 +56,20 @@ function assertExhaustive(val) {
|
|
|
56
56
|
throw new Error(`Never has a value (${val}). This should be impossible`);
|
|
57
57
|
}
|
|
58
58
|
exports.assertExhaustive = assertExhaustive;
|
|
59
|
-
function partition(arr,
|
|
59
|
+
function partition(arr, predicate) {
|
|
60
60
|
return arr.reduce((acc, elem) => {
|
|
61
|
-
acc[
|
|
61
|
+
acc[predicate(elem) ? 0 : 1].push(elem);
|
|
62
62
|
return acc;
|
|
63
63
|
}, [[], []]);
|
|
64
64
|
}
|
|
65
65
|
exports.partition = partition;
|
|
66
|
+
function partitionRecord(rec, predicate) {
|
|
67
|
+
return Object.entries(rec).reduce((acc, [key, val]) => {
|
|
68
|
+
acc[predicate(key, val) ? 0 : 1][key] = val;
|
|
69
|
+
return acc;
|
|
70
|
+
}, [{}, {}]);
|
|
71
|
+
}
|
|
72
|
+
exports.partitionRecord = partitionRecord;
|
|
66
73
|
function mapObject(input, transform) {
|
|
67
74
|
const result = {};
|
|
68
75
|
for (const [k, v] of Object.entries(input)) {
|
package/lib/functions/env.js
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runWithVirtualEnv = void 0;
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const spawn = require("cross-spawn");
|
|
6
|
+
const logger_1 = require("../logger");
|
|
7
|
+
const DEFAULT_VENV_DIR = "venv";
|
|
8
|
+
function runWithVirtualEnv(commandAndArgs, cwd, envs, venvDir = DEFAULT_VENV_DIR) {
|
|
9
|
+
const activateScriptPath = process.platform === "win32" ? ["Scripts", "activate.bat"] : ["bin", "activate"];
|
|
10
|
+
const venvActivate = path.join(cwd, venvDir, ...activateScriptPath);
|
|
11
|
+
const command = process.platform === "win32" ? venvActivate : "source";
|
|
12
|
+
const args = [process.platform === "win32" ? "" : venvActivate, "&&", ...commandAndArgs];
|
|
13
|
+
logger_1.logger.debug(`Running command with virtualenv: command=${command}, args=${JSON.stringify(args)}`);
|
|
14
|
+
return spawn(command, args, {
|
|
15
|
+
shell: true,
|
|
16
|
+
cwd,
|
|
17
|
+
stdio: ["pipe", "pipe", "pipe", "pipe"],
|
|
18
|
+
env: envs,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
exports.runWithVirtualEnv = runWithVirtualEnv;
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.doSetup = void 0;
|
|
4
4
|
const logger_1 = require("../../../logger");
|
|
5
5
|
const apiEnabled = require("../../../ensureApiEnabled");
|
|
6
|
-
const ensureCloudResourceLocation_1 = require("../../../ensureCloudResourceLocation");
|
|
7
6
|
const requirePermissions_1 = require("../../../requirePermissions");
|
|
8
7
|
const checkDatabaseType_1 = require("../../../firestore/checkDatabaseType");
|
|
9
8
|
const rules = require("./rules");
|
|
@@ -21,10 +20,9 @@ async function checkProjectSetup(setup, config, options) {
|
|
|
21
20
|
if (!dbType) {
|
|
22
21
|
throw firestoreUnusedError;
|
|
23
22
|
}
|
|
24
|
-
else if (dbType !== "
|
|
23
|
+
else if (dbType !== "FIRESTORE_NATIVE") {
|
|
25
24
|
throw new error_1.FirebaseError(`It looks like this project is using Cloud Datastore or Cloud Firestore in Datastore mode. The Firebase CLI can only manage projects using Cloud Firestore in Native mode. For more information, visit https://cloud.google.com/datastore/docs/firestore-or-datastore`, { exit: 1 });
|
|
26
25
|
}
|
|
27
|
-
(0, ensureCloudResourceLocation_1.ensureLocationSet)(setup.projectLocation, "Cloud Firestore");
|
|
28
26
|
await (0, requirePermissions_1.requirePermissions)(Object.assign(Object.assign({}, options), { project: setup.projectId }));
|
|
29
27
|
}
|
|
30
28
|
async function doSetup(setup, config, options) {
|
package/lib/serve/functions.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.FunctionsServer = void 0;
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const functionsEmulator_1 = require("../emulator/functionsEmulator");
|
|
6
|
-
const functionsEmulatorUtils_1 = require("../emulator/functionsEmulatorUtils");
|
|
7
6
|
const projectUtils_1 = require("../projectUtils");
|
|
8
7
|
const auth_1 = require("../auth");
|
|
9
8
|
const projectConfig = require("../functions/projectConfig");
|
|
@@ -22,11 +21,10 @@ class FunctionsServer {
|
|
|
22
21
|
const backends = [];
|
|
23
22
|
for (const cfg of config) {
|
|
24
23
|
const functionsDir = path.join(options.config.projectDir, cfg.source);
|
|
25
|
-
const nodeMajorVersion = (0, functionsEmulatorUtils_1.parseRuntimeVersion)(cfg.runtime);
|
|
26
24
|
backends.push({
|
|
27
25
|
functionsDir,
|
|
28
26
|
codebase: cfg.codebase,
|
|
29
|
-
|
|
27
|
+
runtime: cfg.runtime,
|
|
30
28
|
env: {},
|
|
31
29
|
secretEnv: [],
|
|
32
30
|
});
|