@uploadista/core 0.0.12 → 0.0.13-beta.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/dist/{checksum-Do_Vh-tB.mjs → checksum-P9C2JlRk.mjs} +2 -2
- package/dist/checksum-P9C2JlRk.mjs.map +1 -0
- package/dist/{checksum-DgutVB-2.cjs → checksum-jmKtZ9W8.cjs} +1 -1
- package/dist/errors/index.cjs +1 -1
- package/dist/errors/index.d.cts +1 -1
- package/dist/errors/index.d.mts +1 -1
- package/dist/errors/index.mjs +1 -1
- package/dist/flow/index.cjs +1 -1
- package/dist/flow/index.d.cts +5 -5
- package/dist/flow/index.d.mts +5 -5
- package/dist/flow/index.mjs +1 -1
- package/dist/{flow-CpDQ8dgf.mjs → flow-CmDU90LK.mjs} +2 -2
- package/dist/flow-CmDU90LK.mjs.map +1 -0
- package/dist/{flow-wZzF8vml.cjs → flow-mOCq3uEl.cjs} +1 -1
- package/dist/{index-6oHIyVO9.d.cts → index-BPBI84iT.d.mts} +2 -2
- package/dist/{index-6oHIyVO9.d.cts.map → index-BPBI84iT.d.mts.map} +1 -1
- package/dist/{index-C2nrn_49.d.mts → index-BteFEg-c.d.mts} +2 -2
- package/dist/index-BteFEg-c.d.mts.map +1 -0
- package/dist/{index-DdT18SQi.d.mts → index-CyxM7UiT.d.mts} +163 -10
- package/dist/index-CyxM7UiT.d.mts.map +1 -0
- package/dist/{index-CsLVxsad.d.mts → index-DMfADSSJ.d.cts} +2 -2
- package/dist/{index-CsLVxsad.d.mts.map → index-DMfADSSJ.d.cts.map} +1 -1
- package/dist/{index-DHOYyzYt.d.cts → index-DpnmoaRn.d.cts} +165 -12
- package/dist/index-DpnmoaRn.d.cts.map +1 -0
- package/dist/{index-eLYBkDBH.d.cts → index-DubOIur4.d.cts} +2 -2
- package/dist/index-DubOIur4.d.cts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +1 -1
- package/dist/{stream-limiter-Bj_iImMm.cjs → stream-limiter-D9rrsvAT.cjs} +1 -1
- package/dist/{stream-limiter-CEpDLQVB.mjs → stream-limiter-DFtRZczp.mjs} +2 -2
- package/dist/{stream-limiter-CEpDLQVB.mjs.map → stream-limiter-DFtRZczp.mjs.map} +1 -1
- package/dist/streams/index.cjs +1 -1
- package/dist/streams/index.d.cts +2 -2
- package/dist/streams/index.d.mts +2 -2
- package/dist/streams/index.mjs +1 -1
- package/dist/types/index.cjs +1 -1
- package/dist/types/index.d.cts +4 -4
- package/dist/types/index.d.mts +4 -4
- package/dist/types/index.mjs +1 -1
- package/dist/{types-BYfvxhhG.mjs → types-DGZ892my.mjs} +2 -2
- package/dist/{types-BYfvxhhG.mjs.map → types-DGZ892my.mjs.map} +1 -1
- package/dist/{types-C80hlY_o.cjs → types-f08UsX4E.cjs} +1 -1
- package/dist/upload/index.cjs +1 -1
- package/dist/upload/index.d.cts +4 -4
- package/dist/upload/index.d.mts +4 -4
- package/dist/upload/index.mjs +1 -1
- package/dist/{upload-IZuHoQqL.cjs → upload-D-eiOIVG.cjs} +1 -1
- package/dist/{upload-CcmxSO5u.mjs → upload-DJTptYqV.mjs} +2 -2
- package/dist/upload-DJTptYqV.mjs.map +1 -0
- package/dist/{uploadista-error-DHajuvP1.d.mts → uploadista-error-9yLWP7TC.d.cts} +3 -3
- package/dist/uploadista-error-9yLWP7TC.d.cts.map +1 -0
- package/dist/{uploadista-error-CQ1ADme7.cjs → uploadista-error-B-n8Kfyh.cjs} +6 -1
- package/dist/{uploadista-error-B4dn0Ch6.d.cts → uploadista-error-CBkvsyZ3.d.mts} +3 -3
- package/dist/uploadista-error-CBkvsyZ3.d.mts.map +1 -0
- package/dist/{uploadista-error-U9YxwNtM.mjs → uploadista-error-nZ_q-EZy.mjs} +6 -1
- package/dist/uploadista-error-nZ_q-EZy.mjs.map +1 -0
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.d.cts +2 -2
- package/dist/utils/index.d.mts +2 -2
- package/dist/utils/index.mjs +1 -1
- package/dist/{utils-C6k-Fs99.mjs → utils-BicUw_lt.mjs} +2 -2
- package/dist/{utils-C6k-Fs99.mjs.map → utils-BicUw_lt.mjs.map} +1 -1
- package/dist/{utils-DzDTNMnq.cjs → utils-_StwBtxT.cjs} +1 -1
- package/package.json +3 -3
- package/src/errors/__tests__/uploadista-error.test.ts +1 -2
- package/src/errors/uploadista-error.ts +28 -3
- package/src/flow/flow.ts +40 -33
- package/src/flow/index.ts +1 -0
- package/src/flow/nodes/input-node.ts +8 -8
- package/src/flow/nodes/storage-node.ts +7 -7
- package/src/flow/nodes/transform-node.ts +3 -3
- package/src/flow/plugins/plugins.ts +3 -0
- package/src/flow/plugins/types/resize-node.ts +1 -1
- package/src/flow/plugins/video-plugin.ts +181 -0
- package/src/flow/typed-flow.ts +52 -52
- package/src/flow/types/index.ts +1 -3
- package/src/flow/utils/resolve-upload-metadata.ts +2 -2
- package/src/types/upload-event.ts +7 -5
- package/src/types/upload-file.ts +19 -11
- package/src/upload/convert-to-stream.ts +1 -1
- package/src/upload/create-upload.ts +11 -11
- package/src/upload/mime.ts +12 -13
- package/src/upload/upload-chunk.ts +13 -13
- package/src/upload/upload-strategy-negotiator.ts +15 -15
- package/src/upload/upload-url.ts +14 -14
- package/src/upload/write-to-store.ts +10 -10
- package/src/utils/checksum.ts +5 -2
- package/vitest.config.ts +16 -10
- package/dist/checksum-Do_Vh-tB.mjs.map +0 -1
- package/dist/flow-CpDQ8dgf.mjs.map +0 -1
- package/dist/index-C2nrn_49.d.mts.map +0 -1
- package/dist/index-DHOYyzYt.d.cts.map +0 -1
- package/dist/index-DdT18SQi.d.mts.map +0 -1
- package/dist/index-eLYBkDBH.d.cts.map +0 -1
- package/dist/upload-CcmxSO5u.mjs.map +0 -1
- package/dist/uploadista-error-B4dn0Ch6.d.cts.map +0 -1
- package/dist/uploadista-error-DHajuvP1.d.mts.map +0 -1
- package/dist/uploadista-error-U9YxwNtM.mjs.map +0 -1
|
@@ -77,7 +77,7 @@ export class UploadStrategyNegotiator {
|
|
|
77
77
|
*/
|
|
78
78
|
constructor(
|
|
79
79
|
private capabilities: DataStoreCapabilities,
|
|
80
|
-
private validateUploadStrategy: (strategy: UploadStrategy) => boolean
|
|
80
|
+
private validateUploadStrategy: (strategy: UploadStrategy) => boolean,
|
|
81
81
|
) {}
|
|
82
82
|
|
|
83
83
|
/**
|
|
@@ -128,7 +128,7 @@ export class UploadStrategyNegotiator {
|
|
|
128
128
|
if (options.preferredStrategy) {
|
|
129
129
|
if (!this.validateUploadStrategy(options.preferredStrategy)) {
|
|
130
130
|
warnings.push(
|
|
131
|
-
`Preferred strategy '${options.preferredStrategy}' not supported by data store, falling back
|
|
131
|
+
`Preferred strategy '${options.preferredStrategy}' not supported by data store, falling back`,
|
|
132
132
|
);
|
|
133
133
|
} else {
|
|
134
134
|
strategy = options.preferredStrategy;
|
|
@@ -147,14 +147,14 @@ export class UploadStrategyNegotiator {
|
|
|
147
147
|
) {
|
|
148
148
|
strategy = "parallel";
|
|
149
149
|
reasoning.push(
|
|
150
|
-
`Selected parallel upload for large file (${options.fileSize} bytes)
|
|
150
|
+
`Selected parallel upload for large file (${options.fileSize} bytes)`,
|
|
151
151
|
);
|
|
152
152
|
} else {
|
|
153
153
|
strategy = "single";
|
|
154
154
|
reasoning.push(
|
|
155
155
|
this.capabilities.supportsParallelUploads
|
|
156
156
|
? `Selected single upload for small file (${options.fileSize} bytes)`
|
|
157
|
-
: "Selected single upload (parallel not supported by data store)"
|
|
157
|
+
: "Selected single upload (parallel not supported by data store)",
|
|
158
158
|
);
|
|
159
159
|
}
|
|
160
160
|
}
|
|
@@ -165,7 +165,7 @@ export class UploadStrategyNegotiator {
|
|
|
165
165
|
chunkSize < this.capabilities.minChunkSize
|
|
166
166
|
) {
|
|
167
167
|
warnings.push(
|
|
168
|
-
`Chunk size ${chunkSize} below minimum ${this.capabilities.minChunkSize}, adjusting
|
|
168
|
+
`Chunk size ${chunkSize} below minimum ${this.capabilities.minChunkSize}, adjusting`,
|
|
169
169
|
);
|
|
170
170
|
chunkSize = this.capabilities.minChunkSize;
|
|
171
171
|
}
|
|
@@ -175,7 +175,7 @@ export class UploadStrategyNegotiator {
|
|
|
175
175
|
chunkSize > this.capabilities.maxChunkSize
|
|
176
176
|
) {
|
|
177
177
|
warnings.push(
|
|
178
|
-
`Chunk size ${chunkSize} above maximum ${this.capabilities.maxChunkSize}, adjusting
|
|
178
|
+
`Chunk size ${chunkSize} above maximum ${this.capabilities.maxChunkSize}, adjusting`,
|
|
179
179
|
);
|
|
180
180
|
chunkSize = this.capabilities.maxChunkSize;
|
|
181
181
|
}
|
|
@@ -187,7 +187,7 @@ export class UploadStrategyNegotiator {
|
|
|
187
187
|
parallelUploads > this.capabilities.maxConcurrentUploads
|
|
188
188
|
) {
|
|
189
189
|
warnings.push(
|
|
190
|
-
`Parallel uploads ${parallelUploads} exceeds maximum ${this.capabilities.maxConcurrentUploads}, adjusting
|
|
190
|
+
`Parallel uploads ${parallelUploads} exceeds maximum ${this.capabilities.maxConcurrentUploads}, adjusting`,
|
|
191
191
|
);
|
|
192
192
|
parallelUploads = this.capabilities.maxConcurrentUploads;
|
|
193
193
|
}
|
|
@@ -197,10 +197,10 @@ export class UploadStrategyNegotiator {
|
|
|
197
197
|
const estimatedParts = Math.ceil(options.fileSize / chunkSize);
|
|
198
198
|
if (estimatedParts > this.capabilities.maxParts) {
|
|
199
199
|
const minChunkForParts = Math.ceil(
|
|
200
|
-
options.fileSize / this.capabilities.maxParts
|
|
200
|
+
options.fileSize / this.capabilities.maxParts,
|
|
201
201
|
);
|
|
202
202
|
warnings.push(
|
|
203
|
-
`Estimated parts ${estimatedParts} exceeds maximum ${this.capabilities.maxParts}, increasing chunk size
|
|
203
|
+
`Estimated parts ${estimatedParts} exceeds maximum ${this.capabilities.maxParts}, increasing chunk size`,
|
|
204
204
|
);
|
|
205
205
|
chunkSize = Math.max(chunkSize, minChunkForParts);
|
|
206
206
|
}
|
|
@@ -210,7 +210,7 @@ export class UploadStrategyNegotiator {
|
|
|
210
210
|
// Final validation - ensure strategy is still valid after adjustments
|
|
211
211
|
if (!this.validateUploadStrategy(strategy)) {
|
|
212
212
|
warnings.push(
|
|
213
|
-
`Final strategy validation failed, falling back to single upload
|
|
213
|
+
`Final strategy validation failed, falling back to single upload`,
|
|
214
214
|
);
|
|
215
215
|
strategy = "single";
|
|
216
216
|
parallelUploads = 1;
|
|
@@ -218,7 +218,7 @@ export class UploadStrategyNegotiator {
|
|
|
218
218
|
|
|
219
219
|
// Add capability information to reasoning
|
|
220
220
|
reasoning.push(
|
|
221
|
-
`Data store capabilities: parallel=${this.capabilities.supportsParallelUploads}, concatenation=${this.capabilities.supportsConcatenation}, resumable=${this.capabilities.supportsResumableUploads}
|
|
221
|
+
`Data store capabilities: parallel=${this.capabilities.supportsParallelUploads}, concatenation=${this.capabilities.supportsConcatenation}, resumable=${this.capabilities.supportsResumableUploads}`,
|
|
222
222
|
);
|
|
223
223
|
|
|
224
224
|
return {
|
|
@@ -275,7 +275,7 @@ export class UploadStrategyNegotiator {
|
|
|
275
275
|
!this.validateUploadStrategy(options.preferredStrategy)
|
|
276
276
|
) {
|
|
277
277
|
errors.push(
|
|
278
|
-
`Preferred strategy '${options.preferredStrategy}' not supported by data store
|
|
278
|
+
`Preferred strategy '${options.preferredStrategy}' not supported by data store`,
|
|
279
279
|
);
|
|
280
280
|
}
|
|
281
281
|
|
|
@@ -285,7 +285,7 @@ export class UploadStrategyNegotiator {
|
|
|
285
285
|
options.preferredChunkSize < this.capabilities.minChunkSize
|
|
286
286
|
) {
|
|
287
287
|
errors.push(
|
|
288
|
-
`Chunk size ${options.preferredChunkSize} below data store minimum ${this.capabilities.minChunkSize}
|
|
288
|
+
`Chunk size ${options.preferredChunkSize} below data store minimum ${this.capabilities.minChunkSize}`,
|
|
289
289
|
);
|
|
290
290
|
}
|
|
291
291
|
if (
|
|
@@ -293,7 +293,7 @@ export class UploadStrategyNegotiator {
|
|
|
293
293
|
options.preferredChunkSize > this.capabilities.maxChunkSize
|
|
294
294
|
) {
|
|
295
295
|
errors.push(
|
|
296
|
-
`Chunk size ${options.preferredChunkSize} above data store maximum ${this.capabilities.maxChunkSize}
|
|
296
|
+
`Chunk size ${options.preferredChunkSize} above data store maximum ${this.capabilities.maxChunkSize}`,
|
|
297
297
|
);
|
|
298
298
|
}
|
|
299
299
|
}
|
|
@@ -304,7 +304,7 @@ export class UploadStrategyNegotiator {
|
|
|
304
304
|
options.parallelUploads > this.capabilities.maxConcurrentUploads
|
|
305
305
|
) {
|
|
306
306
|
errors.push(
|
|
307
|
-
`Parallel uploads ${options.parallelUploads} exceeds data store maximum ${this.capabilities.maxConcurrentUploads}
|
|
307
|
+
`Parallel uploads ${options.parallelUploads} exceeds data store maximum ${this.capabilities.maxConcurrentUploads}`,
|
|
308
308
|
);
|
|
309
309
|
}
|
|
310
310
|
|
package/src/upload/upload-url.ts
CHANGED
|
@@ -59,7 +59,7 @@ export const fetchFile = (url: string) => {
|
|
|
59
59
|
yield* Metric.increment(
|
|
60
60
|
Metric.counter("upload_from_url_total", {
|
|
61
61
|
description: "Total number of URL-based uploads",
|
|
62
|
-
})
|
|
62
|
+
}),
|
|
63
63
|
);
|
|
64
64
|
|
|
65
65
|
// Track success/failure
|
|
@@ -67,10 +67,10 @@ export const fetchFile = (url: string) => {
|
|
|
67
67
|
yield* Metric.increment(
|
|
68
68
|
Metric.counter("upload_from_url_success_total", {
|
|
69
69
|
description: "Total number of successful URL-based uploads",
|
|
70
|
-
})
|
|
70
|
+
}),
|
|
71
71
|
);
|
|
72
72
|
}
|
|
73
|
-
})
|
|
73
|
+
}),
|
|
74
74
|
),
|
|
75
75
|
// Add structured logging
|
|
76
76
|
Effect.tap((response) =>
|
|
@@ -81,8 +81,8 @@ export const fetchFile = (url: string) => {
|
|
|
81
81
|
"response.ok": response.ok.toString(),
|
|
82
82
|
"response.content_length":
|
|
83
83
|
response.headers.get("content-length") ?? "unknown",
|
|
84
|
-
})
|
|
85
|
-
)
|
|
84
|
+
}),
|
|
85
|
+
),
|
|
86
86
|
),
|
|
87
87
|
// Handle errors with logging and metrics
|
|
88
88
|
Effect.tapError((error) =>
|
|
@@ -91,7 +91,7 @@ export const fetchFile = (url: string) => {
|
|
|
91
91
|
yield* Metric.increment(
|
|
92
92
|
Metric.counter("upload_from_url_failed_total", {
|
|
93
93
|
description: "Total number of failed URL-based uploads",
|
|
94
|
-
})
|
|
94
|
+
}),
|
|
95
95
|
);
|
|
96
96
|
|
|
97
97
|
// Log error
|
|
@@ -99,10 +99,10 @@ export const fetchFile = (url: string) => {
|
|
|
99
99
|
Effect.annotateLogs({
|
|
100
100
|
"upload.url": url,
|
|
101
101
|
error: String(error),
|
|
102
|
-
})
|
|
102
|
+
}),
|
|
103
103
|
);
|
|
104
|
-
})
|
|
105
|
-
)
|
|
104
|
+
}),
|
|
105
|
+
),
|
|
106
106
|
);
|
|
107
107
|
};
|
|
108
108
|
|
|
@@ -158,16 +158,16 @@ export const arrayBuffer = (response: Response) => {
|
|
|
158
158
|
Effect.logDebug("Response converted to array buffer").pipe(
|
|
159
159
|
Effect.annotateLogs({
|
|
160
160
|
"buffer.size": buffer.byteLength.toString(),
|
|
161
|
-
})
|
|
162
|
-
)
|
|
161
|
+
}),
|
|
162
|
+
),
|
|
163
163
|
),
|
|
164
164
|
// Handle errors with logging
|
|
165
165
|
Effect.tapError((error) =>
|
|
166
166
|
Effect.logError("Failed to convert response to array buffer").pipe(
|
|
167
167
|
Effect.annotateLogs({
|
|
168
168
|
error: String(error),
|
|
169
|
-
})
|
|
170
|
-
)
|
|
171
|
-
)
|
|
169
|
+
}),
|
|
170
|
+
),
|
|
171
|
+
),
|
|
172
172
|
);
|
|
173
173
|
};
|
|
@@ -149,13 +149,13 @@ export function writeToStore({
|
|
|
149
149
|
}
|
|
150
150
|
return Effect.void;
|
|
151
151
|
}),
|
|
152
|
-
Effect.runPromise
|
|
152
|
+
Effect.runPromise,
|
|
153
153
|
)
|
|
154
154
|
.catch(() => {
|
|
155
155
|
// Ignore errors during progress emission
|
|
156
156
|
});
|
|
157
157
|
},
|
|
158
|
-
}
|
|
158
|
+
},
|
|
159
159
|
);
|
|
160
160
|
|
|
161
161
|
return offset;
|
|
@@ -168,14 +168,14 @@ export function writeToStore({
|
|
|
168
168
|
return Effect.fail(error);
|
|
169
169
|
}
|
|
170
170
|
return Effect.fail(
|
|
171
|
-
UploadistaError.fromCode("FILE_WRITE_ERROR", { cause: error })
|
|
171
|
+
UploadistaError.fromCode("FILE_WRITE_ERROR", { cause: error }),
|
|
172
172
|
);
|
|
173
|
-
})
|
|
173
|
+
}),
|
|
174
174
|
),
|
|
175
175
|
({ onAbort }) =>
|
|
176
176
|
Effect.sync(() => {
|
|
177
177
|
controller.signal.removeEventListener("abort", onAbort);
|
|
178
|
-
})
|
|
178
|
+
}),
|
|
179
179
|
);
|
|
180
180
|
}).pipe(
|
|
181
181
|
// Add tracing span for write operation
|
|
@@ -194,8 +194,8 @@ export function writeToStore({
|
|
|
194
194
|
"upload.id": upload.id,
|
|
195
195
|
"write.offset": offset.toString(),
|
|
196
196
|
"write.bytes_written": (offset - upload.offset).toString(),
|
|
197
|
-
})
|
|
198
|
-
)
|
|
197
|
+
}),
|
|
198
|
+
),
|
|
199
199
|
),
|
|
200
200
|
// Handle errors with logging
|
|
201
201
|
Effect.tapError((error) =>
|
|
@@ -204,8 +204,8 @@ export function writeToStore({
|
|
|
204
204
|
"upload.id": upload.id,
|
|
205
205
|
"upload.offset": upload.offset.toString(),
|
|
206
206
|
error: error instanceof UploadistaError ? error.code : String(error),
|
|
207
|
-
})
|
|
208
|
-
)
|
|
209
|
-
)
|
|
207
|
+
}),
|
|
208
|
+
),
|
|
209
|
+
),
|
|
210
210
|
);
|
|
211
211
|
}
|
package/src/utils/checksum.ts
CHANGED
|
@@ -10,7 +10,9 @@ export type ChecksumAlgorithm = (typeof SUPPORTED_ALGORITHMS)[number];
|
|
|
10
10
|
/**
|
|
11
11
|
* Check if a checksum algorithm is supported
|
|
12
12
|
*/
|
|
13
|
-
export function isSupportedAlgorithm(
|
|
13
|
+
export function isSupportedAlgorithm(
|
|
14
|
+
algorithm: string,
|
|
15
|
+
): algorithm is ChecksumAlgorithm {
|
|
14
16
|
return SUPPORTED_ALGORITHMS.includes(algorithm as ChecksumAlgorithm);
|
|
15
17
|
}
|
|
16
18
|
|
|
@@ -41,7 +43,8 @@ export function computeChecksum(
|
|
|
41
43
|
// Compute hash using Web Crypto API (available in browsers, Node.js 15+, Deno, Bun, Cloudflare Workers)
|
|
42
44
|
// Pass Uint8Array directly - it's a valid BufferSource
|
|
43
45
|
const hashBuffer = yield* Effect.tryPromise({
|
|
44
|
-
try: () =>
|
|
46
|
+
try: () =>
|
|
47
|
+
crypto.subtle.digest(webCryptoAlgorithm, bytes as BufferSource),
|
|
45
48
|
catch: (error) =>
|
|
46
49
|
UploadistaError.fromCode("UNKNOWN_ERROR", {
|
|
47
50
|
body: `Failed to compute checksum: ${error instanceof Error ? error.message : "Unknown error"}`,
|
package/vitest.config.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import { defineConfig } from
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
2
|
|
|
3
3
|
export default defineConfig({
|
|
4
4
|
test: {
|
|
5
5
|
globals: true,
|
|
6
|
-
environment:
|
|
7
|
-
include: [
|
|
8
|
-
exclude: [
|
|
6
|
+
environment: "node",
|
|
7
|
+
include: ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
|
8
|
+
exclude: ["node_modules", "dist"],
|
|
9
9
|
coverage: {
|
|
10
|
-
provider:
|
|
11
|
-
reporter: [
|
|
12
|
-
exclude: [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
provider: "v8",
|
|
11
|
+
reporter: ["text", "json", "html"],
|
|
12
|
+
exclude: [
|
|
13
|
+
"node_modules/",
|
|
14
|
+
"dist/",
|
|
15
|
+
"**/*.d.ts",
|
|
16
|
+
"**/*.test.ts",
|
|
17
|
+
"**/*.spec.ts",
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"checksum-Do_Vh-tB.mjs","names":[],"sources":["../src/utils/generate-id.ts","../src/utils/checksum.ts"],"sourcesContent":["import { Context, Effect, Layer } from \"effect\";\n\nexport type GenerateIdShape = {\n generateId: () => Effect.Effect<string>;\n};\n\n// Declaring a tag for a service that generates random id\nexport class GenerateId extends Context.Tag(\"UploadistaGenerateIdService\")<\n GenerateId,\n { readonly generateId: () => Effect.Effect<string> }\n>() {}\n\n/**\n * Effect-based ID generation services\n */\nexport const GenerateIdService = GenerateId.Service;\n\n/**\n * Generates a random UUID using Effect\n * @returns Effect that produces a random UUID string\n */\nexport const GenerateIdRandom = GenerateId.of({\n generateId: () => Effect.succeed(crypto.randomUUID()),\n});\n\nexport const GenerateIdLive = Layer.succeed(GenerateId, GenerateIdRandom);\n\n/**\n * Generates a timestamp-based ID using Effect\n * @returns Effect that produces a timestamp-based ID\n */\nexport const GenerateIdTimestamp = GenerateId.of({\n generateId: () =>\n Effect.succeed(`${Date.now()}-${Math.random().toString(36).slice(2, 11)}`),\n});\n","import { Effect } from \"effect\";\nimport { UploadistaError } from \"../errors/uploadista-error\";\n\n/**\n * Supported checksum algorithms\n */\nconst SUPPORTED_ALGORITHMS = [\"sha256\"] as const;\nexport type ChecksumAlgorithm = (typeof SUPPORTED_ALGORITHMS)[number];\n\n/**\n * Check if a checksum algorithm is supported\n */\nexport function isSupportedAlgorithm(algorithm: string): algorithm is ChecksumAlgorithm {\n return SUPPORTED_ALGORITHMS.includes(algorithm as ChecksumAlgorithm);\n}\n\n/**\n * Compute checksum of file bytes using the Web Crypto API.\n * This works across all modern platforms: browsers, Node.js 15+, Deno, Bun, and Cloudflare Workers.\n *\n * @param bytes - File content as Uint8Array\n * @param algorithm - Hashing algorithm to use (currently only 'sha256' is supported)\n * @returns Effect that resolves to hex-encoded checksum string\n */\nexport function computeChecksum(\n bytes: Uint8Array,\n algorithm: string,\n): Effect.Effect<string, UploadistaError> {\n return Effect.gen(function* () {\n // Validate algorithm is supported\n if (!isSupportedAlgorithm(algorithm)) {\n return yield* UploadistaError.fromCode(\"UNSUPPORTED_CHECKSUM_ALGORITHM\", {\n body: `Checksum algorithm '${algorithm}' is not supported. Supported algorithms: ${SUPPORTED_ALGORITHMS.join(\", \")}`,\n details: { algorithm, supportedAlgorithms: SUPPORTED_ALGORITHMS },\n }).toEffect();\n }\n\n // Map algorithm name to Web Crypto API algorithm name\n const webCryptoAlgorithm = algorithm.toUpperCase().replace(/\\d+/, \"-$&\"); // \"sha256\" -> \"SHA-256\"\n\n // Compute hash using Web Crypto API (available in browsers, Node.js 15+, Deno, Bun, Cloudflare Workers)\n // Pass Uint8Array directly - it's a valid BufferSource\n const hashBuffer = yield* Effect.tryPromise({\n try: () => crypto.subtle.digest(webCryptoAlgorithm, bytes as BufferSource),\n catch: (error) =>\n UploadistaError.fromCode(\"UNKNOWN_ERROR\", {\n body: `Failed to compute checksum: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n cause: error,\n details: { algorithm },\n }),\n });\n\n // Convert ArrayBuffer to hex string\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n return hashHex;\n });\n}\n"],"mappings":"4GAOA,IAAa,EAAb,cAAgC,EAAQ,IAAI,8BAA8B,EAGvE,AAAC,GAKJ,MAAa,EAAoB,EAAW,QAM/B,EAAmB,EAAW,GAAG,CAC5C,eAAkB,EAAO,QAAQ,OAAO,YAAY,CAAC,CACtD,CAAC,CAEW,EAAiB,EAAM,QAAQ,EAAY,EAAiB,CAM5D,EAAsB,EAAW,GAAG,CAC/C,eACE,EAAO,QAAQ,GAAG,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAG,GAAG,GAAG,CAC7E,CAAC,CC5BI,EAAuB,CAAC,SAAS,CAMvC,SAAgB,EAAqB,EAAmD,CACtF,OAAO,EAAqB,SAAS,EAA+B,CAWtE,SAAgB,EACd,EACA,EACwC,CACxC,OAAO,EAAO,IAAI,WAAa,CAE7B,GAAI,CAAC,EAAqB,EAAU,CAClC,OAAO,MAAO,EAAgB,SAAS,iCAAkC,CACvE,KAAM,uBAAuB,EAAU,4CAA4C,EAAqB,KAAK,KAAK,GAClH,QAAS,CAAE,YAAW,oBAAqB,EAAsB,CAClE,CAAC,CAAC,UAAU,CAIf,IAAM,EAAqB,EAAU,aAAa,CAAC,QAAQ,MAAO,MAAM,CAIlE,EAAa,MAAO,EAAO,WAAW,CAC1C,QAAW,OAAO,OAAO,OAAO,EAAoB,EAAsB,CAC1E,MAAQ,GACN,EAAgB,SAAS,gBAAiB,CACxC,KAAM,+BAA+B,aAAiB,MAAQ,EAAM,QAAU,kBAC9E,MAAO,EACP,QAAS,CAAE,YAAW,CACvB,CAAC,CACL,CAAC,CAQF,OALkB,MAAM,KAAK,IAAI,WAAW,EAAW,CAAC,CAErD,IAAK,GAAS,EAAK,SAAS,GAAG,CAAC,SAAS,EAAG,IAAI,CAAC,CACjD,KAAK,GAAG,EAGX"}
|