@majikah/majik-file 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/types.d.ts +4 -2
- package/dist/core/utils.d.ts +4 -4
- package/dist/core/utils.js +3 -3
- package/dist/majik-file.d.ts +8 -6
- package/dist/majik-file.js +11 -11
- package/package.json +1 -1
package/dist/core/types.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export type MajikMessagePublicKey = string;
|
|
2
2
|
export type FileContext = "user_upload" | "chat_attachment" | "chat_image" | "thread_attachment";
|
|
3
3
|
export type StorageType = "permanent" | "temporary";
|
|
4
|
+
/** Allowed TTLs for temporary files in days. Maps 1:1 to R2 lifecycle prefixes. */
|
|
5
|
+
export type TempFileDuration = 1 | 2 | 3 | 5 | 7 | 15;
|
|
4
6
|
/**
|
|
5
7
|
* The file owner's full identity.
|
|
6
8
|
* Carries both keys — public for encryption, secret for decryption.
|
|
@@ -185,9 +187,9 @@ export interface CreateOptions {
|
|
|
185
187
|
*/
|
|
186
188
|
bypassSizeLimit?: boolean;
|
|
187
189
|
/**
|
|
188
|
-
*
|
|
190
|
+
* Temporary file duration in days. Required when isTemporary = true.
|
|
189
191
|
*/
|
|
190
|
-
expiresAt?:
|
|
192
|
+
expiresAt?: TempFileDuration;
|
|
191
193
|
/** Associate this file with a chat message (mutually exclusive with threadMessageId). */
|
|
192
194
|
chatMessageId?: string;
|
|
193
195
|
/** Associate this file with a thread message (mutually exclusive with chatMessageId). */
|
package/dist/core/utils.d.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* - Human-readable file size formatting
|
|
12
12
|
* - Expiry helpers
|
|
13
13
|
*/
|
|
14
|
-
import type { DecodedMjkb, MajikFileRecipient, MjkbPayload } from "./types";
|
|
14
|
+
import type { DecodedMjkb, MajikFileRecipient, MjkbPayload, TempFileDuration } from "./types";
|
|
15
15
|
export declare function arrayToBase64(data: Uint8Array): string;
|
|
16
16
|
export declare function arrayBufferToBase64(buffer: ArrayBuffer): string;
|
|
17
17
|
export declare function base64ToUint8Array(base64: string): Uint8Array;
|
|
@@ -37,9 +37,9 @@ export declare function buildPermanentR2Key(userId: string, fileHash: string): s
|
|
|
37
37
|
/**
|
|
38
38
|
* Build an R2 object key for a temporary / public file.
|
|
39
39
|
* Objects under this prefix are auto-deleted by the bucket lifecycle policy.
|
|
40
|
-
* files/public/<userId>_<fileHash>.mjkb
|
|
40
|
+
* files/public/15/<userId>_<fileHash>.mjkb
|
|
41
41
|
*/
|
|
42
|
-
export declare function buildTemporaryR2Key(userId: string, fileHash: string): string;
|
|
42
|
+
export declare function buildTemporaryR2Key(userId: string, fileHash: string, duration?: TempFileDuration): string;
|
|
43
43
|
/**
|
|
44
44
|
* Build an R2 object key for an encrypted WebP chat image.
|
|
45
45
|
*
|
|
@@ -97,7 +97,7 @@ export declare function isExpired(expiresAt: string | null): boolean;
|
|
|
97
97
|
* Build a default expiry ISO string for temporary files.
|
|
98
98
|
* @param days Days from now. Defaults to 15 (matching the R2 lifecycle policy).
|
|
99
99
|
*/
|
|
100
|
-
export declare function buildExpiryDate(days?:
|
|
100
|
+
export declare function buildExpiryDate(days?: TempFileDuration): string;
|
|
101
101
|
/**
|
|
102
102
|
* Deduplicate a recipient list and strip the owner's own key.
|
|
103
103
|
*
|
package/dist/core/utils.js
CHANGED
|
@@ -83,10 +83,10 @@ export function buildPermanentR2Key(userId, fileHash) {
|
|
|
83
83
|
/**
|
|
84
84
|
* Build an R2 object key for a temporary / public file.
|
|
85
85
|
* Objects under this prefix are auto-deleted by the bucket lifecycle policy.
|
|
86
|
-
* files/public/<userId>_<fileHash>.mjkb
|
|
86
|
+
* files/public/15/<userId>_<fileHash>.mjkb
|
|
87
87
|
*/
|
|
88
|
-
export function buildTemporaryR2Key(userId, fileHash) {
|
|
89
|
-
return `${R2_PREFIX.TEMPORARY}/${userId}_${fileHash}.mjkb`;
|
|
88
|
+
export function buildTemporaryR2Key(userId, fileHash, duration = 15) {
|
|
89
|
+
return `${R2_PREFIX.TEMPORARY}/${duration}/${userId}_${fileHash}.mjkb`;
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
92
|
* Build an R2 object key for an encrypted WebP chat image.
|
package/dist/majik-file.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MajikFileJSON, CreateOptions, MajikFileIdentity, MajikFileStats, FileContext, StorageType } from "./core/types";
|
|
1
|
+
import type { MajikFileJSON, CreateOptions, MajikFileIdentity, MajikFileStats, FileContext, StorageType, TempFileDuration } from "./core/types";
|
|
2
2
|
/**
|
|
3
3
|
* MajikFile
|
|
4
4
|
* ----------------
|
|
@@ -181,17 +181,19 @@ export declare class MajikFile {
|
|
|
181
181
|
* @throws MajikFileError when switching to temporary without an expiresAt,
|
|
182
182
|
* or if the instance has no userId / fileHash yet.
|
|
183
183
|
*/
|
|
184
|
-
setStorageType(type: StorageType, expiresAt: string | null): void;
|
|
184
|
+
setStorageType(type: StorageType, expiresAt: string | null, duration?: TempFileDuration): void;
|
|
185
185
|
/**
|
|
186
186
|
* Switch to permanent storage. Clears any expiry date and updates the R2 key.
|
|
187
187
|
*/
|
|
188
188
|
setPermanent(): void;
|
|
189
189
|
/**
|
|
190
|
-
* Switch to temporary storage with
|
|
190
|
+
* Switch to temporary storage with a typed TTL duration.
|
|
191
|
+
* The duration determines both the R2 prefix bucket and the expiry date.
|
|
191
192
|
*
|
|
192
|
-
* @param
|
|
193
|
+
* @param duration Days until expiry. Must be one of: 1 | 2 | 3 | 5 | 7 | 15.
|
|
194
|
+
* Defaults to 15 to match the R2 lifecycle policy.
|
|
193
195
|
*/
|
|
194
|
-
setTemporary(
|
|
196
|
+
setTemporary(duration?: TempFileDuration): void;
|
|
195
197
|
/**
|
|
196
198
|
* Serialise metadata to a plain object matching the `majik_files` Supabase table.
|
|
197
199
|
* The encrypted binary (_binary) is intentionally excluded.
|
|
@@ -306,7 +308,7 @@ export declare class MajikFile {
|
|
|
306
308
|
* Build a default ISO-8601 expiry date for temporary files.
|
|
307
309
|
* @param days Days from now. Defaults to 15 (R2 lifecycle policy).
|
|
308
310
|
*/
|
|
309
|
-
static buildExpiryDate(days?:
|
|
311
|
+
static buildExpiryDate(days?: TempFileDuration): string;
|
|
310
312
|
/** Format bytes as a human-readable string (e.g. "4.2 MB"). */
|
|
311
313
|
static formatBytes(bytes: number): string;
|
|
312
314
|
/**
|
package/dist/majik-file.js
CHANGED
|
@@ -214,7 +214,7 @@ export class MajikFile {
|
|
|
214
214
|
* @throws MajikFileError on validation or crypto failure
|
|
215
215
|
*/
|
|
216
216
|
static async create(options) {
|
|
217
|
-
const { data, identity, context, recipients = [], originalName = null, mimeType: rawMimeType = null, isTemporary = false, isShared = false, id = generateUUID(), bypassSizeLimit = false, expiresAt =
|
|
217
|
+
const { data, identity, context, recipients = [], originalName = null, mimeType: rawMimeType = null, isTemporary = false, isShared = false, id = generateUUID(), bypassSizeLimit = false, expiresAt = 15, chatMessageId = null, threadMessageId = null, conversationId = null, userId, } = options;
|
|
218
218
|
// ── Input validation ─────────────────────────────────────────────────
|
|
219
219
|
if (!data)
|
|
220
220
|
throw MajikFileError.invalidInput("data is required");
|
|
@@ -365,7 +365,7 @@ export class MajikFile {
|
|
|
365
365
|
r2Key = buildChatImageR2Key(conversationId, userId, fileHash);
|
|
366
366
|
}
|
|
367
367
|
else if (isTemporary) {
|
|
368
|
-
r2Key = buildTemporaryR2Key(userId, fileHash);
|
|
368
|
+
r2Key = buildTemporaryR2Key(userId, fileHash, expiresAt); // default TTL at creation time
|
|
369
369
|
}
|
|
370
370
|
else {
|
|
371
371
|
r2Key = buildPermanentR2Key(userId, fileHash);
|
|
@@ -388,7 +388,7 @@ export class MajikFile {
|
|
|
388
388
|
chat_message_id: chatMessageId,
|
|
389
389
|
thread_message_id: threadMessageId,
|
|
390
390
|
conversation_id: conversationId,
|
|
391
|
-
expires_at: expiresAt,
|
|
391
|
+
expires_at: buildExpiryDate(expiresAt),
|
|
392
392
|
timestamp: now,
|
|
393
393
|
last_update: now,
|
|
394
394
|
};
|
|
@@ -565,7 +565,7 @@ export class MajikFile {
|
|
|
565
565
|
* @throws MajikFileError when switching to temporary without an expiresAt,
|
|
566
566
|
* or if the instance has no userId / fileHash yet.
|
|
567
567
|
*/
|
|
568
|
-
setStorageType(type, expiresAt) {
|
|
568
|
+
setStorageType(type, expiresAt, duration = 15) {
|
|
569
569
|
if (!["permanent", "temporary"].includes(type)) {
|
|
570
570
|
throw MajikFileError.invalidInput(`setStorageType: type must be "permanent" or "temporary" (got "${type}")`);
|
|
571
571
|
}
|
|
@@ -573,13 +573,11 @@ export class MajikFile {
|
|
|
573
573
|
throw MajikFileError.invalidInput("setStorageType: expiresAt is required when switching to temporary. " +
|
|
574
574
|
"Use setTemporary(days?) instead.");
|
|
575
575
|
}
|
|
576
|
-
// Rebuild R2 key — context is preserved, only the storage tier changes.
|
|
577
|
-
// chat_image files are context-scoped and must never be rekeyed here.
|
|
578
576
|
if (this._context === "chat_image") {
|
|
579
577
|
throw MajikFileError.invalidInput("setStorageType: chat_image files are conversation-scoped and cannot change storage type.");
|
|
580
578
|
}
|
|
581
579
|
const newR2Key = type === "temporary"
|
|
582
|
-
? buildTemporaryR2Key(this._userId, this._fileHash)
|
|
580
|
+
? buildTemporaryR2Key(this._userId, this._fileHash, duration)
|
|
583
581
|
: buildPermanentR2Key(this._userId, this._fileHash);
|
|
584
582
|
this._storageType = type;
|
|
585
583
|
this._expiresAt = type === "temporary" ? expiresAt : null;
|
|
@@ -593,12 +591,14 @@ export class MajikFile {
|
|
|
593
591
|
this.setStorageType("permanent", null);
|
|
594
592
|
}
|
|
595
593
|
/**
|
|
596
|
-
* Switch to temporary storage with
|
|
594
|
+
* Switch to temporary storage with a typed TTL duration.
|
|
595
|
+
* The duration determines both the R2 prefix bucket and the expiry date.
|
|
597
596
|
*
|
|
598
|
-
* @param
|
|
597
|
+
* @param duration Days until expiry. Must be one of: 1 | 2 | 3 | 5 | 7 | 15.
|
|
598
|
+
* Defaults to 15 to match the R2 lifecycle policy.
|
|
599
599
|
*/
|
|
600
|
-
setTemporary(
|
|
601
|
-
this.setStorageType("temporary", MajikFile.buildExpiryDate(
|
|
600
|
+
setTemporary(duration = 15) {
|
|
601
|
+
this.setStorageType("temporary", MajikFile.buildExpiryDate(duration), duration);
|
|
602
602
|
}
|
|
603
603
|
// ── SERIALISATION ─────────────────────────────────────────────────────────
|
|
604
604
|
/**
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@majikah/majik-file",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "Majik File is the core cryptographic engine for secure file handling in the Majikah ecosystem. It provides a post-quantum secure \"MJKB\" format designed for file encryption, multi-recipient key encapsulation, and transparent compression using NIST-standardized algorithms.",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.11",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "Zelijah",
|
|
8
8
|
"main": "./dist/index.js",
|