fix: extensions (#2926)

This commit is contained in:
Daniel Salazar
2026-05-05 20:55:53 -07:00
committed by GitHub
parent c1dacab4c2
commit 224ea5f7f8
2 changed files with 39 additions and 26 deletions
+25 -22
View File
@@ -99,35 +99,38 @@ async function decodeAndValidateThumbnail(
// Intercept data-URL thumbnails before they hit the DB: upload to S3
// and replace the URL with an s3:// pointer.
extension.on('thumbnail.created', async (event: Record<string, unknown>) => {
const url = event.url;
if (typeof url !== 'string' || !url.startsWith('data:')) return;
extension.on(
'thumbnail.created',
async (_key, event: Record<string, unknown>) => {
const url = event.url;
if (typeof url !== 'string' || !url.startsWith('data:')) return;
const decoded = await decodeAndValidateThumbnail(url);
if (!decoded) {
event.url = null;
return;
}
const decoded = await decodeAndValidateThumbnail(url);
if (!decoded) {
event.url = null;
return;
}
const key = crypto.randomUUID();
event.url = `s3://${thumbnailBucketName}/${key}`;
const key = crypto.randomUUID();
event.url = `s3://${thumbnailBucketName}/${key}`;
await getClient().send(
new PutObjectCommand({
Bucket: thumbnailBucketName,
Key: key,
Body: decoded.data,
ContentType: decoded.mimeType,
}),
);
});
await getClient().send(
new PutObjectCommand({
Bucket: thumbnailBucketName,
Key: key,
Body: decoded.data,
ContentType: decoded.mimeType,
}),
);
},
);
// ── thumbnail.upload.prepare ────────────────────────────────────────
// Generate pre-signed upload URLs so the client can PUT directly to S3.
extension.on(
'thumbnail.upload.prepare',
async (event: Record<string, unknown>) => {
async (_key, event: Record<string, unknown>) => {
if (!event || !Array.isArray(event.items)) return;
const presignClient = getPresignClient();
@@ -169,7 +172,7 @@ extension.on(
// ── thumbnail.read ──────────────────────────────────────────────────
// Convert s3:// or legacy https:// thumbnails to signed URLs.
extension.on('thumbnail.read', async (entry: Record<string, unknown>) => {
extension.on('thumbnail.read', async (_key, entry: Record<string, unknown>) => {
const thumb = entry.thumbnail;
if (typeof thumb !== 'string' || !thumb) return;
const presignClient = getPresignClient();
@@ -233,7 +236,7 @@ extension.on('thumbnail.read', async (entry: Record<string, unknown>) => {
extension.on(
'fs.remove.node',
async ({ target }: { target: Record<string, unknown> }) => {
async (_key, { target }: { target: Record<string, unknown> }) => {
const thumbnailUrl = target.thumbnail as string | undefined;
if (!thumbnailUrl || !thumbnailUrl.startsWith('s3://')) return;
+14 -4
View File
@@ -56,8 +56,10 @@ export const extensionStore = {
controllers: {} as IPuterControllerRegistry,
drivers: {} as IPuterDriverRegistry,
globalMiddlewares: [] as RequestHandler[],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
events: {} as Record<string, ((...args: any[]) => void)[]>,
events: {} as Record<
string,
((key: string, data: unknown, meta: unknown) => void)[]
>,
/**
* Extension-declared routes. Shape matches the controller-layer
* `RouteDescriptor`, so both flow through the same materializer
@@ -192,8 +194,11 @@ export const extension = {
// ── Event subscription ───────────────────────────────────────────
// eslint-disable-next-line @typescript-eslint/no-explicit-any
on: (event: string, handler: (...args: any[]) => void) => {
on: (
event: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
handler: (key: string, data: any, meta: any) => void,
) => {
if (!extensionStore.events[event]) {
extensionStore.events[event] = [];
}
@@ -281,6 +286,7 @@ export const extension = {
const proxyProxyHandler = {
get: (_target2: object, prop2: string) => {
const proxiedObj2 =
// @ts-expect-error any type needed
clientsContainers[prop][prop2];
if (!proxiedObj2) {
throw new Error(
@@ -307,6 +313,7 @@ export const extension = {
const proxyProxyHandler = {
get: (_target2: object, prop2: string) => {
const proxiedObj2 =
// @ts-expect-error any type needed
clientsContainers[prop][prop2];
if (!proxiedObj2) {
throw new Error(
@@ -333,6 +340,7 @@ export const extension = {
const proxyProxyHandler = {
get: (_target2: object, prop2: string) => {
const proxiedObj2 =
// @ts-expect-error any type needed
clientsContainers[prop][prop2];
if (!proxiedObj2) {
throw new Error(
@@ -359,6 +367,7 @@ export const extension = {
const proxyProxyHandler = {
get: (_target2: object, prop2: string) => {
const proxiedObj2 =
// @ts-expect-error any type needed
clientsContainers[prop][prop2];
if (!proxiedObj2) {
throw new Error(
@@ -385,6 +394,7 @@ export const extension = {
const proxyProxyHandler = {
get: (_target2: object, prop2: string) => {
const proxiedObj2 =
// @ts-expect-error any type needed
clientsContainers[prop][prop2];
if (!proxiedObj2) {
throw new Error(