@msssystems/mss-link-sdk 0.1.6 → 0.1.8
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/client/drive-file-runtime.contracts.d.ts +39 -0
- package/dist/client/drive-file-runtime.contracts.js +1 -0
- package/dist/client/drive-file-runtime.d.ts +8 -0
- package/dist/client/drive-file-runtime.js +94 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +4 -0
- package/dist/client/mss-link-browser-client.d.ts +5 -0
- package/dist/client/mss-link-browser-client.js +59 -0
- package/dist/client/storage-metadata-crypto.contracts.d.ts +30 -0
- package/dist/client/storage-metadata-crypto.contracts.js +1 -0
- package/dist/client/storage-metadata-crypto.d.ts +9 -0
- package/dist/client/storage-metadata-crypto.js +76 -0
- package/dist/client/wasm-client.types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { DecryptedMediaBlobResult } from './media-crypto.contracts';
|
|
2
|
+
import type { MediaMessageAttachmentMetadata } from './media-message.contracts';
|
|
3
|
+
export type DriveFilePreviewKind = 'image' | 'pdf' | 'text' | 'unsupported' | 'video';
|
|
4
|
+
export interface DriveFileContentEnvelope {
|
|
5
|
+
algorithm?: 'AES-256-GCM' | string | null;
|
|
6
|
+
keyId?: string | null;
|
|
7
|
+
nonce?: string | null;
|
|
8
|
+
wrappedKey?: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface DriveFileRuntimeMetadataInput {
|
|
11
|
+
fileName: string;
|
|
12
|
+
mimeType: string;
|
|
13
|
+
size: number | string;
|
|
14
|
+
storageKey: string;
|
|
15
|
+
encryption: DriveFileContentEnvelope;
|
|
16
|
+
}
|
|
17
|
+
export interface DriveFileAttachmentInput {
|
|
18
|
+
decrypted: DecryptedMediaBlobResult;
|
|
19
|
+
fallbackFileName?: string;
|
|
20
|
+
fallbackMimeType?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface DriveFilePreviewInput {
|
|
23
|
+
decrypted: DecryptedMediaBlobResult;
|
|
24
|
+
fallbackFileName?: string;
|
|
25
|
+
fallbackMimeType?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface PreparedDriveFileAttachment {
|
|
28
|
+
file: File;
|
|
29
|
+
fileName: string;
|
|
30
|
+
mimeType: string;
|
|
31
|
+
}
|
|
32
|
+
export interface PreparedDriveFilePreview {
|
|
33
|
+
blob: Blob;
|
|
34
|
+
fileName: string;
|
|
35
|
+
kind: DriveFilePreviewKind;
|
|
36
|
+
mimeType: string;
|
|
37
|
+
text?: string;
|
|
38
|
+
}
|
|
39
|
+
export type DriveFileMediaMetadata = MediaMessageAttachmentMetadata;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DecryptedMediaBlobResult } from './media-crypto.contracts';
|
|
2
|
+
import type { DriveFileAttachmentInput, DriveFileMediaMetadata, DriveFilePreviewInput, DriveFilePreviewKind, DriveFileRuntimeMetadataInput, PreparedDriveFileAttachment, PreparedDriveFilePreview } from './drive-file-runtime.contracts';
|
|
3
|
+
export declare function buildDriveFileMediaMetadata(input: DriveFileRuntimeMetadataInput): DriveFileMediaMetadata;
|
|
4
|
+
export declare function getDriveFilePreviewKind(mimeType: string): DriveFilePreviewKind;
|
|
5
|
+
export declare function prepareDriveFileAttachment({ decrypted, fallbackFileName, fallbackMimeType, }: DriveFileAttachmentInput): PreparedDriveFileAttachment;
|
|
6
|
+
export declare function prepareDriveFilePreview({ decrypted, fallbackFileName, fallbackMimeType, }: DriveFilePreviewInput): Promise<PreparedDriveFilePreview>;
|
|
7
|
+
export declare function getDecryptedFileName(decrypted: DecryptedMediaBlobResult, fallbackFileName?: string): string;
|
|
8
|
+
export declare function getDecryptedMimeType(decrypted: DecryptedMediaBlobResult, fallbackMimeType?: string): string;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const DEFAULT_FILE_NAME = 'attachment';
|
|
2
|
+
const DEFAULT_MIME_TYPE = 'application/octet-stream';
|
|
3
|
+
export function buildDriveFileMediaMetadata(input) {
|
|
4
|
+
const fileName = normalizeOptionalText(input.fileName) ?? DEFAULT_FILE_NAME;
|
|
5
|
+
const mimeType = normalizeOptionalText(input.mimeType) ?? DEFAULT_MIME_TYPE;
|
|
6
|
+
const nonce = normalizeRequiredText(input.encryption.nonce, 'Drive file encryption nonce is required.');
|
|
7
|
+
const wrappedKey = normalizeRequiredText(input.encryption.wrappedKey, 'Drive file wrapped content key is required.');
|
|
8
|
+
return {
|
|
9
|
+
assetId: normalizeRequiredText(input.storageKey, 'Drive file storage key is required.'),
|
|
10
|
+
mimeType,
|
|
11
|
+
originalName: fileName,
|
|
12
|
+
size: String(input.size),
|
|
13
|
+
encryption: {
|
|
14
|
+
schema: 'mss.link.media-encryption.v1',
|
|
15
|
+
algorithm: normalizeDriveFileContentAlgorithm(input.encryption.algorithm),
|
|
16
|
+
...(input.encryption.keyId ? { keyId: input.encryption.keyId } : {}),
|
|
17
|
+
nonce,
|
|
18
|
+
wrappedKey,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function getDriveFilePreviewKind(mimeType) {
|
|
23
|
+
const normalizedMimeType = normalizeOptionalText(mimeType) ?? DEFAULT_MIME_TYPE;
|
|
24
|
+
if (normalizedMimeType.startsWith('image/')) {
|
|
25
|
+
return 'image';
|
|
26
|
+
}
|
|
27
|
+
if (normalizedMimeType.startsWith('video/')) {
|
|
28
|
+
return 'video';
|
|
29
|
+
}
|
|
30
|
+
if (normalizedMimeType === 'application/pdf') {
|
|
31
|
+
return 'pdf';
|
|
32
|
+
}
|
|
33
|
+
if (normalizedMimeType.startsWith('text/') ||
|
|
34
|
+
normalizedMimeType.includes('json')) {
|
|
35
|
+
return 'text';
|
|
36
|
+
}
|
|
37
|
+
return 'unsupported';
|
|
38
|
+
}
|
|
39
|
+
export function prepareDriveFileAttachment({ decrypted, fallbackFileName, fallbackMimeType, }) {
|
|
40
|
+
const fileName = getDecryptedFileName(decrypted, fallbackFileName);
|
|
41
|
+
const mimeType = getDecryptedMimeType(decrypted, fallbackMimeType);
|
|
42
|
+
return {
|
|
43
|
+
file: new File([decrypted.blob], fileName, { type: mimeType }),
|
|
44
|
+
fileName,
|
|
45
|
+
mimeType,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export async function prepareDriveFilePreview({ decrypted, fallbackFileName, fallbackMimeType, }) {
|
|
49
|
+
const fileName = getDecryptedFileName(decrypted, fallbackFileName);
|
|
50
|
+
const mimeType = getDecryptedMimeType(decrypted, fallbackMimeType);
|
|
51
|
+
const kind = getDriveFilePreviewKind(mimeType);
|
|
52
|
+
if (kind === 'text') {
|
|
53
|
+
return {
|
|
54
|
+
blob: decrypted.blob,
|
|
55
|
+
fileName,
|
|
56
|
+
kind,
|
|
57
|
+
mimeType,
|
|
58
|
+
text: await decrypted.blob.text(),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
blob: decrypted.blob,
|
|
63
|
+
fileName,
|
|
64
|
+
kind,
|
|
65
|
+
mimeType,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function getDecryptedFileName(decrypted, fallbackFileName) {
|
|
69
|
+
return (normalizeOptionalText(decrypted.fileName) ??
|
|
70
|
+
normalizeOptionalText(fallbackFileName) ??
|
|
71
|
+
DEFAULT_FILE_NAME);
|
|
72
|
+
}
|
|
73
|
+
export function getDecryptedMimeType(decrypted, fallbackMimeType) {
|
|
74
|
+
return (normalizeOptionalText(decrypted.mimeType) ??
|
|
75
|
+
normalizeOptionalText(fallbackMimeType) ??
|
|
76
|
+
DEFAULT_MIME_TYPE);
|
|
77
|
+
}
|
|
78
|
+
function normalizeDriveFileContentAlgorithm(algorithm) {
|
|
79
|
+
if (!algorithm || algorithm === 'AES-256-GCM') {
|
|
80
|
+
return 'AES-256-GCM';
|
|
81
|
+
}
|
|
82
|
+
throw new Error(`Unsupported Drive file encryption algorithm: ${algorithm}`);
|
|
83
|
+
}
|
|
84
|
+
function normalizeRequiredText(value, message) {
|
|
85
|
+
const normalized = normalizeOptionalText(value);
|
|
86
|
+
if (!normalized) {
|
|
87
|
+
throw new Error(message);
|
|
88
|
+
}
|
|
89
|
+
return normalized;
|
|
90
|
+
}
|
|
91
|
+
function normalizeOptionalText(value) {
|
|
92
|
+
const normalized = value?.trim();
|
|
93
|
+
return normalized ? normalized : undefined;
|
|
94
|
+
}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './api-base-url';
|
|
2
2
|
export * from './client-options';
|
|
3
3
|
export * from './decryption-errors';
|
|
4
|
+
export * from './drive-file-runtime';
|
|
5
|
+
export * from './drive-file-runtime.contracts';
|
|
4
6
|
export * from './local-crypto-health';
|
|
5
7
|
export * from './local-crypto-health.contracts';
|
|
6
8
|
export * from './media-crypto.contracts';
|
|
@@ -11,3 +13,5 @@ export * from './message-decryption.contracts';
|
|
|
11
13
|
export * from './message-decryption-state';
|
|
12
14
|
export * from './message.mapper';
|
|
13
15
|
export * from './mss-link-browser-client';
|
|
16
|
+
export * from './storage-metadata-crypto';
|
|
17
|
+
export * from './storage-metadata-crypto.contracts';
|
package/dist/client/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './api-base-url';
|
|
2
2
|
export * from './client-options';
|
|
3
3
|
export * from './decryption-errors';
|
|
4
|
+
export * from './drive-file-runtime';
|
|
5
|
+
export * from './drive-file-runtime.contracts';
|
|
4
6
|
export * from './local-crypto-health';
|
|
5
7
|
export * from './local-crypto-health.contracts';
|
|
6
8
|
export * from './media-crypto.contracts';
|
|
@@ -11,3 +13,5 @@ export * from './message-decryption.contracts';
|
|
|
11
13
|
export * from './message-decryption-state';
|
|
12
14
|
export * from './message.mapper';
|
|
13
15
|
export * from './mss-link-browser-client';
|
|
16
|
+
export * from './storage-metadata-crypto';
|
|
17
|
+
export * from './storage-metadata-crypto.contracts';
|
|
@@ -3,6 +3,7 @@ import type { LocalCryptoHealth } from './local-crypto-health.contracts';
|
|
|
3
3
|
import type { DecryptMediaBlobInput, DecryptedMediaBlobResult, EncryptedMediaBlobResult, EncryptMediaBlobInput } from './media-crypto.contracts';
|
|
4
4
|
import type { SendMediaMessageParams } from './media-message.contracts';
|
|
5
5
|
import type { DecryptedMessage } from './message.contracts';
|
|
6
|
+
import type { DecryptDriveFileMetadataInput, DecryptDriveFolderMetadataInput, DecryptedDriveFileMetadata, DecryptedDriveFolderMetadata, EncryptedDriveFileMetadata, EncryptedDriveFolderMetadata, EncryptDriveFileMetadataInput, EncryptDriveFolderMetadataInput } from './storage-metadata-crypto.contracts';
|
|
6
7
|
export declare class MssLinkBrowserClient {
|
|
7
8
|
private readonly userId;
|
|
8
9
|
private readonly apiBaseUrl;
|
|
@@ -29,6 +30,10 @@ export declare class MssLinkBrowserClient {
|
|
|
29
30
|
sendMediaMessage(params: SendMediaMessageParams): Promise<string>;
|
|
30
31
|
encryptMediaBlob(input: EncryptMediaBlobInput): Promise<EncryptedMediaBlobResult>;
|
|
31
32
|
decryptMediaBlob(input: DecryptMediaBlobInput): Promise<DecryptedMediaBlobResult>;
|
|
33
|
+
encryptDriveFolderMetadata(input: EncryptDriveFolderMetadataInput): Promise<EncryptedDriveFolderMetadata>;
|
|
34
|
+
decryptDriveFolderMetadata(input: DecryptDriveFolderMetadataInput): Promise<DecryptedDriveFolderMetadata>;
|
|
35
|
+
encryptDriveFileMetadata(input: EncryptDriveFileMetadataInput): Promise<EncryptedDriveFileMetadata>;
|
|
36
|
+
decryptDriveFileMetadata(input: DecryptDriveFileMetadataInput): Promise<DecryptedDriveFileMetadata>;
|
|
32
37
|
syncMessages(): Promise<void>;
|
|
33
38
|
getLocalMessages(chatId: string): Promise<DecryptedMessage[]>;
|
|
34
39
|
reset(): void;
|
|
@@ -3,6 +3,7 @@ import { normalizeLocalCryptoError } from './decryption-errors';
|
|
|
3
3
|
import { checkLocalCryptoHealth } from './local-crypto-health';
|
|
4
4
|
import { buildMediaMessageMetadataPayload, extractMediaAssetIds, serializeMediaMessageMetadata, } from './media-message-metadata';
|
|
5
5
|
import { mapLocalSdkMessage } from './message.mapper';
|
|
6
|
+
import { buildDecryptedDriveFileMetadata, buildDecryptedDriveFolderMetadata, buildEncryptedDriveFileMetadata, buildEncryptedDriveFolderMetadata, normalizeDriveFileMetadataInput, normalizeDriveFolderMetadataInput, normalizeEncryptedDriveFileMetadataInput, normalizeEncryptedDriveFolderMetadataInput, } from './storage-metadata-crypto';
|
|
6
7
|
import { WasmCallQueue } from './wasm-call-queue';
|
|
7
8
|
const DEFAULT_DEVICE_ID = 1;
|
|
8
9
|
const DEFAULT_REGISTRATION_ID = 1;
|
|
@@ -150,6 +151,64 @@ export class MssLinkBrowserClient {
|
|
|
150
151
|
throw normalizeLocalCryptoError(error);
|
|
151
152
|
}
|
|
152
153
|
}
|
|
154
|
+
async encryptDriveFolderMetadata(input) {
|
|
155
|
+
try {
|
|
156
|
+
const metadata = normalizeDriveFolderMetadataInput(input);
|
|
157
|
+
const encryptedName = await this.queue.run(async () => {
|
|
158
|
+
const module = await this.loadWasmModule();
|
|
159
|
+
return module.encryptStorageMetadata(metadata.name);
|
|
160
|
+
});
|
|
161
|
+
return buildEncryptedDriveFolderMetadata(encryptedName);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
throw normalizeLocalCryptoError(error);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async decryptDriveFolderMetadata(input) {
|
|
168
|
+
try {
|
|
169
|
+
const metadata = normalizeEncryptedDriveFolderMetadataInput(input);
|
|
170
|
+
const name = await this.queue.run(async () => {
|
|
171
|
+
const module = await this.loadWasmModule();
|
|
172
|
+
return module.decryptStorageMetadata(metadata.encryptedName);
|
|
173
|
+
});
|
|
174
|
+
return buildDecryptedDriveFolderMetadata(name);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
throw normalizeLocalCryptoError(error);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async encryptDriveFileMetadata(input) {
|
|
181
|
+
try {
|
|
182
|
+
const metadata = normalizeDriveFileMetadataInput(input);
|
|
183
|
+
const [encryptedName, encryptedMimeType] = await this.queue.run(async () => {
|
|
184
|
+
const module = await this.loadWasmModule();
|
|
185
|
+
return [
|
|
186
|
+
module.encryptStorageMetadata(metadata.name),
|
|
187
|
+
module.encryptStorageMetadata(metadata.mimeType),
|
|
188
|
+
];
|
|
189
|
+
});
|
|
190
|
+
return buildEncryptedDriveFileMetadata(encryptedName, encryptedMimeType);
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
throw normalizeLocalCryptoError(error);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async decryptDriveFileMetadata(input) {
|
|
197
|
+
try {
|
|
198
|
+
const metadata = normalizeEncryptedDriveFileMetadataInput(input);
|
|
199
|
+
const [name, mimeType] = await this.queue.run(async () => {
|
|
200
|
+
const module = await this.loadWasmModule();
|
|
201
|
+
return [
|
|
202
|
+
module.decryptStorageMetadata(metadata.encryptedName),
|
|
203
|
+
module.decryptStorageMetadata(metadata.encryptedMimeType),
|
|
204
|
+
];
|
|
205
|
+
});
|
|
206
|
+
return buildDecryptedDriveFileMetadata(name, mimeType);
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
throw normalizeLocalCryptoError(error);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
153
212
|
async syncMessages() {
|
|
154
213
|
try {
|
|
155
214
|
await this.runWithClient((client) => client.syncMessages());
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface EncryptDriveFolderMetadataInput {
|
|
2
|
+
name: string;
|
|
3
|
+
}
|
|
4
|
+
export interface EncryptedDriveFolderMetadata {
|
|
5
|
+
schema: 'mss.link.drive-folder-metadata.v1';
|
|
6
|
+
encryptedName: string;
|
|
7
|
+
}
|
|
8
|
+
export interface DecryptDriveFolderMetadataInput {
|
|
9
|
+
encryptedName: string;
|
|
10
|
+
}
|
|
11
|
+
export interface DecryptedDriveFolderMetadata {
|
|
12
|
+
name: string;
|
|
13
|
+
}
|
|
14
|
+
export interface EncryptDriveFileMetadataInput {
|
|
15
|
+
name: string;
|
|
16
|
+
mimeType: string;
|
|
17
|
+
}
|
|
18
|
+
export interface EncryptedDriveFileMetadata {
|
|
19
|
+
schema: 'mss.link.drive-file-metadata.v1';
|
|
20
|
+
encryptedName: string;
|
|
21
|
+
encryptedMimeType: string;
|
|
22
|
+
}
|
|
23
|
+
export interface DecryptDriveFileMetadataInput {
|
|
24
|
+
encryptedName: string;
|
|
25
|
+
encryptedMimeType: string;
|
|
26
|
+
}
|
|
27
|
+
export interface DecryptedDriveFileMetadata {
|
|
28
|
+
mimeType: string;
|
|
29
|
+
name: string;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DecryptDriveFileMetadataInput, DecryptDriveFolderMetadataInput, DecryptedDriveFileMetadata, DecryptedDriveFolderMetadata, EncryptedDriveFileMetadata, EncryptedDriveFolderMetadata, EncryptDriveFileMetadataInput, EncryptDriveFolderMetadataInput } from './storage-metadata-crypto.contracts';
|
|
2
|
+
export declare function normalizeDriveFolderMetadataInput(input: EncryptDriveFolderMetadataInput): EncryptDriveFolderMetadataInput;
|
|
3
|
+
export declare function normalizeDriveFileMetadataInput(input: EncryptDriveFileMetadataInput): EncryptDriveFileMetadataInput;
|
|
4
|
+
export declare function buildEncryptedDriveFolderMetadata(encryptedName: string): EncryptedDriveFolderMetadata;
|
|
5
|
+
export declare function buildEncryptedDriveFileMetadata(encryptedName: string, encryptedMimeType: string): EncryptedDriveFileMetadata;
|
|
6
|
+
export declare function normalizeEncryptedDriveFolderMetadataInput(input: DecryptDriveFolderMetadataInput): DecryptDriveFolderMetadataInput;
|
|
7
|
+
export declare function normalizeEncryptedDriveFileMetadataInput(input: DecryptDriveFileMetadataInput): DecryptDriveFileMetadataInput;
|
|
8
|
+
export declare function buildDecryptedDriveFolderMetadata(name: string): DecryptedDriveFolderMetadata;
|
|
9
|
+
export declare function buildDecryptedDriveFileMetadata(name: string, mimeType: string): DecryptedDriveFileMetadata;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export function normalizeDriveFolderMetadataInput(input) {
|
|
2
|
+
const name = input.name.trim();
|
|
3
|
+
if (!name) {
|
|
4
|
+
throw new Error('Drive folder name is required.');
|
|
5
|
+
}
|
|
6
|
+
return { name };
|
|
7
|
+
}
|
|
8
|
+
export function normalizeDriveFileMetadataInput(input) {
|
|
9
|
+
const name = input.name.trim();
|
|
10
|
+
const mimeType = input.mimeType.trim();
|
|
11
|
+
if (!name) {
|
|
12
|
+
throw new Error('Drive file name is required.');
|
|
13
|
+
}
|
|
14
|
+
if (!mimeType) {
|
|
15
|
+
throw new Error('Drive file mimeType is required.');
|
|
16
|
+
}
|
|
17
|
+
return { mimeType, name };
|
|
18
|
+
}
|
|
19
|
+
export function buildEncryptedDriveFolderMetadata(encryptedName) {
|
|
20
|
+
const normalizedName = normalizeEncryptedField(encryptedName, 'encryptedName');
|
|
21
|
+
return {
|
|
22
|
+
schema: 'mss.link.drive-folder-metadata.v1',
|
|
23
|
+
encryptedName: normalizedName,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function buildEncryptedDriveFileMetadata(encryptedName, encryptedMimeType) {
|
|
27
|
+
const normalizedName = normalizeEncryptedField(encryptedName, 'encryptedName');
|
|
28
|
+
const normalizedMimeType = normalizeEncryptedField(encryptedMimeType, 'encryptedMimeType');
|
|
29
|
+
return {
|
|
30
|
+
schema: 'mss.link.drive-file-metadata.v1',
|
|
31
|
+
encryptedName: normalizedName,
|
|
32
|
+
encryptedMimeType: normalizedMimeType,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function normalizeEncryptedDriveFolderMetadataInput(input) {
|
|
36
|
+
return {
|
|
37
|
+
encryptedName: normalizeEncryptedField(input.encryptedName, 'encryptedName'),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function normalizeEncryptedDriveFileMetadataInput(input) {
|
|
41
|
+
return {
|
|
42
|
+
encryptedName: normalizeEncryptedField(input.encryptedName, 'encryptedName'),
|
|
43
|
+
encryptedMimeType: normalizeEncryptedField(input.encryptedMimeType, 'encryptedMimeType'),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function buildDecryptedDriveFolderMetadata(name) {
|
|
47
|
+
const normalizedName = name.trim();
|
|
48
|
+
if (!normalizedName) {
|
|
49
|
+
throw new Error('Decrypted drive folder name is empty.');
|
|
50
|
+
}
|
|
51
|
+
return { name: normalizedName };
|
|
52
|
+
}
|
|
53
|
+
export function buildDecryptedDriveFileMetadata(name, mimeType) {
|
|
54
|
+
const normalizedName = name.trim();
|
|
55
|
+
const normalizedMimeType = mimeType.trim();
|
|
56
|
+
if (!normalizedName) {
|
|
57
|
+
throw new Error('Decrypted drive file name is empty.');
|
|
58
|
+
}
|
|
59
|
+
if (!normalizedMimeType) {
|
|
60
|
+
throw new Error('Decrypted drive file mimeType is empty.');
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
mimeType: normalizedMimeType,
|
|
64
|
+
name: normalizedName,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function normalizeEncryptedField(value, fieldName) {
|
|
68
|
+
const normalized = value.trim();
|
|
69
|
+
if (!normalized) {
|
|
70
|
+
throw new Error(`Drive metadata ${fieldName} is required.`);
|
|
71
|
+
}
|
|
72
|
+
if (!/^[0-9a-f]+$/i.test(normalized)) {
|
|
73
|
+
throw new Error(`Drive metadata ${fieldName} must be hexadecimal.`);
|
|
74
|
+
}
|
|
75
|
+
return normalized;
|
|
76
|
+
}
|
|
@@ -6,7 +6,9 @@ export interface MssLinkWasmClient extends WasmMssClient {
|
|
|
6
6
|
export type WasmMssClientConstructor = new (userId: string, deviceId: number, apiBaseUrl: string) => MssLinkWasmClient;
|
|
7
7
|
export interface MssCryptoWasmModule {
|
|
8
8
|
WasmMssClient: WasmMssClientConstructor;
|
|
9
|
+
decryptStorageMetadata(encryptedHex: string): string;
|
|
9
10
|
encryptMediaBytes(plaintext: Uint8Array): WasmEncryptedMediaBytes;
|
|
11
|
+
encryptStorageMetadata(plaintext: string): string;
|
|
10
12
|
decryptMediaBytes(ciphertext: Uint8Array, key: string, nonce: string): Uint8Array;
|
|
11
13
|
}
|
|
12
14
|
export type WasmMssClientInstance = MssLinkWasmClient;
|