feat(borg-stmf): add file support to encryptFormData

- Implemented `readFileAsBase64` helper using FileReader.
- Updated `encryptFormData` to support `File` objects by reading them asynchronously as base64 and populating `FormField` structure.
- Updated `encryptFormData` to accept optional `metadata` and `serverPublicKey` to support more flexible usage.
- Refactored `enableInterceptor` to use `encryptFormData`, reducing code duplication and enabling file support for intercepted forms.
- Added `node_modules/` to `.gitignore` to prevent accidental commits of dependencies.
This commit is contained in:
Snider 2026-02-02 01:53:52 +00:00
parent cf2af53ed3
commit 24ba4b8d15
2 changed files with 49 additions and 22 deletions

2
.gitignore vendored
View file

@ -10,3 +10,5 @@ demo-track.smsg
# Dev artifacts
.playwright-mcp/
node_modules/
*.log

View file

@ -102,30 +102,48 @@ export class BorgSTMF {
/**
* Encrypt a FormData object
*/
async encryptFormData(formData: globalThis.FormData): Promise<EncryptResult> {
async encryptFormData(
formData: globalThis.FormData,
metadata?: Record<string, string>,
serverPublicKey?: string
): Promise<EncryptResult> {
this.ensureInitialized();
const fields: Record<string, string | FormField> = {};
const promises: Promise<void>[] = [];
formData.forEach((value, key) => {
if (value instanceof File) {
// Handle file uploads - read as base64
// Note: For large files, consider chunking or streaming
this.log('File field detected:', key, value.name);
// For now, skip files - they need async reading
// TODO: Add file support with FileReader
const promise = readFileAsBase64(value).then((base64) => {
fields[key] = {
name: key,
value: base64,
type: 'file',
filename: value.name,
mime: value.type,
};
});
promises.push(promise);
} else {
fields[key] = value.toString();
}
});
await Promise.all(promises);
const meta = {
origin: window.location.origin,
timestamp: Date.now().toString(),
...metadata,
};
const payload = await this.wasm!.encryptFields(
fields,
this.config.serverPublicKey,
{
origin: window.location.origin,
timestamp: Date.now().toString(),
}
serverPublicKey || this.config.serverPublicKey,
meta
);
return {
@ -218,22 +236,16 @@ export class BorgSTMF {
// Encrypt the form
const originalFormData = new window.FormData(form);
const fields: Record<string, string> = {};
originalFormData.forEach((value, key) => {
if (!(value instanceof File)) {
fields[key] = value.toString();
}
});
const metadata: Record<string, string> = {};
if (form.id) {
metadata.formId = form.id;
}
const payload = await this.wasm!.encryptFields(
fields,
serverKey,
{
origin: window.location.origin,
timestamp: Date.now().toString(),
formId: form.id || undefined,
}
const { payload } = await this.encryptFormData(
originalFormData,
metadata,
serverKey
);
// Callback after encryption
@ -337,6 +349,19 @@ export function createBorgSTMF(config: BorgSTMFConfig): BorgSTMF {
return new BorgSTMF(config);
}
function readFileAsBase64(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const result = reader.result as string;
const base64 = result.split(',')[1];
resolve(base64);
};
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(file);
});
}
// Export types for the Go interface
declare class Go {
constructor();