@vivinkv28/strapi-provider-uploadthing 0.1.5 → 0.1.6

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.
@@ -276,4 +276,3 @@ const index = {
276
276
  services
277
277
  };
278
278
  exports.default = index;
279
- //# sourceMappingURL=index.js.map
@@ -274,4 +274,3 @@ const index = {
274
274
  export {
275
275
  index as default
276
276
  };
277
- //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,7 +1,15 @@
1
1
  {
2
2
  "name": "@vivinkv28/strapi-provider-uploadthing",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "UploadThing provider for the Strapi Upload plugin",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/vivinkv28/strapi-provider-uploadthing.git"
8
+ },
9
+ "homepage": "https://github.com/vivinkv28/strapi-provider-uploadthing#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/vivinkv28/strapi-provider-uploadthing/issues"
12
+ },
5
13
  "main": "index.js",
6
14
  "exports": {
7
15
  ".": "./index.js",
@@ -18,6 +26,7 @@
18
26
  "index.js",
19
27
  "server",
20
28
  "strapi-server.js",
29
+ "LICENSE",
21
30
  "README.md"
22
31
  ],
23
32
  "keywords": [
@@ -45,7 +54,8 @@
45
54
  "build": "node ./node_modules/@strapi/sdk-plugin/bin/strapi-plugin.js build",
46
55
  "watch": "node ./node_modules/@strapi/sdk-plugin/bin/strapi-plugin.js watch",
47
56
  "watch:link": "node ./node_modules/@strapi/sdk-plugin/bin/strapi-plugin.js watch:link",
48
- "verify": "node ./node_modules/@strapi/sdk-plugin/bin/strapi-plugin.js verify"
57
+ "verify": "node ./node_modules/@strapi/sdk-plugin/bin/strapi-plugin.js verify",
58
+ "prepack": "npm run build"
49
59
  },
50
60
  "dependencies": {
51
61
  "uploadthing": "^7.7.2"
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sources":["../../server/src/bootstrap.js","../../server/src/config/index.js","../../server/src/controllers/index.js","../../server/src/content-types/index.js","../../server/src/destroy.js","../../server/src/middlewares/index.js","../../server/src/policies/index.js","../../server/src/register.js","../../server/src/routes/index.js","../../server/src/services/provider.js","../../server/src/services/index.js","../../server/src/index.js"],"sourcesContent":["export default ({ strapi }) => {\n strapi.log.info('[strapi-upload-things] plugin bootstrapped');\n};\n","export default {\n default: {\n enabled: true,\n },\n validator() {},\n};\n","export default {};\n","export default {};\n","export default () => {};\n","export default {};\n","export default {};\n","export default () => {};\n","export default [];\n","import crypto from 'crypto';\nimport { UTApi, UTFile } from 'uploadthing/server';\n\nconst DEFAULT_CONTENT_DISPOSITION = 'inline';\nconst DEFAULT_SIGNED_URL_TTL = 60 * 60;\nconst DEFAULT_UPLOAD_CONCURRENCY = 1;\nconst DEFAULT_UPLOAD_RETRIES = 2;\n\nconst toPositiveInteger = (value, fallback) => {\n const parsed = Number(value);\n\n if (!Number.isInteger(parsed) || parsed < 1) {\n return fallback;\n }\n\n return parsed;\n};\n\nconst buildCustomId = (file) => {\n if (file?.provider_metadata?.uploadthing?.customId) {\n return file.provider_metadata.uploadthing.customId;\n }\n\n return `${file.hash}${file.ext || ''}`;\n};\n\nconst buildUniqueCustomId = (file) => {\n const extension = file.ext || '';\n const base = file.hash || crypto.randomUUID();\n const suffix = crypto.randomBytes(4).toString('hex');\n\n return `${base}-${suffix}${extension}`;\n};\n\nconst getStoredKey = (file) => file?.provider_metadata?.uploadthing?.fileKey;\n\nconst getStoredCustomId = (file) => file?.provider_metadata?.uploadthing?.customId;\n\nconst normalizeUploadResult = (result) => {\n if (!result) {\n throw new Error('UploadThing returned an empty upload response.');\n }\n\n if (result.error) {\n throw new Error(`UploadThing upload failed: ${result.error.message}`);\n }\n\n if (!result.data?.key || !result.data?.ufsUrl) {\n throw new Error('UploadThing upload response is missing the file key or a usable URL.');\n }\n\n return result.data;\n};\n\nconst streamToBuffer = async (stream) => {\n const chunks = [];\n\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n\n return Buffer.concat(chunks);\n};\n\nconst isCustomIdConflictError = (error) => {\n const message = `${error?.message || ''}`.toLowerCase();\n\n if (!message) {\n return false;\n }\n\n return (\n (message.includes('customid') || message.includes('custom id')) &&\n (message.includes('exist') ||\n message.includes('duplicate') ||\n message.includes('already') ||\n message.includes('conflict') ||\n message.includes('taken'))\n );\n};\n\nconst isMissingFileError = (error) => {\n const message = `${error?.message || ''}`.toLowerCase();\n\n if (!message) {\n return false;\n }\n\n return (\n message.includes('not found') ||\n message.includes('no such file') ||\n message.includes('file does not exist') ||\n message.includes('unable to find') ||\n message.includes('unknown file')\n );\n};\n\nconst isRetryableUploadError = (error) => {\n const message = `${error?.message || ''}`.toLowerCase();\n\n if (!message) {\n return false;\n }\n\n return (\n message.includes('failed to upload file') ||\n message.includes('transport error') ||\n message.includes('fetch failed') ||\n message.includes('socket') ||\n message.includes('other side closed') ||\n message.includes('econnreset') ||\n message.includes('timeout')\n );\n};\n\nexport default (providerOptions = {}) => {\n const {\n token = process.env.UPLOADTHING_TOKEN,\n acl,\n apiUrl,\n ingestUrl,\n logLevel,\n logFormat,\n isDev,\n contentDisposition = DEFAULT_CONTENT_DISPOSITION,\n signedUrlExpiresIn = DEFAULT_SIGNED_URL_TTL,\n uploadConcurrency = DEFAULT_UPLOAD_CONCURRENCY,\n uploadRetries = DEFAULT_UPLOAD_RETRIES,\n privateFiles = false,\n useCustomId = true,\n } = providerOptions;\n\n if (!token) {\n throw new Error(\n 'Missing UploadThing token. Set `providerOptions.token` or the `UPLOADTHING_TOKEN` environment variable.'\n );\n }\n\n const utapi = new UTApi({\n token,\n apiUrl,\n ingestUrl,\n logLevel,\n logFormat,\n isDev,\n defaultKeyType: useCustomId ? 'customId' : 'fileKey',\n });\n\n const resolvedSignedUrlTtl = signedUrlExpiresIn;\n const resolvedUploadConcurrency = Math.min(\n 25,\n toPositiveInteger(uploadConcurrency, DEFAULT_UPLOAD_CONCURRENCY)\n );\n const resolvedUploadRetries = Math.max(0, toPositiveInteger(uploadRetries, DEFAULT_UPLOAD_RETRIES));\n let activeUploads = 0;\n const queuedUploads = [];\n\n const runWithUploadSlot = async (task) => {\n if (activeUploads >= resolvedUploadConcurrency) {\n await new Promise((resolve) => {\n queuedUploads.push(resolve);\n });\n }\n\n activeUploads += 1;\n\n try {\n return await task();\n } finally {\n activeUploads -= 1;\n const next = queuedUploads.shift();\n\n if (next) {\n next();\n }\n }\n };\n\n const assignUploadDataToFile = (file, uploaded, customId) => {\n const publicUrl = uploaded.ufsUrl;\n\n file.url = publicUrl;\n file.previewUrl = publicUrl;\n file.provider_metadata = {\n ...(file.provider_metadata || {}),\n uploadthing: {\n fileKey: uploaded.key,\n customId,\n url: publicUrl,\n ufsUrl: uploaded.ufsUrl,\n name: uploaded.name,\n size: uploaded.size,\n },\n };\n };\n\n const performUpload = async (file, buffer, customId) => {\n const uploadFile = new UTFile([buffer], file.name || `${file.hash}${file.ext || ''}`, {\n customId,\n type: file.mime,\n });\n\n let lastError;\n\n for (let attempt = 0; attempt <= resolvedUploadRetries; attempt += 1) {\n try {\n const result = await utapi.uploadFiles(uploadFile, {\n acl,\n contentDisposition,\n concurrency: 1,\n metadata: {\n source: 'strapi',\n hash: file.hash,\n ext: file.ext,\n mime: file.mime,\n },\n });\n\n const uploaded = normalizeUploadResult(result);\n assignUploadDataToFile(file, uploaded, customId);\n return;\n } catch (error) {\n lastError = error;\n\n if (attempt >= resolvedUploadRetries || !isRetryableUploadError(error)) {\n throw error;\n }\n }\n }\n\n throw lastError;\n };\n\n const uploadBuffer = async (file, buffer) => {\n const preferredCustomId = useCustomId ? buildCustomId(file) : undefined;\n\n await runWithUploadSlot(async () => {\n try {\n await performUpload(file, buffer, preferredCustomId);\n } catch (error) {\n if (!useCustomId || !preferredCustomId) {\n throw error;\n }\n\n const fallbackCustomId = buildUniqueCustomId(file);\n\n if (!isCustomIdConflictError(error)) {\n try {\n await performUpload(file, buffer, fallbackCustomId);\n return;\n } catch (retryError) {\n throw error;\n }\n }\n\n await performUpload(file, buffer, fallbackCustomId);\n }\n });\n };\n\n return {\n async isPrivate() {\n return privateFiles || acl === 'private';\n },\n\n async getSignedUrl(file) {\n const keyType = useCustomId && getStoredCustomId(file) ? 'customId' : 'fileKey';\n const key = keyType === 'customId' ? getStoredCustomId(file) : getStoredKey(file);\n\n if (!key) {\n return file;\n }\n\n const signed = await utapi.getSignedURL(key, {\n expiresIn: resolvedSignedUrlTtl,\n keyType,\n });\n\n return {\n url: signed.ufsUrl || signed.url,\n };\n },\n\n async uploadStream(file) {\n if (!file.stream) {\n throw new Error('Missing file stream');\n }\n\n const buffer = await streamToBuffer(file.stream);\n await uploadBuffer(file, buffer);\n },\n\n async upload(file) {\n if (!file.buffer) {\n throw new Error('Missing file buffer');\n }\n\n await uploadBuffer(file, file.buffer);\n },\n\n async delete(file) {\n const keyType = useCustomId && getStoredCustomId(file) ? 'customId' : 'fileKey';\n const key = keyType === 'customId' ? getStoredCustomId(file) : getStoredKey(file);\n\n if (!key) {\n return;\n }\n\n try {\n await utapi.deleteFiles(key, { keyType });\n } catch (error) {\n if (isMissingFileError(error)) {\n return;\n }\n\n throw error;\n }\n },\n };\n};\n","import provider from './provider';\n\nexport default {\n provider,\n};\n","import bootstrap from './bootstrap';\nimport config from './config';\nimport controllers from './controllers';\nimport contentTypes from './content-types';\nimport destroy from './destroy';\nimport middlewares from './middlewares';\nimport policies from './policies';\nimport register from './register';\nimport routes from './routes';\nimport services from './services';\n\nexport default {\n bootstrap,\n config,\n controllers,\n contentTypes,\n destroy,\n middlewares,\n policies,\n register,\n routes,\n services,\n};\n"],"names":["crypto","UTApi","UTFile"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","sources":["../../server/src/bootstrap.js","../../server/src/config/index.js","../../server/src/controllers/index.js","../../server/src/content-types/index.js","../../server/src/destroy.js","../../server/src/middlewares/index.js","../../server/src/policies/index.js","../../server/src/register.js","../../server/src/routes/index.js","../../server/src/services/provider.js","../../server/src/services/index.js","../../server/src/index.js"],"sourcesContent":["export default ({ strapi }) => {\n strapi.log.info('[strapi-upload-things] plugin bootstrapped');\n};\n","export default {\n default: {\n enabled: true,\n },\n validator() {},\n};\n","export default {};\n","export default {};\n","export default () => {};\n","export default {};\n","export default {};\n","export default () => {};\n","export default [];\n","import crypto from 'crypto';\nimport { UTApi, UTFile } from 'uploadthing/server';\n\nconst DEFAULT_CONTENT_DISPOSITION = 'inline';\nconst DEFAULT_SIGNED_URL_TTL = 60 * 60;\nconst DEFAULT_UPLOAD_CONCURRENCY = 1;\nconst DEFAULT_UPLOAD_RETRIES = 2;\n\nconst toPositiveInteger = (value, fallback) => {\n const parsed = Number(value);\n\n if (!Number.isInteger(parsed) || parsed < 1) {\n return fallback;\n }\n\n return parsed;\n};\n\nconst buildCustomId = (file) => {\n if (file?.provider_metadata?.uploadthing?.customId) {\n return file.provider_metadata.uploadthing.customId;\n }\n\n return `${file.hash}${file.ext || ''}`;\n};\n\nconst buildUniqueCustomId = (file) => {\n const extension = file.ext || '';\n const base = file.hash || crypto.randomUUID();\n const suffix = crypto.randomBytes(4).toString('hex');\n\n return `${base}-${suffix}${extension}`;\n};\n\nconst getStoredKey = (file) => file?.provider_metadata?.uploadthing?.fileKey;\n\nconst getStoredCustomId = (file) => file?.provider_metadata?.uploadthing?.customId;\n\nconst normalizeUploadResult = (result) => {\n if (!result) {\n throw new Error('UploadThing returned an empty upload response.');\n }\n\n if (result.error) {\n throw new Error(`UploadThing upload failed: ${result.error.message}`);\n }\n\n if (!result.data?.key || !result.data?.ufsUrl) {\n throw new Error('UploadThing upload response is missing the file key or a usable URL.');\n }\n\n return result.data;\n};\n\nconst streamToBuffer = async (stream) => {\n const chunks = [];\n\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n\n return Buffer.concat(chunks);\n};\n\nconst isCustomIdConflictError = (error) => {\n const message = `${error?.message || ''}`.toLowerCase();\n\n if (!message) {\n return false;\n }\n\n return (\n (message.includes('customid') || message.includes('custom id')) &&\n (message.includes('exist') ||\n message.includes('duplicate') ||\n message.includes('already') ||\n message.includes('conflict') ||\n message.includes('taken'))\n );\n};\n\nconst isMissingFileError = (error) => {\n const message = `${error?.message || ''}`.toLowerCase();\n\n if (!message) {\n return false;\n }\n\n return (\n message.includes('not found') ||\n message.includes('no such file') ||\n message.includes('file does not exist') ||\n message.includes('unable to find') ||\n message.includes('unknown file')\n );\n};\n\nconst isRetryableUploadError = (error) => {\n const message = `${error?.message || ''}`.toLowerCase();\n\n if (!message) {\n return false;\n }\n\n return (\n message.includes('failed to upload file') ||\n message.includes('transport error') ||\n message.includes('fetch failed') ||\n message.includes('socket') ||\n message.includes('other side closed') ||\n message.includes('econnreset') ||\n message.includes('timeout')\n );\n};\n\nexport default (providerOptions = {}) => {\n const {\n token = process.env.UPLOADTHING_TOKEN,\n acl,\n apiUrl,\n ingestUrl,\n logLevel,\n logFormat,\n isDev,\n contentDisposition = DEFAULT_CONTENT_DISPOSITION,\n signedUrlExpiresIn = DEFAULT_SIGNED_URL_TTL,\n uploadConcurrency = DEFAULT_UPLOAD_CONCURRENCY,\n uploadRetries = DEFAULT_UPLOAD_RETRIES,\n privateFiles = false,\n useCustomId = true,\n } = providerOptions;\n\n if (!token) {\n throw new Error(\n 'Missing UploadThing token. Set `providerOptions.token` or the `UPLOADTHING_TOKEN` environment variable.'\n );\n }\n\n const utapi = new UTApi({\n token,\n apiUrl,\n ingestUrl,\n logLevel,\n logFormat,\n isDev,\n defaultKeyType: useCustomId ? 'customId' : 'fileKey',\n });\n\n const resolvedSignedUrlTtl = signedUrlExpiresIn;\n const resolvedUploadConcurrency = Math.min(\n 25,\n toPositiveInteger(uploadConcurrency, DEFAULT_UPLOAD_CONCURRENCY)\n );\n const resolvedUploadRetries = Math.max(0, toPositiveInteger(uploadRetries, DEFAULT_UPLOAD_RETRIES));\n let activeUploads = 0;\n const queuedUploads = [];\n\n const runWithUploadSlot = async (task) => {\n if (activeUploads >= resolvedUploadConcurrency) {\n await new Promise((resolve) => {\n queuedUploads.push(resolve);\n });\n }\n\n activeUploads += 1;\n\n try {\n return await task();\n } finally {\n activeUploads -= 1;\n const next = queuedUploads.shift();\n\n if (next) {\n next();\n }\n }\n };\n\n const assignUploadDataToFile = (file, uploaded, customId) => {\n const publicUrl = uploaded.ufsUrl;\n\n file.url = publicUrl;\n file.previewUrl = publicUrl;\n file.provider_metadata = {\n ...(file.provider_metadata || {}),\n uploadthing: {\n fileKey: uploaded.key,\n customId,\n url: publicUrl,\n ufsUrl: uploaded.ufsUrl,\n name: uploaded.name,\n size: uploaded.size,\n },\n };\n };\n\n const performUpload = async (file, buffer, customId) => {\n const uploadFile = new UTFile([buffer], file.name || `${file.hash}${file.ext || ''}`, {\n customId,\n type: file.mime,\n });\n\n let lastError;\n\n for (let attempt = 0; attempt <= resolvedUploadRetries; attempt += 1) {\n try {\n const result = await utapi.uploadFiles(uploadFile, {\n acl,\n contentDisposition,\n concurrency: 1,\n metadata: {\n source: 'strapi',\n hash: file.hash,\n ext: file.ext,\n mime: file.mime,\n },\n });\n\n const uploaded = normalizeUploadResult(result);\n assignUploadDataToFile(file, uploaded, customId);\n return;\n } catch (error) {\n lastError = error;\n\n if (attempt >= resolvedUploadRetries || !isRetryableUploadError(error)) {\n throw error;\n }\n }\n }\n\n throw lastError;\n };\n\n const uploadBuffer = async (file, buffer) => {\n const preferredCustomId = useCustomId ? buildCustomId(file) : undefined;\n\n await runWithUploadSlot(async () => {\n try {\n await performUpload(file, buffer, preferredCustomId);\n } catch (error) {\n if (!useCustomId || !preferredCustomId) {\n throw error;\n }\n\n const fallbackCustomId = buildUniqueCustomId(file);\n\n if (!isCustomIdConflictError(error)) {\n try {\n await performUpload(file, buffer, fallbackCustomId);\n return;\n } catch (retryError) {\n throw error;\n }\n }\n\n await performUpload(file, buffer, fallbackCustomId);\n }\n });\n };\n\n return {\n async isPrivate() {\n return privateFiles || acl === 'private';\n },\n\n async getSignedUrl(file) {\n const keyType = useCustomId && getStoredCustomId(file) ? 'customId' : 'fileKey';\n const key = keyType === 'customId' ? getStoredCustomId(file) : getStoredKey(file);\n\n if (!key) {\n return file;\n }\n\n const signed = await utapi.getSignedURL(key, {\n expiresIn: resolvedSignedUrlTtl,\n keyType,\n });\n\n return {\n url: signed.ufsUrl || signed.url,\n };\n },\n\n async uploadStream(file) {\n if (!file.stream) {\n throw new Error('Missing file stream');\n }\n\n const buffer = await streamToBuffer(file.stream);\n await uploadBuffer(file, buffer);\n },\n\n async upload(file) {\n if (!file.buffer) {\n throw new Error('Missing file buffer');\n }\n\n await uploadBuffer(file, file.buffer);\n },\n\n async delete(file) {\n const keyType = useCustomId && getStoredCustomId(file) ? 'customId' : 'fileKey';\n const key = keyType === 'customId' ? getStoredCustomId(file) : getStoredKey(file);\n\n if (!key) {\n return;\n }\n\n try {\n await utapi.deleteFiles(key, { keyType });\n } catch (error) {\n if (isMissingFileError(error)) {\n return;\n }\n\n throw error;\n }\n },\n };\n};\n","import provider from './provider';\n\nexport default {\n provider,\n};\n","import bootstrap from './bootstrap';\nimport config from './config';\nimport controllers from './controllers';\nimport contentTypes from './content-types';\nimport destroy from './destroy';\nimport middlewares from './middlewares';\nimport policies from './policies';\nimport register from './register';\nimport routes from './routes';\nimport services from './services';\n\nexport default {\n bootstrap,\n config,\n controllers,\n contentTypes,\n destroy,\n middlewares,\n policies,\n register,\n routes,\n services,\n};\n"],"names":[],"mappings":"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"}