Skip to content

Commit 9977780

Browse files
committed
feat: add uploadFromBuffer method and associated types for file uploads
1 parent 16a3469 commit 9977780

File tree

2 files changed

+56
-13
lines changed

2 files changed

+56
-13
lines changed

index.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
import { PluginOptions } from './types.js';
2+
import { PluginOptions, UploadFromBufferParams } from './types.js';
33
import { AdminForthPlugin, AdminForthResourceColumn, AdminForthResource, Filters, IAdminForth, IHttpServer, suggestIfTypo, RateLimiter, AdminUser, HttpExtra } from "adminforth";
44
import { Readable } from "stream";
55
import { randomUUID } from "crypto";
@@ -554,19 +554,17 @@ export default class UploadPlugin extends AdminForthPlugin {
554554
}
555555

556556

557+
/*
558+
* Uploads a file from a buffer, creates a record in the resource, and returns the file path and preview URL.
559+
*/
557560
async uploadFromBuffer({
558561
filename,
559562
contentType,
560563
buffer,
561564
adminUser,
562565
extra,
563-
}: {
564-
filename: string;
565-
contentType: string;
566-
buffer: Buffer | Uint8Array | ArrayBuffer;
567-
adminUser: AdminUser;
568-
extra?: HttpExtra;
569-
}): Promise<{ path: string; previewUrl: string }> {
566+
recordAttributes,
567+
}: UploadFromBufferParams): Promise<{ path: string; previewUrl: string }> {
570568
if (!filename || !contentType || !buffer) {
571569
throw new Error('filename, contentType and buffer are required');
572570
}
@@ -644,22 +642,22 @@ export default class UploadPlugin extends AdminForthPlugin {
644642
throw new Error(`Upload failed with status ${resp.status}: ${bodyText}`);
645643
}
646644

647-
await this.options.storageAdapter.markKeyForNotDeletation(filePath);
645+
await this.markKeyForNotDeletion(filePath);
648646

649647
if (!this.resourceConfig) {
650648
throw new Error('resourceConfig is not initialized yet');
651649
}
652650

653651
const { error: createError } = await this.adminforth.createResourceRecord({
654652
resource: this.resourceConfig,
655-
record: { [this.options.pathColumnName]: filePath },
653+
record: { ...(recordAttributes ?? {}), [this.options.pathColumnName]: filePath },
656654
adminUser,
657655
extra,
658656
});
659657

660658
if (createError) {
661659
try {
662-
await this.options.storageAdapter.markKeyForDeletation(filePath);
660+
await this.markKeyForDeletion(filePath);
663661
} catch (e) {
664662
// best-effort cleanup, ignore error
665663
}

types.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AdminUser, ImageGenerationAdapter, StorageAdapter } from "adminforth";
1+
import { AdminUser, ImageGenerationAdapter, StorageAdapter, HttpExtra } from "adminforth";
22

33
export type PluginOptions = {
44

@@ -154,4 +154,49 @@ export type PluginOptions = {
154154
* For now only S3 adapter is supported.
155155
*/
156156
storageAdapter: StorageAdapter,
157-
}
157+
}
158+
159+
/**
160+
* Parameters for the UploadPlugin.uploadFromBuffer API.
161+
* Used to upload a binary file buffer, create a record in the resource,
162+
* and return the stored path and preview URL.
163+
*/
164+
export type UploadFromBufferParams = {
165+
/**
166+
* Original file name including extension, used to derive storage path
167+
* and validate the file extension. Example: "photo.png".
168+
*/
169+
filename: string;
170+
171+
/**
172+
* MIME type of the uploaded file. Will be used as Content-Type
173+
* when uploading to the storage adapter. Example: "image/png".
174+
*/
175+
contentType: string;
176+
177+
/**
178+
* Binary contents of the file. Can be a Node.js Buffer, Uint8Array,
179+
* or ArrayBuffer. The plugin uploads this directly without converting
180+
* to base64.
181+
*/
182+
buffer: Buffer | Uint8Array | ArrayBuffer;
183+
184+
/**
185+
* Authenticated admin user on whose behalf the record is created.
186+
* Passed through to AdminForth createResourceRecord hooks.
187+
*/
188+
adminUser: AdminUser;
189+
190+
/**
191+
* Optional HTTP context (headers, IP, etc.) forwarded to AdminForth
192+
* createResourceRecord hooks. Needed to execute hooks on creation resource record for the upload.
193+
*/
194+
extra?: HttpExtra;
195+
196+
/**
197+
* Optional additional attributes to set on the created record
198+
* together with the path column managed by the plugin.
199+
* Values here do NOT affect the generated storage path.
200+
*/
201+
recordAttributes?: Record<string, any>;
202+
};

0 commit comments

Comments
 (0)