firebase-tools 13.0.0-canary.0 → 13.0.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/LICENSE +0 -0
- package/README.md +0 -0
- package/lib/dynamicImport.js +0 -0
- package/lib/frameworks/angular/utils.js +8 -0
- package/lib/frameworks/constants.js +5 -2
- package/lib/gcp/cloudbuild.js +24 -3
- package/lib/gcp/storage.js +5 -1
- package/lib/init/features/frameworks/index.js +4 -4
- package/lib/init/features/frameworks/repo.js +105 -36
- package/lib/utils.js +28 -1
- package/package.json +1 -1
- package/schema/extension-yaml.json +0 -0
- package/schema/firebase-config.json +0 -0
- package/standalone/check.js +0 -0
- package/standalone/config.template.js +0 -0
- package/standalone/firepit.js +0 -0
- package/standalone/package.json +0 -0
- package/standalone/runtime.js +0 -0
- package/standalone/welcome.js +0 -0
- package/templates/_gitignore +0 -0
- package/templates/banner.txt +0 -0
- package/templates/emulators/default_storage.rules +0 -0
- package/templates/extensions/CL-template.md +0 -0
- package/templates/extensions/POSTINSTALL.md +0 -0
- package/templates/extensions/PREINSTALL.md +0 -0
- package/templates/extensions/extension.yaml +0 -0
- package/templates/extensions/integration-test.env +0 -0
- package/templates/extensions/integration-test.json +0 -0
- package/templates/extensions/javascript/WELCOME.md +0 -0
- package/templates/extensions/javascript/_gitignore +0 -0
- package/templates/extensions/javascript/index.js +0 -0
- package/templates/extensions/javascript/integration-test.js +0 -0
- package/templates/extensions/javascript/package.lint.json +0 -0
- package/templates/extensions/javascript/package.nolint.json +0 -0
- package/templates/extensions/typescript/WELCOME.md +0 -0
- package/templates/extensions/typescript/_gitignore +0 -0
- package/templates/extensions/typescript/_mocharc +0 -0
- package/templates/extensions/typescript/index.ts +0 -0
- package/templates/extensions/typescript/integration-test.ts +0 -0
- package/templates/extensions/typescript/package.lint.json +0 -0
- package/templates/extensions/typescript/package.nolint.json +0 -0
- package/templates/extensions/typescript/tsconfig.dev.json +0 -0
- package/templates/extensions/typescript/tsconfig.json +0 -0
- package/templates/firebase.json +0 -0
- package/templates/hosting/init.js +0 -0
- package/templates/init/firestore/firestore.indexes.json +0 -0
- package/templates/init/firestore/firestore.rules +0 -0
- package/templates/init/functions/javascript/_eslintrc +0 -0
- package/templates/init/functions/javascript/_gitignore +0 -0
- package/templates/init/functions/javascript/index.js +0 -0
- package/templates/init/functions/javascript/package.lint.json +0 -0
- package/templates/init/functions/javascript/package.nolint.json +0 -0
- package/templates/init/functions/python/_gitignore +0 -0
- package/templates/init/functions/python/main.py +0 -0
- package/templates/init/functions/python/requirements.txt +0 -0
- package/templates/init/functions/typescript/_eslintrc +0 -0
- package/templates/init/functions/typescript/_gitignore +0 -0
- package/templates/init/functions/typescript/index.ts +0 -0
- package/templates/init/functions/typescript/package.lint.json +0 -0
- package/templates/init/functions/typescript/package.nolint.json +0 -0
- package/templates/init/functions/typescript/tsconfig.dev.json +0 -0
- package/templates/init/functions/typescript/tsconfig.json +0 -0
- package/templates/init/hosting/404.html +0 -0
- package/templates/init/hosting/index.html +0 -0
- package/templates/init/storage/storage.rules +0 -0
- package/templates/loginFailure.html +0 -0
- package/templates/loginSuccess.html +0 -0
- package/templates/loginSuccessGithub.html +0 -0
- package/templates/popup.html +64 -0
- package/templates/setup/web.js +0 -0
- package/standalone/config.js +0 -19
- package/standalone/firepit-log.txt +0 -4
package/LICENSE
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
File without changes
|
package/lib/dynamicImport.js
CHANGED
|
File without changes
|
|
@@ -56,6 +56,7 @@ async function localesForTarget(dir, architectHost, target, workspaceProject) {
|
|
|
56
56
|
const DEV_SERVER_TARGETS = [
|
|
57
57
|
"@angular-devkit/build-angular:dev-server",
|
|
58
58
|
"@nguniversal/builders:ssr-dev-server",
|
|
59
|
+
"@angular-devkit/build-angular:ssr-dev-server",
|
|
59
60
|
];
|
|
60
61
|
function getValidBuilders(purpose) {
|
|
61
62
|
return [
|
|
@@ -63,6 +64,7 @@ function getValidBuilders(purpose) {
|
|
|
63
64
|
"@angular-devkit/build-angular:browser-esbuild",
|
|
64
65
|
"@angular/fire:deploy",
|
|
65
66
|
"@angular-devkit/build-angular:browser",
|
|
67
|
+
"@angular-devkit/build-angular:prerender",
|
|
66
68
|
"@nguniversal/builders:prerender",
|
|
67
69
|
...(purpose === "deploy" ? [] : DEV_SERVER_TARGETS),
|
|
68
70
|
];
|
|
@@ -156,11 +158,13 @@ async function getContext(dir, targetOrConfiguration) {
|
|
|
156
158
|
case "@angular-devkit/build-angular:browser":
|
|
157
159
|
browserTarget = overrideTarget;
|
|
158
160
|
break;
|
|
161
|
+
case "@angular-devkit/build-angular:prerender":
|
|
159
162
|
case "@nguniversal/builders:prerender":
|
|
160
163
|
prerenderTarget = overrideTarget;
|
|
161
164
|
break;
|
|
162
165
|
case "@angular-devkit/build-angular:dev-server":
|
|
163
166
|
case "@nguniversal/builders:ssr-dev-server":
|
|
167
|
+
case "@angular-devkit/build-angular:ssr-dev-server":
|
|
164
168
|
serveTarget = overrideTarget;
|
|
165
169
|
break;
|
|
166
170
|
default:
|
|
@@ -299,12 +303,16 @@ async function getContext(dir, targetOrConfiguration) {
|
|
|
299
303
|
continue;
|
|
300
304
|
if (target === browserTarget && builder === "@angular-devkit/build-angular:browser")
|
|
301
305
|
continue;
|
|
306
|
+
if (target === prerenderTarget && builder === "@angular-devkit/build-angular:prerender")
|
|
307
|
+
continue;
|
|
302
308
|
if (target === prerenderTarget && builder === "@nguniversal/builders:prerender")
|
|
303
309
|
continue;
|
|
304
310
|
if (target === serverTarget && builder === "@angular-devkit/build-angular:server")
|
|
305
311
|
continue;
|
|
306
312
|
if (target === serveTarget && builder === "@nguniversal/builders:ssr-dev-server")
|
|
307
313
|
continue;
|
|
314
|
+
if (target === serveTarget && builder === "@angular-devkit/build-angular:ssr-dev-server")
|
|
315
|
+
continue;
|
|
308
316
|
if (target === serveTarget && builder === "@angular-devkit/build-angular:dev-server")
|
|
309
317
|
continue;
|
|
310
318
|
throw new error_1.FirebaseError(`${definition.builder} (${targetString}) is not a recognized builder. Please check your angular.json`);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DEFAULT_SHOULD_USE_DEV_MODE_HANDLE = exports.GET_DEFAULT_BUILD_TARGETS = exports.I18N_ROOT = exports.ALLOWED_SSR_REGIONS = exports.DEFAULT_REGION = exports.VALID_LOCALE_FORMATS = exports.VALID_ENGINES = exports.NODE_VERSION = exports.SHARP_VERSION = exports.FIREBASE_ADMIN_VERSION = exports.FIREBASE_FUNCTIONS_VERSION = exports.FIREBASE_FRAMEWORKS_VERSION = exports.MAILING_LIST_URL = exports.FEATURE_REQUEST_URL = exports.FILE_BUG_URL = exports.DEFAULT_DOCS_URL = exports.SupportLevelWarnings = exports.NPM_COMMAND_TIMEOUT_MILLIES = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
|
+
const experiments = require("../experiments");
|
|
5
6
|
exports.NPM_COMMAND_TIMEOUT_MILLIES = 10000;
|
|
6
7
|
exports.SupportLevelWarnings = {
|
|
7
8
|
["experimental"]: (framework) => `Thank you for trying our ${clc.italic("experimental")} support for ${framework} on Firebase Hosting.
|
|
@@ -14,10 +15,12 @@ exports.DEFAULT_DOCS_URL = "https://firebase.google.com/docs/hosting/frameworks/
|
|
|
14
15
|
exports.FILE_BUG_URL = "https://github.com/firebase/firebase-tools/issues/new?template=bug_report.md";
|
|
15
16
|
exports.FEATURE_REQUEST_URL = "https://github.com/firebase/firebase-tools/issues/new?template=feature_request.md";
|
|
16
17
|
exports.MAILING_LIST_URL = "https://goo.gle/41enW5X";
|
|
17
|
-
|
|
18
|
+
const DEFAULT_FIREBASE_FRAMEWORKS_VERSION = "^0.11.0";
|
|
19
|
+
exports.FIREBASE_FRAMEWORKS_VERSION = (experiments.isEnabled("internaltesting") && process.env.FIREBASE_FRAMEWORKS_VERSION) ||
|
|
20
|
+
DEFAULT_FIREBASE_FRAMEWORKS_VERSION;
|
|
18
21
|
exports.FIREBASE_FUNCTIONS_VERSION = "^4.5.0";
|
|
19
22
|
exports.FIREBASE_ADMIN_VERSION = "^11.11.1";
|
|
20
|
-
exports.SHARP_VERSION = "^0.
|
|
23
|
+
exports.SHARP_VERSION = "^0.32.1";
|
|
21
24
|
exports.NODE_VERSION = parseInt(process.versions.node, 10);
|
|
22
25
|
exports.VALID_ENGINES = { node: [16, 18, 20] };
|
|
23
26
|
exports.VALID_LOCALE_FORMATS = [/^ALL_[a-z]+$/, /^[a-z]+_ALL$/, /^[a-z]+(_[a-z]+)?$/];
|
package/lib/gcp/cloudbuild.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.deleteRepository = exports.getRepository = exports.createRepository = exports.fetchLinkableRepositories = exports.deleteConnection = exports.getConnection = exports.createConnection = void 0;
|
|
3
|
+
exports.deleteRepository = exports.getRepository = exports.createRepository = exports.fetchLinkableRepositories = exports.deleteConnection = exports.listConnections = exports.getConnection = exports.createConnection = void 0;
|
|
4
4
|
const apiv2_1 = require("../apiv2");
|
|
5
5
|
const api_1 = require("../api");
|
|
6
|
+
const PAGE_SIZE_MAX = 100;
|
|
6
7
|
const client = new apiv2_1.Client({
|
|
7
8
|
urlPrefix: api_1.cloudbuildOrigin,
|
|
8
9
|
auth: true,
|
|
9
10
|
apiVersion: "v2",
|
|
10
11
|
});
|
|
11
|
-
async function createConnection(projectId, location, connectionId) {
|
|
12
|
-
const res = await client.post(`projects/${projectId}/locations/${location}/connections`, { githubConfig
|
|
12
|
+
async function createConnection(projectId, location, connectionId, githubConfig = {}) {
|
|
13
|
+
const res = await client.post(`projects/${projectId}/locations/${location}/connections`, { githubConfig }, { queryParams: { connectionId } });
|
|
13
14
|
return res.body;
|
|
14
15
|
}
|
|
15
16
|
exports.createConnection = createConnection;
|
|
@@ -19,6 +20,26 @@ async function getConnection(projectId, location, connectionId) {
|
|
|
19
20
|
return res.body;
|
|
20
21
|
}
|
|
21
22
|
exports.getConnection = getConnection;
|
|
23
|
+
async function listConnections(projectId, location) {
|
|
24
|
+
const conns = [];
|
|
25
|
+
const getNextPage = async (pageToken = "") => {
|
|
26
|
+
const res = await client.get(`/projects/${projectId}/locations/${location}/connections`, {
|
|
27
|
+
queryParams: {
|
|
28
|
+
pageSize: PAGE_SIZE_MAX,
|
|
29
|
+
pageToken,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
if (Array.isArray(res.body.connections)) {
|
|
33
|
+
conns.push(...res.body.connections);
|
|
34
|
+
}
|
|
35
|
+
if (res.body.nextPageToken) {
|
|
36
|
+
await getNextPage(res.body.nextPageToken);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
await getNextPage();
|
|
40
|
+
return conns;
|
|
41
|
+
}
|
|
42
|
+
exports.listConnections = listConnections;
|
|
22
43
|
async function deleteConnection(projectId, location, connectionId) {
|
|
23
44
|
const name = `projects/${projectId}/locations/${location}/connections/${connectionId}`;
|
|
24
45
|
const res = await client.delete(name);
|
package/lib/gcp/storage.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getServiceAccount = exports.listBuckets = exports.getBucket = exports.deleteObject = exports.uploadObject = exports.upload = exports.getDefaultBucket = void 0;
|
|
4
4
|
const path = require("path");
|
|
5
|
+
const clc = require("colorette");
|
|
5
6
|
const api_1 = require("../api");
|
|
6
7
|
const apiv2_1 = require("../apiv2");
|
|
7
8
|
const error_1 = require("../error");
|
|
@@ -20,7 +21,10 @@ async function getDefaultBucket(projectId) {
|
|
|
20
21
|
return response.body.bucket.name.split("/").pop();
|
|
21
22
|
}
|
|
22
23
|
catch (err) {
|
|
23
|
-
|
|
24
|
+
if ((err === null || err === void 0 ? void 0 : err.status) === 404) {
|
|
25
|
+
throw new error_1.FirebaseError(`Firebase Storage has not been set up on project '${clc.bold(projectId)}'. Go to https://console.firebase.google.com/project/${projectId}/storage and click 'Get Started' to set up Firebase Storage.`);
|
|
26
|
+
}
|
|
27
|
+
logger_1.logger.info("\n\nUnexpected error when fetching default storage bucket.");
|
|
24
28
|
throw err;
|
|
25
29
|
}
|
|
26
30
|
}
|
|
@@ -3,15 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createBackend = exports.getOrCreateBackend = exports.doSetup = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const utils = require("../../../utils");
|
|
6
|
-
const logger_1 = require("../../../logger");
|
|
7
|
-
const prompt_1 = require("../../../prompt");
|
|
8
|
-
const constants_1 = require("./constants");
|
|
9
6
|
const repo = require("./repo");
|
|
10
7
|
const poller = require("../../../operation-poller");
|
|
11
|
-
const api_1 = require("../../../api");
|
|
12
8
|
const gcp = require("../../../gcp/frameworks");
|
|
9
|
+
const api_1 = require("../../../api");
|
|
13
10
|
const frameworks_1 = require("../../../gcp/frameworks");
|
|
14
11
|
const error_1 = require("../../../error");
|
|
12
|
+
const logger_1 = require("../../../logger");
|
|
13
|
+
const prompt_1 = require("../../../prompt");
|
|
14
|
+
const constants_1 = require("./constants");
|
|
15
15
|
const frameworksPollerOptions = {
|
|
16
16
|
apiOrigin: api_1.frameworksOrigin,
|
|
17
17
|
apiVersion: frameworks_1.API_VERSION,
|
|
@@ -1,21 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getOrCreateRepository = exports.getOrCreateConnection = exports.linkGitHubRepository = void 0;
|
|
4
|
-
const
|
|
5
|
-
const error_1 = require("../../../error");
|
|
3
|
+
exports.listFrameworksConnections = exports.getOrCreateRepository = exports.getOrCreateConnection = exports.createConnection = exports.linkGitHubRepository = exports.parseConnectionName = void 0;
|
|
4
|
+
const clc = require("colorette");
|
|
6
5
|
const gcb = require("../../../gcp/cloudbuild");
|
|
7
|
-
const logger_1 = require("../../../logger");
|
|
8
6
|
const poller = require("../../../operation-poller");
|
|
9
7
|
const utils = require("../../../utils");
|
|
8
|
+
const api_1 = require("../../../api");
|
|
9
|
+
const error_1 = require("../../../error");
|
|
10
|
+
const logger_1 = require("../../../logger");
|
|
10
11
|
const prompt_1 = require("../../../prompt");
|
|
11
|
-
const
|
|
12
|
+
const FRAMEWORKS_CONN_PATTERN = /.+\/frameworks-github-conn-.+$/;
|
|
13
|
+
const FRAMEWORKS_OAUTH_CONN_NAME = "frameworks-github-oauth";
|
|
14
|
+
const CONNECTION_NAME_REGEX = /^projects\/(?<projectId>[^\/]+)\/locations\/(?<location>[^\/]+)\/connections\/(?<id>[^\/]+)$/;
|
|
15
|
+
function parseConnectionName(name) {
|
|
16
|
+
const match = name.match(CONNECTION_NAME_REGEX);
|
|
17
|
+
if (!match || typeof match.groups === undefined) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const { projectId, location, id } = match.groups;
|
|
21
|
+
return {
|
|
22
|
+
projectId,
|
|
23
|
+
location,
|
|
24
|
+
id,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
exports.parseConnectionName = parseConnectionName;
|
|
12
28
|
const gcbPollerOptions = {
|
|
13
29
|
apiOrigin: api_1.cloudbuildOrigin,
|
|
14
30
|
apiVersion: "v2",
|
|
15
31
|
masterTimeout: 25 * 60 * 1000,
|
|
16
32
|
maxBackoff: 10000,
|
|
17
33
|
};
|
|
18
|
-
function
|
|
34
|
+
function extractRepoSlugFromUri(remoteUri) {
|
|
19
35
|
const match = /github.com\/(.+).git/.exec(remoteUri);
|
|
20
36
|
if (!match) {
|
|
21
37
|
return undefined;
|
|
@@ -24,77 +40,123 @@ function extractRepoSlugFromURI(remoteUri) {
|
|
|
24
40
|
}
|
|
25
41
|
function generateRepositoryId(remoteUri) {
|
|
26
42
|
var _a;
|
|
27
|
-
return (_a =
|
|
43
|
+
return (_a = extractRepoSlugFromUri(remoteUri)) === null || _a === void 0 ? void 0 : _a.replaceAll("/", "-");
|
|
28
44
|
}
|
|
29
|
-
function generateConnectionId(
|
|
30
|
-
|
|
45
|
+
function generateConnectionId() {
|
|
46
|
+
const randomHash = Math.random().toString(36).slice(6);
|
|
47
|
+
return `frameworks-github-conn-${randomHash}`;
|
|
31
48
|
}
|
|
32
49
|
async function linkGitHubRepository(projectId, location) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
await
|
|
36
|
-
|
|
50
|
+
var _a, _b, _c;
|
|
51
|
+
logger_1.logger.info(clc.bold(`\n${clc.yellow("===")} Connect a GitHub repository`));
|
|
52
|
+
const existingConns = await listFrameworksConnections(projectId);
|
|
53
|
+
if (existingConns.length < 1) {
|
|
54
|
+
let oauthConn = await getOrCreateConnection(projectId, location, FRAMEWORKS_OAUTH_CONN_NAME);
|
|
55
|
+
while (oauthConn.installationState.stage === "PENDING_USER_OAUTH") {
|
|
56
|
+
oauthConn = await promptConnectionAuth(oauthConn);
|
|
57
|
+
}
|
|
58
|
+
const connectionId = generateConnectionId();
|
|
59
|
+
const conn = await createConnection(projectId, location, connectionId, {
|
|
60
|
+
authorizerCredential: (_a = oauthConn.githubConfig) === null || _a === void 0 ? void 0 : _a.authorizerCredential,
|
|
61
|
+
});
|
|
62
|
+
let refreshedConn = conn;
|
|
63
|
+
while (refreshedConn.installationState.stage !== "COMPLETE") {
|
|
64
|
+
refreshedConn = await promptAppInstall(conn);
|
|
65
|
+
}
|
|
66
|
+
existingConns.push(refreshedConn);
|
|
67
|
+
}
|
|
68
|
+
let { remoteUri, connection } = await promptRepositoryUri(projectId, location, existingConns);
|
|
37
69
|
while (remoteUri === "") {
|
|
38
70
|
await utils.openInBrowser("https://github.com/apps/google-cloud-build/installations/new");
|
|
39
71
|
await (0, prompt_1.promptOnce)({
|
|
40
72
|
type: "input",
|
|
41
73
|
message: "Press ENTER once you have finished configuring your installation's access settings.",
|
|
42
74
|
});
|
|
43
|
-
|
|
75
|
+
const selection = await promptRepositoryUri(projectId, location, existingConns);
|
|
76
|
+
remoteUri = selection.remoteUri;
|
|
77
|
+
connection = selection.connection;
|
|
44
78
|
}
|
|
79
|
+
const { id: connectionId } = parseConnectionName(connection.name);
|
|
80
|
+
await getOrCreateConnection(projectId, location, connectionId, {
|
|
81
|
+
authorizerCredential: (_b = connection.githubConfig) === null || _b === void 0 ? void 0 : _b.authorizerCredential,
|
|
82
|
+
appInstallationId: (_c = connection.githubConfig) === null || _c === void 0 ? void 0 : _c.appInstallationId,
|
|
83
|
+
});
|
|
45
84
|
const repo = await getOrCreateRepository(projectId, location, connectionId, remoteUri);
|
|
46
85
|
logger_1.logger.info();
|
|
47
86
|
utils.logSuccess(`Successfully linked GitHub repository at remote URI:\n ${remoteUri}`);
|
|
48
87
|
return repo;
|
|
49
88
|
}
|
|
50
89
|
exports.linkGitHubRepository = linkGitHubRepository;
|
|
51
|
-
async function
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
90
|
+
async function promptRepositoryUri(projectId, location, connections) {
|
|
91
|
+
const remoteUriToConnection = {};
|
|
92
|
+
for (const conn of connections) {
|
|
93
|
+
const { id } = parseConnectionName(conn.name);
|
|
94
|
+
const resp = await gcb.fetchLinkableRepositories(projectId, location, id);
|
|
95
|
+
if (resp.repositories && resp.repositories.length > 1) {
|
|
96
|
+
for (const repo of resp.repositories) {
|
|
97
|
+
remoteUriToConnection[repo.remoteUri] = conn;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
56
100
|
}
|
|
57
|
-
const choices =
|
|
58
|
-
name:
|
|
59
|
-
value:
|
|
101
|
+
const choices = Object.keys(remoteUriToConnection).map((remoteUri) => ({
|
|
102
|
+
name: extractRepoSlugFromUri(remoteUri) || remoteUri,
|
|
103
|
+
value: remoteUri,
|
|
60
104
|
}));
|
|
61
105
|
choices.push({
|
|
62
106
|
name: "Missing a repo? Select this option to configure your installation's access settings",
|
|
63
107
|
value: "",
|
|
64
108
|
});
|
|
65
|
-
|
|
109
|
+
const remoteUri = await (0, prompt_1.promptOnce)({
|
|
66
110
|
type: "list",
|
|
67
111
|
message: "Which of the following repositories would you like to deploy?",
|
|
68
112
|
choices,
|
|
69
113
|
});
|
|
114
|
+
return { remoteUri, connection: remoteUriToConnection[remoteUri] };
|
|
115
|
+
}
|
|
116
|
+
async function promptConnectionAuth(conn) {
|
|
117
|
+
logger_1.logger.info("You must authorize the Cloud Build GitHub app.");
|
|
118
|
+
logger_1.logger.info();
|
|
119
|
+
logger_1.logger.info("First, sign in to GitHub and authorize Cloud Build GitHub app:");
|
|
120
|
+
const cleanup = await utils.openInBrowserPopup(conn.installationState.actionUri, "Authorize the GitHub app");
|
|
121
|
+
await (0, prompt_1.promptOnce)({
|
|
122
|
+
type: "input",
|
|
123
|
+
message: "Press Enter once you have authorized the app",
|
|
124
|
+
});
|
|
125
|
+
cleanup();
|
|
126
|
+
const { projectId, location, id } = parseConnectionName(conn.name);
|
|
127
|
+
return await gcb.getConnection(projectId, location, id);
|
|
70
128
|
}
|
|
71
|
-
async function
|
|
72
|
-
logger_1.logger.info("
|
|
73
|
-
|
|
74
|
-
|
|
129
|
+
async function promptAppInstall(conn) {
|
|
130
|
+
logger_1.logger.info("Now, install the Cloud Build GitHub app:");
|
|
131
|
+
const targetUri = conn.installationState.actionUri.replace("install_v2", "direct_install_v2");
|
|
132
|
+
logger_1.logger.info(targetUri);
|
|
133
|
+
await utils.openInBrowser(targetUri);
|
|
75
134
|
await (0, prompt_1.promptOnce)({
|
|
76
135
|
type: "input",
|
|
77
|
-
message: "Press Enter once you have
|
|
136
|
+
message: "Press Enter once you have installed or configured the Cloud Build GitHub app to access your GitHub repo.",
|
|
78
137
|
});
|
|
79
|
-
|
|
138
|
+
const { projectId, location, id } = parseConnectionName(conn.name);
|
|
139
|
+
return await gcb.getConnection(projectId, location, id);
|
|
140
|
+
}
|
|
141
|
+
async function createConnection(projectId, location, connectionId, githubConfig) {
|
|
142
|
+
const op = await gcb.createConnection(projectId, location, connectionId, githubConfig);
|
|
143
|
+
const conn = await poller.pollOperation(Object.assign(Object.assign({}, gcbPollerOptions), { pollerName: `create-${location}-${connectionId}`, operationResourceName: op.name }));
|
|
144
|
+
return conn;
|
|
80
145
|
}
|
|
81
|
-
|
|
146
|
+
exports.createConnection = createConnection;
|
|
147
|
+
async function getOrCreateConnection(projectId, location, connectionId, githubConfig) {
|
|
82
148
|
let conn;
|
|
83
149
|
try {
|
|
84
150
|
conn = await gcb.getConnection(projectId, location, connectionId);
|
|
85
151
|
}
|
|
86
152
|
catch (err) {
|
|
87
153
|
if (err.status === 404) {
|
|
88
|
-
|
|
89
|
-
conn = await poller.pollOperation(Object.assign(Object.assign({}, gcbPollerOptions), { pollerName: `create-${location}-${connectionId}`, operationResourceName: op.name }));
|
|
154
|
+
conn = await createConnection(projectId, location, connectionId, githubConfig);
|
|
90
155
|
}
|
|
91
156
|
else {
|
|
92
157
|
throw err;
|
|
93
158
|
}
|
|
94
159
|
}
|
|
95
|
-
while (conn.installationState.stage !== "COMPLETE") {
|
|
96
|
-
conn = await promptConnectionAuth(conn, projectId, location, connectionId);
|
|
97
|
-
}
|
|
98
160
|
return conn;
|
|
99
161
|
}
|
|
100
162
|
exports.getOrCreateConnection = getOrCreateConnection;
|
|
@@ -106,7 +168,7 @@ async function getOrCreateRepository(projectId, location, connectionId, remoteUr
|
|
|
106
168
|
let repo;
|
|
107
169
|
try {
|
|
108
170
|
repo = await gcb.getRepository(projectId, location, connectionId, repositoryId);
|
|
109
|
-
const repoSlug =
|
|
171
|
+
const repoSlug = extractRepoSlugFromUri(repo.remoteUri);
|
|
110
172
|
if (repoSlug) {
|
|
111
173
|
throw new error_1.FirebaseError(`${repoSlug} has already been linked.`);
|
|
112
174
|
}
|
|
@@ -123,3 +185,10 @@ async function getOrCreateRepository(projectId, location, connectionId, remoteUr
|
|
|
123
185
|
return repo;
|
|
124
186
|
}
|
|
125
187
|
exports.getOrCreateRepository = getOrCreateRepository;
|
|
188
|
+
async function listFrameworksConnections(projectId) {
|
|
189
|
+
const conns = await gcb.listConnections(projectId, "-");
|
|
190
|
+
return conns.filter((conn) => FRAMEWORKS_CONN_PATTERN.test(conn.name) &&
|
|
191
|
+
conn.installationState.stage === "COMPLETE" &&
|
|
192
|
+
!conn.disabled);
|
|
193
|
+
}
|
|
194
|
+
exports.listFrameworksConnections = listFrameworksConnections;
|
package/lib/utils.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.openInBrowser = exports.connectableHostname = exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isVSCodeExtension = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.withTimeout = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
|
|
3
|
+
exports.openInBrowserPopup = exports.openInBrowser = exports.connectableHostname = exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isVSCodeExtension = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.withTimeout = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const path = require("node:path");
|
|
4
6
|
const _ = require("lodash");
|
|
5
7
|
const url = require("url");
|
|
8
|
+
const http = require("http");
|
|
6
9
|
const clc = require("colorette");
|
|
7
10
|
const open = require("open");
|
|
8
11
|
const ora = require("ora");
|
|
@@ -12,6 +15,7 @@ const winston = require("winston");
|
|
|
12
15
|
const triple_beam_1 = require("triple-beam");
|
|
13
16
|
const assert_1 = require("assert");
|
|
14
17
|
const stripAnsi = require("strip-ansi");
|
|
18
|
+
const portfinder_1 = require("portfinder");
|
|
15
19
|
const configstore_1 = require("./configstore");
|
|
16
20
|
const error_1 = require("./error");
|
|
17
21
|
const logger_1 = require("./logger");
|
|
@@ -486,3 +490,26 @@ async function openInBrowser(url) {
|
|
|
486
490
|
await open(url);
|
|
487
491
|
}
|
|
488
492
|
exports.openInBrowser = openInBrowser;
|
|
493
|
+
async function openInBrowserPopup(url, buttonText) {
|
|
494
|
+
const popupPage = fs
|
|
495
|
+
.readFileSync(path.join(__dirname, "../templates/popup.html"), { encoding: "utf-8" })
|
|
496
|
+
.replace("${url}", url)
|
|
497
|
+
.replace("${buttonText}", buttonText);
|
|
498
|
+
const port = await (0, portfinder_1.getPortPromise)();
|
|
499
|
+
const server = http.createServer((req, res) => {
|
|
500
|
+
res.writeHead(200, {
|
|
501
|
+
"Content-Length": popupPage.length,
|
|
502
|
+
"Content-Type": "text/html",
|
|
503
|
+
});
|
|
504
|
+
res.end(popupPage);
|
|
505
|
+
req.socket.destroy();
|
|
506
|
+
});
|
|
507
|
+
server.listen(port);
|
|
508
|
+
const popupPageUri = `http://localhost:${port}`;
|
|
509
|
+
logger_1.logger.info(popupPageUri);
|
|
510
|
+
await openInBrowser(popupPageUri);
|
|
511
|
+
return () => {
|
|
512
|
+
server.close();
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
exports.openInBrowserPopup = openInBrowserPopup;
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
package/standalone/check.js
CHANGED
|
File without changes
|
|
File without changes
|
package/standalone/firepit.js
CHANGED
|
File without changes
|
package/standalone/package.json
CHANGED
|
File without changes
|
package/standalone/runtime.js
CHANGED
|
File without changes
|
package/standalone/welcome.js
CHANGED
|
File without changes
|
package/templates/_gitignore
CHANGED
|
File without changes
|
package/templates/banner.txt
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/templates/firebase.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<head>
|
|
2
|
+
<style>
|
|
3
|
+
div {
|
|
4
|
+
font-family: sans-serif;
|
|
5
|
+
}
|
|
6
|
+
#popup {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
align-items: center;
|
|
11
|
+
height: 100vh;
|
|
12
|
+
width: 100vw;
|
|
13
|
+
text-align: center;
|
|
14
|
+
}
|
|
15
|
+
#popup button {
|
|
16
|
+
display: inline-flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
border-radius: 0.375rem;
|
|
20
|
+
font-size: 1.5rem;
|
|
21
|
+
font-weight: 500;
|
|
22
|
+
height: 2.5rem;
|
|
23
|
+
padding: 0.5rem 1rem;
|
|
24
|
+
background-color: black;
|
|
25
|
+
color: white;
|
|
26
|
+
outline: none;
|
|
27
|
+
transition: background-color 150ms ease-in-out;
|
|
28
|
+
margin-bottom: 20px;
|
|
29
|
+
}
|
|
30
|
+
#popup button:hover {
|
|
31
|
+
background-color: #333;
|
|
32
|
+
}
|
|
33
|
+
#popup button:disabled {
|
|
34
|
+
opacity: 0.5;
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
}
|
|
37
|
+
#message {
|
|
38
|
+
height: 20px;
|
|
39
|
+
margin-bottom: 20px;
|
|
40
|
+
color: gray;
|
|
41
|
+
font-size: 1.5rem;
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
44
|
+
</head>
|
|
45
|
+
<body>
|
|
46
|
+
<div id="popup">
|
|
47
|
+
<button id="popupBtn" onclick="openPopup()">${buttonText}</button>
|
|
48
|
+
<div id="message">(Close this window after authorizing the app)</div>
|
|
49
|
+
</div>
|
|
50
|
+
<script>
|
|
51
|
+
function openPopup() {
|
|
52
|
+
var w = window.open("${url}", "newwindow", "popup=1");
|
|
53
|
+
var m = document.getElementById("message");
|
|
54
|
+
var d = document.getElementById("popupBtn");
|
|
55
|
+
var timer = setInterval(function () {
|
|
56
|
+
if (w.closed) {
|
|
57
|
+
m.innerText = "You can close this page now";
|
|
58
|
+
d.disabled = true;
|
|
59
|
+
clearInterval(timer);
|
|
60
|
+
}
|
|
61
|
+
}, 1000);
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
</body>
|
package/templates/setup/web.js
CHANGED
|
File without changes
|
package/standalone/config.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
/*
|
|
3
|
-
Headless mode forces the firepit builds to exactly imitate firebase-tools,
|
|
4
|
-
so the resulting binary "firebase" is a drop in replacement for the script
|
|
5
|
-
installed via npm. This is the behavior for CI / Cloud Shell / Docker etc.
|
|
6
|
-
|
|
7
|
-
When headless mode is disabled, the "double click" experience is enabled
|
|
8
|
-
which allows the binary to spawn a terminal on Windows and Mac. The is the
|
|
9
|
-
behavior for desktop users.
|
|
10
|
-
*/
|
|
11
|
-
headless: true,
|
|
12
|
-
|
|
13
|
-
/*
|
|
14
|
-
This is generally set to "firebase-tools@latest" however a custom value
|
|
15
|
-
can be supplied for EAPs which would like to have builds pointed at
|
|
16
|
-
specific tgz bundles.
|
|
17
|
-
*/
|
|
18
|
-
firebase_tools_package: "firebase-tools@latest"
|
|
19
|
-
};
|