@autonomys/auto-drive 1.0.5 → 1.0.7

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,8 +1,14 @@
1
- # auto-drive
1
+ # Autonomys Auto Drive SDK
2
2
 
3
- ## auto-drive API Tools
3
+ ![Autonomys Banner](https://github.com/autonomys/auto-sdk/blob/main/.github/images/autonomys-banner.webp)
4
4
 
5
- The `auto-drive` package provides a set of tools to interact with the auto-drive API. Below are some key functionalities:
5
+ [![Latest Github release](https://img.shields.io/github/v/tag/autonomys/auto-sdk.svg)](https://github.com/autonomys/auto-sdk/tags)
6
+ [![Build status of the main branch on Linux/OSX](https://img.shields.io/github/actions/workflow/status/autonomys/auto-sdk/build.yaml?branch=main&label=Linux%2FOSX%20build)](https://github.com/autonomys/auto-sdk/actions/workflows/build.yaml)
7
+ [![npm version](https://badge.fury.io/js/@autonomys%2Fauto-drive.svg)](https://badge.fury.io/js/@autonomys/auto-drive)
8
+
9
+ ## Overview
10
+
11
+ The `auto-drive` package provides a set of tools to interact with the Autonomys Auto-Drive API. Below are some key functionalities:
6
12
 
7
13
  ### Installation
8
14
 
@@ -72,3 +78,19 @@ getRoots(api)
72
78
  console.error('Error retrieving root directories:', error)
73
79
  })
74
80
  ```
81
+
82
+ ## License
83
+
84
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
85
+
86
+ ## Additional Resources
87
+
88
+ - **Autonomys Academy**: Learn more at [Autonomys Academy](https://academy.autonomys.xyz).
89
+
90
+ ## Contact
91
+
92
+ If you have any questions or need support, feel free to reach out:
93
+
94
+ - **GitHub Issues**: [GitHub Issues Page](https://github.com/autonomys/auto-sdk/issues)
95
+
96
+ We appreciate your feedback and contributions!
@@ -24,6 +24,24 @@ type UploadFileOptions = {
24
24
  * @throws {Error} - Throws an error if the upload fails at any stage.
25
25
  */
26
26
  export declare const uploadFileFromFilepath: (api: AutoDriveApi, filePath: string, { password, compression }: UploadFileOptions, uploadChunkSize?: number) => PromisedObservable<UploadFileStatus>;
27
+ /**
28
+ * Uploads a file to the server with optional encryption and compression.
29
+ *
30
+ * This function reads a file from the provided input, optionally encrypts it
31
+ * using the specified password, and compresses it using the specified algorithm if requested.
32
+ * It uploads the file in chunks to the server, creating an upload session and
33
+ * completing it once all chunks have been successfully uploaded.
34
+ *
35
+ * @param {AutoDriveApi} api - The API instance used to send requests.
36
+ * @param {File} file - The file to be uploaded.
37
+ * @param {UploadFileOptions} options - Options for the upload process.
38
+ * @param {string} [options.password] - The password for encryption (optional).
39
+ * @param {boolean} [options.compression=true] - Whether to compress the file (optional).
40
+ * @param {number} [uploadChunkSize] - The size of each chunk to upload (optional).
41
+ * @returns {PromisedObservable<UploadFileStatus>} - An observable that emits the upload status.
42
+ * @throws {Error} - Throws an error if the upload fails at any stage.
43
+ */
44
+ export declare const uploadFileFromInput: (api: AutoDriveApi, file: File, { password, compression }: UploadFileOptions, uploadChunkSize?: number) => PromisedObservable<UploadFileStatus>;
27
45
  /**
28
46
  * Uploads a file to the server with optional encryption and compression.
29
47
  *
@@ -38,10 +56,10 @@ export declare const uploadFileFromFilepath: (api: AutoDriveApi, filePath: strin
38
56
  * @param {string} [options.password] - The password for encryption (optional).
39
57
  * @param {boolean} [options.compression=true] - Whether to compress the file (optional).
40
58
  * @param {number} [uploadChunkSize] - The size of each chunk to upload (optional).
41
- * @returns {Promise<CID>} - A promise that resolves with the CID of the uploaded file.
59
+ * @returns {PromisedObservable<UploadFileStatus>} - An observable that emits the upload status.
42
60
  * @throws {Error} - Throws an error if the upload fails at any stage.
43
61
  */
44
- export declare const uploadFileFromInput: (api: AutoDriveApi, file: File | GenericFile, { password, compression }: UploadFileOptions, uploadChunkSize?: number) => PromisedObservable<UploadFileStatus>;
62
+ export declare const uploadFile: (api: AutoDriveApi, file: GenericFile, { password, compression }: UploadFileOptions, uploadChunkSize?: number) => PromisedObservable<UploadFileStatus>;
45
63
  /**
46
64
  * Uploads an entire folder to the server.
47
65
  *
@@ -1 +1 @@
1
- {"version":3,"file":"wrappers.d.ts","sourceRoot":"","sources":["../../src/api/wrappers.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAU3D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAM9C,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAE9F,KAAK,iBAAiB,GAAG;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAuBD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,QAC5B,YAAY,YACP,MAAM,6BACkB,iBAAiB,oBACjC,MAAM,KACvB,kBAAkB,CAAC,gBAAgB,CAkBrC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mBAAmB,QACzB,YAAY,QACX,IAAI,GAAG,WAAW,6BACU,iBAAiB,oBACjC,MAAM,KACvB,kBAAkB,CAAC,gBAAgB,CA8CrC,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,0BAA0B,QAChC,YAAY,cACL,MAAM,kCACa;IAAE,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KAC7E,OAAO,CAAC,kBAAkB,CAAC,gBAAgB,GAAG,kBAAkB,CAAC,CA6DnE,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,qBAAqB,QAC3B,YAAY,YACP,QAAQ,GAAG,IAAI,EAAE,kCACI;IAAE,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KAC7E,OAAO,CAAC,kBAAkB,CAAC,gBAAgB,GAAG,kBAAkB,CAAC,CA+DnE,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,QAClC,YAAY,YACP,MAAM,QACV,WAAW,oBACC,MAAM,KACvB,kBAAkB,CAAC,kBAAkB,CAkBvC,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,QAClB,YAAY,OACZ,MAAM,aACA,MAAM,KAChB,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAoB/B,CAAA"}
1
+ {"version":3,"file":"wrappers.d.ts","sourceRoot":"","sources":["../../src/api/wrappers.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAU3D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAM9C,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAE9F,KAAK,iBAAiB,GAAG;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAuBD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,QAC5B,YAAY,YACP,MAAM,6BACkB,iBAAiB,oBACjC,MAAM,KACvB,kBAAkB,CAAC,gBAAgB,CAkBrC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mBAAmB,QACzB,YAAY,QACX,IAAI,6BACwB,iBAAiB,oBACjC,MAAM,KACvB,kBAAkB,CAAC,gBAAgB,CA6CrC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,UAAU,QAChB,YAAY,QACX,WAAW,6BACiB,iBAAiB,oBACjC,MAAM,KACvB,kBAAkB,CAAC,gBAAgB,CA6CrC,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,0BAA0B,QAChC,YAAY,cACL,MAAM,kCACa;IAAE,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KAC7E,OAAO,CAAC,kBAAkB,CAAC,gBAAgB,GAAG,kBAAkB,CAAC,CA6DnE,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,qBAAqB,QAC3B,YAAY,YACP,QAAQ,GAAG,IAAI,EAAE,kCACI;IAAE,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KAC7E,OAAO,CAAC,kBAAkB,CAAC,gBAAgB,GAAG,kBAAkB,CAAC,CA+DnE,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,QAClC,YAAY,YACP,MAAM,QACV,WAAW,oBACC,MAAM,KACvB,kBAAkB,CAAC,kBAAkB,CAkBvC,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,QAClB,YAAY,OACZ,MAAM,aACA,MAAM,KAChB,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAoB/B,CAAA"}
@@ -69,7 +69,7 @@ const uploadFileChunks = (api, fileUploadId, asyncIterable, uploadChunkSize = UP
69
69
  */
70
70
  export const uploadFileFromFilepath = (api, filePath, { password, compression = true }, uploadChunkSize) => {
71
71
  const name = filePath.split('/').pop();
72
- return uploadFileFromInput(api, {
72
+ return uploadFile(api, {
73
73
  read: () => fs.createReadStream(filePath),
74
74
  name,
75
75
  mimeType: mime.lookup(name) || undefined,
@@ -89,17 +89,72 @@ export const uploadFileFromFilepath = (api, filePath, { password, compression =
89
89
  * completing it once all chunks have been successfully uploaded.
90
90
  *
91
91
  * @param {AutoDriveApi} api - The API instance used to send requests.
92
- * @param {File | GenericFile} file - The file to be uploaded, which can be a File or a GenericFile.
92
+ * @param {File} file - The file to be uploaded.
93
93
  * @param {UploadFileOptions} options - Options for the upload process.
94
94
  * @param {string} [options.password] - The password for encryption (optional).
95
95
  * @param {boolean} [options.compression=true] - Whether to compress the file (optional).
96
96
  * @param {number} [uploadChunkSize] - The size of each chunk to upload (optional).
97
- * @returns {Promise<CID>} - A promise that resolves with the CID of the uploaded file.
97
+ * @returns {PromisedObservable<UploadFileStatus>} - An observable that emits the upload status.
98
98
  * @throws {Error} - Throws an error if the upload fails at any stage.
99
99
  */
100
100
  export const uploadFileFromInput = (api, file, { password, compression = true }, uploadChunkSize) => {
101
101
  return new PromisedObservable((subscriber) => __awaiter(void 0, void 0, void 0, function* () {
102
- let asyncIterable = file instanceof File ? fileToIterable(file) : file.read();
102
+ let asyncIterable = fileToIterable(file);
103
+ if (compression) {
104
+ asyncIterable = compressFile(asyncIterable, {
105
+ level: 9,
106
+ algorithm: CompressionAlgorithm.ZLIB,
107
+ });
108
+ }
109
+ if (password) {
110
+ asyncIterable = encryptFile(asyncIterable, password, {
111
+ algorithm: EncryptionAlgorithm.AES_256_GCM,
112
+ });
113
+ }
114
+ const uploadOptions = {
115
+ compression: compression
116
+ ? {
117
+ level: 9,
118
+ algorithm: CompressionAlgorithm.ZLIB,
119
+ }
120
+ : undefined,
121
+ encryption: password
122
+ ? {
123
+ algorithm: EncryptionAlgorithm.AES_256_GCM,
124
+ }
125
+ : undefined,
126
+ };
127
+ const fileUpload = yield createFileUpload(api, {
128
+ mimeType: mime.lookup(file.name) || undefined,
129
+ filename: file.name,
130
+ uploadOptions,
131
+ });
132
+ yield uploadFileChunks(api, fileUpload.id, asyncIterable, uploadChunkSize).forEach((e) => subscriber.next({ type: 'file', progress: progressToPercentage(e.uploadBytes, file.size) }));
133
+ const result = yield completeUpload(api, { uploadId: fileUpload.id });
134
+ subscriber.next({ type: 'file', progress: 100, cid: stringToCid(result.cid) });
135
+ subscriber.complete();
136
+ }));
137
+ };
138
+ /**
139
+ * Uploads a file to the server with optional encryption and compression.
140
+ *
141
+ * This function reads a file from the provided input, optionally encrypts it
142
+ * using the specified password, and compresses it using the specified algorithm if requested.
143
+ * It uploads the file in chunks to the server, creating an upload session and
144
+ * completing it once all chunks have been successfully uploaded.
145
+ *
146
+ * @param {AutoDriveApi} api - The API instance used to send requests.
147
+ * @param {File | GenericFile} file - The file to be uploaded, which can be a File or a GenericFile.
148
+ * @param {UploadFileOptions} options - Options for the upload process.
149
+ * @param {string} [options.password] - The password for encryption (optional).
150
+ * @param {boolean} [options.compression=true] - Whether to compress the file (optional).
151
+ * @param {number} [uploadChunkSize] - The size of each chunk to upload (optional).
152
+ * @returns {PromisedObservable<UploadFileStatus>} - An observable that emits the upload status.
153
+ * @throws {Error} - Throws an error if the upload fails at any stage.
154
+ */
155
+ export const uploadFile = (api, file, { password, compression = true }, uploadChunkSize) => {
156
+ return new PromisedObservable((subscriber) => __awaiter(void 0, void 0, void 0, function* () {
157
+ let asyncIterable = file.read();
103
158
  if (compression) {
104
159
  asyncIterable = compressFile(asyncIterable, {
105
160
  level: 9,
@@ -160,9 +215,9 @@ export const uploadFolderFromFolderPath = (api_1, folderPath_1, ...args_1) => __
160
215
  const filesMap = Object.fromEntries(files.map((file) => [file, file]));
161
216
  const zipBlob = yield constructZipBlobFromTreeAndPaths(fileTree, filesMap);
162
217
  const name = folderPath.split('/').pop();
163
- return uploadFileFromInput(api, {
218
+ return uploadFile(api, {
164
219
  read: () => fileToIterable(zipBlob),
165
- name,
220
+ name: `${name}.zip`,
166
221
  mimeType: 'application/zip',
167
222
  size: zipBlob.size,
168
223
  path: name,
@@ -227,7 +282,7 @@ export const uploadFolderFromInput = (api_1, fileList_1, ...args_1) => __awaiter
227
282
  const filesMap = Object.fromEntries(files.map((file) => [file.webkitRelativePath, file]));
228
283
  const zipBlob = yield constructZipBlobFromTreeAndPaths(fileTree, filesMap);
229
284
  const name = fileList[0].webkitRelativePath.split('/').filter(Boolean)[0];
230
- return uploadFileFromInput(api, {
285
+ return uploadFile(api, {
231
286
  read: () => fileToIterable(zipBlob),
232
287
  name: `${name}.zip`,
233
288
  mimeType: 'application/zip',
package/package.json CHANGED
@@ -3,11 +3,14 @@
3
3
  "packageManager": "yarn@4.2.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
- "version": "1.0.5",
6
+ "version": "1.0.7",
7
7
  "author": {
8
8
  "name": "Autonomys",
9
9
  "url": "https://autonomys.net"
10
10
  },
11
+ "engines": {
12
+ "node": ">=20.8.0"
13
+ },
11
14
  "scripts": {
12
15
  "build": "tsc"
13
16
  },
@@ -16,7 +19,7 @@
16
19
  "typescript": "^5.6.3"
17
20
  },
18
21
  "dependencies": {
19
- "@autonomys/auto-dag-data": "^1.0.5",
22
+ "@autonomys/auto-dag-data": "^1.0.7",
20
23
  "jszip": "^3.10.1",
21
24
  "mime-types": "^2.1.35",
22
25
  "zod": "^3.23.8"
@@ -1,5 +1,4 @@
1
1
  import {
2
- CID,
3
2
  compressFile,
4
3
  CompressionAlgorithm,
5
4
  decompressFile,
@@ -83,7 +82,7 @@ export const uploadFileFromFilepath = (
83
82
  ): PromisedObservable<UploadFileStatus> => {
84
83
  const name = filePath.split('/').pop()!
85
84
 
86
- return uploadFileFromInput(
85
+ return uploadFile(
87
86
  api,
88
87
  {
89
88
  read: () => fs.createReadStream(filePath),
@@ -109,23 +108,91 @@ export const uploadFileFromFilepath = (
109
108
  * completing it once all chunks have been successfully uploaded.
110
109
  *
111
110
  * @param {AutoDriveApi} api - The API instance used to send requests.
112
- * @param {File | GenericFile} file - The file to be uploaded, which can be a File or a GenericFile.
111
+ * @param {File} file - The file to be uploaded.
113
112
  * @param {UploadFileOptions} options - Options for the upload process.
114
113
  * @param {string} [options.password] - The password for encryption (optional).
115
114
  * @param {boolean} [options.compression=true] - Whether to compress the file (optional).
116
115
  * @param {number} [uploadChunkSize] - The size of each chunk to upload (optional).
117
- * @returns {Promise<CID>} - A promise that resolves with the CID of the uploaded file.
116
+ * @returns {PromisedObservable<UploadFileStatus>} - An observable that emits the upload status.
118
117
  * @throws {Error} - Throws an error if the upload fails at any stage.
119
118
  */
120
119
  export const uploadFileFromInput = (
121
120
  api: AutoDriveApi,
122
- file: File | GenericFile,
121
+ file: File,
122
+ { password, compression = true }: UploadFileOptions,
123
+ uploadChunkSize?: number,
124
+ ): PromisedObservable<UploadFileStatus> => {
125
+ return new PromisedObservable<UploadFileStatus>(async (subscriber) => {
126
+ let asyncIterable: AsyncIterable<Buffer> = fileToIterable(file)
127
+
128
+ if (compression) {
129
+ asyncIterable = compressFile(asyncIterable, {
130
+ level: 9,
131
+ algorithm: CompressionAlgorithm.ZLIB,
132
+ })
133
+ }
134
+
135
+ if (password) {
136
+ asyncIterable = encryptFile(asyncIterable, password, {
137
+ algorithm: EncryptionAlgorithm.AES_256_GCM,
138
+ })
139
+ }
140
+
141
+ const uploadOptions = {
142
+ compression: compression
143
+ ? {
144
+ level: 9,
145
+ algorithm: CompressionAlgorithm.ZLIB,
146
+ }
147
+ : undefined,
148
+ encryption: password
149
+ ? {
150
+ algorithm: EncryptionAlgorithm.AES_256_GCM,
151
+ }
152
+ : undefined,
153
+ }
154
+ const fileUpload = await createFileUpload(api, {
155
+ mimeType: mime.lookup(file.name) || undefined,
156
+ filename: file.name,
157
+ uploadOptions,
158
+ })
159
+
160
+ await uploadFileChunks(api, fileUpload.id, asyncIterable, uploadChunkSize).forEach((e) =>
161
+ subscriber.next({ type: 'file', progress: progressToPercentage(e.uploadBytes, file.size) }),
162
+ )
163
+
164
+ const result = await completeUpload(api, { uploadId: fileUpload.id })
165
+
166
+ subscriber.next({ type: 'file', progress: 100, cid: stringToCid(result.cid) })
167
+ subscriber.complete()
168
+ })
169
+ }
170
+
171
+ /**
172
+ * Uploads a file to the server with optional encryption and compression.
173
+ *
174
+ * This function reads a file from the provided input, optionally encrypts it
175
+ * using the specified password, and compresses it using the specified algorithm if requested.
176
+ * It uploads the file in chunks to the server, creating an upload session and
177
+ * completing it once all chunks have been successfully uploaded.
178
+ *
179
+ * @param {AutoDriveApi} api - The API instance used to send requests.
180
+ * @param {File | GenericFile} file - The file to be uploaded, which can be a File or a GenericFile.
181
+ * @param {UploadFileOptions} options - Options for the upload process.
182
+ * @param {string} [options.password] - The password for encryption (optional).
183
+ * @param {boolean} [options.compression=true] - Whether to compress the file (optional).
184
+ * @param {number} [uploadChunkSize] - The size of each chunk to upload (optional).
185
+ * @returns {PromisedObservable<UploadFileStatus>} - An observable that emits the upload status.
186
+ * @throws {Error} - Throws an error if the upload fails at any stage.
187
+ */
188
+ export const uploadFile = (
189
+ api: AutoDriveApi,
190
+ file: GenericFile,
123
191
  { password, compression = true }: UploadFileOptions,
124
192
  uploadChunkSize?: number,
125
193
  ): PromisedObservable<UploadFileStatus> => {
126
194
  return new PromisedObservable<UploadFileStatus>(async (subscriber) => {
127
- let asyncIterable: AsyncIterable<Buffer> =
128
- file instanceof File ? fileToIterable(file) : file.read()
195
+ let asyncIterable: AsyncIterable<Buffer> = file.read()
129
196
 
130
197
  if (compression) {
131
198
  asyncIterable = compressFile(asyncIterable, {
@@ -200,11 +267,11 @@ export const uploadFolderFromFolderPath = async (
200
267
  const filesMap = Object.fromEntries(files.map((file) => [file, file]))
201
268
  const zipBlob = await constructZipBlobFromTreeAndPaths(fileTree, filesMap)
202
269
  const name = folderPath.split('/').pop()!
203
- return uploadFileFromInput(
270
+ return uploadFile(
204
271
  api,
205
272
  {
206
273
  read: () => fileToIterable(zipBlob),
207
- name,
274
+ name: `${name}.zip`,
208
275
  mimeType: 'application/zip',
209
276
  size: zipBlob.size,
210
277
  path: name,
@@ -288,7 +355,7 @@ export const uploadFolderFromInput = async (
288
355
  const zipBlob = await constructZipBlobFromTreeAndPaths(fileTree, filesMap)
289
356
  const name = fileList[0].webkitRelativePath.split('/').filter(Boolean)[0]!
290
357
 
291
- return uploadFileFromInput(
358
+ return uploadFile(
292
359
  api,
293
360
  {
294
361
  read: () => fileToIterable(zipBlob),
package/LICENSE DELETED
@@ -1,18 +0,0 @@
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
- ---