@meistrari/vault-sdk 0.0.11 → 0.0.13
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/index.cjs +192 -0
- package/dist/index.d.cts +87 -0
- package/package.json +5 -4
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
class FetchError extends Error {
|
|
4
|
+
constructor(message, response) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.response = response;
|
|
7
|
+
this.name = "FetchError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async function blobToBase64(blob) {
|
|
12
|
+
const fileContent = new Uint8Array(await blob.arrayBuffer());
|
|
13
|
+
let content = "";
|
|
14
|
+
for (const part of fileContent)
|
|
15
|
+
content += String.fromCharCode(part);
|
|
16
|
+
return btoa(content);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function getFileHash(blob) {
|
|
20
|
+
const arrayBuffer = await blob.arrayBuffer();
|
|
21
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", arrayBuffer);
|
|
22
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
23
|
+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
24
|
+
return hashHex;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var __defProp$1 = Object.defineProperty;
|
|
28
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
29
|
+
var __publicField$1 = (obj, key, value) => {
|
|
30
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
31
|
+
return value;
|
|
32
|
+
};
|
|
33
|
+
class VaultFile {
|
|
34
|
+
constructor(params) {
|
|
35
|
+
__publicField$1(this, "vaultUrl");
|
|
36
|
+
__publicField$1(this, "name");
|
|
37
|
+
__publicField$1(this, "headers");
|
|
38
|
+
this.name = params.name;
|
|
39
|
+
this.vaultUrl = params.vaultUrl;
|
|
40
|
+
this.headers = params.authStrategy.getHeaders();
|
|
41
|
+
}
|
|
42
|
+
getVaultUrl() {
|
|
43
|
+
if (this.name.includes("vault://")) {
|
|
44
|
+
return this.name;
|
|
45
|
+
}
|
|
46
|
+
return `vault://${this.name}`;
|
|
47
|
+
}
|
|
48
|
+
removeVaultPrefix(url) {
|
|
49
|
+
return url.replace("vault://", "");
|
|
50
|
+
}
|
|
51
|
+
async getUploadUrl() {
|
|
52
|
+
const response = await this._fetch({
|
|
53
|
+
method: "POST",
|
|
54
|
+
path: `/v2/files/${this.removeVaultPrefix(this.name)}`
|
|
55
|
+
});
|
|
56
|
+
return new URL(response.url);
|
|
57
|
+
}
|
|
58
|
+
async getDownloadUrl() {
|
|
59
|
+
const response = await this._fetch({
|
|
60
|
+
method: "GET",
|
|
61
|
+
path: `/v2/files/${this.removeVaultPrefix(this.name)}`
|
|
62
|
+
});
|
|
63
|
+
return new URL(response.url);
|
|
64
|
+
}
|
|
65
|
+
refreshAuth(authStrategy) {
|
|
66
|
+
this.headers = authStrategy.getHeaders();
|
|
67
|
+
}
|
|
68
|
+
async _fetch(params) {
|
|
69
|
+
const { method, path, body, ignoreHeaders } = params;
|
|
70
|
+
const url = new URL(this.vaultUrl + path).toString();
|
|
71
|
+
const response = await fetch(url, {
|
|
72
|
+
method,
|
|
73
|
+
body,
|
|
74
|
+
headers: ignoreHeaders ? void 0 : this.headers
|
|
75
|
+
});
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
throw new FetchError(`Failed to ${method} ${url}: ${response.status} ${response.statusText}`, response);
|
|
78
|
+
}
|
|
79
|
+
const content = await response.json();
|
|
80
|
+
return content;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Adds a SHA-256 hash of the file content as a prefix to the filename. This ensures uniqueness and prevents
|
|
84
|
+
* files with identical names but different content from overwriting each other in the vault.
|
|
85
|
+
*
|
|
86
|
+
* The resulting filename format is: "{hash}-{originalName}"
|
|
87
|
+
*
|
|
88
|
+
* IMPORTANT: The modified filename must be stored and used for all future operations with this file in the vault,
|
|
89
|
+
* as it becomes the file's unique identifier. The original filename alone will not be sufficient to retrieve
|
|
90
|
+
* the file later.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* const file = new File(['content'], 'document.txt')
|
|
94
|
+
* await vaultFile.addHashToName(file)
|
|
95
|
+
* // vaultFile.name becomes: "a1b2c3...xyz-document.txt"
|
|
96
|
+
*
|
|
97
|
+
* @param file - The file to generate a hash for
|
|
98
|
+
* @returns The new filename with the hash prefix
|
|
99
|
+
*/
|
|
100
|
+
async addHashToName(file) {
|
|
101
|
+
const fileHash = await getFileHash(file);
|
|
102
|
+
if (!this.name.includes(fileHash))
|
|
103
|
+
this.name = `${fileHash}-${this.name}`;
|
|
104
|
+
return this.name;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Uploads a file to the vault.
|
|
108
|
+
*
|
|
109
|
+
* Files are saved with the given file names, so files with the same name within the same workspace
|
|
110
|
+
* will overwrite each other. To prevent accidental overwrites and support multiple files with the
|
|
111
|
+
* same original name, you should call addHashToName() before uploading to add a unique content-based
|
|
112
|
+
* hash to the filename.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* const file = new File(['content'], 'document.txt')
|
|
116
|
+
* await vaultFile.addHashToName(file) // Adds hash prefix to filename
|
|
117
|
+
* await vaultFile.upload(file)
|
|
118
|
+
*
|
|
119
|
+
* @param file - The file to upload to the vault
|
|
120
|
+
* @throws {FetchError} If the upload fails
|
|
121
|
+
* @returns Promise that resolves when upload is complete
|
|
122
|
+
*/
|
|
123
|
+
async upload(file) {
|
|
124
|
+
const uploadUrl = await this.getUploadUrl();
|
|
125
|
+
const response = await fetch(uploadUrl, {
|
|
126
|
+
method: "PUT",
|
|
127
|
+
body: file
|
|
128
|
+
});
|
|
129
|
+
if (!response.ok) {
|
|
130
|
+
throw new FetchError(`Error uploading file ${this.name}: ${response.status} ${response.statusText}`, response);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async download(responseType = "blob") {
|
|
134
|
+
const downloadUrl = await this.getDownloadUrl();
|
|
135
|
+
const response = await fetch(downloadUrl, {
|
|
136
|
+
method: "GET"
|
|
137
|
+
});
|
|
138
|
+
if (!response.ok) {
|
|
139
|
+
throw new FetchError(`Error downloading file ${this.name}: ${response.status} ${response.statusText}`, response);
|
|
140
|
+
}
|
|
141
|
+
const blob = await response.blob();
|
|
142
|
+
if (responseType === "blob")
|
|
143
|
+
return blob;
|
|
144
|
+
return await blobToBase64(blob);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
var __defProp = Object.defineProperty;
|
|
149
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
150
|
+
var __publicField = (obj, key, value) => {
|
|
151
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
152
|
+
return value;
|
|
153
|
+
};
|
|
154
|
+
class DataTokenAuthStrategy {
|
|
155
|
+
constructor(dataToken) {
|
|
156
|
+
__publicField(this, "dataToken");
|
|
157
|
+
this.dataToken = dataToken;
|
|
158
|
+
}
|
|
159
|
+
getHeaders() {
|
|
160
|
+
return new Headers({
|
|
161
|
+
"x-data-token": this.dataToken
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
class APIKeyAuthStrategy {
|
|
166
|
+
constructor(apiKey) {
|
|
167
|
+
__publicField(this, "apiKey");
|
|
168
|
+
this.apiKey = apiKey;
|
|
169
|
+
}
|
|
170
|
+
getHeaders() {
|
|
171
|
+
return new Headers({
|
|
172
|
+
Authorization: this.apiKey
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function useVault(vaultUrl, authStrategy) {
|
|
178
|
+
function createVaultFile(name) {
|
|
179
|
+
return new VaultFile({
|
|
180
|
+
name,
|
|
181
|
+
authStrategy,
|
|
182
|
+
vaultUrl
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return { createVaultFile };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
exports.APIKeyAuthStrategy = APIKeyAuthStrategy;
|
|
189
|
+
exports.DataTokenAuthStrategy = DataTokenAuthStrategy;
|
|
190
|
+
exports.FetchError = FetchError;
|
|
191
|
+
exports.VaultFile = VaultFile;
|
|
192
|
+
exports.useVault = useVault;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
interface AuthStrategy {
|
|
2
|
+
getHeaders: () => Headers;
|
|
3
|
+
}
|
|
4
|
+
declare class DataTokenAuthStrategy implements AuthStrategy {
|
|
5
|
+
dataToken: string;
|
|
6
|
+
getHeaders(): Headers;
|
|
7
|
+
constructor(dataToken: string);
|
|
8
|
+
}
|
|
9
|
+
declare class APIKeyAuthStrategy implements AuthStrategy {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
getHeaders(): Headers;
|
|
12
|
+
constructor(apiKey: string);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type FetchParams = {
|
|
16
|
+
method: 'GET' | 'POST' | 'PUT';
|
|
17
|
+
path: string;
|
|
18
|
+
body?: any;
|
|
19
|
+
ignoreHeaders?: boolean;
|
|
20
|
+
};
|
|
21
|
+
type VaultParams = {
|
|
22
|
+
name: string;
|
|
23
|
+
authStrategy: AuthStrategy;
|
|
24
|
+
vaultUrl: string;
|
|
25
|
+
};
|
|
26
|
+
declare class VaultFile {
|
|
27
|
+
readonly vaultUrl: string;
|
|
28
|
+
name: string;
|
|
29
|
+
headers: Headers;
|
|
30
|
+
constructor(params: VaultParams);
|
|
31
|
+
getVaultUrl(): string;
|
|
32
|
+
removeVaultPrefix(url: string): string;
|
|
33
|
+
getUploadUrl(): Promise<URL>;
|
|
34
|
+
getDownloadUrl(): Promise<URL>;
|
|
35
|
+
refreshAuth(authStrategy: AuthStrategy): void;
|
|
36
|
+
_fetch(params: FetchParams): Promise<any>;
|
|
37
|
+
/**
|
|
38
|
+
* Adds a SHA-256 hash of the file content as a prefix to the filename. This ensures uniqueness and prevents
|
|
39
|
+
* files with identical names but different content from overwriting each other in the vault.
|
|
40
|
+
*
|
|
41
|
+
* The resulting filename format is: "{hash}-{originalName}"
|
|
42
|
+
*
|
|
43
|
+
* IMPORTANT: The modified filename must be stored and used for all future operations with this file in the vault,
|
|
44
|
+
* as it becomes the file's unique identifier. The original filename alone will not be sufficient to retrieve
|
|
45
|
+
* the file later.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const file = new File(['content'], 'document.txt')
|
|
49
|
+
* await vaultFile.addHashToName(file)
|
|
50
|
+
* // vaultFile.name becomes: "a1b2c3...xyz-document.txt"
|
|
51
|
+
*
|
|
52
|
+
* @param file - The file to generate a hash for
|
|
53
|
+
* @returns The new filename with the hash prefix
|
|
54
|
+
*/
|
|
55
|
+
addHashToName(file: Blob): Promise<string>;
|
|
56
|
+
/**
|
|
57
|
+
* Uploads a file to the vault.
|
|
58
|
+
*
|
|
59
|
+
* Files are saved with the given file names, so files with the same name within the same workspace
|
|
60
|
+
* will overwrite each other. To prevent accidental overwrites and support multiple files with the
|
|
61
|
+
* same original name, you should call addHashToName() before uploading to add a unique content-based
|
|
62
|
+
* hash to the filename.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* const file = new File(['content'], 'document.txt')
|
|
66
|
+
* await vaultFile.addHashToName(file) // Adds hash prefix to filename
|
|
67
|
+
* await vaultFile.upload(file)
|
|
68
|
+
*
|
|
69
|
+
* @param file - The file to upload to the vault
|
|
70
|
+
* @throws {FetchError} If the upload fails
|
|
71
|
+
* @returns Promise that resolves when upload is complete
|
|
72
|
+
*/
|
|
73
|
+
upload(file: Blob): Promise<void>;
|
|
74
|
+
download(responseType?: 'blob'): Promise<Blob>;
|
|
75
|
+
download(responseType: 'base64'): Promise<string>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
declare class FetchError extends Error {
|
|
79
|
+
readonly response: Response;
|
|
80
|
+
constructor(message: string, response: Response);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
declare function useVault(vaultUrl: string, authStrategy: AuthStrategy): {
|
|
84
|
+
createVaultFile: (name: string) => VaultFile;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export { APIKeyAuthStrategy, type AuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, useVault };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meistrari/vault-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/index.mjs"
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
13
14
|
}
|
|
14
15
|
},
|
|
15
16
|
"main": "dist/index.mjs",
|
|
@@ -18,10 +19,10 @@
|
|
|
18
19
|
"dist"
|
|
19
20
|
],
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"ofetch": "1.4.1"
|
|
22
|
-
"vitest": "2.1.8"
|
|
22
|
+
"ofetch": "1.4.1"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
+
"vitest": "2.1.9",
|
|
25
26
|
"@types/bun": "latest",
|
|
26
27
|
"msw": "2.6.8",
|
|
27
28
|
"unbuild": "2.0.0"
|