@meistrari/vault-sdk 3.1.1 → 3.2.1

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/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # @meistrari/vault-sdk-sdk
1
+ # Vault SDK
2
2
 
3
- This is the SDK for Vault V2.
3
+ TypeScript SDK for interacting with the Vault file storage service. Provides file upload, download, streaming, hierarchy management, permalinks, and vault reference utilities.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- ni @meistrari/vault-sdk
8
+ bun add @meistrari/vault-sdk
9
9
  ```
10
10
 
11
11
  ## Table of Contents
@@ -17,6 +17,8 @@ ni @meistrari/vault-sdk
17
17
  - [VaultFile](#vaultfile)
18
18
  - [Vault Client](#vault-client)
19
19
  - [Permalinks](#permalinks)
20
+ - [File Hierarchies](#file-hierarchies)
21
+ - [Vault Reference Utilities](#vault-reference-utilities)
20
22
  - [Advanced Usage](#advanced-usage)
21
23
 
22
24
  ## Core Concepts
@@ -332,6 +334,50 @@ Deletes the permalink.
332
334
  await permalink.delete()
333
335
  ```
334
336
 
337
+ ## File Hierarchies
338
+
339
+ Files can be organized into parent-child relationships. See the [File Hierarchy Guide](docs/guides/file-hierarchy.md) for full details, patterns, and best practices.
340
+
341
+ ```ts
342
+ // Create a child file
343
+ const child = await parentFile.createChildFromContent({
344
+ name: 'page-1.png',
345
+ content: imageBlob,
346
+ })
347
+
348
+ // List children
349
+ const children = await parentFile.getChildren()
350
+
351
+ // Iterate children with auto-pagination
352
+ for await (const child of parentFile.iterateChildren()) {
353
+ console.log(child.name)
354
+ }
355
+ ```
356
+
357
+ Options for handling edge cases:
358
+
359
+ - `onMissingParent`: `'error'` (default) or `'create-as-root'`
360
+ - `onParentConflict`: `'error'` (default), `'update-parent-id'`, or `'ignore'`
361
+
362
+ ## Vault Reference Utilities
363
+
364
+ Utilities for working with `vault://` URIs and S3 presigned URLs.
365
+
366
+ ```ts
367
+ import {
368
+ isVaultReference,
369
+ extractVaultReferences,
370
+ isS3UrlExpired,
371
+ convertS3UrlToVaultReference,
372
+ extractVaultFileIdFromS3Url,
373
+ } from '@meistrari/vault-sdk'
374
+
375
+ isVaultReference('vault://abc-123') // true
376
+ extractVaultReferences('See vault://a and vault://b') // ['vault://a', 'vault://b']
377
+ isS3UrlExpired(presignedUrl) // boolean
378
+ convertS3UrlToVaultReference(s3Url) // 'vault://...'
379
+ ```
380
+
335
381
  ## Advanced Usage
336
382
 
337
383
  ### Complete Workflow Example
package/dist/index.cjs CHANGED
@@ -224,6 +224,16 @@ async function detectFileMimeType(blob) {
224
224
  }
225
225
  return void 0;
226
226
  }
227
+ function sanitizeFileName(name) {
228
+ if (!name.includes("\0"))
229
+ return name;
230
+ const sanitized = name.replace(/\0/g, "");
231
+ console.warn(
232
+ "[Vault SDK - WARNING] Null bytes found in file name and were removed.",
233
+ { original: name, sanitized }
234
+ );
235
+ return sanitized;
236
+ }
227
237
  function basename(name, separator = "/") {
228
238
  if (!name)
229
239
  return void 0;
@@ -237,7 +247,7 @@ function getFileName(content) {
237
247
  }
238
248
 
239
249
  const name = "@meistrari/vault-sdk";
240
- const version = "3.1.1";
250
+ const version = "3.2.1";
241
251
  const license = "UNLICENSED";
242
252
  const repository = {
243
253
  type: "git",
@@ -265,10 +275,10 @@ const scripts = {
265
275
  };
266
276
  const dependencies = {
267
277
  "@meistrari/file-type": "22.0.0",
268
- "@meistrari/vault-shared": "0.1.0",
278
+ "@meistrari/vault-shared": "0.1.2",
269
279
  "mime-types": "3.0.1",
270
280
  ofetch: "1.4.1",
271
- zod: "3.23.8"
281
+ zod: "4.3.6"
272
282
  };
273
283
  const devDependencies = {
274
284
  "@types/bun": "latest",
@@ -603,7 +613,8 @@ class VaultFile {
603
613
  */
604
614
  static async fromContent(params, options) {
605
615
  const { content, config: vaultConfig, upload = false, parentId, onMissingParent, onParentConflict } = params;
606
- const name = basename(params.name) ?? getFileName(content);
616
+ const rawName = basename(params.name) ?? getFileName(content);
617
+ const name = rawName ? sanitizeFileName(rawName) : rawName;
607
618
  const config = resolveConfig(vaultConfig);
608
619
  const { vaultUrl, authStrategy } = config;
609
620
  const sha256sum = await getFileHash(content);
@@ -686,7 +697,8 @@ class VaultFile {
686
697
  onMissingParent,
687
698
  onParentConflict
688
699
  } = params;
689
- const name = basename(params.name);
700
+ const rawName = basename(params.name);
701
+ const name = rawName ? sanitizeFileName(rawName) : rawName;
690
702
  const config = resolveConfig(vaultConfig);
691
703
  const file = new VaultFile({ config, name });
692
704
  await file._createFile({
@@ -727,7 +739,8 @@ class VaultFile {
727
739
  const config = resolveConfig(vaultConfig);
728
740
  const preparedFiles = await Promise.all(
729
741
  fileInputs.map(async (input) => {
730
- const name = basename(input.name) ?? getFileName(input.content);
742
+ const rawName = basename(input.name) ?? getFileName(input.content);
743
+ const name = rawName ? sanitizeFileName(rawName) : rawName;
731
744
  const sha256sum = await getFileHash(input.content);
732
745
  const mimeType = input.mimeType ?? await detectFileMimeType(input.content);
733
746
  const size = input.content.size;
@@ -810,7 +823,8 @@ class VaultFile {
810
823
  const { files: fileInputs, config: vaultConfig } = params;
811
824
  const config = resolveConfig(vaultConfig);
812
825
  const preparedFiles = fileInputs.map((input) => {
813
- const name = basename(input.name);
826
+ const rawName = basename(input.name);
827
+ const name = rawName ? sanitizeFileName(rawName) : rawName;
814
828
  const mimeType = input.contentType || "application/octet-stream";
815
829
  const size = input.contentLength;
816
830
  return { ...input, name, mimeType, size };
package/dist/index.mjs CHANGED
@@ -218,6 +218,16 @@ async function detectFileMimeType(blob) {
218
218
  }
219
219
  return void 0;
220
220
  }
221
+ function sanitizeFileName(name) {
222
+ if (!name.includes("\0"))
223
+ return name;
224
+ const sanitized = name.replace(/\0/g, "");
225
+ console.warn(
226
+ "[Vault SDK - WARNING] Null bytes found in file name and were removed.",
227
+ { original: name, sanitized }
228
+ );
229
+ return sanitized;
230
+ }
221
231
  function basename(name, separator = "/") {
222
232
  if (!name)
223
233
  return void 0;
@@ -231,7 +241,7 @@ function getFileName(content) {
231
241
  }
232
242
 
233
243
  const name = "@meistrari/vault-sdk";
234
- const version = "3.1.1";
244
+ const version = "3.2.1";
235
245
  const license = "UNLICENSED";
236
246
  const repository = {
237
247
  type: "git",
@@ -259,10 +269,10 @@ const scripts = {
259
269
  };
260
270
  const dependencies = {
261
271
  "@meistrari/file-type": "22.0.0",
262
- "@meistrari/vault-shared": "0.1.0",
272
+ "@meistrari/vault-shared": "0.1.2",
263
273
  "mime-types": "3.0.1",
264
274
  ofetch: "1.4.1",
265
- zod: "3.23.8"
275
+ zod: "4.3.6"
266
276
  };
267
277
  const devDependencies = {
268
278
  "@types/bun": "latest",
@@ -597,7 +607,8 @@ class VaultFile {
597
607
  */
598
608
  static async fromContent(params, options) {
599
609
  const { content, config: vaultConfig, upload = false, parentId, onMissingParent, onParentConflict } = params;
600
- const name = basename(params.name) ?? getFileName(content);
610
+ const rawName = basename(params.name) ?? getFileName(content);
611
+ const name = rawName ? sanitizeFileName(rawName) : rawName;
601
612
  const config = resolveConfig(vaultConfig);
602
613
  const { vaultUrl, authStrategy } = config;
603
614
  const sha256sum = await getFileHash(content);
@@ -680,7 +691,8 @@ class VaultFile {
680
691
  onMissingParent,
681
692
  onParentConflict
682
693
  } = params;
683
- const name = basename(params.name);
694
+ const rawName = basename(params.name);
695
+ const name = rawName ? sanitizeFileName(rawName) : rawName;
684
696
  const config = resolveConfig(vaultConfig);
685
697
  const file = new VaultFile({ config, name });
686
698
  await file._createFile({
@@ -721,7 +733,8 @@ class VaultFile {
721
733
  const config = resolveConfig(vaultConfig);
722
734
  const preparedFiles = await Promise.all(
723
735
  fileInputs.map(async (input) => {
724
- const name = basename(input.name) ?? getFileName(input.content);
736
+ const rawName = basename(input.name) ?? getFileName(input.content);
737
+ const name = rawName ? sanitizeFileName(rawName) : rawName;
725
738
  const sha256sum = await getFileHash(input.content);
726
739
  const mimeType = input.mimeType ?? await detectFileMimeType(input.content);
727
740
  const size = input.content.size;
@@ -804,7 +817,8 @@ class VaultFile {
804
817
  const { files: fileInputs, config: vaultConfig } = params;
805
818
  const config = resolveConfig(vaultConfig);
806
819
  const preparedFiles = fileInputs.map((input) => {
807
- const name = basename(input.name);
820
+ const rawName = basename(input.name);
821
+ const name = rawName ? sanitizeFileName(rawName) : rawName;
808
822
  const mimeType = input.contentType || "application/octet-stream";
809
823
  const size = input.contentLength;
810
824
  return { ...input, name, mimeType, size };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/vault-sdk",
3
- "version": "3.1.1",
3
+ "version": "3.2.1",
4
4
  "license": "UNLICENSED",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,10 +28,10 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@meistrari/file-type": "22.0.0",
31
- "@meistrari/vault-shared": "0.1.0",
31
+ "@meistrari/vault-shared": "0.1.2",
32
32
  "mime-types": "3.0.1",
33
33
  "ofetch": "1.4.1",
34
- "zod": "3.23.8"
34
+ "zod": "4.3.6"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/bun": "latest",