digital-tools 2.1.3 → 2.4.0
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +19 -0
- package/README.md +2 -0
- package/dist/client.d.ts +109 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +69 -0
- package/dist/client.js.map +1 -0
- package/dist/define.d.ts +2 -2
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +21 -11
- package/dist/define.js.map +1 -1
- package/dist/function-ref.d.ts +229 -0
- package/dist/function-ref.d.ts.map +1 -0
- package/dist/function-ref.js +28 -0
- package/dist/function-ref.js.map +1 -0
- package/dist/function-sugar.d.ts +57 -0
- package/dist/function-sugar.d.ts.map +1 -0
- package/dist/function-sugar.js +79 -0
- package/dist/function-sugar.js.map +1 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -4
- package/dist/index.js.map +1 -1
- package/dist/providers/analytics/mixpanel.d.ts.map +1 -1
- package/dist/providers/analytics/mixpanel.js +21 -18
- package/dist/providers/analytics/mixpanel.js.map +1 -1
- package/dist/providers/calendar/cal-com.d.ts.map +1 -1
- package/dist/providers/calendar/cal-com.js +10 -10
- package/dist/providers/calendar/cal-com.js.map +1 -1
- package/dist/providers/calendar/google-calendar.d.ts.map +1 -1
- package/dist/providers/calendar/google-calendar.js +4 -4
- package/dist/providers/calendar/google-calendar.js.map +1 -1
- package/dist/providers/crm/hubspot.d.ts.map +1 -1
- package/dist/providers/crm/hubspot.js +107 -85
- package/dist/providers/crm/hubspot.js.map +1 -1
- package/dist/providers/development/github.d.ts.map +1 -1
- package/dist/providers/development/github.js +40 -43
- package/dist/providers/development/github.js.map +1 -1
- package/dist/providers/ecommerce/shopify.d.ts.map +1 -1
- package/dist/providers/ecommerce/shopify.js +79 -62
- package/dist/providers/ecommerce/shopify.js.map +1 -1
- package/dist/providers/email/resend.d.ts.map +1 -1
- package/dist/providers/email/resend.js +20 -16
- package/dist/providers/email/resend.js.map +1 -1
- package/dist/providers/email/sendgrid.d.ts.map +1 -1
- package/dist/providers/email/sendgrid.js +12 -9
- package/dist/providers/email/sendgrid.js.map +1 -1
- package/dist/providers/finance/stripe.d.ts.map +1 -1
- package/dist/providers/finance/stripe.js +44 -42
- package/dist/providers/finance/stripe.js.map +1 -1
- package/dist/providers/forms/typeform.d.ts.map +1 -1
- package/dist/providers/forms/typeform.js +68 -58
- package/dist/providers/forms/typeform.js.map +1 -1
- package/dist/providers/knowledge/notion.d.ts.map +1 -1
- package/dist/providers/knowledge/notion.js +75 -41
- package/dist/providers/knowledge/notion.js.map +1 -1
- package/dist/providers/marketing/mailchimp.d.ts.map +1 -1
- package/dist/providers/marketing/mailchimp.js +74 -61
- package/dist/providers/marketing/mailchimp.js.map +1 -1
- package/dist/providers/media/cloudinary.d.ts.map +1 -1
- package/dist/providers/media/cloudinary.js +30 -28
- package/dist/providers/media/cloudinary.js.map +1 -1
- package/dist/providers/messaging/slack.d.ts.map +1 -1
- package/dist/providers/messaging/slack.js +75 -58
- package/dist/providers/messaging/slack.js.map +1 -1
- package/dist/providers/messaging/twilio-sms.d.ts.map +1 -1
- package/dist/providers/messaging/twilio-sms.js +33 -15
- package/dist/providers/messaging/twilio-sms.js.map +1 -1
- package/dist/providers/project-management/linear.d.ts.map +1 -1
- package/dist/providers/project-management/linear.js +31 -27
- package/dist/providers/project-management/linear.js.map +1 -1
- package/dist/providers/spreadsheet/google-sheets.d.ts.map +1 -1
- package/dist/providers/spreadsheet/google-sheets.js +21 -18
- package/dist/providers/spreadsheet/google-sheets.js.map +1 -1
- package/dist/providers/spreadsheet/xlsx.d.ts.map +1 -1
- package/dist/providers/spreadsheet/xlsx.js +4 -4
- package/dist/providers/spreadsheet/xlsx.js.map +1 -1
- package/dist/providers/storage/index.js +1 -0
- package/dist/providers/storage/index.js.map +1 -1
- package/dist/providers/storage/s3.d.ts.map +1 -1
- package/dist/providers/storage/s3.js +36 -27
- package/dist/providers/storage/s3.js.map +1 -1
- package/dist/providers/support/zendesk.d.ts.map +1 -1
- package/dist/providers/support/zendesk.js +24 -25
- package/dist/providers/support/zendesk.js.map +1 -1
- package/dist/providers/tasks/todoist.d.ts.map +1 -1
- package/dist/providers/tasks/todoist.js +18 -18
- package/dist/providers/tasks/todoist.js.map +1 -1
- package/dist/providers/video-conferencing/google-meet.d.ts.map +1 -1
- package/dist/providers/video-conferencing/google-meet.js +11 -11
- package/dist/providers/video-conferencing/google-meet.js.map +1 -1
- package/dist/providers/video-conferencing/jitsi.js +14 -14
- package/dist/providers/video-conferencing/jitsi.js.map +1 -1
- package/dist/providers/video-conferencing/teams.d.ts.map +1 -1
- package/dist/providers/video-conferencing/teams.js +9 -7
- package/dist/providers/video-conferencing/teams.js.map +1 -1
- package/dist/providers/video-conferencing/zoom.d.ts.map +1 -1
- package/dist/providers/video-conferencing/zoom.js +26 -24
- package/dist/providers/video-conferencing/zoom.js.map +1 -1
- package/dist/tools/data.d.ts.map +1 -1
- package/dist/tools/data.js +5 -12
- package/dist/tools/data.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/system.d.ts +289 -0
- package/dist/tools/system.d.ts.map +1 -0
- package/dist/tools/system.js +752 -0
- package/dist/tools/system.js.map +1 -0
- package/dist/tools/web.d.ts.map +1 -1
- package/dist/tools/web.js +22 -10
- package/dist/tools/web.js.map +1 -1
- package/dist/track-record.d.ts +101 -0
- package/dist/track-record.d.ts.map +1 -0
- package/dist/track-record.js +17 -0
- package/dist/track-record.js.map +1 -0
- package/dist/types.d.ts +210 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/verb-registration.d.ts +122 -0
- package/dist/verb-registration.d.ts.map +1 -0
- package/dist/verb-registration.js +176 -0
- package/dist/verb-registration.js.map +1 -0
- package/dist/worker.d.ts +93 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +315 -0
- package/dist/worker.js.map +1 -0
- package/dist/wrap.d.ts +89 -0
- package/dist/wrap.d.ts.map +1 -0
- package/dist/wrap.js +225 -0
- package/dist/wrap.js.map +1 -0
- package/package.json +31 -14
- package/src/client.ts +136 -0
- package/src/define.ts +30 -24
- package/src/function-ref.ts +264 -0
- package/src/function-sugar.ts +134 -0
- package/src/index.ts +132 -10
- package/src/providers/analytics/mixpanel.ts +19 -18
- package/src/providers/calendar/cal-com.ts +29 -18
- package/src/providers/calendar/google-calendar.ts +20 -14
- package/src/providers/crm/hubspot.ts +225 -99
- package/src/providers/development/github.ts +206 -135
- package/src/providers/ecommerce/shopify.ts +250 -89
- package/src/providers/email/resend.ts +101 -28
- package/src/providers/email/sendgrid.ts +12 -9
- package/src/providers/finance/stripe.ts +128 -49
- package/src/providers/forms/typeform.ts +74 -58
- package/src/providers/knowledge/notion.ts +340 -88
- package/src/providers/marketing/mailchimp.ts +86 -70
- package/src/providers/media/cloudinary.ts +99 -41
- package/src/providers/messaging/slack.ts +283 -85
- package/src/providers/messaging/twilio-sms.ts +35 -15
- package/src/providers/project-management/linear.ts +143 -55
- package/src/providers/spreadsheet/google-sheets.ts +222 -56
- package/src/providers/spreadsheet/xlsx.ts +47 -16
- package/src/providers/storage/s3.ts +119 -47
- package/src/providers/support/zendesk.ts +196 -46
- package/src/providers/tasks/todoist.ts +20 -26
- package/src/providers/video-conferencing/google-meet.ts +17 -20
- package/src/providers/video-conferencing/jitsi.ts +14 -14
- package/src/providers/video-conferencing/teams.ts +14 -13
- package/src/providers/video-conferencing/zoom.ts +54 -49
- package/src/tools/data.ts +6 -16
- package/src/tools/index.ts +1 -0
- package/src/tools/system.ts +887 -0
- package/src/tools/web.ts +22 -10
- package/src/track-record.ts +106 -0
- package/src/types.ts +241 -13
- package/src/verb-registration.ts +197 -0
- package/src/worker.ts +370 -0
- package/src/wrap.ts +260 -0
- package/test/client.test.ts +146 -0
- package/test/communication-tools-extended.test.ts +734 -0
- package/test/data-tools-extended.test.ts +743 -0
- package/test/define-extended.test.ts +819 -0
- package/test/define.test.ts +150 -41
- package/test/entities.test.ts +623 -0
- package/test/extended-entities.test.ts +1228 -0
- package/test/provider-implementations.test.ts +725 -0
- package/test/provider-registry-extended.test.ts +583 -0
- package/test/providers/google-sheets.test.ts +851 -0
- package/test/providers/helpers.ts +554 -0
- package/test/providers/hubspot.test.ts +576 -0
- package/test/providers/slack.test.ts +932 -0
- package/test/providers/stripe.test.ts +701 -0
- package/test/providers.test.ts +578 -0
- package/test/system-tools-extended.test.ts +632 -0
- package/test/system.test.ts +673 -0
- package/test/tools.test.ts +15 -11
- package/test/types.test.ts +402 -0
- package/test/verb-registration.test.ts +395 -0
- package/test/web-tools.test.ts +553 -0
- package/test/worker-extended.test.ts +699 -0
- package/test/worker.test.ts +576 -0
- package/test/wrap.test.ts +366 -0
- package/tsconfig.json +3 -13
- package/vitest.config.ts +37 -0
- package/wrangler.jsonc +9 -0
- package/LICENSE +0 -21
- package/dist/providers/voice/vapi.d.ts +0 -27
- package/dist/providers/voice/vapi.d.ts.map +0 -1
- package/dist/providers/voice/vapi.js +0 -440
- package/dist/providers/voice/vapi.js.map +0 -1
- package/src/define.js +0 -259
- package/src/entities/advertising.js +0 -999
- package/src/entities/ai.js +0 -756
- package/src/entities/analytics.js +0 -1588
- package/src/entities/automation.js +0 -601
- package/src/entities/communication.js +0 -1150
- package/src/entities/crm.js +0 -1386
- package/src/entities/design.js +0 -546
- package/src/entities/development.js +0 -2212
- package/src/entities/document.js +0 -874
- package/src/entities/ecommerce.js +0 -1429
- package/src/entities/experiment.js +0 -1039
- package/src/entities/finance.js +0 -3478
- package/src/entities/forms.js +0 -1892
- package/src/entities/hr.js +0 -661
- package/src/entities/identity.js +0 -997
- package/src/entities/index.js +0 -282
- package/src/entities/infrastructure.js +0 -1153
- package/src/entities/knowledge.js +0 -1438
- package/src/entities/marketing.js +0 -1610
- package/src/entities/media.js +0 -1634
- package/src/entities/notification.js +0 -1199
- package/src/entities/presentation.js +0 -1274
- package/src/entities/productivity.js +0 -1317
- package/src/entities/project-management.js +0 -1136
- package/src/entities/recruiting.js +0 -736
- package/src/entities/shipping.js +0 -509
- package/src/entities/signature.js +0 -1102
- package/src/entities/site.js +0 -222
- package/src/entities/spreadsheet.js +0 -1341
- package/src/entities/storage.js +0 -1198
- package/src/entities/support.js +0 -1166
- package/src/entities/video-conferencing.js +0 -1750
- package/src/entities/video.js +0 -950
- package/src/entities.js +0 -1663
- package/src/index.js +0 -74
- package/src/providers/analytics/index.js +0 -17
- package/src/providers/analytics/mixpanel.js +0 -255
- package/src/providers/calendar/cal-com.js +0 -303
- package/src/providers/calendar/google-calendar.js +0 -335
- package/src/providers/calendar/index.js +0 -20
- package/src/providers/crm/hubspot.js +0 -566
- package/src/providers/crm/index.js +0 -17
- package/src/providers/development/github.js +0 -472
- package/src/providers/development/index.js +0 -17
- package/src/providers/ecommerce/index.js +0 -17
- package/src/providers/ecommerce/shopify.js +0 -378
- package/src/providers/email/index.js +0 -20
- package/src/providers/email/resend.js +0 -258
- package/src/providers/email/sendgrid.js +0 -161
- package/src/providers/finance/index.js +0 -17
- package/src/providers/finance/stripe.js +0 -549
- package/src/providers/forms/index.js +0 -17
- package/src/providers/forms/typeform.js +0 -500
- package/src/providers/index.js +0 -123
- package/src/providers/knowledge/index.js +0 -17
- package/src/providers/knowledge/notion.js +0 -389
- package/src/providers/marketing/index.js +0 -17
- package/src/providers/marketing/mailchimp.js +0 -443
- package/src/providers/media/cloudinary.js +0 -318
- package/src/providers/media/index.js +0 -17
- package/src/providers/messaging/index.js +0 -20
- package/src/providers/messaging/slack.js +0 -393
- package/src/providers/messaging/twilio-sms.js +0 -249
- package/src/providers/project-management/index.js +0 -17
- package/src/providers/project-management/linear.js +0 -575
- package/src/providers/registry.js +0 -86
- package/src/providers/spreadsheet/google-sheets.js +0 -375
- package/src/providers/spreadsheet/index.js +0 -20
- package/src/providers/spreadsheet/xlsx.js +0 -423
- package/src/providers/storage/index.js +0 -24
- package/src/providers/storage/s3.js +0 -419
- package/src/providers/support/index.js +0 -17
- package/src/providers/support/zendesk.js +0 -373
- package/src/providers/tasks/index.js +0 -17
- package/src/providers/tasks/todoist.js +0 -286
- package/src/providers/types.js +0 -9
- package/src/providers/video-conferencing/google-meet.js +0 -286
- package/src/providers/video-conferencing/index.js +0 -31
- package/src/providers/video-conferencing/jitsi.js +0 -254
- package/src/providers/video-conferencing/teams.js +0 -270
- package/src/providers/video-conferencing/zoom.js +0 -332
- package/src/registry.js +0 -128
- package/src/tools/communication.js +0 -184
- package/src/tools/data.js +0 -205
- package/src/tools/index.js +0 -11
- package/src/tools/web.js +0 -137
- package/src/types.js +0 -10
- package/test/define.test.js +0 -306
- package/test/registry.test.js +0 -357
- package/test/tools.test.js +0 -363
|
@@ -69,7 +69,7 @@ class AwsSignatureV4 {
|
|
|
69
69
|
private getCanonicalQueryString(params: Record<string, string>): string {
|
|
70
70
|
return Object.keys(params)
|
|
71
71
|
.sort()
|
|
72
|
-
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
|
72
|
+
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key] ?? '')}`)
|
|
73
73
|
.join('&')
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -103,7 +103,7 @@ class AwsSignatureV4 {
|
|
|
103
103
|
// Create canonical request
|
|
104
104
|
const canonicalHeaders = Object.keys(signedHeaders)
|
|
105
105
|
.sort()
|
|
106
|
-
.map((key) => `${key.toLowerCase()}:${signedHeaders[key]
|
|
106
|
+
.map((key) => `${key.toLowerCase()}:${signedHeaders[key]!.trim()}`)
|
|
107
107
|
.join('\n')
|
|
108
108
|
|
|
109
109
|
const signedHeadersList = Object.keys(signedHeaders)
|
|
@@ -163,11 +163,11 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
163
163
|
info: s3Info,
|
|
164
164
|
|
|
165
165
|
async initialize(cfg: ProviderConfig): Promise<void> {
|
|
166
|
-
accessKeyId = cfg
|
|
167
|
-
secretAccessKey = cfg
|
|
168
|
-
bucket = cfg
|
|
169
|
-
region = cfg
|
|
170
|
-
endpoint = (cfg
|
|
166
|
+
accessKeyId = cfg['accessKeyId'] as string
|
|
167
|
+
secretAccessKey = cfg['secretAccessKey'] as string
|
|
168
|
+
bucket = cfg['bucket'] as string
|
|
169
|
+
region = cfg['region'] as string
|
|
170
|
+
endpoint = (cfg['endpoint'] as string) || `https://${bucket}.s3.${region}.amazonaws.com`
|
|
171
171
|
|
|
172
172
|
if (!accessKeyId || !secretAccessKey || !bucket || !region) {
|
|
173
173
|
throw new Error('S3 requires accessKeyId, secretAccessKey, bucket, and region')
|
|
@@ -179,7 +179,12 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
179
179
|
async healthCheck(): Promise<ProviderHealth> {
|
|
180
180
|
const start = Date.now()
|
|
181
181
|
try {
|
|
182
|
-
const headers = await signer.sign(
|
|
182
|
+
const headers = await signer.sign(
|
|
183
|
+
'HEAD',
|
|
184
|
+
'/',
|
|
185
|
+
{ host: `${bucket}.s3.${region}.amazonaws.com` },
|
|
186
|
+
null
|
|
187
|
+
)
|
|
183
188
|
|
|
184
189
|
const response = await fetch(`${endpoint}/`, {
|
|
185
190
|
method: 'HEAD',
|
|
@@ -206,7 +211,11 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
206
211
|
// No cleanup needed
|
|
207
212
|
},
|
|
208
213
|
|
|
209
|
-
async upload(
|
|
214
|
+
async upload(
|
|
215
|
+
path: string,
|
|
216
|
+
content: Buffer | string,
|
|
217
|
+
options?: StorageUploadOptions
|
|
218
|
+
): Promise<StorageFileData> {
|
|
210
219
|
try {
|
|
211
220
|
const buffer = typeof content === 'string' ? Buffer.from(content) : content
|
|
212
221
|
const headers: Record<string, string> = {
|
|
@@ -244,20 +253,27 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
244
253
|
path,
|
|
245
254
|
name: path.split('/').pop() || path,
|
|
246
255
|
size: buffer.length,
|
|
247
|
-
contentType: options
|
|
248
|
-
etag,
|
|
256
|
+
...(options?.contentType !== undefined && { contentType: options.contentType }),
|
|
257
|
+
...(etag !== undefined && { etag }),
|
|
249
258
|
lastModified: new Date(),
|
|
250
259
|
isFolder: false,
|
|
251
260
|
url: `${endpoint}/${path}`,
|
|
252
261
|
}
|
|
253
262
|
} catch (error) {
|
|
254
|
-
throw new Error(
|
|
263
|
+
throw new Error(
|
|
264
|
+
`Failed to upload to S3: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
265
|
+
)
|
|
255
266
|
}
|
|
256
267
|
},
|
|
257
268
|
|
|
258
269
|
async download(path: string): Promise<Buffer> {
|
|
259
270
|
try {
|
|
260
|
-
const headers = await signer.sign(
|
|
271
|
+
const headers = await signer.sign(
|
|
272
|
+
'GET',
|
|
273
|
+
`/${path}`,
|
|
274
|
+
{ host: `${bucket}.s3.${region}.amazonaws.com` },
|
|
275
|
+
null
|
|
276
|
+
)
|
|
261
277
|
|
|
262
278
|
const response = await fetch(`${endpoint}/${path}`, {
|
|
263
279
|
method: 'GET',
|
|
@@ -271,13 +287,20 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
271
287
|
const arrayBuffer = await response.arrayBuffer()
|
|
272
288
|
return Buffer.from(arrayBuffer)
|
|
273
289
|
} catch (error) {
|
|
274
|
-
throw new Error(
|
|
290
|
+
throw new Error(
|
|
291
|
+
`Failed to download from S3: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
292
|
+
)
|
|
275
293
|
}
|
|
276
294
|
},
|
|
277
295
|
|
|
278
296
|
async delete(path: string): Promise<boolean> {
|
|
279
297
|
try {
|
|
280
|
-
const headers = await signer.sign(
|
|
298
|
+
const headers = await signer.sign(
|
|
299
|
+
'DELETE',
|
|
300
|
+
`/${path}`,
|
|
301
|
+
{ host: `${bucket}.s3.${region}.amazonaws.com` },
|
|
302
|
+
null
|
|
303
|
+
)
|
|
281
304
|
|
|
282
305
|
const response = await fetch(`${endpoint}/${path}`, {
|
|
283
306
|
method: 'DELETE',
|
|
@@ -286,22 +309,27 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
286
309
|
|
|
287
310
|
return response.ok || response.status === 204
|
|
288
311
|
} catch (error) {
|
|
289
|
-
throw new Error(
|
|
312
|
+
throw new Error(
|
|
313
|
+
`Failed to delete from S3: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
314
|
+
)
|
|
290
315
|
}
|
|
291
316
|
},
|
|
292
317
|
|
|
293
|
-
async list(
|
|
318
|
+
async list(
|
|
319
|
+
prefix: string = '',
|
|
320
|
+
options?: StorageListOptions
|
|
321
|
+
): Promise<PaginatedResult<StorageFileData>> {
|
|
294
322
|
try {
|
|
295
323
|
const queryParams: Record<string, string> = {
|
|
296
324
|
'list-type': '2',
|
|
297
325
|
}
|
|
298
326
|
|
|
299
327
|
if (prefix) {
|
|
300
|
-
queryParams
|
|
328
|
+
queryParams['prefix'] = prefix
|
|
301
329
|
}
|
|
302
330
|
|
|
303
331
|
if (options?.delimiter) {
|
|
304
|
-
queryParams
|
|
332
|
+
queryParams['delimiter'] = options.delimiter
|
|
305
333
|
}
|
|
306
334
|
|
|
307
335
|
if (options?.limit) {
|
|
@@ -312,10 +340,16 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
312
340
|
queryParams['continuation-token'] = options.cursor
|
|
313
341
|
}
|
|
314
342
|
|
|
315
|
-
const headers = await signer.sign(
|
|
343
|
+
const headers = await signer.sign(
|
|
344
|
+
'GET',
|
|
345
|
+
'/',
|
|
346
|
+
{ host: `${bucket}.s3.${region}.amazonaws.com` },
|
|
347
|
+
null,
|
|
348
|
+
queryParams
|
|
349
|
+
)
|
|
316
350
|
|
|
317
351
|
const queryString = Object.keys(queryParams)
|
|
318
|
-
.map((key) => `${key}=${encodeURIComponent(queryParams[key])}`)
|
|
352
|
+
.map((key) => `${key}=${encodeURIComponent(queryParams[key] ?? '')}`)
|
|
319
353
|
.join('&')
|
|
320
354
|
|
|
321
355
|
const response = await fetch(`${endpoint}/?${queryString}`, {
|
|
@@ -334,29 +368,33 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
334
368
|
const contentsMatches = xmlText.matchAll(/<Contents>(.*?)<\/Contents>/gs)
|
|
335
369
|
for (const match of contentsMatches) {
|
|
336
370
|
const content = match[1]
|
|
371
|
+
if (!content) continue
|
|
337
372
|
const keyMatch = content.match(/<Key>(.*?)<\/Key>/)
|
|
338
373
|
const sizeMatch = content.match(/<Size>(.*?)<\/Size>/)
|
|
339
374
|
const lastModifiedMatch = content.match(/<LastModified>(.*?)<\/LastModified>/)
|
|
340
375
|
const etagMatch = content.match(/<ETag>(.*?)<\/ETag>/)
|
|
341
376
|
|
|
342
|
-
|
|
343
|
-
|
|
377
|
+
const pathValue = keyMatch?.[1]
|
|
378
|
+
if (pathValue) {
|
|
344
379
|
items.push({
|
|
345
|
-
path,
|
|
346
|
-
name:
|
|
347
|
-
size: sizeMatch ? parseInt(sizeMatch[1], 10) : 0,
|
|
348
|
-
etag: etagMatch
|
|
349
|
-
lastModified: lastModifiedMatch ? new Date(lastModifiedMatch[1]) : new Date(),
|
|
380
|
+
path: pathValue,
|
|
381
|
+
name: pathValue.split('/').pop() || pathValue,
|
|
382
|
+
size: sizeMatch?.[1] ? parseInt(sizeMatch[1], 10) : 0,
|
|
383
|
+
...(etagMatch?.[1] && { etag: etagMatch[1].replace(/"/g, '') }),
|
|
384
|
+
lastModified: lastModifiedMatch?.[1] ? new Date(lastModifiedMatch[1]) : new Date(),
|
|
350
385
|
isFolder: false,
|
|
351
|
-
url: `${endpoint}/${
|
|
386
|
+
url: `${endpoint}/${pathValue}`,
|
|
352
387
|
})
|
|
353
388
|
}
|
|
354
389
|
}
|
|
355
390
|
|
|
356
391
|
// Parse common prefixes (folders)
|
|
357
|
-
const prefixMatches = xmlText.matchAll(
|
|
392
|
+
const prefixMatches = xmlText.matchAll(
|
|
393
|
+
/<CommonPrefixes>.*?<Prefix>(.*?)<\/Prefix>.*?<\/CommonPrefixes>/gs
|
|
394
|
+
)
|
|
358
395
|
for (const match of prefixMatches) {
|
|
359
396
|
const folderPath = match[1]
|
|
397
|
+
if (!folderPath) continue
|
|
360
398
|
items.push({
|
|
361
399
|
path: folderPath,
|
|
362
400
|
name: folderPath.split('/').filter(Boolean).pop() || folderPath,
|
|
@@ -367,21 +405,30 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
367
405
|
}
|
|
368
406
|
|
|
369
407
|
const isTruncated = xmlText.includes('<IsTruncated>true</IsTruncated>')
|
|
370
|
-
const nextTokenMatch = xmlText.match(
|
|
408
|
+
const nextTokenMatch = xmlText.match(
|
|
409
|
+
/<NextContinuationToken>(.*?)<\/NextContinuationToken>/
|
|
410
|
+
)
|
|
371
411
|
|
|
372
412
|
return {
|
|
373
413
|
items,
|
|
374
414
|
hasMore: isTruncated,
|
|
375
|
-
nextCursor: nextTokenMatch
|
|
415
|
+
...(nextTokenMatch?.[1] !== undefined && { nextCursor: nextTokenMatch[1] }),
|
|
376
416
|
}
|
|
377
417
|
} catch (error) {
|
|
378
|
-
throw new Error(
|
|
418
|
+
throw new Error(
|
|
419
|
+
`Failed to list S3 objects: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
420
|
+
)
|
|
379
421
|
}
|
|
380
422
|
},
|
|
381
423
|
|
|
382
424
|
async getMetadata(path: string): Promise<StorageFileData | null> {
|
|
383
425
|
try {
|
|
384
|
-
const headers = await signer.sign(
|
|
426
|
+
const headers = await signer.sign(
|
|
427
|
+
'HEAD',
|
|
428
|
+
`/${path}`,
|
|
429
|
+
{ host: `${bucket}.s3.${region}.amazonaws.com` },
|
|
430
|
+
null
|
|
431
|
+
)
|
|
385
432
|
|
|
386
433
|
const response = await fetch(`${endpoint}/${path}`, {
|
|
387
434
|
method: 'HEAD',
|
|
@@ -404,14 +451,16 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
404
451
|
path,
|
|
405
452
|
name: path.split('/').pop() || path,
|
|
406
453
|
size: contentLength ? parseInt(contentLength, 10) : 0,
|
|
407
|
-
contentType
|
|
408
|
-
etag,
|
|
454
|
+
...(contentType && { contentType }),
|
|
455
|
+
...(etag && { etag }),
|
|
409
456
|
lastModified: lastModified ? new Date(lastModified) : new Date(),
|
|
410
457
|
isFolder: false,
|
|
411
458
|
url: `${endpoint}/${path}`,
|
|
412
459
|
}
|
|
413
460
|
} catch (error) {
|
|
414
|
-
throw new Error(
|
|
461
|
+
throw new Error(
|
|
462
|
+
`Failed to get S3 metadata: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
463
|
+
)
|
|
415
464
|
}
|
|
416
465
|
},
|
|
417
466
|
|
|
@@ -444,7 +493,9 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
444
493
|
|
|
445
494
|
return metadata
|
|
446
495
|
} catch (error) {
|
|
447
|
-
throw new Error(
|
|
496
|
+
throw new Error(
|
|
497
|
+
`Failed to copy in S3: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
498
|
+
)
|
|
448
499
|
}
|
|
449
500
|
},
|
|
450
501
|
|
|
@@ -458,7 +509,9 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
458
509
|
|
|
459
510
|
return metadata
|
|
460
511
|
} catch (error) {
|
|
461
|
-
throw new Error(
|
|
512
|
+
throw new Error(
|
|
513
|
+
`Failed to move in S3: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
514
|
+
)
|
|
462
515
|
}
|
|
463
516
|
},
|
|
464
517
|
|
|
@@ -469,28 +522,43 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
469
522
|
|
|
470
523
|
const queryParams: Record<string, string> = {
|
|
471
524
|
'X-Amz-Algorithm': 'AWS4-HMAC-SHA256',
|
|
472
|
-
'X-Amz-Credential': `${accessKeyId}/${new Date()
|
|
525
|
+
'X-Amz-Credential': `${accessKeyId}/${new Date()
|
|
526
|
+
.toISOString()
|
|
527
|
+
.slice(0, 10)
|
|
528
|
+
.replace(/-/g, '')}/${region}/s3/aws4_request`,
|
|
473
529
|
'X-Amz-Date': new Date().toISOString().replace(/[:-]|\.\d{3}/g, ''),
|
|
474
530
|
'X-Amz-Expires': expiresIn.toString(),
|
|
475
531
|
'X-Amz-SignedHeaders': 'host',
|
|
476
532
|
}
|
|
477
533
|
|
|
478
|
-
const headers = await signer.sign(
|
|
534
|
+
const headers = await signer.sign(
|
|
535
|
+
'GET',
|
|
536
|
+
`/${path}`,
|
|
537
|
+
{ host: `${bucket}.s3.${region}.amazonaws.com` },
|
|
538
|
+
null,
|
|
539
|
+
queryParams
|
|
540
|
+
)
|
|
479
541
|
|
|
480
542
|
// Extract signature from Authorization header
|
|
481
543
|
const authHeader = headers['Authorization']
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
544
|
+
if (authHeader) {
|
|
545
|
+
const signatureMatch = authHeader.match(/Signature=([a-f0-9]+)/)
|
|
546
|
+
if (signatureMatch?.[1]) {
|
|
547
|
+
queryParams['X-Amz-Signature'] = signatureMatch[1]
|
|
548
|
+
}
|
|
485
549
|
}
|
|
486
550
|
|
|
487
551
|
const queryString = Object.keys(queryParams)
|
|
488
|
-
.map((key) => `${key}=${encodeURIComponent(queryParams[key])}`)
|
|
552
|
+
.map((key) => `${key}=${encodeURIComponent(queryParams[key] ?? '')}`)
|
|
489
553
|
.join('&')
|
|
490
554
|
|
|
491
555
|
return `${endpoint}/${path}?${queryString}`
|
|
492
556
|
} catch (error) {
|
|
493
|
-
throw new Error(
|
|
557
|
+
throw new Error(
|
|
558
|
+
`Failed to generate signed URL: ${
|
|
559
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
560
|
+
}`
|
|
561
|
+
)
|
|
494
562
|
}
|
|
495
563
|
},
|
|
496
564
|
|
|
@@ -501,7 +569,11 @@ export function createS3Provider(config: ProviderConfig): StorageProvider {
|
|
|
501
569
|
await this.upload(folderPath, Buffer.from(''), { contentType: 'application/x-directory' })
|
|
502
570
|
return true
|
|
503
571
|
} catch (error) {
|
|
504
|
-
throw new Error(
|
|
572
|
+
throw new Error(
|
|
573
|
+
`Failed to create folder in S3: ${
|
|
574
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
575
|
+
}`
|
|
576
|
+
)
|
|
505
577
|
}
|
|
506
578
|
},
|
|
507
579
|
}
|