@rmartz/envctl 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -0
- package/dist/envctl.d.ts +3 -0
- package/dist/envctl.d.ts.map +1 -0
- package/dist/envctl.js +36 -0
- package/dist/envctl.js.map +1 -0
- package/dist/lib/auth.d.ts +21 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +148 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/check-firebase.d.ts +6 -0
- package/dist/lib/check-firebase.d.ts.map +1 -0
- package/dist/lib/check-firebase.js +81 -0
- package/dist/lib/check-firebase.js.map +1 -0
- package/dist/lib/check-live.d.ts +3 -0
- package/dist/lib/check-live.d.ts.map +1 -0
- package/dist/lib/check-live.js +50 -0
- package/dist/lib/check-live.js.map +1 -0
- package/dist/lib/check.d.ts +9 -0
- package/dist/lib/check.d.ts.map +1 -0
- package/dist/lib/check.js +165 -0
- package/dist/lib/check.js.map +1 -0
- package/dist/lib/cli/help.d.ts +4 -0
- package/dist/lib/cli/help.d.ts.map +1 -0
- package/dist/lib/cli/help.js +52 -0
- package/dist/lib/cli/help.js.map +1 -0
- package/dist/lib/cli/registry.d.ts +19 -0
- package/dist/lib/cli/registry.d.ts.map +1 -0
- package/dist/lib/cli/registry.js +111 -0
- package/dist/lib/cli/registry.js.map +1 -0
- package/dist/lib/cli/router.d.ts +22 -0
- package/dist/lib/cli/router.d.ts.map +1 -0
- package/dist/lib/cli/router.js +98 -0
- package/dist/lib/cli/router.js.map +1 -0
- package/dist/lib/cli/version.d.ts +2 -0
- package/dist/lib/cli/version.d.ts.map +1 -0
- package/dist/lib/cli/version.js +58 -0
- package/dist/lib/cli/version.js.map +1 -0
- package/dist/lib/commands/auth.d.ts +2 -0
- package/dist/lib/commands/auth.d.ts.map +1 -0
- package/dist/lib/commands/auth.js +33 -0
- package/dist/lib/commands/auth.js.map +1 -0
- package/dist/lib/commands/bootstrap-args.d.ts +11 -0
- package/dist/lib/commands/bootstrap-args.d.ts.map +1 -0
- package/dist/lib/commands/bootstrap-args.js +111 -0
- package/dist/lib/commands/bootstrap-args.js.map +1 -0
- package/dist/lib/commands/bootstrap.d.ts +5 -0
- package/dist/lib/commands/bootstrap.d.ts.map +1 -0
- package/dist/lib/commands/bootstrap.js +166 -0
- package/dist/lib/commands/bootstrap.js.map +1 -0
- package/dist/lib/commands/check.d.ts +3 -0
- package/dist/lib/commands/check.d.ts.map +1 -0
- package/dist/lib/commands/check.js +47 -0
- package/dist/lib/commands/check.js.map +1 -0
- package/dist/lib/commands/config-pull.d.ts +12 -0
- package/dist/lib/commands/config-pull.d.ts.map +1 -0
- package/dist/lib/commands/config-pull.js +161 -0
- package/dist/lib/commands/config-pull.js.map +1 -0
- package/dist/lib/commands/config-push-args.d.ts +9 -0
- package/dist/lib/commands/config-push-args.d.ts.map +1 -0
- package/dist/lib/commands/config-push-args.js +108 -0
- package/dist/lib/commands/config-push-args.js.map +1 -0
- package/dist/lib/commands/config-push.d.ts +6 -0
- package/dist/lib/commands/config-push.d.ts.map +1 -0
- package/dist/lib/commands/config-push.js +166 -0
- package/dist/lib/commands/config-push.js.map +1 -0
- package/dist/lib/commands/deployment-config.d.ts +9 -0
- package/dist/lib/commands/deployment-config.d.ts.map +1 -0
- package/dist/lib/commands/deployment-config.js +73 -0
- package/dist/lib/commands/deployment-config.js.map +1 -0
- package/dist/lib/commands/env-plan.d.ts +4 -0
- package/dist/lib/commands/env-plan.d.ts.map +1 -0
- package/dist/lib/commands/env-plan.js +85 -0
- package/dist/lib/commands/env-plan.js.map +1 -0
- package/dist/lib/commands/env.d.ts +4 -0
- package/dist/lib/commands/env.d.ts.map +1 -0
- package/dist/lib/commands/env.js +122 -0
- package/dist/lib/commands/env.js.map +1 -0
- package/dist/lib/commands/init.d.ts +3 -0
- package/dist/lib/commands/init.d.ts.map +1 -0
- package/dist/lib/commands/init.js +59 -0
- package/dist/lib/commands/init.js.map +1 -0
- package/dist/lib/commands/secrets-args.d.ts +13 -0
- package/dist/lib/commands/secrets-args.d.ts.map +1 -0
- package/dist/lib/commands/secrets-args.js +136 -0
- package/dist/lib/commands/secrets-args.js.map +1 -0
- package/dist/lib/commands/secrets-plan.d.ts +9 -0
- package/dist/lib/commands/secrets-plan.d.ts.map +1 -0
- package/dist/lib/commands/secrets-plan.js +109 -0
- package/dist/lib/commands/secrets-plan.js.map +1 -0
- package/dist/lib/commands/secrets.d.ts +7 -0
- package/dist/lib/commands/secrets.d.ts.map +1 -0
- package/dist/lib/commands/secrets.js +191 -0
- package/dist/lib/commands/secrets.js.map +1 -0
- package/dist/lib/deployments.d.ts +4 -0
- package/dist/lib/deployments.d.ts.map +1 -0
- package/dist/lib/deployments.js +83 -0
- package/dist/lib/deployments.js.map +1 -0
- package/dist/lib/environments.d.ts +4 -0
- package/dist/lib/environments.d.ts.map +1 -0
- package/dist/lib/environments.js +97 -0
- package/dist/lib/environments.js.map +1 -0
- package/dist/lib/firebase-credential.d.ts +28 -0
- package/dist/lib/firebase-credential.d.ts.map +1 -0
- package/dist/lib/firebase-credential.js +50 -0
- package/dist/lib/firebase-credential.js.map +1 -0
- package/dist/lib/firebase-invalidate.d.ts +4 -0
- package/dist/lib/firebase-invalidate.d.ts.map +1 -0
- package/dist/lib/firebase-invalidate.js +61 -0
- package/dist/lib/firebase-invalidate.js.map +1 -0
- package/dist/lib/firebase-vars.d.ts +14 -0
- package/dist/lib/firebase-vars.d.ts.map +1 -0
- package/dist/lib/firebase-vars.js +40 -0
- package/dist/lib/firebase-vars.js.map +1 -0
- package/dist/lib/firebase.d.ts +20 -0
- package/dist/lib/firebase.d.ts.map +1 -0
- package/dist/lib/firebase.js +189 -0
- package/dist/lib/firebase.js.map +1 -0
- package/dist/lib/gcp.d.ts +4 -0
- package/dist/lib/gcp.d.ts.map +1 -0
- package/dist/lib/gcp.js +53 -0
- package/dist/lib/gcp.js.map +1 -0
- package/dist/lib/generated-secrets.d.ts +16 -0
- package/dist/lib/generated-secrets.d.ts.map +1 -0
- package/dist/lib/generated-secrets.js +68 -0
- package/dist/lib/generated-secrets.js.map +1 -0
- package/dist/lib/logger.d.ts +7 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +60 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/manifest/index.d.ts +6 -0
- package/dist/lib/manifest/index.d.ts.map +1 -0
- package/dist/lib/manifest/index.js +15 -0
- package/dist/lib/manifest/index.js.map +1 -0
- package/dist/lib/manifest/parse.d.ts +11 -0
- package/dist/lib/manifest/parse.d.ts.map +1 -0
- package/dist/lib/manifest/parse.js +214 -0
- package/dist/lib/manifest/parse.js.map +1 -0
- package/dist/lib/manifest/resolve.d.ts +9 -0
- package/dist/lib/manifest/resolve.d.ts.map +1 -0
- package/dist/lib/manifest/resolve.js +34 -0
- package/dist/lib/manifest/resolve.js.map +1 -0
- package/dist/lib/manifest/types.d.ts +57 -0
- package/dist/lib/manifest/types.d.ts.map +1 -0
- package/dist/lib/manifest/types.js +12 -0
- package/dist/lib/manifest/types.js.map +1 -0
- package/dist/lib/manifest/write.d.ts +3 -0
- package/dist/lib/manifest/write.d.ts.map +1 -0
- package/dist/lib/manifest/write.js +110 -0
- package/dist/lib/manifest/write.js.map +1 -0
- package/dist/lib/project.d.ts +6 -0
- package/dist/lib/project.d.ts.map +1 -0
- package/dist/lib/project.js +56 -0
- package/dist/lib/project.js.map +1 -0
- package/dist/lib/providers/deployment.d.ts +19 -0
- package/dist/lib/providers/deployment.d.ts.map +1 -0
- package/dist/lib/providers/deployment.js +62 -0
- package/dist/lib/providers/deployment.js.map +1 -0
- package/dist/lib/providers/registry.d.ts +5 -0
- package/dist/lib/providers/registry.d.ts.map +1 -0
- package/dist/lib/providers/registry.js +31 -0
- package/dist/lib/providers/registry.js.map +1 -0
- package/dist/lib/providers/service.d.ts +35 -0
- package/dist/lib/providers/service.d.ts.map +1 -0
- package/dist/lib/providers/service.js +81 -0
- package/dist/lib/providers/service.js.map +1 -0
- package/dist/lib/rotation-preflight.d.ts +11 -0
- package/dist/lib/rotation-preflight.d.ts.map +1 -0
- package/dist/lib/rotation-preflight.js +47 -0
- package/dist/lib/rotation-preflight.js.map +1 -0
- package/dist/lib/rotation.d.ts +33 -0
- package/dist/lib/rotation.d.ts.map +1 -0
- package/dist/lib/rotation.js +168 -0
- package/dist/lib/rotation.js.map +1 -0
- package/dist/lib/sentry.d.ts +5 -0
- package/dist/lib/sentry.d.ts.map +1 -0
- package/dist/lib/sentry.js +132 -0
- package/dist/lib/sentry.js.map +1 -0
- package/dist/lib/subprocess.d.ts +8 -0
- package/dist/lib/subprocess.d.ts.map +1 -0
- package/dist/lib/subprocess.js +30 -0
- package/dist/lib/subprocess.js.map +1 -0
- package/dist/lib/targets.d.ts +3 -0
- package/dist/lib/targets.d.ts.map +1 -0
- package/dist/lib/targets.js +25 -0
- package/dist/lib/targets.js.map +1 -0
- package/dist/lib/vercel-api.d.ts +50 -0
- package/dist/lib/vercel-api.d.ts.map +1 -0
- package/dist/lib/vercel-api.js +176 -0
- package/dist/lib/vercel-api.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.triggerAndWaitRedeployments = triggerAndWaitRedeployments;
|
|
4
|
+
exports.refreshPreviewDeployments = refreshPreviewDeployments;
|
|
5
|
+
const logger_1 = require("./logger");
|
|
6
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
7
|
+
function targetEnvs(targetEnv) {
|
|
8
|
+
if (targetEnv === "all")
|
|
9
|
+
return ["production", "preview", "development"];
|
|
10
|
+
return [targetEnv];
|
|
11
|
+
}
|
|
12
|
+
// Poll one redeployment and report its outcome. A `canceled` result is benign
|
|
13
|
+
// (#125): Vercel auto-cancels a redeploy when a newer build supersedes it, so
|
|
14
|
+
// verification simply didn't complete on this deployment — the pushed variables
|
|
15
|
+
// are already saved on the target and take effect on its next successful build.
|
|
16
|
+
// It is a warning, not a failure; only a genuine ERROR/timeout throws (from
|
|
17
|
+
// pollDeploymentStatus).
|
|
18
|
+
async function pollAndReport(client, id) {
|
|
19
|
+
(0, logger_1.log)(` Polling ${id}...`);
|
|
20
|
+
const status = await client.pollDeploymentStatus(id, 60, 10_000);
|
|
21
|
+
if (status === "canceled") {
|
|
22
|
+
(0, logger_1.warn)(` ${id} → CANCELED (superseded by a newer build or auto-canceled). The pushed variables are saved on the target and apply on its next successful build; verification did not complete for this deployment.`);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
(0, logger_1.log)(` ${id} → READY`);
|
|
26
|
+
}
|
|
27
|
+
return status;
|
|
28
|
+
}
|
|
29
|
+
// ─── Redeployment ─────────────────────────────────────────────────────────────
|
|
30
|
+
async function triggerAndWaitRedeployments(targetEnv, client) {
|
|
31
|
+
(0, logger_1.log)("Triggering redeployments...");
|
|
32
|
+
const deploymentIds = [];
|
|
33
|
+
for (const vercelEnv of targetEnvs(targetEnv)) {
|
|
34
|
+
if (vercelEnv === "development") {
|
|
35
|
+
(0, logger_1.log)(` [${vercelEnv}] No remote deployment target — skipping`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const deployTarget = vercelEnv === "production" ? "production" : "staging";
|
|
39
|
+
const latest = await client.getLatestDeployment(deployTarget);
|
|
40
|
+
if (!latest) {
|
|
41
|
+
(0, logger_1.warn)(`No READY deployment found for '${vercelEnv}' — skipping redeployment`);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
(0, logger_1.log)(` Redeploying ${vercelEnv} (${latest.url})...`);
|
|
45
|
+
const newId = await client.triggerRedeployment(latest.uid, latest.name, deployTarget);
|
|
46
|
+
deploymentIds.push(newId);
|
|
47
|
+
(0, logger_1.log)(` Queued: ${newId}`);
|
|
48
|
+
}
|
|
49
|
+
if (deploymentIds.length === 0)
|
|
50
|
+
return;
|
|
51
|
+
(0, logger_1.log)(`Waiting for ${deploymentIds.length} deployment(s) to finish...`);
|
|
52
|
+
let allReady = true;
|
|
53
|
+
for (const id of deploymentIds) {
|
|
54
|
+
if ((await pollAndReport(client, id)) === "canceled")
|
|
55
|
+
allReady = false;
|
|
56
|
+
}
|
|
57
|
+
(0, logger_1.log)(allReady ? "All deployments ready." : "Redeployment polling complete.");
|
|
58
|
+
}
|
|
59
|
+
async function refreshPreviewDeployments(client) {
|
|
60
|
+
const previews = await client.listPreviewDeployments();
|
|
61
|
+
if (previews.length === 0) {
|
|
62
|
+
(0, logger_1.log)("No active preview deployments found — skipping preview refresh.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
(0, logger_1.log)(`Refreshing ${previews.length} active preview deployment(s)...`);
|
|
66
|
+
const newIds = [];
|
|
67
|
+
for (const preview of previews) {
|
|
68
|
+
(0, logger_1.log)(` Redeploying ${preview.url}...`);
|
|
69
|
+
const newId = await client.triggerRedeployment(preview.uid, preview.name);
|
|
70
|
+
newIds.push(newId);
|
|
71
|
+
(0, logger_1.log)(` Queued: ${newId}`);
|
|
72
|
+
}
|
|
73
|
+
(0, logger_1.log)(`Waiting for ${newIds.length} preview deployment(s) to finish...`);
|
|
74
|
+
let allReady = true;
|
|
75
|
+
for (const id of newIds) {
|
|
76
|
+
if ((await pollAndReport(client, id)) === "canceled")
|
|
77
|
+
allReady = false;
|
|
78
|
+
}
|
|
79
|
+
(0, logger_1.log)(allReady
|
|
80
|
+
? "Preview deployments refreshed."
|
|
81
|
+
: "Preview redeployment polling complete.");
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=deployments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployments.js","sourceRoot":"","sources":["../../src/lib/deployments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function listActiveEnvs(deploymentDir: string): string[];
|
|
2
|
+
export declare function parseDeploymentEnv(deploymentDir: string, envName: string): Record<string, string>;
|
|
3
|
+
export declare function vercelTarget(envName: string): string;
|
|
4
|
+
//# sourceMappingURL=environments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environments.d.ts","sourceRoot":"","sources":["../../src/lib/environments.ts"],"names":[],"mappings":"AAiBA,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAI9D;AAED,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA8BxB;AAgBD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.listActiveEnvs = listActiveEnvs;
|
|
37
|
+
exports.parseDeploymentEnv = parseDeploymentEnv;
|
|
38
|
+
exports.vercelTarget = vercelTarget;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const yaml = __importStar(require("js-yaml"));
|
|
42
|
+
// js-yaml 5 throws "expected a document, but the input is empty" on blank
|
|
43
|
+
// input, where v4 returned undefined. Treat a blank file as null so empty
|
|
44
|
+
// configs degrade to the empty result instead of raising.
|
|
45
|
+
function loadYamlFile(filePath) {
|
|
46
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
47
|
+
return content.trim() === "" ? null : yaml.load(content);
|
|
48
|
+
}
|
|
49
|
+
function listActiveEnvs(deploymentDir) {
|
|
50
|
+
const envFile = path.join(deploymentDir, "environments.yml");
|
|
51
|
+
const data = loadYamlFile(envFile);
|
|
52
|
+
return data?.active ?? [];
|
|
53
|
+
}
|
|
54
|
+
function parseDeploymentEnv(deploymentDir, envName) {
|
|
55
|
+
const envFile = path.join(deploymentDir, `${envName}.yml`);
|
|
56
|
+
if (!fs.existsSync(envFile))
|
|
57
|
+
return {};
|
|
58
|
+
const data = loadYamlFile(envFile);
|
|
59
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
60
|
+
return {};
|
|
61
|
+
// Support nested `variables:` format ({ environment: "staging", variables: { KEY: val } })
|
|
62
|
+
// as well as flat format ({ KEY: val }).
|
|
63
|
+
const vars = data.variables !== null &&
|
|
64
|
+
data.variables !== undefined &&
|
|
65
|
+
typeof data.variables === "object" &&
|
|
66
|
+
!Array.isArray(data.variables)
|
|
67
|
+
? data.variables
|
|
68
|
+
: data;
|
|
69
|
+
const result = {};
|
|
70
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
71
|
+
if (typeof value !== "string" &&
|
|
72
|
+
typeof value !== "number" &&
|
|
73
|
+
typeof value !== "boolean")
|
|
74
|
+
continue;
|
|
75
|
+
const strValue = typeof value === "boolean" ? String(value).toLowerCase() : String(value);
|
|
76
|
+
if (strValue)
|
|
77
|
+
result[key] = strValue;
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
// The name→target convention. As of #87 this is the **fallback** used only when
|
|
82
|
+
// the manifest's authoritative `deployments[].targets` map does not declare a
|
|
83
|
+
// target for an environment (a legacy config with no `targets:` block, or an env
|
|
84
|
+
// omitted from the map). Manifest-aware resolution lives in `targets.ts`
|
|
85
|
+
// (`resolveEnvTarget` / `envTargetResolver`); prefer it over calling this
|
|
86
|
+
// directly. It is also the basis parseManifest uses to derive targets for a
|
|
87
|
+
// legacy config, so back-compat resolution is unchanged.
|
|
88
|
+
const TARGET_MAP = {
|
|
89
|
+
production: "production",
|
|
90
|
+
staging: "preview",
|
|
91
|
+
preview: "preview",
|
|
92
|
+
development: "development",
|
|
93
|
+
};
|
|
94
|
+
function vercelTarget(envName) {
|
|
95
|
+
return TARGET_MAP[envName] ?? envName;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=environments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environments.js","sourceRoot":"","sources":["../../src/lib/environments.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,wCAIC;AAED,gDAiCC;AAgBD,oCAEC;AA1ED,uCAAyB;AACzB,2CAA6B;AAE7B,8CAAgC;AAMhC,0EAA0E;AAC1E,0EAA0E;AAC1E,0DAA0D;AAC1D,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,OAAO,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC3D,CAAC;AAED,SAAgB,cAAc,CAAC,aAAqB;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAA8B,CAAC;IAChE,OAAO,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED,SAAgB,kBAAkB,CAChC,aAAqB,EACrB,OAAe;IAEf,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,OAAO,MAAM,CAAC,CAAC;IAC3D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IAEvC,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAmC,CAAC;IACrE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAExE,2FAA2F;IAC3F,yCAAyC;IACzC,MAAM,IAAI,GACR,IAAI,CAAC,SAAS,KAAK,IAAI;QACvB,IAAI,CAAC,SAAS,KAAK,SAAS;QAC5B,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ;QAClC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;QAC5B,CAAC,CAAE,IAAI,CAAC,SAAqC;QAC7C,CAAC,CAAC,IAAI,CAAC;IAEX,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IACE,OAAO,KAAK,KAAK,QAAQ;YACzB,OAAO,KAAK,KAAK,QAAQ;YACzB,OAAO,KAAK,KAAK,SAAS;YAE1B,SAAS;QACX,MAAM,QAAQ,GACZ,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3E,IAAI,QAAQ;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gFAAgF;AAChF,8EAA8E;AAC9E,iFAAiF;AACjF,yEAAyE;AACzE,0EAA0E;AAC1E,4EAA4E;AAC5E,yDAAyD;AACzD,MAAM,UAAU,GAA2B;IACzC,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,aAAa;CAC3B,CAAC;AAEF,SAAgB,YAAY,CAAC,OAAe;IAC1C,OAAO,UAAU,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ServiceDecl } from "./manifest/types";
|
|
2
|
+
/** The provider's logical credential fields. */
|
|
3
|
+
export type FirebaseField = "projectId" | "clientEmail" | "privateKey" | "privateKeyId";
|
|
4
|
+
/** The default var name for each field — the back-compat naming envctl assumed. */
|
|
5
|
+
export declare const DEFAULT_FIREBASE_VAR_NAMES: Record<FirebaseField, string>;
|
|
6
|
+
export interface FirebaseCredentialSpec {
|
|
7
|
+
/** Resolved var name for every field (declared override ?? default). */
|
|
8
|
+
readonly names: Readonly<Record<FirebaseField, string>>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a `firebase` service declaration into a concrete credential contract:
|
|
12
|
+
* the resolved var name for every field. A missing declaration (or missing
|
|
13
|
+
* fields) falls back to the default names.
|
|
14
|
+
*
|
|
15
|
+
* Throws if any override value is empty or if two fields resolve to the same
|
|
16
|
+
* var name — both produce unusable Vercel credentials.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveFirebaseCredential(service?: ServiceDecl): FirebaseCredentialSpec;
|
|
19
|
+
/**
|
|
20
|
+
* Keys whose presence in Vercel means Firebase is provisioned under the
|
|
21
|
+
* declared contract. Uses only the resolved names so the presence check is
|
|
22
|
+
* consistent with what the readers ({@link firebase-vars}) look for —
|
|
23
|
+
* advertising a legacy default name for a custom-named contract would cause
|
|
24
|
+
* `rotation.run` to detect Firebase as present but then fail inside
|
|
25
|
+
* `rotateFirebase` when the custom var can't be resolved.
|
|
26
|
+
*/
|
|
27
|
+
export declare function firebasePresenceKeys(spec: FirebaseCredentialSpec): string[];
|
|
28
|
+
//# sourceMappingURL=firebase-credential.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase-credential.d.ts","sourceRoot":"","sources":["../../src/lib/firebase-credential.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQpD,gDAAgD;AAChD,MAAM,MAAM,aAAa,GACvB,WAAW,GAAG,aAAa,GAAG,YAAY,GAAG,cAAc,CAAC;AAE9D,mFAAmF;AACnF,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAKpE,CAAC;AAIF,MAAM,WAAW,sBAAsB;IACrC,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;CACzD;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,CAAC,EAAE,WAAW,GACpB,sBAAsB,CA2BxB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,sBAAsB,GAAG,MAAM,EAAE,CAE3E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_FIREBASE_VAR_NAMES = void 0;
|
|
4
|
+
exports.resolveFirebaseCredential = resolveFirebaseCredential;
|
|
5
|
+
exports.firebasePresenceKeys = firebasePresenceKeys;
|
|
6
|
+
/** The default var name for each field — the back-compat naming envctl assumed. */
|
|
7
|
+
exports.DEFAULT_FIREBASE_VAR_NAMES = {
|
|
8
|
+
projectId: "FIREBASE_PROJECT_ID",
|
|
9
|
+
clientEmail: "FIREBASE_CLIENT_EMAIL",
|
|
10
|
+
privateKey: "FIREBASE_PRIVATE_KEY",
|
|
11
|
+
privateKeyId: "FIREBASE_PRIVATE_KEY_ID",
|
|
12
|
+
};
|
|
13
|
+
const ALL_FIELDS = Object.keys(exports.DEFAULT_FIREBASE_VAR_NAMES);
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a `firebase` service declaration into a concrete credential contract:
|
|
16
|
+
* the resolved var name for every field. A missing declaration (or missing
|
|
17
|
+
* fields) falls back to the default names.
|
|
18
|
+
*
|
|
19
|
+
* Throws if any override value is empty or if two fields resolve to the same
|
|
20
|
+
* var name — both produce unusable Vercel credentials.
|
|
21
|
+
*/
|
|
22
|
+
function resolveFirebaseCredential(service) {
|
|
23
|
+
const overrides = service?.variables ?? {};
|
|
24
|
+
for (const [field, name] of Object.entries(overrides)) {
|
|
25
|
+
if (!name || !name.trim())
|
|
26
|
+
throw new Error(`Firebase credential override for '${field}' must not be empty`);
|
|
27
|
+
}
|
|
28
|
+
const names = {};
|
|
29
|
+
for (const field of ALL_FIELDS)
|
|
30
|
+
names[field] = overrides[field] ?? exports.DEFAULT_FIREBASE_VAR_NAMES[field];
|
|
31
|
+
const seen = new Set();
|
|
32
|
+
for (const [field, name] of Object.entries(names)) {
|
|
33
|
+
if (seen.has(name))
|
|
34
|
+
throw new Error(`Firebase credential var names must be unique; '${name}' is mapped to multiple fields (including '${field}')`);
|
|
35
|
+
seen.add(name);
|
|
36
|
+
}
|
|
37
|
+
return { names };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Keys whose presence in Vercel means Firebase is provisioned under the
|
|
41
|
+
* declared contract. Uses only the resolved names so the presence check is
|
|
42
|
+
* consistent with what the readers ({@link firebase-vars}) look for —
|
|
43
|
+
* advertising a legacy default name for a custom-named contract would cause
|
|
44
|
+
* `rotation.run` to detect Firebase as present but then fail inside
|
|
45
|
+
* `rotateFirebase` when the custom var can't be resolved.
|
|
46
|
+
*/
|
|
47
|
+
function firebasePresenceKeys(spec) {
|
|
48
|
+
return [spec.names.privateKey];
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=firebase-credential.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase-credential.js","sourceRoot":"","sources":["../../src/lib/firebase-credential.ts"],"names":[],"mappings":";;;AAmCA,8DA6BC;AAUD,oDAEC;AAhED,mFAAmF;AACtE,QAAA,0BAA0B,GAAkC;IACvE,SAAS,EAAE,qBAAqB;IAChC,WAAW,EAAE,uBAAuB;IACpC,UAAU,EAAE,sBAAsB;IAClC,YAAY,EAAE,yBAAyB;CACxC,CAAC;AAEF,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,kCAA0B,CAAoB,CAAC;AAO9E;;;;;;;GAOG;AACH,SAAgB,yBAAyB,CACvC,OAAqB;IAErB,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACtD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YACvB,MAAM,IAAI,KAAK,CACb,qCAAqC,KAAK,qBAAqB,CAChE,CAAC;IACN,CAAC;IAED,MAAM,KAAK,GAAG,EAAmC,CAAC;IAClD,KAAK,MAAM,KAAK,IAAI,UAAU;QAC5B,KAAK,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,kCAA0B,CAAC,KAAK,CAAC,CAAC;IAEvE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAG7C,EAAE,CAAC;QACJ,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAChB,MAAM,IAAI,KAAK,CACb,kDAAkD,IAAI,8CAA8C,KAAK,IAAI,CAC9G,CAAC;QACJ,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,CAAC;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,oBAAoB,CAAC,IAA4B;IAC/D,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FirebaseIdentity } from "./firebase";
|
|
2
|
+
import type { DeploymentProvider } from "./providers/deployment";
|
|
3
|
+
export declare function invalidateFirebaseKeys(client: DeploymentProvider, fp: FirebaseIdentity): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=firebase-invalidate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase-invalidate.d.ts","sourceRoot":"","sources":["../../src/lib/firebase-invalidate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAMjE,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,kBAAkB,EAC1B,EAAE,EAAE,gBAAgB,GACnB,OAAO,CAAC,IAAI,CAAC,CAiEf"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.invalidateFirebaseKeys = invalidateFirebaseKeys;
|
|
4
|
+
const firebase_vars_1 = require("./firebase-vars");
|
|
5
|
+
const gcp_1 = require("./gcp");
|
|
6
|
+
const logger_1 = require("./logger");
|
|
7
|
+
// Post-redeploy cleanup: once a rotation's new key is proven live, sweep every
|
|
8
|
+
// non-active user-managed key for each service account so old credentials can't
|
|
9
|
+
// be used. Kept separate from the mint/rotate/init flow (firebase.ts) as its own
|
|
10
|
+
// concern.
|
|
11
|
+
async function invalidateFirebaseKeys(client, fp) {
|
|
12
|
+
(0, logger_1.log)("Invalidating old Firebase keys (sweeping all non-active user-managed keys)...");
|
|
13
|
+
const allEnvs = await client.listEnvVars();
|
|
14
|
+
const activeKeys = new Set();
|
|
15
|
+
const saPairs = new Map(); // email → gcpProject
|
|
16
|
+
const unsweepable = new Set();
|
|
17
|
+
for (const checkEnv of ["production", "preview", "development"]) {
|
|
18
|
+
if (!(0, firebase_vars_1.hasFirebaseCredentialForEnv)(allEnvs.envs, fp.names, checkEnv))
|
|
19
|
+
continue;
|
|
20
|
+
const kid = await (0, firebase_vars_1.getFirebaseKeyIdForEnv)(checkEnv, allEnvs.envs, fp.names, client);
|
|
21
|
+
const saInfo = await (0, firebase_vars_1.getFirebaseSaForEnv)(checkEnv, allEnvs.envs, fp.names, client);
|
|
22
|
+
if (kid) {
|
|
23
|
+
activeKeys.add(kid);
|
|
24
|
+
(0, logger_1.log)(` Active key [${checkEnv}]: ${kid}`);
|
|
25
|
+
}
|
|
26
|
+
if (saInfo) {
|
|
27
|
+
saPairs.set(saInfo.email, saInfo.gcpProject);
|
|
28
|
+
if (!kid)
|
|
29
|
+
unsweepable.add(saInfo.email);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
for (const [saEmail, gcpProject] of saPairs) {
|
|
33
|
+
if (unsweepable.has(saEmail)) {
|
|
34
|
+
(0, logger_1.warn)(`Skipping stray-key sweep for ${saEmail} — not all environments have the key id tracked.`);
|
|
35
|
+
(0, logger_1.warn)(" Rotate all environments first, then re-run to sweep old keys.");
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
(0, logger_1.log)(` Sweeping SA: ${saEmail}`);
|
|
39
|
+
const allKeys = (0, gcp_1.listUserManagedGcpKeys)(saEmail, gcpProject);
|
|
40
|
+
let deleted = 0;
|
|
41
|
+
for (const keyId of allKeys) {
|
|
42
|
+
if (activeKeys.has(keyId))
|
|
43
|
+
continue;
|
|
44
|
+
(0, logger_1.log)(` Deleting stray key: ${keyId}`);
|
|
45
|
+
try {
|
|
46
|
+
(0, gcp_1.deleteGcpKey)(keyId, saEmail, gcpProject);
|
|
47
|
+
(0, logger_1.log)(` Deleted: ${keyId}`);
|
|
48
|
+
deleted++;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
(0, logger_1.warn)(`Failed to delete key ${keyId} — remove manually:`);
|
|
52
|
+
(0, logger_1.warn)(` gcloud iam service-accounts keys delete ${keyId} --iam-account=${saEmail}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (deleted === 0)
|
|
56
|
+
(0, logger_1.log)(` No stray keys for ${saEmail}.`);
|
|
57
|
+
else
|
|
58
|
+
(0, logger_1.log)(` Deleted ${deleted} stray key(s) for ${saEmail}.`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=firebase-invalidate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase-invalidate.js","sourceRoot":"","sources":["../../src/lib/firebase-invalidate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FirebaseCredentialSpec } from "./firebase-credential";
|
|
2
|
+
import type { DeploymentProvider } from "./providers/deployment";
|
|
3
|
+
import type { VercelEnvVar } from "./vercel-api";
|
|
4
|
+
type FieldNames = FirebaseCredentialSpec["names"];
|
|
5
|
+
export interface FirebaseSaInfo {
|
|
6
|
+
email: string;
|
|
7
|
+
gcpProject: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function getFirebaseSaForEnv(vercelEnv: string, envs: VercelEnvVar[], names: FieldNames, client: DeploymentProvider): Promise<FirebaseSaInfo | null>;
|
|
10
|
+
export declare function getFirebaseKeyIdForEnv(vercelEnv: string, envs: VercelEnvVar[], names: FieldNames, client: DeploymentProvider): Promise<string>;
|
|
11
|
+
export declare function hasFirebaseCredential(envs: VercelEnvVar[], names: FieldNames): boolean;
|
|
12
|
+
export declare function hasFirebaseCredentialForEnv(envs: VercelEnvVar[], names: FieldNames, vercelEnv: string): boolean;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=firebase-vars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase-vars.d.ts","sourceRoot":"","sources":["../../src/lib/firebase-vars.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAMjD,KAAK,UAAU,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,YAAY,EAAE,EACpB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAehC;AAID,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,YAAY,EAAE,EACpB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CAMjB;AAGD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,YAAY,EAAE,EACpB,KAAK,EAAE,UAAU,GAChB,OAAO,CAET;AAID,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,YAAY,EAAE,EACpB,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAIT"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getFirebaseSaForEnv = getFirebaseSaForEnv;
|
|
4
|
+
exports.getFirebaseKeyIdForEnv = getFirebaseKeyIdForEnv;
|
|
5
|
+
exports.hasFirebaseCredential = hasFirebaseCredential;
|
|
6
|
+
exports.hasFirebaseCredentialForEnv = hasFirebaseCredentialForEnv;
|
|
7
|
+
// The service-account identity (email + GCP project) for an environment, read
|
|
8
|
+
// from the discrete `clientEmail` / `projectId` vars. Returns null when the
|
|
9
|
+
// credential is absent for that environment.
|
|
10
|
+
async function getFirebaseSaForEnv(vercelEnv, envs, names, client) {
|
|
11
|
+
const ceRecord = envs.find((e) => e.key === names.clientEmail && e.target.includes(vercelEnv));
|
|
12
|
+
if (!ceRecord)
|
|
13
|
+
return null;
|
|
14
|
+
const email = await client.getEnvVarValue(ceRecord.id);
|
|
15
|
+
let gcpProject = "";
|
|
16
|
+
const pidRecord = envs.find((e) => e.key === names.projectId && e.target.includes(vercelEnv));
|
|
17
|
+
if (pidRecord)
|
|
18
|
+
gcpProject = await client.getEnvVarValue(pidRecord.id);
|
|
19
|
+
if (!gcpProject)
|
|
20
|
+
gcpProject = process.env.GCLOUD_PROJECT ?? "";
|
|
21
|
+
return { email, gcpProject };
|
|
22
|
+
}
|
|
23
|
+
// The active key id for an environment, from the tracked privateKeyId var.
|
|
24
|
+
// "" when untracked.
|
|
25
|
+
async function getFirebaseKeyIdForEnv(vercelEnv, envs, names, client) {
|
|
26
|
+
const record = envs.find((e) => e.key === names.privateKeyId && e.target.includes(vercelEnv));
|
|
27
|
+
if (!record)
|
|
28
|
+
return "";
|
|
29
|
+
return client.getEnvVarValue(record.id);
|
|
30
|
+
}
|
|
31
|
+
// Whether the credential is present anywhere in Vercel (by the resolved names).
|
|
32
|
+
function hasFirebaseCredential(envs, names) {
|
|
33
|
+
return envs.some((e) => e.key === names.privateKey);
|
|
34
|
+
}
|
|
35
|
+
// Whether the credential is present in one environment — so per-env reads and
|
|
36
|
+
// sweeps skip a target that has no credential.
|
|
37
|
+
function hasFirebaseCredentialForEnv(envs, names, vercelEnv) {
|
|
38
|
+
return envs.some((e) => e.key === names.privateKey && e.target.includes(vercelEnv));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=firebase-vars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase-vars.js","sourceRoot":"","sources":["../../src/lib/firebase-vars.ts"],"names":[],"mappings":";;AAkBA,kDAoBC;AAID,wDAWC;AAGD,sDAKC;AAID,kEAQC;AA1DD,8EAA8E;AAC9E,4EAA4E;AAC5E,6CAA6C;AACtC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,IAAoB,EACpB,KAAiB,EACjB,MAA0B;IAE1B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACxB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CACnE,CAAC;IACF,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEvD,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CACjE,CAAC;IACF,IAAI,SAAS;QAAE,UAAU,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACtE,IAAI,CAAC,UAAU;QAAE,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC;IAE/D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC/B,CAAC;AAED,2EAA2E;AAC3E,qBAAqB;AACd,KAAK,UAAU,sBAAsB,CAC1C,SAAiB,EACjB,IAAoB,EACpB,KAAiB,EACjB,MAA0B;IAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CACpE,CAAC;IACF,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,gFAAgF;AAChF,SAAgB,qBAAqB,CACnC,IAAoB,EACpB,KAAiB;IAEjB,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,UAAU,CAAC,CAAC;AACtD,CAAC;AAED,8EAA8E;AAC9E,+CAA+C;AAC/C,SAAgB,2BAA2B,CACzC,IAAoB,EACpB,KAAiB,EACjB,SAAiB;IAEjB,OAAO,IAAI,CAAC,IAAI,CACd,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAClE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type FirebaseCredentialSpec } from "./firebase-credential";
|
|
2
|
+
import type { DeploymentProvider } from "./providers/deployment";
|
|
3
|
+
export interface FirebaseIdentity {
|
|
4
|
+
saEmail: string;
|
|
5
|
+
gcpProject: string;
|
|
6
|
+
/** Resolved credential var names for this project (#98). */
|
|
7
|
+
names: FirebaseCredentialSpec["names"];
|
|
8
|
+
}
|
|
9
|
+
export interface OldFirebaseKey {
|
|
10
|
+
vercelEnv: string;
|
|
11
|
+
keyId: string;
|
|
12
|
+
saEmail: string;
|
|
13
|
+
gcpProject: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function rotateFirebase(targetEnv: string, client: DeploymentProvider, tempDir: string, spec?: FirebaseCredentialSpec, allowedTargets?: string[]): Promise<{
|
|
16
|
+
oldKeys: OldFirebaseKey[];
|
|
17
|
+
fp: FirebaseIdentity;
|
|
18
|
+
}>;
|
|
19
|
+
export declare function initFirebase(targetEnv: string, client: DeploymentProvider, tempDir: string, saEmailOverride?: string, gcpProjectOverride?: string, spec?: FirebaseCredentialSpec, allowedTargets?: string[]): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=firebase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase.d.ts","sourceRoot":"","sources":["../../src/lib/firebase.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,uBAAuB,CAAC;AAQ/B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAKjE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,KAAK,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAmFD,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,sBAAoD,EAC1D,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC;IAAE,OAAO,EAAE,cAAc,EAAE,CAAC;IAAC,EAAE,EAAE,gBAAgB,CAAA;CAAE,CAAC,CA2G9D;AAID,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,EACxB,kBAAkB,CAAC,EAAE,MAAM,EAC3B,IAAI,GAAE,sBAAoD,EAC1D,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC,CA4Df"}
|