diff --git a/.gitignore b/.gitignore index d3a3066..1608946 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ coverage.txt # Demo content (hosted on CDN) demo-track.smsg +!pkg/player/frontend/demo-track.smsg # Dev artifacts .playwright-mcp/ +node_modules/ +*.log diff --git a/js/borg-stmf/src/index.ts b/js/borg-stmf/src/index.ts index 8c4078e..2752118 100644 --- a/js/borg-stmf/src/index.ts +++ b/js/borg-stmf/src/index.ts @@ -102,30 +102,48 @@ export class BorgSTMF { /** * Encrypt a FormData object */ - async encryptFormData(formData: globalThis.FormData): Promise { + async encryptFormData( + formData: globalThis.FormData, + metadata?: Record, + serverPublicKey?: string + ): Promise { this.ensureInitialized(); const fields: Record = {}; + const promises: Promise[] = []; 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 = {}; - originalFormData.forEach((value, key) => { - if (!(value instanceof File)) { - fields[key] = value.toString(); - } - }); + const metadata: Record = {}; + 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 { + 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(); diff --git a/pkg/player/frontend/demo-track.smsg b/pkg/player/frontend/demo-track.smsg new file mode 100644 index 0000000..1683434 --- /dev/null +++ b/pkg/player/frontend/demo-track.smsg @@ -0,0 +1 @@ +Placeholder for CI build.