From 345dce3e3f7d0454a3967ce32d438d0d320a9c6f Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Wed, 1 Apr 2026 11:43:17 -0700 Subject: [PATCH 1/2] First pass. Gonna try it out --- src/commands/ext-info.ts | 8 +++++-- src/extensions/listExtensions.spec.ts | 32 +++++++++++++++++++++++++++ src/extensions/listExtensions.ts | 6 +++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/commands/ext-info.ts b/src/commands/ext-info.ts index 064fdac822e..955b50b018f 100644 --- a/src/commands/ext-info.ts +++ b/src/commands/ext-info.ts @@ -11,7 +11,7 @@ import * as utils from "../utils"; import { marked } from "marked"; import { markedTerminal } from "marked-terminal"; -import { ExtensionSpec } from "../extensions/types"; +import { ExtensionSpec, ExtensionVersion } from "../extensions/types"; const FUNCTION_TYPE_REGEX = /\..+\.function/; @@ -23,6 +23,7 @@ export const command = new Command("ext:info ") .before(checkMinRequiredVersion, "extMinVersion") .action(async (extensionName: string, options: any) => { let spec: ExtensionSpec; + let version: ExtensionVersion | undefined; if (isLocalExtension(extensionName)) { if (!options.markdown) { utils.logLabeledBullet(logPrefix, `reading extension from directory: ${extensionName}`); @@ -41,7 +42,7 @@ export const command = new Command("ext:info ") const [name, version] = extensionName.split("@"); extensionName = `firebase/${name}@${version || "latest"}`; } - const version = await extensionsApi.getExtensionVersion(extensionName); + version = await extensionsApi.getExtensionVersion(extensionName); spec = version.spec; } @@ -60,6 +61,9 @@ export const command = new Command("ext:info ") const url = spec.author?.url; const urlMarkdown = url ? `(**[${url}](${url})**)` : ""; lines.push(`**Author**: ${authorName} ${urlMarkdown}`); + if (version?.sourceDownloadUri) { + lines.push(`**Download URL**: ${version.sourceDownloadUri}`); + } if (spec.description) { lines.push(`**Description**: ${spec.description}`); diff --git a/src/extensions/listExtensions.spec.ts b/src/extensions/listExtensions.spec.ts index 0d50ad60c15..2e95d328617 100644 --- a/src/extensions/listExtensions.spec.ts +++ b/src/extensions/listExtensions.spec.ts @@ -14,6 +14,14 @@ const MOCK_INSTANCES = [ extensionRef: "firebase/image-resizer", name: "projects/my-test-proj/instances/image-resizer/configurations/95355951-397f-4821-a5c2-9c9788b2cc63", createTime: "2019-05-19T00:20:10.416947Z", + params: { + IMG_BUCKET: "my-test-proj.firebasestorage.app", + IMG_SIZES: "200x200,400x400", + DELETE_ORIGINAL_FILE: "false", + }, + systemParams: { + "firebaseextensions.v1beta.function/location": "us-central1", + }, source: { state: "ACTIVE", spec: { @@ -35,6 +43,14 @@ const MOCK_INSTANCES = [ extensionRef: "firebase/image-resizer", name: "projects/my-test-proj/instances/image-resizer-1/configurations/5b1fb749-764d-4bd1-af60-bb7f22d27860", createTime: "2019-06-19T00:21:06.722782Z", + params: { + IMG_BUCKET: "my-test-proj.firebasestorage.app", + IMG_SIZES: "300x300", + DELETE_ORIGINAL_FILE: "true", + }, + systemParams: { + "firebaseextensions.v1beta.function/location": "us-central1", + }, source: { spec: { version: "0.1.0", @@ -78,6 +94,14 @@ describe("listExtensions", () => { state: "ACTIVE", updateTime: "2019-06-19 00:21:06", version: "0.1.0", + params: { + IMG_BUCKET: "my-test-proj.firebasestorage.app", + IMG_SIZES: "300x300", + DELETE_ORIGINAL_FILE: "true", + }, + systemParams: { + "firebaseextensions.v1beta.function/location": "us-central1", + }, }, { extension: "firebase/image-resizer", @@ -86,6 +110,14 @@ describe("listExtensions", () => { state: "ACTIVE", updateTime: "2019-05-19 00:20:10", version: "0.1.0", + params: { + IMG_BUCKET: "my-test-proj.firebasestorage.app", + IMG_SIZES: "200x200,400x400", + DELETE_ORIGINAL_FILE: "false", + }, + systemParams: { + "firebaseextensions.v1beta.function/location": "us-central1", + }, }, ]; expect(result).to.eql(expected); diff --git a/src/extensions/listExtensions.ts b/src/extensions/listExtensions.ts index fe4140d39fc..8da14a19753 100644 --- a/src/extensions/listExtensions.ts +++ b/src/extensions/listExtensions.ts @@ -12,7 +12,7 @@ import * as extensionsUtils from "./utils"; * @param projectId ID of the project we're querying * @return mapping that contains a list of instances under the "instances" key */ -export async function listExtensions(projectId: string): Promise[]> { +export async function listExtensions(projectId: string): Promise[]> { const instances = await listInstances(projectId); if (instances.length < 1) { logLabeledBullet( @@ -30,7 +30,7 @@ export async function listExtensions(projectId: string): Promise new Date(b.createTime).valueOf() - new Date(a.createTime).valueOf(), ); - const formatted: Record[] = []; + const formatted: Record[] = []; sorted.forEach((instance) => { let extension = instance.config.extensionRef || ""; let publisher; @@ -54,6 +54,8 @@ export async function listExtensions(projectId: string): Promise Date: Thu, 2 Apr 2026 10:59:58 -0700 Subject: [PATCH 2/2] PR feedbacK --- src/extensions/listExtensions.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/extensions/listExtensions.ts b/src/extensions/listExtensions.ts index 8da14a19753..bbd0cb36ebf 100644 --- a/src/extensions/listExtensions.ts +++ b/src/extensions/listExtensions.ts @@ -10,9 +10,20 @@ import * as extensionsUtils from "./utils"; /** * Lists the extensions installed under a project * @param projectId ID of the project we're querying - * @return mapping that contains a list of instances under the "instances" key + * @return list of listed extensions */ -export async function listExtensions(projectId: string): Promise[]> { +export interface ListedExtension { + extension: string; + publisher: string; + instanceId: string; + state: string; + version?: string; + updateTime: string; + params: Record; + systemParams: Record; +} + +export async function listExtensions(projectId: string): Promise { const instances = await listInstances(projectId); if (instances.length < 1) { logLabeledBullet( @@ -30,7 +41,7 @@ export async function listExtensions(projectId: string): Promise new Date(b.createTime).valueOf() - new Date(a.createTime).valueOf(), ); - const formatted: Record[] = []; + const formatted: ListedExtension[] = []; sorted.forEach((instance) => { let extension = instance.config.extensionRef || ""; let publisher;