Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Added `crashlytics:onboard:web` CLI command to support Crashlytics onboarding for web apps.
5 changes: 4 additions & 1 deletion firebase-vscode/src/test/runTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ async function main() {
const extensionTestsPath = path.resolve(__dirname, "./suite/index");

// Download VS Code, unzip it and run the integration test
const tmpUserData = path.join(os.tmpdir(), `vsc-ud-${Math.random().toString(36).substring(2, 7)}`);
const tmpUserData = path.join(
os.tmpdir(),
`vsc-ud-${Math.random().toString(36).substring(2, 7)}`,
);
await runTests({
version: VSCODE_VERSION,
extensionDevelopmentPath,
Expand Down
150 changes: 81 additions & 69 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,68 +5,68 @@ import * as utils from "./utils";

let commandScopes = new Set<string>();

export const authProxyOrigin = () =>
export const authProxyOrigin = (): string =>
utils.envOverride("FIREBASE_AUTHPROXY_URL", "https://auth.firebase.tools");
// "In this context, the client secret is obviously not treated as a secret"
// https://developers.google.com/identity/protocols/OAuth2InstalledApp
export const clientId = () =>
export const clientId = (): string =>
utils.envOverride(
"FIREBASE_CLIENT_ID",
"563584335869-fgrhgmd47bqnekij5i8b5pr03ho849e6.apps.googleusercontent.com",
);
export const clientSecret = () =>
export const clientSecret = (): string =>
utils.envOverride("FIREBASE_CLIENT_SECRET", "j9iVZfS8kkCEFUPaAeJV0sAi");
export const cloudbillingOrigin = () =>
export const cloudbillingOrigin = (): string =>
utils.envOverride("FIREBASE_CLOUDBILLING_URL", "https://cloudbilling.googleapis.com");
export const cloudloggingOrigin = () =>
export const cloudloggingOrigin = (): string =>
utils.envOverride("FIREBASE_CLOUDLOGGING_URL", "https://logging.googleapis.com");
export const cloudMonitoringOrigin = () =>
export const cloudMonitoringOrigin = (): string =>
utils.envOverride("CLOUD_MONITORING_URL", "https://monitoring.googleapis.com");
export const containerRegistryDomain = () =>
export const containerRegistryDomain = (): string =>
utils.envOverride("CONTAINER_REGISTRY_DOMAIN", "gcr.io");

export const developerConnectOrigin = () =>
export const developerConnectOrigin = (): string =>
utils.envOverride("DEVELOPERCONNECT_URL", "https://developerconnect.googleapis.com");
export const developerConnectP4SADomain = () =>
export const developerConnectP4SADomain = (): string =>
utils.envOverride("DEVELOPERCONNECT_P4SA_DOMAIN", "gcp-sa-devconnect.iam.gserviceaccount.com");

export const artifactRegistryDomain = () =>
export const artifactRegistryDomain = (): string =>
utils.envOverride("ARTIFACT_REGISTRY_DOMAIN", "https://artifactregistry.googleapis.com");
export const appCheckOrigin = () =>
export const appCheckOrigin = (): string =>
utils.envOverride("FIREBASE_APPCHECK_URL", "https://firebaseappcheck.googleapis.com");
export const appDistributionOrigin = () =>
export const appDistributionOrigin = (): string =>
utils.envOverride(
"FIREBASE_APP_DISTRIBUTION_URL",
"https://firebaseappdistribution.googleapis.com",
);
export const apphostingOrigin = () =>
export const apphostingOrigin = (): string =>
utils.envOverride("FIREBASE_APPHOSTING_URL", "https://firebaseapphosting.googleapis.com");
export const apphostingP4SADomain = () =>
export const apphostingP4SADomain = (): string =>
utils.envOverride(
"FIREBASE_APPHOSTING_P4SA_DOMAIN",
"gcp-sa-firebaseapphosting.iam.gserviceaccount.com",
);
export const apphostingGitHubAppInstallationURL = () =>
export const apphostingGitHubAppInstallationURL = (): string =>
utils.envOverride(
"FIREBASE_APPHOSTING_GITHUB_INSTALLATION_URL",
"https://github.com/apps/firebase-app-hosting/installations/new",
);

export const authOrigin = () =>
export const authOrigin = (): string =>
utils.envOverride("FIREBASE_AUTH_URL", "https://accounts.google.com");
export const authManagementOrigin = () =>
export const authManagementOrigin = (): string =>
utils.envOverride("FIREBASE_AUTH_MANAGEMENT_URL", "https://identitytoolkit.googleapis.com");
export const consoleOrigin = () =>
export const consoleOrigin = (): string =>
utils.envOverride("FIREBASE_CONSOLE_URL", "https://console.firebase.google.com");
export const eventarcOrigin = () =>
export const eventarcOrigin = (): string =>
utils.envOverride("EVENTARC_URL", "https://eventarc.googleapis.com");
export const firebaseApiOrigin = () =>
export const firebaseApiOrigin = (): string =>
utils.envOverride("FIREBASE_API_URL", "https://firebase.googleapis.com");
export const firebaseExtensionsRegistryOrigin = () =>
export const firebaseExtensionsRegistryOrigin = (): string =>
utils.envOverride("FIREBASE_EXT_REGISTRY_ORIGIN", "https://extensions-registry.firebaseapp.com");
export const firedataOrigin = () =>
export const firedataOrigin = (): string =>
utils.envOverride("FIREBASE_FIREDATA_URL", "https://mobilesdk-pa.googleapis.com");
export const firestoreOriginOrEmulator = () =>
export const firestoreOriginOrEmulator = (): string =>
utils.envOverride(
Constants.FIRESTORE_EMULATOR_HOST,
utils.envOverride("FIRESTORE_URL", "https://firestore.googleapis.com"),
Expand All @@ -77,105 +77,117 @@ export const firestoreOriginOrEmulator = () =>
return `http://${val}`;
},
);
export const firestoreOrigin = () =>
export const firestoreOrigin = (): string =>
utils.envOverride("FIRESTORE_URL", "https://firestore.googleapis.com");
export const functionsOrigin = () =>
export const functionsOrigin = (): string =>
utils.envOverride("FIREBASE_FUNCTIONS_URL", "https://cloudfunctions.googleapis.com");
export const functionsV2Origin = () =>
export const functionsV2Origin = (): string =>
utils.envOverride("FIREBASE_FUNCTIONS_V2_URL", "https://cloudfunctions.googleapis.com");
export const runOrigin = () => utils.envOverride("CLOUD_RUN_URL", "https://run.googleapis.com");
export const functionsDefaultRegion = () =>
export const runOrigin = (): string =>
utils.envOverride("CLOUD_RUN_URL", "https://run.googleapis.com");
export const functionsDefaultRegion = (): string =>
utils.envOverride("FIREBASE_FUNCTIONS_DEFAULT_REGION", "REGION_TBD");

export const cloudbuildOrigin = () =>
export const cloudbuildOrigin = (): string =>
utils.envOverride("FIREBASE_CLOUDBUILD_URL", "https://cloudbuild.googleapis.com");
export const cloudschedulerOrigin = () =>
export const cloudschedulerOrigin = (): string =>
utils.envOverride("FIREBASE_CLOUDSCHEDULER_URL", "https://cloudscheduler.googleapis.com");
export const cloudTasksOrigin = () =>
export const cloudTasksOrigin = (): string =>
utils.envOverride("FIREBASE_CLOUD_TAKS_URL", "https://cloudtasks.googleapis.com");
export const pubsubOrigin = () =>
export const pubsubOrigin = (): string =>
utils.envOverride("FIREBASE_PUBSUB_URL", "https://pubsub.googleapis.com");
export const googleOrigin = () =>
export const googleOrigin = (): string =>
utils.envOverride(
"FIREBASE_TOKEN_URL",
utils.envOverride("FIREBASE_GOOGLE_URL", "https://www.googleapis.com"),
);
export const hostingOrigin = () => utils.envOverride("FIREBASE_HOSTING_URL", "https://web.app");
export const identityOrigin = () =>
export const hostingOrigin = (): string =>
utils.envOverride("FIREBASE_HOSTING_URL", "https://web.app");
export const identityOrigin = (): string =>
utils.envOverride("FIREBASE_IDENTITY_URL", "https://identitytoolkit.googleapis.com");
export const iamOrigin = () => utils.envOverride("FIREBASE_IAM_URL", "https://iam.googleapis.com");
export const extensionsOrigin = () =>
export const iamOrigin = (): string =>
utils.envOverride("FIREBASE_IAM_URL", "https://iam.googleapis.com");
export const extensionsOrigin = (): string =>
utils.envOverride("FIREBASE_EXT_URL", "https://firebaseextensions.googleapis.com");
export const extensionsPublisherOrigin = () =>
export const extensionsPublisherOrigin = (): string =>
utils.envOverride(
"FIREBASE_EXT_PUBLISHER_URL",
"https://firebaseextensionspublisher.googleapis.com",
);
export const extensionsTOSOrigin = () =>
export const extensionsTOSOrigin = (): string =>
utils.envOverride("FIREBASE_EXT_TOS_URL", "https://firebaseextensionstos-pa.googleapis.com");
export const realtimeOrigin = () =>
export const realtimeOrigin = (): string =>
utils.envOverride("FIREBASE_REALTIME_URL", "https://firebaseio.com");
export const rtdbManagementOrigin = () =>
export const rtdbManagementOrigin = (): string =>
utils.envOverride("FIREBASE_RTDB_MANAGEMENT_URL", "https://firebasedatabase.googleapis.com");
export const rtdbMetadataOrigin = () =>
export const rtdbMetadataOrigin = (): string =>
utils.envOverride("FIREBASE_RTDB_METADATA_URL", "https://metadata-dot-firebase-prod.appspot.com");
export const remoteConfigApiOrigin = () =>
export const remoteConfigApiOrigin = (): string =>
utils.envOverride("FIREBASE_REMOTE_CONFIG_URL", "https://firebaseremoteconfig.googleapis.com");
export const messagingApiOrigin = () =>
export const messagingApiOrigin = (): string =>
utils.envOverride("FIREBASE_MESSAGING_CONFIG_URL", "https://fcm.googleapis.com");
export const crashlyticsApiOrigin = () =>
export const crashlyticsApiOrigin = (): string =>
utils.envOverride("FIREBASE_CRASHLYTICS_URL", "https://firebasecrashlytics.googleapis.com");
export const resourceManagerOrigin = () =>
export const firebaseTelemetryOrigin = (): string =>
utils.envOverride("FIREBASE_TELEMETRY_URL", "https://firebasetelemetry.googleapis.com");
export const firebaseTelemetryAdminOrigin = (): string =>
utils.envOverride(
"FIREBASE_TELEMETRY_ADMIN_URL",
"https://firebasetelemetryadmin.googleapis.com",
);
export const resourceManagerOrigin = (): string =>
utils.envOverride("FIREBASE_RESOURCEMANAGER_URL", "https://cloudresourcemanager.googleapis.com");
export const rulesOrigin = () =>
export const rulesOrigin = (): string =>
utils.envOverride("FIREBASE_RULES_URL", "https://firebaserules.googleapis.com");
export const runtimeconfigOrigin = () =>
export const runtimeconfigOrigin = (): string =>
utils.envOverride("FIREBASE_RUNTIMECONFIG_URL", "https://runtimeconfig.googleapis.com");
export const storageOrigin = () =>
export const storageOrigin = (): string =>
utils.envOverride("FIREBASE_STORAGE_URL", "https://storage.googleapis.com");
export const firebaseStorageOrigin = () =>
export const firebaseStorageOrigin = (): string =>
utils.envOverride("FIREBASE_FIREBASESTORAGE_URL", "https://firebasestorage.googleapis.com");
export const hostingApiOrigin = () =>
export const hostingApiOrigin = (): string =>
utils.envOverride("FIREBASE_HOSTING_API_URL", "https://firebasehosting.googleapis.com");
export const cloudRunApiOrigin = () =>
export const cloudRunApiOrigin = (): string =>
utils.envOverride("CLOUD_RUN_API_URL", "https://run.googleapis.com");
export const serviceUsageOrigin = () =>
export const serviceUsageOrigin = (): string =>
utils.envOverride("FIREBASE_SERVICE_USAGE_URL", "https://serviceusage.googleapis.com");
export const studioApiOrigin = () =>
export const studioApiOrigin = (): string =>
utils.envOverride("FIREBASE_STUDIO_URL", "https://monospace-pa.googleapis.com");

export const githubOrigin = () => utils.envOverride("GITHUB_URL", "https://github.com");
export const githubApiOrigin = () => utils.envOverride("GITHUB_API_URL", "https://api.github.com");
export const secretManagerOrigin = () =>
export const githubOrigin = (): string => utils.envOverride("GITHUB_URL", "https://github.com");
export const githubApiOrigin = (): string =>
utils.envOverride("GITHUB_API_URL", "https://api.github.com");
export const secretManagerOrigin = (): string =>
utils.envOverride("CLOUD_SECRET_MANAGER_URL", "https://secretmanager.googleapis.com");
export const computeOrigin = () =>
export const computeOrigin = (): string =>
utils.envOverride("COMPUTE_URL", "https://compute.googleapis.com");
export const githubClientId = () => utils.envOverride("GITHUB_CLIENT_ID", "89cf50f02ac6aaed3484");
export const githubClientSecret = () =>
export const githubClientId = (): string =>
utils.envOverride("GITHUB_CLIENT_ID", "89cf50f02ac6aaed3484");
export const githubClientSecret = (): string =>
utils.envOverride("GITHUB_CLIENT_SECRET", "3330d14abc895d9a74d5f17cd7a00711fa2c5bf0");

export const dataconnectOrigin = () =>
export const dataconnectOrigin = (): string =>
utils.envOverride("FIREBASE_DATACONNECT_URL", "https://firebasedataconnect.googleapis.com");
export const dataconnectP4SADomain = () =>
export const dataconnectP4SADomain = (): string =>
utils.envOverride(
"FIREBASE_DATACONNECT_P4SA_DOMAIN",
"gcp-sa-firebasedataconnect.iam.gserviceaccount.com",
);
export const dataConnectLocalConnString = () =>
export const dataConnectLocalConnString = (): string =>
utils.envOverride("FIREBASE_DATACONNECT_POSTGRESQL_STRING", "");
export const cloudSQLAdminOrigin = () =>
export const cloudSQLAdminOrigin = (): string =>
utils.envOverride("CLOUD_SQL_URL", "https://sqladmin.googleapis.com");
export const vertexAIOrigin = () =>
export const vertexAIOrigin = (): string =>
utils.envOverride("VERTEX_AI_URL", "https://aiplatform.googleapis.com");
export const aiLogicProxyOrigin = () =>
export const aiLogicProxyOrigin = (): string =>
utils.envOverride("AI_LOGIC_PROXY_URL", "https://firebasevertexai.googleapis.com");

export const appTestingOrigin = () =>
export const appTestingOrigin = (): string =>
utils.envOverride("FIREBASE_APP_TESTING_URL", "https://firebaseapptesting.googleapis.com");
export const cloudTestingOrigin = () =>
export const cloudTestingOrigin = (): string =>
utils.envOverride("CLOUD_TESTING_URL", "https://testing.googleapis.com");

export const developerKnowledgeOrigin = () =>
export const developerKnowledgeOrigin = (): string =>
utils.envOverride("DEVELOPER_KNOWLEDGE_URL", "https://developerknowledge.googleapis.com");

/** Gets scopes that have been set. */
Expand Down
70 changes: 70 additions & 0 deletions src/commands/crashlytics-onboard-web.ts
Comment thread
tonybaroneee marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Command } from "../command";
import { FirebaseError } from "../error";
import { logger } from "../logger";
import {
AppPlatform,
checkForApps,
listFirebaseApps,
selectAppInteractively,
} from "../management/apps";
import { needProjectId } from "../projectUtils";
import { requireAuth } from "../requireAuth";
import { onboardCrashlyticsWeb, OnboardWebResult } from "../crashlytics/onboarding";
import { Options } from "../options";

export interface CrashlyticsOnboardOptions extends Options {
app?: string;
}

export const command = new Command("crashlytics:onboard:web [appId]")
.description("onboard a Firebase web app to Crashlytics")
.option("--app <appID>", "the app id of your Firebase app")
.before(requireAuth)
.action(
async (
appIdInput = "",
options: CrashlyticsOnboardOptions,
): Promise<OnboardWebResult | undefined> => {
const projectId = needProjectId(options);
let appId = appIdInput || options.app || "";

Check warning on line 29 in src/commands/crashlytics-onboard-web.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe assignment of an `any` value

let appPlatform: AppPlatform = AppPlatform.ANY;
if (!appId) {
const apps = await listFirebaseApps(projectId, AppPlatform.ANY);
checkForApps(apps, AppPlatform.ANY);
if (apps.length === 1) {
appId = apps[0].appId;
appPlatform = apps[0].platform;
} else if (options.nonInteractive) {
throw new FirebaseError(
`Project ${projectId} has multiple apps, must specify an app id.`,
);
} else {
const appMetadata = await selectAppInteractively(apps, AppPlatform.ANY);
appId = appMetadata.appId;
appPlatform = appMetadata.platform;
}
} else {
const apps = await listFirebaseApps(projectId, AppPlatform.ANY);
const matchedApp = apps.find((a) => a.appId === appId);
if (matchedApp) {
appPlatform = matchedApp.platform;
} else if (appId.includes(":web:")) {

Check warning on line 52 in src/commands/crashlytics-onboard-web.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe call of an `any` typed value

Check warning on line 52 in src/commands/crashlytics-onboard-web.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe member access .includes on an `any` value
appPlatform = AppPlatform.WEB;
} else if (appId.includes(":android:")) {

Check warning on line 54 in src/commands/crashlytics-onboard-web.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe call of an `any` typed value

Check warning on line 54 in src/commands/crashlytics-onboard-web.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe member access .includes on an `any` value
appPlatform = AppPlatform.ANDROID;
} else if (appId.includes(":ios:")) {

Check warning on line 56 in src/commands/crashlytics-onboard-web.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe call of an `any` typed value

Check warning on line 56 in src/commands/crashlytics-onboard-web.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe member access .includes on an `any` value
appPlatform = AppPlatform.IOS;
}
}

if (appPlatform !== AppPlatform.WEB && !appId.includes(":web:")) {

Check warning on line 61 in src/commands/crashlytics-onboard-web.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe call of an `any` typed value

Check warning on line 61 in src/commands/crashlytics-onboard-web.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Unsafe member access .includes on an `any` value
logger.info(
`Crashlytics onboarding via the CLI is currently only supported for Web apps. No onboarding steps needed for non-Web app: ${appId}`,

Check warning on line 63 in src/commands/crashlytics-onboard-web.ts

View workflow job for this annotation

GitHub Actions / lint (24)

Invalid type "any" of template literal expression
);
return undefined;
}

return await onboardCrashlyticsWeb(projectId, appId, options);
},
);
2 changes: 2 additions & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export function load(client: CLIClient): CLIClient {
client.auth.export = loadCommand("auth-export");
client.auth.import = loadCommand("auth-import");
client.crashlytics = {};
client.crashlytics.onboard = {};
client.crashlytics.onboard.web = loadCommand("crashlytics-onboard-web");
client.crashlytics.symbols = {};
client.crashlytics.symbols.upload = loadCommand("crashlytics-symbols-upload");
client.crashlytics.mappingfile = {};
Expand Down
Loading
Loading