Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions packages/embeddings/src/dataconnect-generated/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Stub types for Firebase Data Connect SDK
*
* In production, this file would be auto-generated by Firebase Data Connect.
* For Vercel builds where Data Connect isn't available, we provide stubs
* that throw helpful errors at runtime.
*/
export interface VideoEmbedding {
id: string;
segmentType: string;
segmentIndex: number;
content: string;
job?: {
id: string;
title?: string;
videoUrl?: string;
};
}
export interface ListEmbeddingsResponse {
data: {
videoEmbeddings: VideoEmbedding[];
};
}
export interface GetJobEmbeddingsResponse {
data: {
videoEmbeddings: VideoEmbedding[];
};
}
type UUID = `${string}-${string}-${string}-${string}-${string}`;
/**
* List embeddings - stub that throws when Data Connect unavailable
*/
export declare function listEmbeddings(_params: {
limit: number;
}): Promise<ListEmbeddingsResponse>;
/**
* Get embeddings for a specific job - stub
*/
export declare function getJobEmbeddings(_params: {
jobId: UUID;
}): Promise<GetJobEmbeddingsResponse>;
/**
* Delete embeddings for a job - stub
*/
export declare function deleteJobEmbeddings(_params: {
jobId: UUID;
}): Promise<void>;
export {};
//# sourceMappingURL=index.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions packages/embeddings/src/dataconnect-generated/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

74 changes: 74 additions & 0 deletions packages/embeddings/src/dataconnect-generated/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Stub types for Firebase Data Connect SDK
*
* In production, this file would be auto-generated by Firebase Data Connect.
* For Vercel builds where Data Connect isn't available, we provide stubs
* that throw helpful errors at runtime.
*/
Comment on lines +1 to +7
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These dataconnect-generated stubs are TypeScript source, but this PR also checks in compiled artifacts (index.js, .map, .d.ts, .d.ts.map) under src/. Keeping build outputs alongside sources is prone to drift and can confuse module resolution; it’s usually better to commit only the .ts stub here and let tsc generate JS/declarations into dist/ during the package build.

Copilot uses AI. Check for mistakes.

// Type definitions matching expected Data Connect schema
export interface VideoEmbedding {
id: string;
segmentType: string;
segmentIndex: number;
content: string;
job?: {
id: string;
title?: string;
videoUrl?: string;
};
}

export interface ListEmbeddingsResponse {
data: {
videoEmbeddings: VideoEmbedding[];
};
}

export interface GetJobEmbeddingsResponse {
data: {
videoEmbeddings: VideoEmbedding[];
};
}

// UUID type for job IDs
type UUID = `${string}-${string}-${string}-${string}-${string}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The UUID type is used in the signatures of exported functions like getJobEmbeddings, but it's not exported itself. Exporting it would allow other modules, like embedding.ts, to use it directly. This would avoid the need to redefine or cast to the template literal string `${string}-${string}-${string}-${string}-${string}`, reducing duplication and improving maintainability.

Suggested change
type UUID = `${string}-${string}-${string}-${string}-${string}`;
export type UUID = `${string}-${string}-${string}-${string}-${string}`;


/**
* List embeddings - stub that throws when Data Connect unavailable
*/
export async function listEmbeddings(_params: {
limit: number;
}): Promise<ListEmbeddingsResponse> {
throw new Error(
"Firebase Data Connect is not configured. " +
"Run 'firebase dataconnect:sdk:generate' to generate the SDK, " +
"or use raw SQL queries for embedding operations."
);
}

/**
* Get embeddings for a specific job - stub
*/
export async function getJobEmbeddings(_params: {
jobId: UUID;
}): Promise<GetJobEmbeddingsResponse> {
throw new Error(
"Firebase Data Connect is not configured. " +
"Run 'firebase dataconnect:sdk:generate' to generate the SDK, " +
"or use raw SQL queries for embedding operations."
);
}

/**
* Delete embeddings for a job - stub
*/
export async function deleteJobEmbeddings(_params: {
jobId: UUID;
}): Promise<void> {
throw new Error(
"Firebase Data Connect is not configured. " +
"Run 'firebase dataconnect:sdk:generate' to generate the SDK, " +
"or use raw SQL queries for embedding operations."
);
}
19 changes: 12 additions & 7 deletions packages/embeddings/src/embedding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {
listEmbeddings,
getJobEmbeddings,
deleteJobEmbeddings,
} from "../dataconnect-generated";
type VideoEmbedding,
} from "./dataconnect-generated";

// =============================================================================
// Types
Expand Down Expand Up @@ -108,7 +109,9 @@ export async function generateEmbedding(text: string): Promise<number[]> {
throw new Error(`Embedding API error: ${response.status} ${await response.text()}`);
}

const data = await response.json();
const data = (await response.json()) as {
predictions: Array<{ embeddings: { values: number[] } }>;
};
return data.predictions[0].embeddings.values;
}

Expand All @@ -134,8 +137,10 @@ export async function generateEmbeddings(texts: string[]): Promise<number[][]> {
throw new Error(`Embedding API error: ${response.status} ${await response.text()}`);
}

const data = await response.json();
return data.predictions.map((p: { embeddings: { values: number[] } }) => p.embeddings.values);
const data = (await response.json()) as {
predictions: Array<{ embeddings: { values: number[] } }>;
};
Comment on lines +140 to +142
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This anonymous type for the API response is also used in the generateEmbedding function. To improve maintainability and avoid code duplication, it would be better to define a named interface (e.g., EmbeddingResponse) in a shared location (like the types section at the top of this file) and reuse it here and in generateEmbedding.

return data.predictions.map((p) => p.embeddings.values);
}

/**
Expand All @@ -148,7 +153,7 @@ async function getAccessToken(): Promise<string> {
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token",
{ headers: { "Metadata-Flavor": "Google" } }
);
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In getAccessToken(), the metadata server fetch result isn’t checked before calling response.json(). If the metadata server returns a non-2xx (e.g., permission/availability issues), this will throw a less-informative JSON parsing error. Consider checking response.ok and throwing an error that includes the status and response body before parsing.

Suggested change
);
);
if (!response.ok) {
const body = await response.text().catch(() => "<unable to read response body>");
throw new Error(`Metadata server error: ${response.status} ${body}`);
}

Copilot uses AI. Check for mistakes.
const data = await response.json();
const data = (await response.json()) as { access_token: string };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve readability and maintainability, consider defining a named interface for this API response shape (e.g., AccessTokenResponse) instead of using an inline anonymous type. This makes the code more self-documenting and easier to manage.

return data.access_token;
}

Expand Down Expand Up @@ -356,7 +361,7 @@ export async function embedJobAnalysis(
*/
export async function getEmbeddingsForJob(jobId: string): Promise<EmbeddingRecord[]> {
const result = await getJobEmbeddings({ jobId: jobId as `${string}-${string}-${string}-${string}-${string}` });
return result.data.videoEmbeddings.map((e) => ({
return result.data.videoEmbeddings.map((e: VideoEmbedding) => ({
id: e.id,
segmentType: e.segmentType,
segmentIndex: e.segmentIndex,
Expand All @@ -377,7 +382,7 @@ export async function clearJobEmbeddings(jobId: string): Promise<void> {
*/
export async function listRecentEmbeddings(limit: number = 100): Promise<EmbeddingRecord[]> {
const result = await listEmbeddings({ limit });
return result.data.videoEmbeddings.map((e) => ({
return result.data.videoEmbeddings.map((e: VideoEmbedding) => ({
id: e.id,
segmentType: e.segmentType,
segmentIndex: e.segmentIndex,
Expand Down