@payloadcms/plugin-cloud-storage 1.0.19 → 1.1.0-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.
Files changed (171) hide show
  1. package/.editorconfig +10 -0
  2. package/.gitignore +248 -0
  3. package/.prettierignore +1 -0
  4. package/.prettierrc.js +8 -0
  5. package/.vscode/launch.json +40 -0
  6. package/.vscode/settings.json +9 -0
  7. package/dev/.env +21 -0
  8. package/dev/.env.example +21 -0
  9. package/dev/dist/dev/src/collections/Media.js +56 -0
  10. package/dev/dist/dev/src/collections/Media.js.map +1 -0
  11. package/dev/dist/dev/src/collections/Users.js +23 -0
  12. package/dev/dist/dev/src/collections/Users.js.map +1 -0
  13. package/dev/dist/dev/src/payload.config.js +153 -0
  14. package/dev/dist/dev/src/payload.config.js.map +1 -0
  15. package/dev/dist/dev/src/server.js +26 -0
  16. package/dev/dist/dev/src/server.js.map +1 -0
  17. package/dev/dist/src/adapters/azure/generateURL.js +16 -0
  18. package/dev/dist/src/adapters/azure/generateURL.js.map +1 -0
  19. package/dev/dist/src/adapters/azure/handleDelete.js +64 -0
  20. package/dev/dist/src/adapters/azure/handleDelete.js.map +1 -0
  21. package/dev/dist/src/adapters/azure/handleUpload.js +81 -0
  22. package/dev/dist/src/adapters/azure/handleUpload.js.map +1 -0
  23. package/dev/dist/src/adapters/azure/index.js +43 -0
  24. package/dev/dist/src/adapters/azure/index.js.map +1 -0
  25. package/dev/dist/src/adapters/azure/staticHandler.js +82 -0
  26. package/dev/dist/src/adapters/azure/staticHandler.js.map +1 -0
  27. package/dev/dist/src/adapters/azure/webpack.js +25 -0
  28. package/dev/dist/src/adapters/azure/webpack.js.map +1 -0
  29. package/dev/dist/src/adapters/gcs/generateURL.js +16 -0
  30. package/dev/dist/src/adapters/gcs/generateURL.js.map +1 -0
  31. package/dev/dist/src/adapters/gcs/handleDelete.js +63 -0
  32. package/dev/dist/src/adapters/gcs/handleDelete.js.map +1 -0
  33. package/dev/dist/src/adapters/gcs/handleUpload.js +73 -0
  34. package/dev/dist/src/adapters/gcs/handleUpload.js.map +1 -0
  35. package/dev/dist/src/adapters/gcs/index.js +36 -0
  36. package/dev/dist/src/adapters/gcs/index.js.map +1 -0
  37. package/dev/dist/src/adapters/gcs/staticHandler.js +77 -0
  38. package/dev/dist/src/adapters/gcs/staticHandler.js.map +1 -0
  39. package/dev/dist/src/adapters/gcs/webpack.js +25 -0
  40. package/dev/dist/src/adapters/gcs/webpack.js.map +1 -0
  41. package/dev/dist/src/adapters/s3/generateURL.js +16 -0
  42. package/dev/dist/src/adapters/s3/generateURL.js.map +1 -0
  43. package/dev/dist/src/adapters/s3/handleDelete.js +64 -0
  44. package/dev/dist/src/adapters/s3/handleDelete.js.map +1 -0
  45. package/dev/dist/src/adapters/s3/handleUpload.js +94 -0
  46. package/dev/dist/src/adapters/s3/handleUpload.js.map +1 -0
  47. package/dev/dist/src/adapters/s3/index.js +60 -0
  48. package/dev/dist/src/adapters/s3/index.js.map +1 -0
  49. package/dev/dist/src/adapters/s3/staticHandler.js +82 -0
  50. package/dev/dist/src/adapters/s3/staticHandler.js.map +1 -0
  51. package/dev/dist/src/adapters/s3/webpack.js +25 -0
  52. package/dev/dist/src/adapters/s3/webpack.js.map +1 -0
  53. package/dev/dist/src/fields/getFields.js +119 -0
  54. package/dev/dist/src/fields/getFields.js.map +1 -0
  55. package/dev/dist/src/hooks/afterDelete.js +92 -0
  56. package/dev/dist/src/hooks/afterDelete.js.map +1 -0
  57. package/dev/dist/src/hooks/afterRead.js +80 -0
  58. package/dev/dist/src/hooks/afterRead.js.map +1 -0
  59. package/dev/dist/src/hooks/beforeChange.js +106 -0
  60. package/dev/dist/src/hooks/beforeChange.js.map +1 -0
  61. package/dev/dist/src/index.js +6 -0
  62. package/dev/dist/src/index.js.map +1 -0
  63. package/dev/dist/src/plugin.js +131 -0
  64. package/dev/dist/src/plugin.js.map +1 -0
  65. package/{dist/adapters/s3/fileStub.js → dev/dist/src/types.js} +1 -2
  66. package/dev/dist/src/types.js.map +1 -0
  67. package/dev/dist/src/utilities/getFilePrefix.js +81 -0
  68. package/dev/dist/src/utilities/getFilePrefix.js.map +1 -0
  69. package/dev/dist/src/utilities/getIncomingFiles.js +38 -0
  70. package/dev/dist/src/utilities/getIncomingFiles.js.map +1 -0
  71. package/dev/dist/src/utilities/getRangeFromHeader.js +67 -0
  72. package/dev/dist/src/utilities/getRangeFromHeader.js.map +1 -0
  73. package/dev/dist/src/webpack.js +40 -0
  74. package/dev/dist/src/webpack.js.map +1 -0
  75. package/dev/nodemon.json +8 -0
  76. package/dev/package.json +34 -0
  77. package/dev/src/collections/Media.ts +56 -0
  78. package/dev/src/collections/Users.ts +23 -0
  79. package/dev/src/mocks/fsMock.js +1 -0
  80. package/dev/src/mocks/promisifyMock.js +1 -0
  81. package/dev/src/payload.config.ts +123 -0
  82. package/dev/src/server.ts +26 -0
  83. package/dev/tmp/tmp-1-1688568985997 +0 -0
  84. package/dev/tmp/tmp-2-1687546883112 +0 -0
  85. package/dev/tsconfig.json +20 -0
  86. package/dist/adapters/azure/mock.d.ts +1 -13
  87. package/dist/adapters/azure/mock.js +4 -11
  88. package/dist/adapters/azure/mock.js.map +1 -1
  89. package/dist/adapters/azure/webpack.js +1 -1
  90. package/dist/adapters/azure/webpack.js.map +1 -1
  91. package/dist/adapters/gcs/index.d.ts +1 -1
  92. package/dist/adapters/gcs/index.js +2 -1
  93. package/dist/adapters/gcs/index.js.map +1 -1
  94. package/dist/adapters/gcs/mock.d.ts +1 -1
  95. package/dist/adapters/gcs/mock.js +4 -3
  96. package/dist/adapters/gcs/mock.js.map +1 -1
  97. package/dist/adapters/s3/mock.d.ts +1 -8
  98. package/dist/adapters/s3/mock.js +4 -8
  99. package/dist/adapters/s3/mock.js.map +1 -1
  100. package/dist/adapters/s3/webpack.js +1 -1
  101. package/dist/adapters/s3/webpack.js.map +1 -1
  102. package/dist/admin/fields/getFields.d.ts +7 -0
  103. package/dist/admin/fields/getFields.js +102 -0
  104. package/dist/admin/fields/getFields.js.map +1 -0
  105. package/dist/admin/index.d.ts +3 -0
  106. package/dist/admin/index.js +40 -0
  107. package/dist/admin/index.js.map +1 -0
  108. package/dist/fields/getFields.js +1 -1
  109. package/dist/fields/getFields.js.map +1 -1
  110. package/dist/webpack.js +5 -1
  111. package/dist/webpack.js.map +1 -1
  112. package/docs/local-dev.md +47 -0
  113. package/eslint-config/index.js +15 -0
  114. package/eslint-config/rules/import.js +38 -0
  115. package/eslint-config/rules/prettier.js +7 -0
  116. package/eslint-config/rules/style.js +21 -0
  117. package/eslint-config/rules/typescript.js +628 -0
  118. package/package.json +1 -1
  119. package/src/adapters/azure/emulator/docker-compose.yml +16 -0
  120. package/src/adapters/azure/generateURL.ts +13 -0
  121. package/src/adapters/azure/handleDelete.ts +16 -0
  122. package/src/adapters/azure/handleUpload.ts +43 -0
  123. package/src/adapters/azure/index.ts +48 -0
  124. package/src/adapters/azure/mock.js +1 -0
  125. package/src/adapters/azure/staticHandler.ts +38 -0
  126. package/src/adapters/azure/webpack.ts +21 -0
  127. package/src/adapters/gcs/emulator/docker-compose.yml +15 -0
  128. package/src/adapters/gcs/generateURL.ts +16 -0
  129. package/src/adapters/gcs/handleDelete.ts +16 -0
  130. package/src/adapters/gcs/handleUpload.ts +36 -0
  131. package/src/adapters/gcs/index.ts +40 -0
  132. package/src/adapters/gcs/mock.js +1 -0
  133. package/src/adapters/gcs/staticHandler.ts +34 -0
  134. package/src/adapters/gcs/webpack.ts +21 -0
  135. package/src/adapters/s3/emulator/.localstack/cache/machine.json +1 -0
  136. package/src/adapters/s3/emulator/.localstack/cache/server.test.pem +127 -0
  137. package/src/adapters/s3/emulator/.localstack/cache/server.test.pem.crt +99 -0
  138. package/src/adapters/s3/emulator/.localstack/cache/server.test.pem.key +28 -0
  139. package/src/adapters/s3/emulator/.localstack/cache/service-catalog-2_1_1_dev-1_29_149.pickle +0 -0
  140. package/src/adapters/s3/emulator/docker-compose.yml +15 -0
  141. package/src/adapters/s3/generateURL.ts +14 -0
  142. package/src/adapters/s3/handleDelete.ts +17 -0
  143. package/src/adapters/s3/handleUpload.ts +62 -0
  144. package/src/adapters/s3/index.ts +48 -0
  145. package/src/adapters/s3/mock.js +1 -0
  146. package/src/adapters/s3/staticHandler.ts +41 -0
  147. package/src/adapters/s3/webpack.ts +21 -0
  148. package/src/admin/fields/getFields.ts +126 -0
  149. package/src/admin/index.ts +39 -0
  150. package/src/fields/getFields.ts +155 -0
  151. package/src/hooks/afterDelete.ts +35 -0
  152. package/src/hooks/afterRead.ts +38 -0
  153. package/src/hooks/beforeChange.ts +59 -0
  154. package/src/index.ts +1 -0
  155. package/src/plugin.ts +101 -0
  156. package/src/types.ts +79 -0
  157. package/src/utilities/getFilePrefix.ts +26 -0
  158. package/src/utilities/getIncomingFiles.ts +44 -0
  159. package/src/utilities/getRangeFromHeader.ts +27 -0
  160. package/src/webpack.ts +48 -0
  161. package/tsconfig.json +23 -0
  162. package/yarn-error.log +8163 -0
  163. package/yarn.lock +8062 -0
  164. package/dist/adapters/azure/fileStub.d.ts +0 -2
  165. package/dist/adapters/azure/fileStub.js +0 -4
  166. package/dist/adapters/azure/fileStub.js.map +0 -1
  167. package/dist/adapters/s3/fileStub.d.ts +0 -2
  168. package/dist/adapters/s3/fileStub.js.map +0 -1
  169. package/dist/adapters/s3/fsMock.d.ts +0 -3
  170. package/dist/adapters/s3/fsMock.js +0 -3
  171. package/dist/adapters/s3/fsMock.js.map +0 -1
@@ -0,0 +1,16 @@
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
+ }
@@ -0,0 +1,43 @@
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 fileKey = path.posix.join(data.prefix || prefix, file.filename)
19
+
20
+ const blockBlobClient = getStorageClient().getBlockBlobClient(
21
+ fileKey,
22
+ )
23
+
24
+ // when there are no temp files, or the upload is less than the threshold size, do not stream files
25
+ if (!file.tempFilePath && file.buffer.length > 0 && file.buffer.length < multipartThreshold) {
26
+ await blockBlobClient.upload(file.buffer, file.buffer.byteLength, {
27
+ blobHTTPHeaders: { blobContentType: file.mimeType },
28
+ })
29
+
30
+ return data
31
+ }
32
+
33
+ const fileBufferOrStream: Readable = file.tempFilePath
34
+ ? fs.createReadStream(file.tempFilePath)
35
+ : Readable.from(file.buffer)
36
+
37
+ await blockBlobClient.uploadStream(fileBufferOrStream, 4 * 1024 * 1024, 4, {
38
+ abortSignal: AbortController.timeout(30 * 60 * 1000),
39
+ })
40
+
41
+ return data
42
+ }
43
+ }
@@ -0,0 +1,48 @@
1
+ import type { ContainerClient } from '@azure/storage-blob'
2
+ import { BlobServiceClient } from '@azure/storage-blob'
3
+ import type { Adapter, GeneratedAdapter } from '../../types'
4
+ import { getHandler } from './staticHandler'
5
+ import { getGenerateURL } from './generateURL'
6
+ import { getHandleDelete } from './handleDelete'
7
+ import { getHandleUpload } from './handleUpload'
8
+ import { extendWebpackConfig } from './webpack'
9
+
10
+ export interface Args {
11
+ connectionString: string
12
+ containerName: string
13
+ baseURL: string
14
+ allowContainerCreate: boolean
15
+ }
16
+
17
+ export const azureBlobStorageAdapter = ({
18
+ connectionString,
19
+ allowContainerCreate,
20
+ containerName,
21
+ baseURL,
22
+ }: Args): Adapter => {
23
+ let storageClient: ContainerClient | null = null
24
+ const getStorageClient = () => {
25
+ if (storageClient) return storageClient
26
+ const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString)
27
+ return (storageClient = blobServiceClient.getContainerClient(containerName))
28
+ }
29
+
30
+ const createContainerIfNotExists = () => {
31
+ getStorageClient().createIfNotExists({ access: 'blob' })
32
+ }
33
+
34
+ return ({ collection, prefix }): GeneratedAdapter => {
35
+ return {
36
+ handleUpload: getHandleUpload({
37
+ collection,
38
+ getStorageClient,
39
+ prefix,
40
+ }),
41
+ handleDelete: getHandleDelete({ collection, getStorageClient }),
42
+ generateURL: getGenerateURL({ containerName, baseURL }),
43
+ staticHandler: getHandler({ getStorageClient, collection }),
44
+ webpack: extendWebpackConfig,
45
+ ...(allowContainerCreate && { onInit: createContainerIfNotExists }),
46
+ }
47
+ }
48
+ }
@@ -0,0 +1 @@
1
+ export const azureBlobStorageAdapter = () => ({})
@@ -0,0 +1,38 @@
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
+ }
@@ -0,0 +1,21 @@
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
+ fallback: {
10
+ ...(existingWebpackConfig.resolve?.fallback ? existingWebpackConfig.resolve.fallback : {}),
11
+ stream: false,
12
+ },
13
+ alias: {
14
+ ...(existingWebpackConfig.resolve?.alias ? existingWebpackConfig.resolve.alias : {}),
15
+ '@payloadcms/plugin-cloud-storage/azure': path.resolve(__dirname, './mock.js'),
16
+ },
17
+ },
18
+ }
19
+
20
+ return newConfig
21
+ }
@@ -0,0 +1,15 @@
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
+
@@ -0,0 +1,16 @@
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
+ }
@@ -0,0 +1,16 @@
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
+ }
@@ -0,0 +1,36 @@
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 fileKey = path.posix.join(data.prefix || prefix, file.filename)
22
+
23
+ const gcsFile = getStorageClient().bucket(bucket).file(fileKey)
24
+ await gcsFile.save(file.buffer, {
25
+ metadata: {
26
+ contentType: file.mimeType,
27
+ },
28
+ })
29
+
30
+ if (acl) {
31
+ await gcsFile[`make${acl}`]()
32
+ }
33
+
34
+ return data
35
+ }
36
+ }
@@ -0,0 +1,40 @@
1
+ import type { StorageOptions } from '@google-cloud/storage'
2
+ import { Storage } from '@google-cloud/storage'
3
+ import type { Adapter, GeneratedAdapter } from '../../types'
4
+ import { getGenerateURL } from './generateURL'
5
+ import { getHandler } from './staticHandler'
6
+ import { getHandleDelete } from './handleDelete'
7
+ import { getHandleUpload } from './handleUpload'
8
+ import { extendWebpackConfig } from './webpack'
9
+
10
+ export interface Args {
11
+ options: StorageOptions
12
+ bucket: string
13
+ acl?: 'Private' | 'Public'
14
+ }
15
+
16
+ export const gcsAdapter =
17
+ ({ options, bucket, acl }: Args): Adapter =>
18
+ ({ collection, prefix }): GeneratedAdapter => {
19
+ let storageClient: Storage | null = null
20
+
21
+ const getStorageClient = (): Storage => {
22
+ if (storageClient) return storageClient
23
+ storageClient = new Storage(options)
24
+ return storageClient
25
+ }
26
+
27
+ return {
28
+ handleUpload: getHandleUpload({
29
+ collection,
30
+ getStorageClient,
31
+ bucket,
32
+ acl,
33
+ prefix,
34
+ }),
35
+ handleDelete: getHandleDelete({ getStorageClient, bucket }),
36
+ generateURL: getGenerateURL({ getStorageClient, bucket }),
37
+ staticHandler: getHandler({ getStorageClient, bucket, collection }),
38
+ webpack: extendWebpackConfig,
39
+ }
40
+ }
@@ -0,0 +1 @@
1
+ export const gcsAdapter = () => ({})
@@ -0,0 +1,34 @@
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
+ }
@@ -0,0 +1,21 @@
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
+ fallback: {
10
+ ...(existingWebpackConfig.resolve?.fallback ? existingWebpackConfig.resolve.fallback : {}),
11
+ stream: false,
12
+ },
13
+ alias: {
14
+ ...(existingWebpackConfig.resolve?.alias ? existingWebpackConfig.resolve.alias : {}),
15
+ '@google-cloud/storage': path.resolve(__dirname, './mock.js'),
16
+ },
17
+ },
18
+ }
19
+
20
+ return newConfig
21
+ }
@@ -0,0 +1 @@
1
+ {"machine_id": "22a7ad76"}
@@ -0,0 +1,127 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCaPWhTRm/+I3kq
3
+ KZkATLlXtZBGACSvPcJKs/xo1YZX1uCm9mI2/21sqXSArd89lPNJky3LzJavUpRk
4
+ EAZunryuqB6ktxiDU5lG5AihlRXOHPdGDhMSCtyuhgqawY316H/n1LeYt/vjDJ9d
5
+ Qq4CE0vUQMI4OApo3b74Ww2G+xxPoqjPiGCc4L1zdiUKYZm2cxk6tyy89udTbfZu
6
+ pKGqFYQYOMVxh1EVOayg9HExHJV2woYyPNF4LIF5zrqt6VVGyiVnFTnWCMCa2Wky
7
+ p33E76w5PgaDpUhORdwYqMkmAlMnAiFrxmtc4OKoYOZoCP7+tqKLndBvUpWdfMp4
8
+ a4BEyMStAgMBAAECggEAWG8tCdIxFD2ykwIWv50+B5QKjJg4cGGwrLRV3KXQyTxi
9
+ wlgyJ+Z8Dvl52u3WObDVbTH96AP9wbhPbK/jgDlzZZDvQPHaFDIyh/rnF/4q6mqh
10
+ PIGFXarsrQQdwG2Jv5z2+S11txKGUcBC/23j5zy5FZGryiAXl9jMTgmmz+Xaba2p
11
+ rrlwCkbf5NTRSmMrM6i5n7D6bqqE9xm+zdowzX6IxvQN+GwnqH/gebC9Bbt8ZXW8
12
+ MmAvz8odX3PQznSmS7QkvL6YdRonj/XQts1BgoC/zb4zvhRIBxNJGKmu//7nyyFc
13
+ 4/5i1T1YXSMW8W602xRLc/A9hLek6g9XeLAF/g6i4QKBgQDNbTOprhMMEprNxnFM
14
+ BkxByERNRVAE7HujRoMlbwPGpaBbUNpYfoc5EAAgc0QjXAeONU/++L5uyR/J12vM
15
+ jGo05DF0HXfhzXEcwG3qw+/xYM2nO76iQtoJESCs+k3N/HKmsIIK58md35v32CEy
16
+ iPvOSYVTeyNGCvXVtq7jN9M4VwKBgQDANjeCa9cpXlFMQt9si3HNMpuuXNt0dXQA
17
+ XqB8c24GcbC+ab/iDBl0iV7ErftQJIa+YLCi3Me/476U0k+cPNaI5TCx6UYPg3cC
18
+ gkM4GEGbrhqTFXxTjxPbA7KR8KNoX/ckzGnGFJ6dm2Y7izv2eCyyFVLZyv/9wH+k
19
+ a1pohd6YmwKBgCtuix200BIdXN1kt097hWPjE43CuchQt1Mt9UxUzFeTbPPhhEhx
20
+ d+V4nI4/0IgpTO+kFeWycZC6tR3XjdMRXOMR2+LQ2CfFZ8TManDYPEKsVM6mswdb
21
+ Wv3PwTjRMuH6HcNgTh5AI0BdpnwgFeS5UYOrx6R+xFZqus8UcKVZiC7BAoGAe4Jb
22
+ KPMizvJMSzStXJI+Dhz27JO+cJcIczRa651AleN4LuLE6fvcX4Xl33vsgRL3gl2f
23
+ Iwe7UxKE5BxAC6UMNesP30KGQnG3h2UszF7Jyb+WU+z6drb5i0JU/HIkjm0b4gl3
24
+ 7lBRm/S/PIO7hCS0k7ogAtLuq5+GZaCV95QN9QECgYAjRQbu8TPcs7HXLkqNZuQU
25
+ JEcSa3oihbkvWODbKLktWm9V+MpRpf3L60G/PSFcWe5X1ronYMxXDu26upsxa8l4
26
+ lsSmvaZsN/Mi50bGVYFaqBtHOGM93r2LXX8n17RV8SeORIFtUW+I4HlhRoAQtdHG
27
+ ffRxPAr0bF9ix2ehkJQW4A==
28
+ -----END PRIVATE KEY-----
29
+ -----BEGIN CERTIFICATE-----
30
+ MIIGnjCCBYagAwIBAgISBP01h2GLqWhtt2kfNROuC+1gMA0GCSqGSIb3DQEBCwUA
31
+ MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
32
+ EwJSMzAeFw0yMzAzMjgyMTE0MDVaFw0yMzA2MjYyMTE0MDRaMDIxMDAuBgNVBAMM
33
+ JyouYW1wbGlmeWFwcC5sb2NhbGhvc3QubG9jYWxzdGFjay5jbG91ZDCCASIwDQYJ
34
+ KoZIhvcNAQEBBQADggEPADCCAQoCggEBAJo9aFNGb/4jeSopmQBMuVe1kEYAJK89
35
+ wkqz/GjVhlfW4Kb2Yjb/bWypdICt3z2U80mTLcvMlq9SlGQQBm6evK6oHqS3GINT
36
+ mUbkCKGVFc4c90YOExIK3K6GCprBjfXof+fUt5i3++MMn11CrgITS9RAwjg4Cmjd
37
+ vvhbDYb7HE+iqM+IYJzgvXN2JQphmbZzGTq3LLz251Nt9m6koaoVhBg4xXGHURU5
38
+ rKD0cTEclXbChjI80XgsgXnOuq3pVUbKJWcVOdYIwJrZaTKnfcTvrDk+BoOlSE5F
39
+ 3BioySYCUycCIWvGa1zg4qhg5mgI/v62ooud0G9SlZ18ynhrgETIxK0CAwEAAaOC
40
+ A6wwggOoMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB
41
+ BQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUGcegmIXfOIoNR2owsgQkS0zC
42
+ v5cwHwYDVR0jBBgwFoAUFC6zF7dYVsuuUAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEE
43
+ STBHMCEGCCsGAQUFBzABhhVodHRwOi8vcjMuby5sZW5jci5vcmcwIgYIKwYBBQUH
44
+ MAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9yZy8wggF6BgNVHREEggFxMIIBbYInKi5h
45
+ bXBsaWZ5YXBwLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgicqLmNsb3VkZnJv
46
+ bnQubG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCICouZWxiLmxvY2FsaG9zdC5s
47
+ b2NhbHN0YWNrLmNsb3VkgigqLmV4ZWN1dGUtYXBpLmxvY2FsaG9zdC5sb2NhbHN0
48
+ YWNrLmNsb3VkghwqLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgicqLm9wZW5z
49
+ ZWFyY2gubG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCJyouczMtd2Vic2l0ZS5s
50
+ b2NhbGhvc3QubG9jYWxzdGFjay5jbG91ZIIfKi5zMy5sb2NhbGhvc3QubG9jYWxz
51
+ dGFjay5jbG91ZIIgKi5zY20ubG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCGmxv
52
+ Y2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcG
53
+ CysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5
54
+ cHQub3JnMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHYAejKMVNi3LbYg6jjgUh7p
55
+ hBZwMhOFTTvSK8E6V6NS61IAAAGHKkkVgwAABAMARzBFAiEAzEZtyk7PSZ4v/rd5
56
+ hmjTaO7iVf7zGyTHDge2EHwXXmMCIAyXJu07nplXKF+BRKGMU2o6BIczdLRolNe1
57
+ UwgkJwWsAHYA6D7Q2j71BjUy51covIlryQPTy9ERa+zraeF3fW0GvW4AAAGHKkkV
58
+ fAAABAMARzBFAiEAgguUGxdQScQtffmvnT6rEgvHmTU64SnTXKkdZhvkX2cCIEay
59
+ SFS/7ndCLwZtkvfPRoZEQwifFWCOCE77mbyBaC+SMA0GCSqGSIb3DQEBCwUAA4IB
60
+ AQAcBhzd5jQFtE4tlgug5d0xMynPipw55GT3q/8kW/x5SLJG9vckJMZwsbtt+f9l
61
+ B0OtEPaeias8+U8iJnMhfIz1pFGY0ZYipcl6/OsqjdiR3UJMJYGCQrGjeIahXPD6
62
+ PMrrP5/k103U/Lyxq8+BzVKp5orLp4Qc/kJ+JwXbXJvs5+f8eGDbKQW+s1wrPJK3
63
+ A7uESMqyVV4hC9oepqIsZJ+Viod9YKEGtRgJygJixPbgyUl8WRSpCQc/vhdfjW5/
64
+ Shf4CKRYULu/UKB63n8uaQ6vbvUZF4DKau9898DXRzDHo0ADI9gE0X3EN7BHsUjB
65
+ pLF5oIqUc4XhS0f86j4lMenn
66
+ -----END CERTIFICATE-----
67
+ -----BEGIN CERTIFICATE-----
68
+ MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
69
+ TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
70
+ cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
71
+ WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
72
+ RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
73
+ AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
74
+ R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
75
+ sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
76
+ NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
77
+ Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
78
+ /kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
79
+ AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
80
+ Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
81
+ FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
82
+ AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
83
+ Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
84
+ gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
85
+ PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
86
+ ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
87
+ CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
88
+ lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
89
+ avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
90
+ yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
91
+ yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
92
+ hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
93
+ HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
94
+ MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
95
+ nLRbwHOoq7hHwg==
96
+ -----END CERTIFICATE-----
97
+ -----BEGIN CERTIFICATE-----
98
+ MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
99
+ MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
100
+ DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
101
+ TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
102
+ cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
103
+ AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
104
+ ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
105
+ wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
106
+ LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
107
+ 4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
108
+ bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
109
+ sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
110
+ Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
111
+ FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
112
+ SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
113
+ PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
114
+ TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
115
+ SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
116
+ c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
117
+ +tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
118
+ ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
119
+ b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
120
+ U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
121
+ MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
122
+ 5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
123
+ 9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
124
+ WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
125
+ he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
126
+ Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
127
+ -----END CERTIFICATE-----
@@ -0,0 +1,99 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIGnjCCBYagAwIBAgISBP01h2GLqWhtt2kfNROuC+1gMA0GCSqGSIb3DQEBCwUA
3
+ MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
4
+ EwJSMzAeFw0yMzAzMjgyMTE0MDVaFw0yMzA2MjYyMTE0MDRaMDIxMDAuBgNVBAMM
5
+ JyouYW1wbGlmeWFwcC5sb2NhbGhvc3QubG9jYWxzdGFjay5jbG91ZDCCASIwDQYJ
6
+ KoZIhvcNAQEBBQADggEPADCCAQoCggEBAJo9aFNGb/4jeSopmQBMuVe1kEYAJK89
7
+ wkqz/GjVhlfW4Kb2Yjb/bWypdICt3z2U80mTLcvMlq9SlGQQBm6evK6oHqS3GINT
8
+ mUbkCKGVFc4c90YOExIK3K6GCprBjfXof+fUt5i3++MMn11CrgITS9RAwjg4Cmjd
9
+ vvhbDYb7HE+iqM+IYJzgvXN2JQphmbZzGTq3LLz251Nt9m6koaoVhBg4xXGHURU5
10
+ rKD0cTEclXbChjI80XgsgXnOuq3pVUbKJWcVOdYIwJrZaTKnfcTvrDk+BoOlSE5F
11
+ 3BioySYCUycCIWvGa1zg4qhg5mgI/v62ooud0G9SlZ18ynhrgETIxK0CAwEAAaOC
12
+ A6wwggOoMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB
13
+ BQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUGcegmIXfOIoNR2owsgQkS0zC
14
+ v5cwHwYDVR0jBBgwFoAUFC6zF7dYVsuuUAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEE
15
+ STBHMCEGCCsGAQUFBzABhhVodHRwOi8vcjMuby5sZW5jci5vcmcwIgYIKwYBBQUH
16
+ MAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9yZy8wggF6BgNVHREEggFxMIIBbYInKi5h
17
+ bXBsaWZ5YXBwLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgicqLmNsb3VkZnJv
18
+ bnQubG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCICouZWxiLmxvY2FsaG9zdC5s
19
+ b2NhbHN0YWNrLmNsb3VkgigqLmV4ZWN1dGUtYXBpLmxvY2FsaG9zdC5sb2NhbHN0
20
+ YWNrLmNsb3VkghwqLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgicqLm9wZW5z
21
+ ZWFyY2gubG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCJyouczMtd2Vic2l0ZS5s
22
+ b2NhbGhvc3QubG9jYWxzdGFjay5jbG91ZIIfKi5zMy5sb2NhbGhvc3QubG9jYWxz
23
+ dGFjay5jbG91ZIIgKi5zY20ubG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCGmxv
24
+ Y2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcG
25
+ CysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5
26
+ cHQub3JnMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHYAejKMVNi3LbYg6jjgUh7p
27
+ hBZwMhOFTTvSK8E6V6NS61IAAAGHKkkVgwAABAMARzBFAiEAzEZtyk7PSZ4v/rd5
28
+ hmjTaO7iVf7zGyTHDge2EHwXXmMCIAyXJu07nplXKF+BRKGMU2o6BIczdLRolNe1
29
+ UwgkJwWsAHYA6D7Q2j71BjUy51covIlryQPTy9ERa+zraeF3fW0GvW4AAAGHKkkV
30
+ fAAABAMARzBFAiEAgguUGxdQScQtffmvnT6rEgvHmTU64SnTXKkdZhvkX2cCIEay
31
+ SFS/7ndCLwZtkvfPRoZEQwifFWCOCE77mbyBaC+SMA0GCSqGSIb3DQEBCwUAA4IB
32
+ AQAcBhzd5jQFtE4tlgug5d0xMynPipw55GT3q/8kW/x5SLJG9vckJMZwsbtt+f9l
33
+ B0OtEPaeias8+U8iJnMhfIz1pFGY0ZYipcl6/OsqjdiR3UJMJYGCQrGjeIahXPD6
34
+ PMrrP5/k103U/Lyxq8+BzVKp5orLp4Qc/kJ+JwXbXJvs5+f8eGDbKQW+s1wrPJK3
35
+ A7uESMqyVV4hC9oepqIsZJ+Viod9YKEGtRgJygJixPbgyUl8WRSpCQc/vhdfjW5/
36
+ Shf4CKRYULu/UKB63n8uaQ6vbvUZF4DKau9898DXRzDHo0ADI9gE0X3EN7BHsUjB
37
+ pLF5oIqUc4XhS0f86j4lMenn
38
+ -----END CERTIFICATE-----
39
+ -----BEGIN CERTIFICATE-----
40
+ MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
41
+ TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
42
+ cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
43
+ WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
44
+ RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
45
+ AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
46
+ R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
47
+ sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
48
+ NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
49
+ Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
50
+ /kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
51
+ AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
52
+ Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
53
+ FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
54
+ AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
55
+ Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
56
+ gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
57
+ PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
58
+ ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
59
+ CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
60
+ lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
61
+ avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
62
+ yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
63
+ yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
64
+ hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
65
+ HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
66
+ MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
67
+ nLRbwHOoq7hHwg==
68
+ -----END CERTIFICATE-----
69
+ -----BEGIN CERTIFICATE-----
70
+ MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
71
+ MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
72
+ DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
73
+ TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
74
+ cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
75
+ AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
76
+ ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
77
+ wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
78
+ LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
79
+ 4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
80
+ bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
81
+ sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
82
+ Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
83
+ FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
84
+ SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
85
+ PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
86
+ TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
87
+ SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
88
+ c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
89
+ +tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
90
+ ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
91
+ b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
92
+ U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
93
+ MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
94
+ 5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
95
+ 9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
96
+ WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
97
+ he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
98
+ Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
99
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCaPWhTRm/+I3kq
3
+ KZkATLlXtZBGACSvPcJKs/xo1YZX1uCm9mI2/21sqXSArd89lPNJky3LzJavUpRk
4
+ EAZunryuqB6ktxiDU5lG5AihlRXOHPdGDhMSCtyuhgqawY316H/n1LeYt/vjDJ9d
5
+ Qq4CE0vUQMI4OApo3b74Ww2G+xxPoqjPiGCc4L1zdiUKYZm2cxk6tyy89udTbfZu
6
+ pKGqFYQYOMVxh1EVOayg9HExHJV2woYyPNF4LIF5zrqt6VVGyiVnFTnWCMCa2Wky
7
+ p33E76w5PgaDpUhORdwYqMkmAlMnAiFrxmtc4OKoYOZoCP7+tqKLndBvUpWdfMp4
8
+ a4BEyMStAgMBAAECggEAWG8tCdIxFD2ykwIWv50+B5QKjJg4cGGwrLRV3KXQyTxi
9
+ wlgyJ+Z8Dvl52u3WObDVbTH96AP9wbhPbK/jgDlzZZDvQPHaFDIyh/rnF/4q6mqh
10
+ PIGFXarsrQQdwG2Jv5z2+S11txKGUcBC/23j5zy5FZGryiAXl9jMTgmmz+Xaba2p
11
+ rrlwCkbf5NTRSmMrM6i5n7D6bqqE9xm+zdowzX6IxvQN+GwnqH/gebC9Bbt8ZXW8
12
+ MmAvz8odX3PQznSmS7QkvL6YdRonj/XQts1BgoC/zb4zvhRIBxNJGKmu//7nyyFc
13
+ 4/5i1T1YXSMW8W602xRLc/A9hLek6g9XeLAF/g6i4QKBgQDNbTOprhMMEprNxnFM
14
+ BkxByERNRVAE7HujRoMlbwPGpaBbUNpYfoc5EAAgc0QjXAeONU/++L5uyR/J12vM
15
+ jGo05DF0HXfhzXEcwG3qw+/xYM2nO76iQtoJESCs+k3N/HKmsIIK58md35v32CEy
16
+ iPvOSYVTeyNGCvXVtq7jN9M4VwKBgQDANjeCa9cpXlFMQt9si3HNMpuuXNt0dXQA
17
+ XqB8c24GcbC+ab/iDBl0iV7ErftQJIa+YLCi3Me/476U0k+cPNaI5TCx6UYPg3cC
18
+ gkM4GEGbrhqTFXxTjxPbA7KR8KNoX/ckzGnGFJ6dm2Y7izv2eCyyFVLZyv/9wH+k
19
+ a1pohd6YmwKBgCtuix200BIdXN1kt097hWPjE43CuchQt1Mt9UxUzFeTbPPhhEhx
20
+ d+V4nI4/0IgpTO+kFeWycZC6tR3XjdMRXOMR2+LQ2CfFZ8TManDYPEKsVM6mswdb
21
+ Wv3PwTjRMuH6HcNgTh5AI0BdpnwgFeS5UYOrx6R+xFZqus8UcKVZiC7BAoGAe4Jb
22
+ KPMizvJMSzStXJI+Dhz27JO+cJcIczRa651AleN4LuLE6fvcX4Xl33vsgRL3gl2f
23
+ Iwe7UxKE5BxAC6UMNesP30KGQnG3h2UszF7Jyb+WU+z6drb5i0JU/HIkjm0b4gl3
24
+ 7lBRm/S/PIO7hCS0k7ogAtLuq5+GZaCV95QN9QECgYAjRQbu8TPcs7HXLkqNZuQU
25
+ JEcSa3oihbkvWODbKLktWm9V+MpRpf3L60G/PSFcWe5X1ronYMxXDu26upsxa8l4
26
+ lsSmvaZsN/Mi50bGVYFaqBtHOGM93r2LXX8n17RV8SeORIFtUW+I4HlhRoAQtdHG
27
+ ffRxPAr0bF9ix2ehkJQW4A==
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,15 @@
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'
@@ -0,0 +1,14 @@
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
+ }