@autonomys/auto-files 1.4.34 → 1.5.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/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Autonomys Network (autonomys.xyz)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ 1. **Attribution**: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
13
+
14
+ 2. **No Warranty**: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
15
+
16
+ 3. **Limitation of Liability**: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+
18
+ ---
package/dist/api.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { CompressionOptions, EncryptionOptions } from '@autonomys/auto-drive';
2
+ import { Readable } from 'stream';
3
+ interface FetchedFile {
4
+ length: bigint;
5
+ compression: CompressionOptions | undefined;
6
+ encryption: EncryptionOptions | undefined;
7
+ data: Readable;
8
+ }
9
+ /**
10
+ * Creates an API client for interacting with the Auto Files service
11
+ * @param baseUrl - The base URL of the Auto Files API
12
+ * @param apiSecret - The API secret key for authentication
13
+ * @returns An object containing methods to interact with the API
14
+ */
15
+ export declare const createAutoFilesApi: (baseUrl: string, apiSecret: string) => {
16
+ getFile: (cid: string, { retriesPerFetch, onProgress, ignoreCache, }?: {
17
+ retriesPerFetch?: number;
18
+ onProgress?: (progress: number) => void;
19
+ ignoreCache?: boolean;
20
+ }) => Promise<Readable>;
21
+ isFileCached: (cid: string) => Promise<any>;
22
+ getChunkedFile: (cid: string, { retriesPerFetch, onProgress, }?: {
23
+ retriesPerFetch?: number;
24
+ onProgress?: (progress: number) => void;
25
+ }) => Promise<FetchedFile>;
26
+ };
27
+ export {};
28
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjC,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,kBAAkB,GAAG,SAAS,CAAA;IAC3C,UAAU,EAAE,iBAAiB,GAAG,SAAS,CAAA;IACzC,IAAI,EAAE,QAAQ,CAAA;CACf;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,EAAE,WAAW,MAAM;mBA+H5D,MAAM,kDAKR;QACD,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;QACvC,WAAW,CAAC,EAAE,OAAO,CAAA;KACtB;wBAxC8B,MAAM;0BAlDhC,MAAM,qCAIR;QAAE,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,KACvE,OAAO,CAAC,WAAW,CAAC;CAmGxB,CAAA"}
package/dist/api.js ADDED
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.createAutoFilesApi = void 0;
13
+ const asynchronous_1 = require("@autonomys/asynchronous");
14
+ const stream_1 = require("stream");
15
+ const utils_1 = require("./utils");
16
+ /**
17
+ * Creates an API client for interacting with the Auto Files service
18
+ * @param baseUrl - The base URL of the Auto Files API
19
+ * @param apiSecret - The API secret key for authentication
20
+ * @returns An object containing methods to interact with the API
21
+ */
22
+ const createAutoFilesApi = (baseUrl, apiSecret) => {
23
+ /**
24
+ * Makes an authenticated fetch request to the API
25
+ * @param url - The URL to fetch from
26
+ * @param options - Optional fetch request options
27
+ * @returns A Promise that resolves to the fetch Response
28
+ */
29
+ const authFetch = (url, options = {}) => {
30
+ const urlObj = new URL(url);
31
+ return fetch(urlObj.toString(), Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { Authorization: `Bearer ${apiSecret}` }) }));
32
+ };
33
+ /**
34
+ * Fetches a specific chunk of a file from the API
35
+ * @param cid - The content identifier of the file
36
+ * @param chunk - The chunk number to fetch
37
+ * @returns A Promise that resolves to the chunk data as ArrayBuffer, or null if chunk doesn't exist
38
+ * @throws Error if the chunk fetch fails
39
+ */
40
+ const getChunk = (cid, chunk) => __awaiter(void 0, void 0, void 0, function* () {
41
+ const response = yield authFetch(`${baseUrl}/files/${cid}/partial?chunk=${chunk}`);
42
+ if (!response.ok) {
43
+ throw new Error(`Error fetching chunk: ${response.status} ${response.statusText}`);
44
+ }
45
+ if (response.status === 204) {
46
+ return null;
47
+ }
48
+ const buffer = yield response.arrayBuffer();
49
+ return buffer;
50
+ });
51
+ /**
52
+ * Fetches a complete file from the API with support for progress tracking and retries
53
+ * @param cid - The content identifier of the file to fetch
54
+ * @param options - Optional configuration for the fetch operation
55
+ * @param options.retriesPerFetch - Number of retry attempts for failed requests (default: 3)
56
+ * @param options.onProgress - Optional callback function to track download progress (0-1)
57
+ * @returns A Promise that resolves to a FetchedFile object containing the file data and metadata
58
+ * @throws Error if the file metadata fetch fails
59
+ */
60
+ const getChunkedFile = (cid_1, ...args_1) => __awaiter(void 0, [cid_1, ...args_1], void 0, function* (cid, { retriesPerFetch = 3, onProgress, } = {}) {
61
+ var _a, _b, _c;
62
+ const response = yield (0, utils_1.withRetries)(() => authFetch(`${baseUrl}/files/${cid}/metadata`), {
63
+ retries: retriesPerFetch,
64
+ onRetry: (error, pendingRetries) => {
65
+ console.error(`Error fetching file header, pending retries: ${pendingRetries}`, error);
66
+ },
67
+ });
68
+ if (!response.ok) {
69
+ throw new Error(`Error fetching file header: ${response.status} ${response.statusText}`);
70
+ }
71
+ const metadata = yield response.json();
72
+ // Parse size from string to bigint
73
+ const length = BigInt((_a = metadata.size) !== null && _a !== void 0 ? _a : 0);
74
+ const compression = (_b = metadata.uploadOptions) === null || _b === void 0 ? void 0 : _b.compression;
75
+ const encryption = (_c = metadata.uploadOptions) === null || _c === void 0 ? void 0 : _c.encryption;
76
+ let i = 0;
77
+ let totalDownloaded = BigInt(0);
78
+ const precision = Math.pow(10, 4);
79
+ return {
80
+ data: new stream_1.Readable({
81
+ read() {
82
+ return __awaiter(this, void 0, void 0, function* () {
83
+ var _a;
84
+ const chunk = yield (0, utils_1.withRetries)(() => getChunk(cid, i++), {
85
+ retries: retriesPerFetch,
86
+ });
87
+ this.push(chunk ? Buffer.from(chunk) : null);
88
+ totalDownloaded += BigInt((_a = chunk === null || chunk === void 0 ? void 0 : chunk.byteLength) !== null && _a !== void 0 ? _a : 0);
89
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(Number((BigInt(precision) * totalDownloaded) / length) / precision);
90
+ });
91
+ },
92
+ }),
93
+ length,
94
+ compression,
95
+ encryption,
96
+ };
97
+ });
98
+ /**
99
+ * Checks if a file is cached on the gateway
100
+ * @param cid - The content identifier of the file
101
+ * @returns A Promise that resolves to true if the file is cached, false otherwise
102
+ * @throws Error if the file status check fails
103
+ */
104
+ const isFileCached = (cid) => __awaiter(void 0, void 0, void 0, function* () {
105
+ const response = yield authFetch(`${baseUrl}/files/${cid}/status`);
106
+ if (!response.ok) {
107
+ throw new Error(`Error checking file status: ${response.status} ${response.statusText}`);
108
+ }
109
+ const status = yield response.json();
110
+ return status.isCached;
111
+ });
112
+ const getFileFromCache = (cid) => __awaiter(void 0, void 0, void 0, function* () {
113
+ const response = yield authFetch(`${baseUrl}/files/${cid}`);
114
+ if (!response.ok) {
115
+ throw new Error(`Error fetching file from cache: ${response.status} ${response.statusText}`);
116
+ }
117
+ if (!response.body) {
118
+ throw new Error('No body in response');
119
+ }
120
+ return (0, asynchronous_1.httpBodyToStream)(response.body);
121
+ });
122
+ /**
123
+ * Fetches a complete file from the API with support for progress tracking and retries
124
+ * @param cid - The content identifier of the file to fetch
125
+ * @returns A Promise that resolves to a FetchedFile object containing the file data and metadata
126
+ * @throws Error if the file metadata fetch fails
127
+ */
128
+ const getFile = (cid_1, ...args_1) => __awaiter(void 0, [cid_1, ...args_1], void 0, function* (cid, { retriesPerFetch = 3, onProgress, ignoreCache = false, } = {}) {
129
+ if (!ignoreCache && (yield isFileCached(cid))) {
130
+ return getFileFromCache(cid);
131
+ }
132
+ const file = yield getChunkedFile(cid, {
133
+ retriesPerFetch,
134
+ onProgress,
135
+ });
136
+ return file.data;
137
+ });
138
+ return { getFile, isFileCached, getChunkedFile };
139
+ };
140
+ exports.createAutoFilesApi = createAutoFilesApi;
@@ -0,0 +1,2 @@
1
+ export * from './api';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./api"), exports);
@@ -0,0 +1,6 @@
1
+ export declare const withRetries: <T>(fn: () => Promise<T>, { retries, delay, onRetry, }?: {
2
+ retries?: number;
3
+ delay?: number;
4
+ onRetry?: (error: Error, pendingRetries: number) => void;
5
+ }) => Promise<T>;
6
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,GAAI,CAAC,EAC3B,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,+BAIG;IACD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAA;CACpD,eAmBP,CAAA"}
package/dist/utils.js ADDED
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.withRetries = void 0;
13
+ const withRetries = (fn, { retries = 3, delay = 1000, onRetry, } = {}) => {
14
+ return new Promise((resolve, reject) => {
15
+ const attempt = () => __awaiter(void 0, void 0, void 0, function* () {
16
+ try {
17
+ const result = yield fn();
18
+ resolve(result);
19
+ }
20
+ catch (error) {
21
+ if (retries > 0) {
22
+ onRetry === null || onRetry === void 0 ? void 0 : onRetry(error, retries);
23
+ yield new Promise((resolve) => setTimeout(resolve, delay));
24
+ attempt();
25
+ }
26
+ else {
27
+ reject(error);
28
+ }
29
+ }
30
+ });
31
+ attempt();
32
+ });
33
+ };
34
+ exports.withRetries = withRetries;
package/package.json CHANGED
@@ -1,14 +1,18 @@
1
1
  {
2
2
  "name": "@autonomys/auto-files",
3
- "version": "1.4.34",
3
+ "version": "1.5.1",
4
4
  "packageManager": "yarn@4.7.0",
5
- "private": false,
6
5
  "scripts": {
7
6
  "build": "tsc"
8
7
  },
9
8
  "devDependencies": {
10
9
  "typescript": "^5.5.4"
11
10
  },
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "files": [
14
+ "dist"
15
+ ],
12
16
  "exports": {
13
17
  ".": {
14
18
  "require": "./dist/index.js",
@@ -17,6 +21,7 @@
17
21
  }
18
22
  },
19
23
  "dependencies": {
20
- "@autonomys/auto-drive": "^1.4.34"
21
- }
24
+ "@autonomys/auto-drive": "^1.5.1"
25
+ },
26
+ "gitHead": "91ccdc57a7bc69d3587915ac654b770aba1681a4"
22
27
  }
package/src/api.ts DELETED
@@ -1,106 +0,0 @@
1
- import { CompressionOptions, EncryptionOptions } from '@autonomys/auto-drive'
2
- import { Readable } from 'stream'
3
- import { withRetries } from './utils'
4
-
5
- interface FetchedFile {
6
- length: bigint
7
- compression: CompressionOptions | undefined
8
- encryption: EncryptionOptions | undefined
9
- data: Readable
10
- }
11
-
12
- /**
13
- * Creates an API client for interacting with the Auto Files service
14
- * @param baseUrl - The base URL of the Auto Files API
15
- * @param apiSecret - The API secret key for authentication
16
- * @returns An object containing methods to interact with the API
17
- */
18
- export const createAutoFilesApi = (baseUrl: string, apiSecret: string) => {
19
- /**
20
- * Makes an authenticated fetch request to the API
21
- * @param url - The URL to fetch from
22
- * @param options - Optional fetch request options
23
- * @returns A Promise that resolves to the fetch Response
24
- */
25
- const authFetch = (url: string, options: RequestInit = {}) => {
26
- const urlObj = new URL(url)
27
- return fetch(urlObj.toString(), {
28
- ...options,
29
- headers: { ...options.headers, Authorization: `Bearer ${apiSecret}` },
30
- })
31
- }
32
-
33
- /**
34
- * Fetches a specific chunk of a file from the API
35
- * @param cid - The content identifier of the file
36
- * @param chunk - The chunk number to fetch
37
- * @returns A Promise that resolves to the chunk data as ArrayBuffer, or null if chunk doesn't exist
38
- * @throws Error if the chunk fetch fails
39
- */
40
- const getChunk = async (cid: string, chunk: number): Promise<ArrayBuffer | null> => {
41
- const response = await authFetch(`${baseUrl}/files/${cid}/partial?chunk=${chunk}`)
42
- if (!response.ok) {
43
- throw new Error('Error fetching chunk')
44
- }
45
-
46
- if (response.status === 204) {
47
- return null
48
- }
49
-
50
- const buffer = await response.arrayBuffer()
51
- console.log('Chunk download finished:', buffer.byteLength)
52
- return buffer
53
- }
54
-
55
- /**
56
- * Fetches a complete file from the API with support for progress tracking and retries
57
- * @param cid - The content identifier of the file to fetch
58
- * @param options - Optional configuration for the fetch operation
59
- * @param options.retriesPerFetch - Number of retry attempts for failed requests (default: 3)
60
- * @param options.onProgress - Optional callback function to track download progress (0-1)
61
- * @returns A Promise that resolves to a FetchedFile object containing the file data and metadata
62
- * @throws Error if the file metadata fetch fails
63
- */
64
- const getFile = async (
65
- cid: string,
66
- {
67
- retriesPerFetch = 3,
68
- onProgress,
69
- }: { retriesPerFetch?: number; onProgress?: (progress: number) => void } = {},
70
- ): Promise<FetchedFile> => {
71
- const response = await withRetries(
72
- () => authFetch(`${baseUrl}/files/${cid}/metadata`),
73
- retriesPerFetch,
74
- )
75
- if (!response.ok) {
76
- throw new Error('Error fetching file header')
77
- }
78
-
79
- const metadata = await response.json()
80
-
81
- // Parse size from string to bigint
82
- const length = BigInt(metadata.size ?? 0)
83
-
84
- const compression = metadata.uploadOptions?.compression
85
- const encryption = metadata.uploadOptions?.encryption
86
-
87
- let i = 0
88
- let totalDownloaded = BigInt(0)
89
- const precision = 10 ** 4
90
- return {
91
- data: new Readable({
92
- async read() {
93
- const chunk = await withRetries(() => getChunk(cid, i++), retriesPerFetch)
94
- this.push(chunk ? Buffer.from(chunk) : null)
95
- totalDownloaded += BigInt(chunk?.byteLength ?? 0)
96
- onProgress?.(Number((BigInt(precision) * totalDownloaded) / length) / precision)
97
- },
98
- }),
99
- length,
100
- compression,
101
- encryption,
102
- }
103
- }
104
-
105
- return { getFile }
106
- }
package/src/index.ts DELETED
@@ -1 +0,0 @@
1
- export * from './api'
package/src/utils.ts DELETED
@@ -1,18 +0,0 @@
1
- export const withRetries = <T>(fn: () => Promise<T>, retries: number, delay: number = 1000) => {
2
- return new Promise<T>((resolve, reject) => {
3
- const attempt = async () => {
4
- try {
5
- const result = await fn()
6
- resolve(result)
7
- } catch (error) {
8
- if (retries > 0) {
9
- await new Promise((resolve) => setTimeout(resolve, delay))
10
- attempt()
11
- } else {
12
- reject(error)
13
- }
14
- }
15
- }
16
- attempt()
17
- })
18
- }
package/tsconfig.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "./dist",
5
- "rootDir": "./src",
6
- "module": "Node16",
7
- "moduleResolution": "Node16",
8
- "resolveJsonModule": true
9
- },
10
- "include": ["src"]
11
- }