@payloadcms/plugin-cloud-storage 1.0.15 → 1.0.16
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/.eslintrc.js +14 -14
- package/LICENSE.md +22 -22
- package/README.md +178 -178
- package/azure.d.ts +1 -1
- package/azure.js +1 -1
- package/dist/adapters/azure/fileStub.d.ts +2 -2
- package/dist/adapters/azure/fileStub.js +3 -3
- package/dist/adapters/azure/generateURL.d.ts +7 -7
- package/dist/adapters/azure/generateURL.js +15 -15
- package/dist/adapters/azure/handleDelete.d.ts +9 -9
- package/dist/adapters/azure/handleDelete.js +63 -63
- package/dist/adapters/azure/handleUpload.d.ts +10 -10
- package/dist/adapters/azure/handleUpload.js +80 -80
- package/dist/adapters/azure/index.d.ts +8 -8
- package/dist/adapters/azure/index.js +42 -42
- package/dist/adapters/azure/index.js.map +1 -1
- package/dist/adapters/azure/mock.d.ts +13 -13
- package/dist/adapters/azure/mock.js +12 -12
- package/dist/adapters/azure/staticHandler.d.ts +9 -9
- package/dist/adapters/azure/staticHandler.js +81 -81
- package/dist/adapters/azure/webpack.d.ts +2 -2
- package/dist/adapters/azure/webpack.js +24 -24
- package/dist/adapters/azure/webpack.js.map +1 -1
- package/dist/adapters/gcs/generateURL.d.ts +8 -8
- package/dist/adapters/gcs/generateURL.js +15 -15
- package/dist/adapters/gcs/handleDelete.d.ts +8 -8
- package/dist/adapters/gcs/handleDelete.js +62 -62
- package/dist/adapters/gcs/handleUpload.d.ts +12 -12
- package/dist/adapters/gcs/handleUpload.js +72 -72
- package/dist/adapters/gcs/index.d.ts +8 -8
- package/dist/adapters/gcs/index.js +35 -35
- package/dist/adapters/gcs/mock.d.ts +1 -1
- package/dist/adapters/gcs/mock.js +4 -4
- package/dist/adapters/gcs/staticHandler.d.ts +10 -10
- package/dist/adapters/gcs/staticHandler.js +76 -76
- package/dist/adapters/gcs/webpack.d.ts +2 -2
- package/dist/adapters/gcs/webpack.js +24 -24
- package/dist/adapters/gcs/webpack.js.map +1 -1
- package/dist/adapters/s3/fileStub.d.ts +2 -2
- package/dist/adapters/s3/fileStub.js +3 -3
- package/dist/adapters/s3/generateURL.d.ts +8 -8
- package/dist/adapters/s3/generateURL.js +15 -15
- package/dist/adapters/s3/handleDelete.d.ts +8 -8
- package/dist/adapters/s3/handleDelete.js +63 -63
- package/dist/adapters/s3/handleUpload.d.ts +12 -12
- package/dist/adapters/s3/handleUpload.js +93 -93
- package/dist/adapters/s3/index.d.ts +8 -8
- package/dist/adapters/s3/index.js +59 -59
- package/dist/adapters/s3/mock.d.ts +8 -8
- package/dist/adapters/s3/mock.js +9 -9
- package/dist/adapters/s3/staticHandler.d.ts +10 -10
- package/dist/adapters/s3/staticHandler.js +81 -80
- package/dist/adapters/s3/staticHandler.js.map +1 -1
- package/dist/adapters/s3/webpack.d.ts +2 -2
- package/dist/adapters/s3/webpack.js +24 -24
- package/dist/adapters/s3/webpack.js.map +1 -1
- package/dist/fields/getFields.d.ts +11 -11
- package/dist/fields/getFields.js +118 -118
- package/dist/hooks/afterDelete.d.ts +10 -10
- package/dist/hooks/afterDelete.js +91 -88
- package/dist/hooks/afterDelete.js.map +1 -1
- package/dist/hooks/afterRead.d.ts +12 -12
- package/dist/hooks/afterRead.js +79 -79
- package/dist/hooks/beforeChange.d.ts +10 -10
- package/dist/hooks/beforeChange.js +105 -77
- package/dist/hooks/beforeChange.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -5
- package/dist/plugin.d.ts +3 -3
- package/dist/plugin.js +124 -124
- package/dist/plugin.js.map +1 -1
- package/dist/types.d.ts +62 -62
- package/dist/types.js +2 -2
- package/dist/utilities/getFilePrefix.d.ts +5 -5
- package/dist/utilities/getFilePrefix.js +80 -80
- package/dist/utilities/getIncomingFiles.d.ts +7 -7
- package/dist/utilities/getIncomingFiles.js +37 -37
- package/dist/utilities/getRangeFromHeader.d.ts +6 -6
- package/dist/utilities/getRangeFromHeader.js +66 -66
- package/dist/webpack.d.ts +9 -9
- package/dist/webpack.js +39 -39
- package/gcs.d.ts +1 -1
- package/gcs.js +1 -1
- package/package.json +67 -67
- package/s3.d.ts +1 -1
- package/s3.js +1 -1
- package/.editorconfig +0 -10
- package/.gitignore +0 -248
- package/.idea/.gitignore +0 -5
- package/.idea/httpRequests/2023-04-07T152957.206.png +0 -0
- package/.idea/httpRequests/2023-04-07T153025.403.html +0 -10
- package/.idea/httpRequests/2023-04-07T153146.200.png +0 -0
- package/.idea/httpRequests/http-client.cookies +0 -1
- package/.idea/httpRequests/http-requests-log.http +0 -74
- package/.idea/inspectionProfiles/Project_Default.xml +0 -6
- package/.idea/jsLinters/eslint.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/plugin-cloud-storage.iml +0 -12
- package/.idea/vcs.xml +0 -6
- package/.idea/workspace.xml +0 -269
- package/.prettierignore +0 -1
- package/.prettierrc.js +0 -8
- package/.vscode/launch.json +0 -28
- package/.vscode/settings.json +0 -9
- package/dev/.env +0 -25
- package/dev/.env.example +0 -21
- package/dev/build/127.d2c2ffcfff69fabfdd1b.js +0 -1
- package/dev/build/16.17dbe03b1d0a96f3e564.js +0 -2
- package/dev/build/16.17dbe03b1d0a96f3e564.js.LICENSE.txt +0 -8
- package/dev/build/171.bbcbae3ea90468ad0cad.js +0 -2
- package/dev/build/171.bbcbae3ea90468ad0cad.js.LICENSE.txt +0 -8
- package/dev/build/18.e50c27edff6716f930d9.js +0 -1
- package/dev/build/205.33c7a29683ba98de93e0.js +0 -1
- package/dev/build/2211c49456cd07331ea9.woff +0 -0
- package/dev/build/234.79395f82c18207c13766.js +0 -1
- package/dev/build/266.9d4a240b3e0985bd7dd5.js +0 -1
- package/dev/build/296.4c5d646257b42c915834.js +0 -1
- package/dev/build/304.40dbe690de322c8f7c0d.js +0 -2
- package/dev/build/304.40dbe690de322c8f7c0d.js.LICENSE.txt +0 -37
- package/dev/build/349.446c12bffd3905085fdb.js +0 -1
- package/dev/build/354.5acd04b85b96a9839125.js +0 -1
- package/dev/build/40ad7515b8674bb854a1.woff2 +0 -0
- package/dev/build/422.086542466cdc9f6a2437.js +0 -2
- package/dev/build/422.086542466cdc9f6a2437.js.LICENSE.txt +0 -6
- package/dev/build/491.0bfe1bb0ecfe383179aa.js +0 -1
- package/dev/build/4d8845b830f4e8e2affb.png +0 -0
- package/dev/build/51922ceb71da289688d3.woff2 +0 -0
- package/dev/build/522443364fda49e9e0ed.woff2 +0 -0
- package/dev/build/531.1c6f53f3b44a3c45b444.js +0 -2
- package/dev/build/531.1c6f53f3b44a3c45b444.js.LICENSE.txt +0 -6
- package/dev/build/570.f2d9b99706765fbf0225.js +0 -1
- package/dev/build/599.570a04990d5806004f61.js +0 -1
- package/dev/build/5b718d9772de251a8c0a.woff2 +0 -0
- package/dev/build/778.41ae26bcd617861ad586.js +0 -1
- package/dev/build/783.0117995f2ff6036d6746.js +0 -1
- package/dev/build/787999a6af6a17efbc7c.woff +0 -0
- package/dev/build/78b8935fb481e11c92ce.woff +0 -0
- package/dev/build/860.7688681d3269f3f16e9a.js +0 -1
- package/dev/build/892.1a4ca5ac67d81038ceec.js +0 -1
- package/dev/build/896.d8cb1160388dc29d6364.js +0 -1
- package/dev/build/8b4ddd0d08500553efde.woff +0 -0
- package/dev/build/8f612153248094525d9d.woff +0 -0
- package/dev/build/995.cc11e738ff81a85821b4.js +0 -1
- package/dev/build/9c7dfd0036f7bd24b053.woff2 +0 -0
- package/dev/build/a1cfdc5b5250b7c4b481.woff2 +0 -0
- package/dev/build/d7aeda9e48ce098e7b48.woff +0 -0
- package/dev/build/e009f21405b4d7e89367.woff2 +0 -0
- package/dev/build/e7caa9e17af6ac87d182.woff +0 -0
- package/dev/build/ebcc1430049fddb274f8.svg +0 -15
- package/dev/build/efe8f6a3b46446cc9135.woff +0 -0
- package/dev/build/f53bb8d4b29adc903703.woff2 +0 -0
- package/dev/build/index.html +0 -1
- package/dev/build/main.a2003d502fbb9aaa3e8d.js +0 -2
- package/dev/build/main.a2003d502fbb9aaa3e8d.js.LICENSE.txt +0 -57
- package/dev/build/styles.css +0 -1
- package/dev/build/styles.fa29d16b0baf5b98a1cf.js +0 -1
- package/dev/nodemon.json +0 -8
- package/dev/package.json +0 -32
- package/dev/src/collections/Media.ts +0 -56
- package/dev/src/collections/Users.ts +0 -23
- package/dev/src/mocks/fsMock.js +0 -1
- package/dev/src/mocks/promisifyMock.js +0 -1
- package/dev/src/payload.config.ts +0 -111
- package/dev/src/server.ts +0 -26
- package/dev/tsconfig.json +0 -20
- package/docs/local-dev.md +0 -47
- package/eslint-config/index.js +0 -15
- package/eslint-config/rules/import.js +0 -38
- package/eslint-config/rules/prettier.js +0 -7
- package/eslint-config/rules/style.js +0 -21
- package/eslint-config/rules/typescript.js +0 -628
- package/src/adapters/azure/emulator/docker-compose.yml +0 -16
- package/src/adapters/azure/fileStub.js +0 -1
- package/src/adapters/azure/generateURL.ts +0 -13
- package/src/adapters/azure/handleDelete.ts +0 -16
- package/src/adapters/azure/handleUpload.ts +0 -41
- package/src/adapters/azure/index.ts +0 -47
- package/src/adapters/azure/mock.js +0 -13
- package/src/adapters/azure/staticHandler.ts +0 -38
- package/src/adapters/azure/webpack.ts +0 -20
- package/src/adapters/gcs/emulator/docker-compose.yml +0 -15
- package/src/adapters/gcs/generateURL.ts +0 -16
- package/src/adapters/gcs/handleDelete.ts +0 -16
- package/src/adapters/gcs/handleUpload.ts +0 -34
- package/src/adapters/gcs/index.ts +0 -37
- package/src/adapters/gcs/mock.js +0 -3
- package/src/adapters/gcs/staticHandler.ts +0 -34
- package/src/adapters/gcs/webpack.ts +0 -17
- package/src/adapters/s3/emulator/docker-compose.yml +0 -15
- package/src/adapters/s3/fileStub.js +0 -1
- package/src/adapters/s3/generateURL.ts +0 -14
- package/src/adapters/s3/handleDelete.ts +0 -17
- package/src/adapters/s3/handleUpload.ts +0 -62
- package/src/adapters/s3/index.ts +0 -38
- package/src/adapters/s3/mock.js +0 -9
- package/src/adapters/s3/staticHandler.ts +0 -40
- package/src/adapters/s3/webpack.ts +0 -19
- package/src/fields/getFields.ts +0 -155
- package/src/hooks/afterDelete.ts +0 -35
- package/src/hooks/afterRead.ts +0 -38
- package/src/hooks/beforeChange.ts +0 -30
- package/src/index.ts +0 -1
- package/src/plugin.ts +0 -94
- package/src/types.ts +0 -73
- package/src/utilities/getFilePrefix.ts +0 -26
- package/src/utilities/getIncomingFiles.ts +0 -44
- package/src/utilities/getRangeFromHeader.ts +0 -27
- package/src/webpack.ts +0 -46
- package/tsconfig.json +0 -23
- package/yarn.lock +0 -8155
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type { CollectionConfig } from 'payload/types'
|
|
3
|
-
import type { ContainerClient } from '@azure/storage-blob'
|
|
4
|
-
import type { HandleDelete } from '../../types'
|
|
5
|
-
|
|
6
|
-
interface Args {
|
|
7
|
-
collection: CollectionConfig
|
|
8
|
-
getStorageClient: () => ContainerClient
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const getHandleDelete = ({ getStorageClient }: Args): HandleDelete => {
|
|
12
|
-
return async ({ filename, doc: { prefix = '' } }) => {
|
|
13
|
-
const blockBlobClient = getStorageClient().getBlockBlobClient(path.posix.join(prefix, filename))
|
|
14
|
-
await blockBlobClient.deleteIfExists()
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import fs from 'fs'
|
|
3
|
-
import { Readable } from 'stream'
|
|
4
|
-
import type { ContainerClient } from '@azure/storage-blob'
|
|
5
|
-
import { AbortController } from '@azure/abort-controller'
|
|
6
|
-
import type { CollectionConfig } from 'payload/types'
|
|
7
|
-
import type { HandleUpload } from '../../types'
|
|
8
|
-
|
|
9
|
-
interface Args {
|
|
10
|
-
collection: CollectionConfig
|
|
11
|
-
getStorageClient: () => ContainerClient
|
|
12
|
-
prefix?: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const multipartThreshold = 1024 * 1024 * 50 // 50MB
|
|
16
|
-
export const getHandleUpload = ({ getStorageClient, prefix = '' }: Args): HandleUpload => {
|
|
17
|
-
return async ({ data, file }) => {
|
|
18
|
-
const blockBlobClient = getStorageClient().getBlockBlobClient(
|
|
19
|
-
path.posix.join(prefix, file.filename),
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
// when there are no temp files, or the upload is less than the threshold size, do not stream files
|
|
23
|
-
if (!file.tempFilePath && file.buffer.length > 0 && file.buffer.length < multipartThreshold) {
|
|
24
|
-
await blockBlobClient.upload(file.buffer, file.buffer.byteLength, {
|
|
25
|
-
blobHTTPHeaders: { blobContentType: file.mimeType },
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
return data
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const fileBufferOrStream: Readable = file.tempFilePath
|
|
32
|
-
? fs.createReadStream(file.tempFilePath)
|
|
33
|
-
: Readable.from(file.buffer)
|
|
34
|
-
|
|
35
|
-
await blockBlobClient.uploadStream(fileBufferOrStream, 4 * 1024 * 1024, 4, {
|
|
36
|
-
abortSignal: AbortController.timeout(30 * 60 * 1000),
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
return data
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { BlobServiceClient, ContainerClient } from '@azure/storage-blob'
|
|
2
|
-
import type { Adapter, GeneratedAdapter } from '../../types'
|
|
3
|
-
import { getHandler } from './staticHandler'
|
|
4
|
-
import { getGenerateURL } from './generateURL'
|
|
5
|
-
import { getHandleDelete } from './handleDelete'
|
|
6
|
-
import { getHandleUpload } from './handleUpload'
|
|
7
|
-
import { extendWebpackConfig } from './webpack'
|
|
8
|
-
|
|
9
|
-
export interface Args {
|
|
10
|
-
connectionString: string
|
|
11
|
-
containerName: string
|
|
12
|
-
baseURL: string
|
|
13
|
-
allowContainerCreate: boolean
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const azureBlobStorageAdapter = ({
|
|
17
|
-
connectionString,
|
|
18
|
-
allowContainerCreate,
|
|
19
|
-
containerName,
|
|
20
|
-
baseURL,
|
|
21
|
-
}: Args): Adapter => {
|
|
22
|
-
let storageClient: ContainerClient | null = null
|
|
23
|
-
const getStorageClient = () => {
|
|
24
|
-
if (storageClient) return storageClient
|
|
25
|
-
const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString)
|
|
26
|
-
return (storageClient = blobServiceClient.getContainerClient(containerName))
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const createContainerIfNotExists = () => {
|
|
30
|
-
getStorageClient().createIfNotExists({ access: 'blob' })
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return ({ collection, prefix }): GeneratedAdapter => {
|
|
34
|
-
return {
|
|
35
|
-
handleUpload: getHandleUpload({
|
|
36
|
-
collection,
|
|
37
|
-
getStorageClient,
|
|
38
|
-
prefix,
|
|
39
|
-
}),
|
|
40
|
-
handleDelete: getHandleDelete({ collection, getStorageClient }),
|
|
41
|
-
generateURL: getGenerateURL({ containerName, baseURL }),
|
|
42
|
-
staticHandler: getHandler({ getStorageClient, collection }),
|
|
43
|
-
webpack: extendWebpackConfig,
|
|
44
|
-
...(allowContainerCreate && { onInit: createContainerIfNotExists }),
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { ContainerClient } from '@azure/storage-blob'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
import type { CollectionConfig } from 'payload/types'
|
|
4
|
-
import type { StaticHandler } from '../../types'
|
|
5
|
-
import { getFilePrefix } from '../../utilities/getFilePrefix'
|
|
6
|
-
import getRangeFromHeader from '../../utilities/getRangeFromHeader'
|
|
7
|
-
|
|
8
|
-
interface Args {
|
|
9
|
-
getStorageClient: () => ContainerClient
|
|
10
|
-
collection: CollectionConfig
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const getHandler = ({ getStorageClient, collection }: Args): StaticHandler => {
|
|
14
|
-
return async (req, res, next) => {
|
|
15
|
-
try {
|
|
16
|
-
const prefix = await getFilePrefix({ req, collection })
|
|
17
|
-
const blockBlobClient = getStorageClient().getBlockBlobClient(
|
|
18
|
-
path.posix.join(prefix, req.params.filename),
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
const { start, end } = await getRangeFromHeader(blockBlobClient, req.headers.range)
|
|
22
|
-
|
|
23
|
-
const blob = await blockBlobClient.download(start, end)
|
|
24
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
25
|
-
const response = blob._response
|
|
26
|
-
res.header(response.headers.rawHeaders())
|
|
27
|
-
res.status(response.status)
|
|
28
|
-
|
|
29
|
-
if (blob?.readableStreamBody) {
|
|
30
|
-
return blob.readableStreamBody.pipe(res)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return next()
|
|
34
|
-
} catch (err: unknown) {
|
|
35
|
-
return next()
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { Configuration as WebpackConfig } from 'webpack'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
|
|
4
|
-
export const extendWebpackConfig = (existingWebpackConfig: WebpackConfig): WebpackConfig => {
|
|
5
|
-
const newConfig: WebpackConfig = {
|
|
6
|
-
...existingWebpackConfig,
|
|
7
|
-
resolve: {
|
|
8
|
-
...(existingWebpackConfig.resolve || {}),
|
|
9
|
-
alias: {
|
|
10
|
-
...(existingWebpackConfig.resolve?.alias ? existingWebpackConfig.resolve.alias : {}),
|
|
11
|
-
stream: path.resolve(__dirname, './mock.js'),
|
|
12
|
-
'@azure/storage-blob': path.resolve(__dirname, './mock.js'),
|
|
13
|
-
'@azure/abort-controller': path.resolve(__dirname, './mock.js'),
|
|
14
|
-
fs: path.resolve(__dirname, './fileStub.js'),
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return newConfig
|
|
20
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
version: "3"
|
|
2
|
-
|
|
3
|
-
services:
|
|
4
|
-
google-cloud-storage:
|
|
5
|
-
image: fsouza/fake-gcs-server
|
|
6
|
-
restart: always
|
|
7
|
-
command: ["-scheme", "http", "-port", "4443", "-public-host", "http://localhost:4443", "-external-url", "http://localhost:4443", "-backend", "memory"]
|
|
8
|
-
ports:
|
|
9
|
-
- "4443:4443"
|
|
10
|
-
volumes:
|
|
11
|
-
- ./google-cloud-storage/payload-bucket:/data/payload-bucket
|
|
12
|
-
|
|
13
|
-
volumes:
|
|
14
|
-
google-cloud-storage:
|
|
15
|
-
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import { Storage } from '@google-cloud/storage'
|
|
3
|
-
import type { GenerateURL } from '../../types'
|
|
4
|
-
|
|
5
|
-
interface Args {
|
|
6
|
-
getStorageClient: () => Storage
|
|
7
|
-
bucket: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const getGenerateURL =
|
|
11
|
-
({ getStorageClient, bucket }: Args): GenerateURL =>
|
|
12
|
-
({ filename, prefix = '' }) => {
|
|
13
|
-
return decodeURIComponent(
|
|
14
|
-
getStorageClient().bucket(bucket).file(path.posix.join(prefix, filename)).publicUrl(),
|
|
15
|
-
)
|
|
16
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import { Storage } from '@google-cloud/storage'
|
|
3
|
-
import type { HandleDelete } from '../../types'
|
|
4
|
-
|
|
5
|
-
interface Args {
|
|
6
|
-
getStorageClient: () => Storage
|
|
7
|
-
bucket: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const getHandleDelete = ({ getStorageClient, bucket }: Args): HandleDelete => {
|
|
11
|
-
return async ({ filename, doc: { prefix = '' } }) => {
|
|
12
|
-
await getStorageClient().bucket(bucket).file(path.posix.join(prefix, filename)).delete({
|
|
13
|
-
ignoreNotFound: true,
|
|
14
|
-
})
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type { Storage } from '@google-cloud/storage'
|
|
3
|
-
import type { CollectionConfig } from 'payload/types'
|
|
4
|
-
import type { HandleUpload } from '../../types'
|
|
5
|
-
|
|
6
|
-
interface Args {
|
|
7
|
-
collection: CollectionConfig
|
|
8
|
-
bucket: string
|
|
9
|
-
acl?: 'Private' | 'Public'
|
|
10
|
-
prefix?: string
|
|
11
|
-
getStorageClient: () => Storage
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const getHandleUpload = ({
|
|
15
|
-
getStorageClient,
|
|
16
|
-
bucket,
|
|
17
|
-
acl,
|
|
18
|
-
prefix = '',
|
|
19
|
-
}: Args): HandleUpload => {
|
|
20
|
-
return async ({ data, file }) => {
|
|
21
|
-
const gcsFile = getStorageClient().bucket(bucket).file(path.posix.join(prefix, file.filename))
|
|
22
|
-
await gcsFile.save(file.buffer, {
|
|
23
|
-
metadata: {
|
|
24
|
-
contentType: file.mimeType,
|
|
25
|
-
},
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
if (acl) {
|
|
29
|
-
await gcsFile[`make${acl}`]()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return data
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { Storage, StorageOptions } from '@google-cloud/storage'
|
|
2
|
-
import type { Adapter, GeneratedAdapter } from '../../types'
|
|
3
|
-
import { getGenerateURL } from './generateURL'
|
|
4
|
-
import { getHandler } from './staticHandler'
|
|
5
|
-
import { getHandleDelete } from './handleDelete'
|
|
6
|
-
import { getHandleUpload } from './handleUpload'
|
|
7
|
-
import { extendWebpackConfig } from './webpack'
|
|
8
|
-
|
|
9
|
-
export interface Args {
|
|
10
|
-
options: StorageOptions
|
|
11
|
-
bucket: string
|
|
12
|
-
acl?: 'Private' | 'Public'
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const gcsAdapter =
|
|
16
|
-
({ options, bucket, acl }: Args): Adapter =>
|
|
17
|
-
({ collection, prefix }): GeneratedAdapter => {
|
|
18
|
-
let storageClient: Storage | null = null
|
|
19
|
-
const getStorageClient = () => {
|
|
20
|
-
if (storageClient) return storageClient
|
|
21
|
-
return (storageClient = new Storage(options))
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
handleUpload: getHandleUpload({
|
|
26
|
-
collection,
|
|
27
|
-
getStorageClient,
|
|
28
|
-
bucket,
|
|
29
|
-
acl,
|
|
30
|
-
prefix,
|
|
31
|
-
}),
|
|
32
|
-
handleDelete: getHandleDelete({ getStorageClient, bucket }),
|
|
33
|
-
generateURL: getGenerateURL({ getStorageClient, bucket }),
|
|
34
|
-
staticHandler: getHandler({ getStorageClient, bucket, collection }),
|
|
35
|
-
webpack: extendWebpackConfig,
|
|
36
|
-
}
|
|
37
|
-
}
|
package/src/adapters/gcs/mock.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type { Storage } from '@google-cloud/storage'
|
|
3
|
-
import type { CollectionConfig } from 'payload/types'
|
|
4
|
-
import type { StaticHandler } from '../../types'
|
|
5
|
-
import { getFilePrefix } from '../../utilities/getFilePrefix'
|
|
6
|
-
|
|
7
|
-
interface Args {
|
|
8
|
-
getStorageClient: () => Storage
|
|
9
|
-
bucket: string
|
|
10
|
-
collection: CollectionConfig
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const getHandler = ({ getStorageClient, bucket, collection }: Args): StaticHandler => {
|
|
14
|
-
return async (req, res, next) => {
|
|
15
|
-
try {
|
|
16
|
-
const prefix = await getFilePrefix({ req, collection })
|
|
17
|
-
const file = getStorageClient()
|
|
18
|
-
.bucket(bucket)
|
|
19
|
-
.file(path.posix.join(prefix, req.params.filename))
|
|
20
|
-
|
|
21
|
-
const [metadata] = await file.getMetadata()
|
|
22
|
-
|
|
23
|
-
res.set({
|
|
24
|
-
'Content-Length': metadata.size,
|
|
25
|
-
'Content-Type': metadata.contentType,
|
|
26
|
-
ETag: metadata.etag,
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
return file.createReadStream().pipe(res)
|
|
30
|
-
} catch (err: unknown) {
|
|
31
|
-
return next()
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Configuration as WebpackConfig } from 'webpack'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
|
|
4
|
-
export const extendWebpackConfig = (existingWebpackConfig: WebpackConfig): WebpackConfig => {
|
|
5
|
-
const newConfig: WebpackConfig = {
|
|
6
|
-
...existingWebpackConfig,
|
|
7
|
-
resolve: {
|
|
8
|
-
...(existingWebpackConfig.resolve || {}),
|
|
9
|
-
alias: {
|
|
10
|
-
...(existingWebpackConfig.resolve?.alias ? existingWebpackConfig.resolve.alias : {}),
|
|
11
|
-
'@google-cloud/storage': path.resolve(__dirname, './mock.js'),
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return newConfig
|
|
17
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
version: '3.2'
|
|
2
|
-
services:
|
|
3
|
-
localstack:
|
|
4
|
-
image: localstack/localstack:latest
|
|
5
|
-
container_name: localstack_demo
|
|
6
|
-
ports:
|
|
7
|
-
- '4563-4599:4563-4599'
|
|
8
|
-
- '8055:8080'
|
|
9
|
-
environment:
|
|
10
|
-
- SERVICES=s3
|
|
11
|
-
- DEBUG=1
|
|
12
|
-
- DATA_DIR=/tmp/localstack/data
|
|
13
|
-
volumes:
|
|
14
|
-
- './.localstack:/var/lib/localstack'
|
|
15
|
-
- '/var/run/docker.sock:/var/run/docker.sock'
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default 'file-stub'
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type * as AWS from '@aws-sdk/client-s3'
|
|
3
|
-
import type { GenerateURL } from '../../types'
|
|
4
|
-
|
|
5
|
-
interface Args {
|
|
6
|
-
config: AWS.S3ClientConfig
|
|
7
|
-
bucket: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const getGenerateURL =
|
|
11
|
-
({ config: { endpoint }, bucket }: Args): GenerateURL =>
|
|
12
|
-
({ filename, prefix = '' }) => {
|
|
13
|
-
return `${endpoint}/${bucket}/${path.posix.join(prefix, filename)}`
|
|
14
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type * as AWS from '@aws-sdk/client-s3'
|
|
3
|
-
import type { HandleDelete } from '../../types'
|
|
4
|
-
|
|
5
|
-
interface Args {
|
|
6
|
-
getStorageClient: () => AWS.S3
|
|
7
|
-
bucket: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const getHandleDelete = ({ getStorageClient, bucket }: Args): HandleDelete => {
|
|
11
|
-
return async ({ filename, doc: { prefix = '' } }) => {
|
|
12
|
-
await getStorageClient().deleteObject({
|
|
13
|
-
Bucket: bucket,
|
|
14
|
-
Key: path.posix.join(prefix, filename),
|
|
15
|
-
})
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
import type * as AWS from '@aws-sdk/client-s3'
|
|
4
|
-
import type { CollectionConfig } from 'payload/types'
|
|
5
|
-
import type stream from 'stream'
|
|
6
|
-
|
|
7
|
-
import { Upload } from '@aws-sdk/lib-storage'
|
|
8
|
-
import type { HandleUpload } from '../../types'
|
|
9
|
-
|
|
10
|
-
interface Args {
|
|
11
|
-
collection: CollectionConfig
|
|
12
|
-
bucket: string
|
|
13
|
-
acl?: 'private' | 'public-read'
|
|
14
|
-
prefix?: string
|
|
15
|
-
getStorageClient: () => AWS.S3
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const multipartThreshold = 1024 * 1024 * 50 // 50MB
|
|
19
|
-
|
|
20
|
-
export const getHandleUpload = ({
|
|
21
|
-
getStorageClient,
|
|
22
|
-
bucket,
|
|
23
|
-
acl,
|
|
24
|
-
prefix = '',
|
|
25
|
-
}: Args): HandleUpload => {
|
|
26
|
-
return async ({ data, file }) => {
|
|
27
|
-
const fileKey = path.posix.join(prefix, file.filename)
|
|
28
|
-
|
|
29
|
-
const fileBufferOrStream: Buffer | stream.Readable = file.tempFilePath
|
|
30
|
-
? fs.createReadStream(file.tempFilePath)
|
|
31
|
-
: file.buffer
|
|
32
|
-
|
|
33
|
-
if (file.buffer.length > 0 && file.buffer.length < multipartThreshold) {
|
|
34
|
-
await getStorageClient().putObject({
|
|
35
|
-
Bucket: bucket,
|
|
36
|
-
Key: fileKey,
|
|
37
|
-
Body: fileBufferOrStream,
|
|
38
|
-
ACL: acl,
|
|
39
|
-
ContentType: file.mimeType,
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
return data
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const parallelUploadS3 = new Upload({
|
|
46
|
-
client: getStorageClient(),
|
|
47
|
-
params: {
|
|
48
|
-
Bucket: bucket,
|
|
49
|
-
Key: fileKey,
|
|
50
|
-
Body: fileBufferOrStream,
|
|
51
|
-
ACL: acl,
|
|
52
|
-
ContentType: file.mimeType,
|
|
53
|
-
},
|
|
54
|
-
queueSize: 4,
|
|
55
|
-
partSize: multipartThreshold,
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
await parallelUploadS3.done()
|
|
59
|
-
|
|
60
|
-
return data
|
|
61
|
-
}
|
|
62
|
-
}
|
package/src/adapters/s3/index.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import * as AWS from '@aws-sdk/client-s3'
|
|
2
|
-
import type { Adapter, GeneratedAdapter } from '../../types'
|
|
3
|
-
import { getGenerateURL } from './generateURL'
|
|
4
|
-
import { getHandler } from './staticHandler'
|
|
5
|
-
import { getHandleDelete } from './handleDelete'
|
|
6
|
-
import { getHandleUpload } from './handleUpload'
|
|
7
|
-
import { extendWebpackConfig } from './webpack'
|
|
8
|
-
|
|
9
|
-
export interface Args {
|
|
10
|
-
config: AWS.S3ClientConfig
|
|
11
|
-
bucket: string
|
|
12
|
-
acl?: 'private' | 'public-read'
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const s3Adapter =
|
|
16
|
-
({ config, bucket, acl }: Args): Adapter =>
|
|
17
|
-
({ collection, prefix }): GeneratedAdapter => {
|
|
18
|
-
let storageClient: AWS.S3 | null = null
|
|
19
|
-
const getStorageClient: () => AWS.S3 = () => {
|
|
20
|
-
if (storageClient) return storageClient
|
|
21
|
-
storageClient = new AWS.S3(config)
|
|
22
|
-
return storageClient
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return {
|
|
26
|
-
handleUpload: getHandleUpload({
|
|
27
|
-
collection,
|
|
28
|
-
getStorageClient,
|
|
29
|
-
bucket,
|
|
30
|
-
acl,
|
|
31
|
-
prefix,
|
|
32
|
-
}),
|
|
33
|
-
handleDelete: getHandleDelete({ getStorageClient, bucket }),
|
|
34
|
-
generateURL: getGenerateURL({ bucket, config }),
|
|
35
|
-
staticHandler: getHandler({ bucket, getStorageClient, collection }),
|
|
36
|
-
webpack: extendWebpackConfig,
|
|
37
|
-
}
|
|
38
|
-
}
|
package/src/adapters/s3/mock.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
exports.S3 = () => null
|
|
2
|
-
exports.Upload = () => null
|
|
3
|
-
|
|
4
|
-
exports.HeadObjectCommand = () => null
|
|
5
|
-
exports.PutObjectCommand = () => null
|
|
6
|
-
exports.UploadPartCommand = () => null
|
|
7
|
-
exports.CreateMultipartUploadCommand = () => null
|
|
8
|
-
exports.CompleteMultipartUploadCommand = () => null
|
|
9
|
-
exports.PutObjectTaggingCommand = () => null
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type { Readable } from 'stream'
|
|
3
|
-
import type * as AWS from '@aws-sdk/client-s3'
|
|
4
|
-
import type { CollectionConfig } from 'payload/types'
|
|
5
|
-
import type { StaticHandler } from '../../types'
|
|
6
|
-
import { getFilePrefix } from '../../utilities/getFilePrefix'
|
|
7
|
-
|
|
8
|
-
interface Args {
|
|
9
|
-
getStorageClient: () => AWS.S3
|
|
10
|
-
bucket: string
|
|
11
|
-
collection: CollectionConfig
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const getHandler = ({ getStorageClient, bucket, collection }: Args): StaticHandler => {
|
|
15
|
-
return async (req, res, next) => {
|
|
16
|
-
try {
|
|
17
|
-
const prefix = await getFilePrefix({ req, collection })
|
|
18
|
-
|
|
19
|
-
const object = await getStorageClient().getObject({
|
|
20
|
-
Bucket: bucket,
|
|
21
|
-
Key: path.posix.join(prefix, req.params.filename),
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
res.set({
|
|
25
|
-
'Content-Length': object.ContentLength,
|
|
26
|
-
'Content-Type': object.ContentType,
|
|
27
|
-
ETag: object.ETag,
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
if (object?.Body) {
|
|
31
|
-
return (object.Body as Readable).pipe(res)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return next()
|
|
35
|
-
} catch (err: unknown) {
|
|
36
|
-
req.payload.logger.error(err)
|
|
37
|
-
return next()
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { Configuration as WebpackConfig } from 'webpack'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
|
|
4
|
-
export const extendWebpackConfig = (existingWebpackConfig: WebpackConfig): WebpackConfig => {
|
|
5
|
-
const newConfig: WebpackConfig = {
|
|
6
|
-
...existingWebpackConfig,
|
|
7
|
-
resolve: {
|
|
8
|
-
...(existingWebpackConfig.resolve || {}),
|
|
9
|
-
alias: {
|
|
10
|
-
...(existingWebpackConfig.resolve?.alias ? existingWebpackConfig.resolve.alias : {}),
|
|
11
|
-
'@aws-sdk/client-s3': path.resolve(__dirname, './mock.js'),
|
|
12
|
-
'@aws-sdk/lib-storage': path.resolve(__dirname, './mock.js'),
|
|
13
|
-
fs: path.resolve(__dirname, './fileStub.js'),
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return newConfig
|
|
19
|
-
}
|