From a61556d75bab9a1d6381a23d7b8a47ec068f837b Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sat, 11 Feb 2023 23:38:23 +0100 Subject: [PATCH 01/12] feat: install dependencies and setup the basics --- dev/package.json | 3 + dev/src/payload.config.ts | 19 +++- package.json | 8 +- src/adapters/supabase/generateURL.ts | 0 src/adapters/supabase/handleDelete.ts | 0 src/adapters/supabase/handleUpload.ts | 0 src/adapters/supabase/index.ts | 23 +++++ src/adapters/supabase/mock.js | 2 + src/adapters/supabase/staticHandler.ts | 0 src/adapters/supabase/webpack.ts | 18 ++++ yarn.lock | 117 ++++++++++++++++++++++++- 11 files changed, 184 insertions(+), 6 deletions(-) create mode 100644 src/adapters/supabase/generateURL.ts create mode 100644 src/adapters/supabase/handleDelete.ts create mode 100644 src/adapters/supabase/handleUpload.ts create mode 100644 src/adapters/supabase/index.ts create mode 100644 src/adapters/supabase/mock.js create mode 100644 src/adapters/supabase/staticHandler.ts create mode 100644 src/adapters/supabase/webpack.ts diff --git a/dev/package.json b/dev/package.json index 50641eb..e7610ab 100644 --- a/dev/package.json +++ b/dev/package.json @@ -5,9 +5,11 @@ "license": "MIT", "private": true, "scripts": { + "dev": "nodemon", "dev:azure": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER=azure nodemon", "dev:s3": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER=s3 nodemon", "dev:gcs": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER=gcs nodemon", + "dev:supabase": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER=supabase nodemon", "build:payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload build", "build:server": "tsc", "build": "yarn build:payload && yarn build:server", @@ -18,6 +20,7 @@ "@aws-sdk/client-s3": "^3.142.0", "@azure/storage-blob": "^12.11.0", "@google-cloud/storage": "^6.4.2", + "@supabase/supabase-js": "^2.7.1", "dotenv": "^8.2.0", "express": "^4.17.1", "payload": "^1.6.6" diff --git a/dev/src/payload.config.ts b/dev/src/payload.config.ts index f6e792b..48cfcbb 100644 --- a/dev/src/payload.config.ts +++ b/dev/src/payload.config.ts @@ -1,16 +1,26 @@ -import { buildConfig } from 'payload/config' import path from 'path' -import Users from './collections/Users' +import { buildConfig } from 'payload/config' import { cloudStorage } from '../../src' -import { s3Adapter } from '../../src/adapters/s3' -import { gcsAdapter } from '../../src/adapters/gcs' import { azureBlobStorageAdapter } from '../../src/adapters/azure' +import { gcsAdapter } from '../../src/adapters/gcs' +import { s3Adapter } from '../../src/adapters/s3' +import { supabaseAdapter } from '../../src/adapters/supabase' import type { Adapter } from '../../src/types' import { Media } from './collections/Media' +import Users from './collections/Users' let adapter: Adapter let uploadOptions +if (process.env.PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER === 'supabase') { + adapter = supabaseAdapter({ + config: { + url: process.env.SUPABASE_ENDPOINT, + key: process.env.SUPABASE_ANON_PUBLIC_KEY, + }, + }) +} + if (process.env.PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER === 'azure') { adapter = azureBlobStorageAdapter({ connectionString: process.env.AZURE_STORAGE_CONNECTION_STRING, @@ -69,6 +79,7 @@ export default buildConfig({ '@azure/storage-blob': path.resolve(__dirname, '../../src/adapters/azure/mock.js'), '@aws-sdk/client-s3': path.resolve(__dirname, '../../src/adapters/s3/mock.js'), '@google-cloud/storage': path.resolve(__dirname, '../../src/adapters/gcs/mock.js'), + '@supabase/supabase-js': path.resolve(__dirname, '../../src/adapters/gcs/mock.js'), }, }, } diff --git a/package.json b/package.json index 2c5159a..5b4425e 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@aws-sdk/lib-storage": "^3.267.0", "@azure/storage-blob": "^12.11.0", "@google-cloud/storage": "^6.4.1", + "@supabase/supabase-js": "^2.7.1", "payload": "^1.0.27" }, "peerDependenciesMeta": { @@ -31,6 +32,9 @@ }, "@google-cloud/storage": { "optional": true + }, + "@supabase/supabase-js": { + "optional": true } }, "files": [ @@ -44,6 +48,7 @@ "@aws-sdk/lib-storage": "^3.267.0", "@azure/storage-blob": "^12.11.0", "@google-cloud/storage": "^6.4.1", + "@supabase/supabase-js": "^2.7.1", "@types/express": "^4.17.9", "@typescript-eslint/eslint-plugin": "5.12.1", "@typescript-eslint/parser": "5.12.1", @@ -60,5 +65,6 @@ "rimraf": "^4.1.2", "ts-node": "^9.1.1", "typescript": "^4.1.3" - } + }, + "dependencies": {} } diff --git a/src/adapters/supabase/generateURL.ts b/src/adapters/supabase/generateURL.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/adapters/supabase/handleDelete.ts b/src/adapters/supabase/handleDelete.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/adapters/supabase/handleUpload.ts b/src/adapters/supabase/handleUpload.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/adapters/supabase/index.ts b/src/adapters/supabase/index.ts new file mode 100644 index 0000000..0724c25 --- /dev/null +++ b/src/adapters/supabase/index.ts @@ -0,0 +1,23 @@ +import { createClient } from '@supabase/supabase-js' +import { extendWebpackConfig } from './webpack' + +interface Args { + config: { + url: string + key: string + } +} + +export const supabaseAdapter = async ({ config }: Args): any => { + const supabase = createClient(config.url, config.key) + + const { data, error } = await supabase.storage.getBucket('avatars') + console.log({ data, error }) + return { + handleUpload: () => null, + handleDelete: () => null, + generateURL: () => null, + staticHandler: () => null, + webpack: extendWebpackConfig, + } +} diff --git a/src/adapters/supabase/mock.js b/src/adapters/supabase/mock.js new file mode 100644 index 0000000..3b3a7a1 --- /dev/null +++ b/src/adapters/supabase/mock.js @@ -0,0 +1,2 @@ +exports.createClient = () => null +exports.Upload = () => null diff --git a/src/adapters/supabase/staticHandler.ts b/src/adapters/supabase/staticHandler.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/adapters/supabase/webpack.ts b/src/adapters/supabase/webpack.ts new file mode 100644 index 0000000..97d5155 --- /dev/null +++ b/src/adapters/supabase/webpack.ts @@ -0,0 +1,18 @@ +import path from 'path' +import type { Configuration as WebpackConfig } from 'webpack' + +export const extendWebpackConfig = (existingWebpackConfig: WebpackConfig): WebpackConfig => { + const newConfig: WebpackConfig = { + ...existingWebpackConfig, + resolve: { + ...(existingWebpackConfig.resolve || {}), + alias: { + ...(existingWebpackConfig.resolve?.alias ? existingWebpackConfig.resolve.alias : {}), + '@supabase/supabase-js': path.resolve(__dirname, './mock.js'), + // fs: path.resolve(__dirname, './fileStub.js'), + }, + }, + } + + return newConfig +} diff --git a/yarn.lock b/yarn.lock index cd2b208..43d92d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1570,6 +1570,54 @@ resolved "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== +"@supabase/functions-js@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-2.0.0.tgz#4ba0c9e6dff031e17666bef6779c48eff290a8a0" + integrity sha512-ozb7bds2yvf5k7NM2ZzUkxvsx4S4i2eRKFSJetdTADV91T65g4gCzEs9L3LUXSrghcGIkUaon03VPzOrFredqg== + dependencies: + cross-fetch "^3.1.5" + +"@supabase/gotrue-js@^2.10.2": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@supabase/gotrue-js/-/gotrue-js-2.11.0.tgz#aa3322096588e8ceaa50b0b62c0c98db044ad831" + integrity sha512-yo3yExoTqpJH4YpdI5PDjZ1YLOj3wURppimfsV0ep5uxDY/lE1uOhiMCPnhy59DbFAKG7bjnhJ1L7sk+B2os3w== + dependencies: + cross-fetch "^3.1.5" + +"@supabase/postgrest-js@^1.1.1": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-1.4.0.tgz#cfbefb20e13ad9cfc3e2dacaca1a809268451bda" + integrity sha512-Qwk7T/thG4gtVjxxVGlnhH9tPWXyBGIpQMxNUtAIyASgJoEEuUFS/Wx/GqGDIfwRtrn1qqZjE6sZon5ULAdRLQ== + dependencies: + cross-fetch "^3.1.5" + +"@supabase/realtime-js@^2.4.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.6.0.tgz#eff000c2fd9f5cd8d59f4adf6d76165b81ebd536" + integrity sha512-tOVulMobhpxyDuu8VIImpL8FXmZOKsGNOSyS5ihJdj2xYmPPvYG+D2J51Ewfl+MFF65tweiB6p9N9bNIW1cDNA== + dependencies: + "@types/phoenix" "^1.5.4" + websocket "^1.0.34" + +"@supabase/storage-js@^2.1.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@supabase/storage-js/-/storage-js-2.3.0.tgz#296b36eb0bde378763117217b2f99303f1d4ec71" + integrity sha512-YGWVCEYYYF3+UiyL8O4xC78N9n9paLbT0hHl8dmYAtd3DqyWtu5Eph9JTu0PWm+/29Zhns5TbhUZW4xpWjJfPQ== + dependencies: + cross-fetch "^3.1.5" + +"@supabase/supabase-js@^2.7.1": + version "2.7.1" + resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.7.1.tgz#3b982ca15acf77a8909a43ef325e734fd61ff6e5" + integrity sha512-Q/e+JAluZEvy7D4ul3aAs3aOiKkGvHlZULy6wjchWQyU9YlJKZLr6VPYcwUeitcnRKZi4al5iTS55LgdJFfqIA== + dependencies: + "@supabase/functions-js" "^2.0.0" + "@supabase/gotrue-js" "^2.10.2" + "@supabase/postgrest-js" "^1.1.1" + "@supabase/realtime-js" "^2.4.0" + "@supabase/storage-js" "^2.1.0" + cross-fetch "^3.1.5" + "@swc/core-darwin-arm64@1.3.34": version "1.3.34" resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.34.tgz#1885fec4bd734c840897a68937a52ecab06cffbb" @@ -1789,6 +1837,11 @@ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/phoenix@^1.5.4": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.5.4.tgz#c08a1da6d7b4e365f6a1fe1ff9aada55f5356d24" + integrity sha512-L5eZmzw89eXBKkiqVBcJfU1QGx9y+wurRIEgt0cuLH0hwNtVUxtx+6cu0R2STwWj468sjXyBYPYDtGclUd1kjQ== + "@types/prettier@^2.6.1": version "2.7.2" resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" @@ -2479,6 +2532,13 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" +bufferutil@^4.0.1: + version "4.0.7" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== + dependencies: + node-gyp-build "^4.3.0" + busboy@^1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -2825,6 +2885,13 @@ cross-env@^7.0.3: dependencies: cross-spawn "^7.0.1" +cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -3033,7 +3100,7 @@ debounce-fn@^4.0.0: dependencies: mimic-fn "^3.0.0" -debug@2, debug@2.6.9, debug@^2.6.9: +debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -4710,6 +4777,11 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.9: gopd "^1.0.1" has-tostringtag "^1.0.0" +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + is-weakmap@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" @@ -5380,6 +5452,13 @@ node-addon-api@^5.0.0: resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.9" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" @@ -5392,6 +5471,11 @@ node-forge@^1.3.1: resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== +node-gyp-build@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + node-releases@^2.0.8: version "2.0.10" resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" @@ -7780,6 +7864,13 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + typescript@^4.1.3: version "4.9.5" resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" @@ -7857,6 +7948,13 @@ use-memo-one@^1.1.1: resolved "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99" integrity sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ== +utf-8-validate@^5.0.2: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + utf8-byte-length@^1.0.1: version "1.0.4" resolved "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" @@ -8032,6 +8130,18 @@ webpack@^5.75.0: watchpack "^2.4.0" webpack-sources "^3.2.3" +websocket@^1.0.34: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + whatwg-fetch@^3.4.1: version "3.6.2" resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" @@ -8134,6 +8244,11 @@ xss@^1.0.6: commander "^2.20.3" cssfilter "0.0.10" +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" From 7f49c6e6152d68a54d60c91db04c559110074349 Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 12 Feb 2023 20:11:53 +0100 Subject: [PATCH 02/12] Feat: Working on supabase/staticHandler.ts --- dev/package.json | 2 +- dev/src/payload.config.ts | 9 ++- package.json | 6 +- src/adapters/supabase/generateURL.ts | 13 ++++ src/adapters/supabase/handleDelete.ts | 16 +++++ src/adapters/supabase/handleUpload.ts | 18 +++++ src/adapters/supabase/index.ts | 43 ++++++----- src/adapters/supabase/mock.js | 3 +- src/adapters/supabase/staticHandler.ts | 39 ++++++++++ src/adapters/supabase/webpack.ts | 4 +- yarn.lock | 98 +------------------------- 11 files changed, 127 insertions(+), 124 deletions(-) diff --git a/dev/package.json b/dev/package.json index e7610ab..7f76f35 100644 --- a/dev/package.json +++ b/dev/package.json @@ -20,7 +20,7 @@ "@aws-sdk/client-s3": "^3.142.0", "@azure/storage-blob": "^12.11.0", "@google-cloud/storage": "^6.4.2", - "@supabase/supabase-js": "^2.7.1", + "@supabase/storage-js": "^2.3.0", "dotenv": "^8.2.0", "express": "^4.17.1", "payload": "^1.6.6" diff --git a/dev/src/payload.config.ts b/dev/src/payload.config.ts index 48cfcbb..83d215b 100644 --- a/dev/src/payload.config.ts +++ b/dev/src/payload.config.ts @@ -14,10 +14,9 @@ let uploadOptions if (process.env.PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER === 'supabase') { adapter = supabaseAdapter({ - config: { - url: process.env.SUPABASE_ENDPOINT, - key: process.env.SUPABASE_ANON_PUBLIC_KEY, - }, + apiKey: process.env.SUPABASE_SECRET_KEY, + bucket: process.env.SUPABASE_BUCKET_NAME, + url: process.env.SUPABASE_ENDPOINT, }) } @@ -79,7 +78,7 @@ export default buildConfig({ '@azure/storage-blob': path.resolve(__dirname, '../../src/adapters/azure/mock.js'), '@aws-sdk/client-s3': path.resolve(__dirname, '../../src/adapters/s3/mock.js'), '@google-cloud/storage': path.resolve(__dirname, '../../src/adapters/gcs/mock.js'), - '@supabase/supabase-js': path.resolve(__dirname, '../../src/adapters/gcs/mock.js'), + '@supabase/storage-js': path.resolve(__dirname, '../../src/adapters/supabase/mock.js'), }, }, } diff --git a/package.json b/package.json index 5b4425e..4e330fd 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@aws-sdk/lib-storage": "^3.267.0", "@azure/storage-blob": "^12.11.0", "@google-cloud/storage": "^6.4.1", - "@supabase/supabase-js": "^2.7.1", + "@supabase/storage-js": "^2.3.0", "payload": "^1.0.27" }, "peerDependenciesMeta": { @@ -33,7 +33,7 @@ "@google-cloud/storage": { "optional": true }, - "@supabase/supabase-js": { + "@supabase/storage-js": { "optional": true } }, @@ -48,7 +48,7 @@ "@aws-sdk/lib-storage": "^3.267.0", "@azure/storage-blob": "^12.11.0", "@google-cloud/storage": "^6.4.1", - "@supabase/supabase-js": "^2.7.1", + "@supabase/storage-js": "^2.3.0", "@types/express": "^4.17.9", "@typescript-eslint/eslint-plugin": "5.12.1", "@typescript-eslint/parser": "5.12.1", diff --git a/src/adapters/supabase/generateURL.ts b/src/adapters/supabase/generateURL.ts index e69de29..8225d0d 100644 --- a/src/adapters/supabase/generateURL.ts +++ b/src/adapters/supabase/generateURL.ts @@ -0,0 +1,13 @@ +import path from 'path' +import type { GenerateURL } from '../../types' + +interface Args { + endpoint: string + bucket: string +} + +export const getGenerateURL = + ({ endpoint, bucket }: Args): GenerateURL => + ({ filename, prefix = '' }) => { + return `${endpoint}/object/public/${bucket}/${path.posix.join(prefix, filename)}` + } diff --git a/src/adapters/supabase/handleDelete.ts b/src/adapters/supabase/handleDelete.ts index e69de29..67fd2c5 100644 --- a/src/adapters/supabase/handleDelete.ts +++ b/src/adapters/supabase/handleDelete.ts @@ -0,0 +1,16 @@ +import type { StorageClient } from '@supabase/storage-js' +import path from 'path' +import type { HandleDelete } from '../../types' + +interface Args { + getStorageClient: () => StorageClient + bucket: string +} + +export const getHandleDelete = ({ getStorageClient, bucket }: Args): HandleDelete => { + return async ({ filename, doc: { prefix = '' } }) => { + const fileKey: string = path.posix.join(prefix, filename) + + await getStorageClient().from(bucket).remove([fileKey]) + } +} diff --git a/src/adapters/supabase/handleUpload.ts b/src/adapters/supabase/handleUpload.ts index e69de29..8ed39ae 100644 --- a/src/adapters/supabase/handleUpload.ts +++ b/src/adapters/supabase/handleUpload.ts @@ -0,0 +1,18 @@ +import type { StorageClient } from '@supabase/storage-js' +import path from 'path' + +interface Args { + getStorageClient: () => StorageClient + bucket: string + prefix?: string +} + +export const getHandleUpload = ({ getStorageClient, bucket, prefix = '' }: Args): any => { + return async ({ data, file }: any) => { + const fileKey: string = path.posix.join(prefix, file.filename) + + await getStorageClient().from(bucket).upload(fileKey, file) + + return data + } +} diff --git a/src/adapters/supabase/index.ts b/src/adapters/supabase/index.ts index 0724c25..708593c 100644 --- a/src/adapters/supabase/index.ts +++ b/src/adapters/supabase/index.ts @@ -1,23 +1,34 @@ -import { createClient } from '@supabase/supabase-js' +import { StorageClient } from '@supabase/storage-js' +import { getGenerateURL } from './generateURL' +import { getHandleDelete } from './handleDelete' +import { getHandleUpload } from './handleUpload' +import { getHandler } from './staticHandler' import { extendWebpackConfig } from './webpack' interface Args { - config: { - url: string - key: string - } + url: string + apiKey: string + bucket: string } -export const supabaseAdapter = async ({ config }: Args): any => { - const supabase = createClient(config.url, config.key) +export const supabaseAdapter = + ({ url, apiKey, bucket }: Args): any => + ({ collection, prefix }: any): any => { + let storageClient: StorageClient | null = null + const getStorageClient: () => StorageClient = () => { + if (storageClient) return storageClient + storageClient = new StorageClient(url, { + apikey: apiKey, + Authorization: `Bearer ${apiKey}`, + }) + return storageClient + } - const { data, error } = await supabase.storage.getBucket('avatars') - console.log({ data, error }) - return { - handleUpload: () => null, - handleDelete: () => null, - generateURL: () => null, - staticHandler: () => null, - webpack: extendWebpackConfig, + return { + handleUpload: getHandleUpload({ getStorageClient, bucket, prefix }), + handleDelete: getHandleDelete({ getStorageClient, bucket }), + generateURL: getGenerateURL({ bucket, endpoint: url }), + staticHandler: getHandler({ getStorageClient, bucket, collection }), + webpack: extendWebpackConfig, + } } -} diff --git a/src/adapters/supabase/mock.js b/src/adapters/supabase/mock.js index 3b3a7a1..1ac1b20 100644 --- a/src/adapters/supabase/mock.js +++ b/src/adapters/supabase/mock.js @@ -1,2 +1,3 @@ -exports.createClient = () => null +exports.StorageClient = () => null exports.Upload = () => null +exports.getBucket = () => null diff --git a/src/adapters/supabase/staticHandler.ts b/src/adapters/supabase/staticHandler.ts index e69de29..43db4bf 100644 --- a/src/adapters/supabase/staticHandler.ts +++ b/src/adapters/supabase/staticHandler.ts @@ -0,0 +1,39 @@ +import type { StorageClient } from '@supabase/storage-js' +import path from 'path' +import type { CollectionConfig } from 'payload/types' +import type { StaticHandler } from '../../types' +import { getFilePrefix } from '../../utilities/getFilePrefix' + +interface Args { + getStorageClient: () => StorageClient + bucket: string + collection: CollectionConfig +} + +export const getHandler = ({ getStorageClient, bucket, collection }: Args): StaticHandler => { + return async (req, res, next) => { + try { + const prefix = await getFilePrefix({ req, collection }) + const key: string = path.posix.join(prefix, req.params.filename) + + const { data } = await getStorageClient().from(bucket).list('', { + limit: 1, + offset: 0, + search: key, + }) + const file = data![0] + const fileDownloaded = await getStorageClient().from(bucket).download(key) + const blobFile = fileDownloaded.data + res.set({ + 'Content-Length': file.metadata.contentLength, + 'Content-Type': file.metadata.mimetype, + ETag: file.metadata.eTag, + }) + // NOT WORKING + return res + } catch (err: unknown) { + req.payload.logger.error(err) + return next() + } + } +} diff --git a/src/adapters/supabase/webpack.ts b/src/adapters/supabase/webpack.ts index 97d5155..16c9c1f 100644 --- a/src/adapters/supabase/webpack.ts +++ b/src/adapters/supabase/webpack.ts @@ -8,8 +8,8 @@ export const extendWebpackConfig = (existingWebpackConfig: WebpackConfig): Webpa ...(existingWebpackConfig.resolve || {}), alias: { ...(existingWebpackConfig.resolve?.alias ? existingWebpackConfig.resolve.alias : {}), - '@supabase/supabase-js': path.resolve(__dirname, './mock.js'), - // fs: path.resolve(__dirname, './fileStub.js'), + '@supabase/storage-js': path.resolve(__dirname, './mock.js'), + fs: path.resolve(__dirname, './fileStub.js'), }, }, } diff --git a/yarn.lock b/yarn.lock index 43d92d4..b4e4366 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1570,54 +1570,13 @@ resolved "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== -"@supabase/functions-js@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-2.0.0.tgz#4ba0c9e6dff031e17666bef6779c48eff290a8a0" - integrity sha512-ozb7bds2yvf5k7NM2ZzUkxvsx4S4i2eRKFSJetdTADV91T65g4gCzEs9L3LUXSrghcGIkUaon03VPzOrFredqg== - dependencies: - cross-fetch "^3.1.5" - -"@supabase/gotrue-js@^2.10.2": - version "2.11.0" - resolved "https://registry.yarnpkg.com/@supabase/gotrue-js/-/gotrue-js-2.11.0.tgz#aa3322096588e8ceaa50b0b62c0c98db044ad831" - integrity sha512-yo3yExoTqpJH4YpdI5PDjZ1YLOj3wURppimfsV0ep5uxDY/lE1uOhiMCPnhy59DbFAKG7bjnhJ1L7sk+B2os3w== - dependencies: - cross-fetch "^3.1.5" - -"@supabase/postgrest-js@^1.1.1": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-1.4.0.tgz#cfbefb20e13ad9cfc3e2dacaca1a809268451bda" - integrity sha512-Qwk7T/thG4gtVjxxVGlnhH9tPWXyBGIpQMxNUtAIyASgJoEEuUFS/Wx/GqGDIfwRtrn1qqZjE6sZon5ULAdRLQ== - dependencies: - cross-fetch "^3.1.5" - -"@supabase/realtime-js@^2.4.0": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.6.0.tgz#eff000c2fd9f5cd8d59f4adf6d76165b81ebd536" - integrity sha512-tOVulMobhpxyDuu8VIImpL8FXmZOKsGNOSyS5ihJdj2xYmPPvYG+D2J51Ewfl+MFF65tweiB6p9N9bNIW1cDNA== - dependencies: - "@types/phoenix" "^1.5.4" - websocket "^1.0.34" - -"@supabase/storage-js@^2.1.0": +"@supabase/storage-js@^2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@supabase/storage-js/-/storage-js-2.3.0.tgz#296b36eb0bde378763117217b2f99303f1d4ec71" integrity sha512-YGWVCEYYYF3+UiyL8O4xC78N9n9paLbT0hHl8dmYAtd3DqyWtu5Eph9JTu0PWm+/29Zhns5TbhUZW4xpWjJfPQ== dependencies: cross-fetch "^3.1.5" -"@supabase/supabase-js@^2.7.1": - version "2.7.1" - resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.7.1.tgz#3b982ca15acf77a8909a43ef325e734fd61ff6e5" - integrity sha512-Q/e+JAluZEvy7D4ul3aAs3aOiKkGvHlZULy6wjchWQyU9YlJKZLr6VPYcwUeitcnRKZi4al5iTS55LgdJFfqIA== - dependencies: - "@supabase/functions-js" "^2.0.0" - "@supabase/gotrue-js" "^2.10.2" - "@supabase/postgrest-js" "^1.1.1" - "@supabase/realtime-js" "^2.4.0" - "@supabase/storage-js" "^2.1.0" - cross-fetch "^3.1.5" - "@swc/core-darwin-arm64@1.3.34": version "1.3.34" resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.34.tgz#1885fec4bd734c840897a68937a52ecab06cffbb" @@ -1837,11 +1796,6 @@ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== -"@types/phoenix@^1.5.4": - version "1.5.4" - resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.5.4.tgz#c08a1da6d7b4e365f6a1fe1ff9aada55f5356d24" - integrity sha512-L5eZmzw89eXBKkiqVBcJfU1QGx9y+wurRIEgt0cuLH0hwNtVUxtx+6cu0R2STwWj468sjXyBYPYDtGclUd1kjQ== - "@types/prettier@^2.6.1": version "2.7.2" resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" @@ -2532,13 +2486,6 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -bufferutil@^4.0.1: - version "4.0.7" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" - integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== - dependencies: - node-gyp-build "^4.3.0" - busboy@^1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -3100,7 +3047,7 @@ debounce-fn@^4.0.0: dependencies: mimic-fn "^3.0.0" -debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.6.9: +debug@2, debug@2.6.9, debug@^2.6.9: version "2.6.9" resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -4777,11 +4724,6 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.9: gopd "^1.0.1" has-tostringtag "^1.0.0" -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== - is-weakmap@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" @@ -5471,11 +5413,6 @@ node-forge@^1.3.1: resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== -node-gyp-build@^4.3.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" - integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== - node-releases@^2.0.8: version "2.0.10" resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" @@ -7864,13 +7801,6 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - typescript@^4.1.3: version "4.9.5" resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" @@ -7948,13 +7878,6 @@ use-memo-one@^1.1.1: resolved "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99" integrity sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ== -utf-8-validate@^5.0.2: - version "5.0.10" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" - integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== - dependencies: - node-gyp-build "^4.3.0" - utf8-byte-length@^1.0.1: version "1.0.4" resolved "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" @@ -8130,18 +8053,6 @@ webpack@^5.75.0: watchpack "^2.4.0" webpack-sources "^3.2.3" -websocket@^1.0.34: - version "1.0.34" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" - integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.50" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - whatwg-fetch@^3.4.1: version "3.6.2" resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" @@ -8244,11 +8155,6 @@ xss@^1.0.6: commander "^2.20.3" cssfilter "0.0.10" -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== - yallist@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" From ffc2a397f11945d82acbd9a84b9eb558634ab793 Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 19 Feb 2023 17:05:06 +0100 Subject: [PATCH 03/12] New package 'fast-blob-stream' added --- dev/package.json | 1 + package.json | 5 +++++ yarn.lock | 31 +++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/dev/package.json b/dev/package.json index 7f76f35..bdeccff 100644 --- a/dev/package.json +++ b/dev/package.json @@ -23,6 +23,7 @@ "@supabase/storage-js": "^2.3.0", "dotenv": "^8.2.0", "express": "^4.17.1", + "fast-blob-stream": "^1.1.1", "payload": "^1.6.6" }, "devDependencies": { diff --git a/package.json b/package.json index 4e330fd..dc17e08 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@azure/storage-blob": "^12.11.0", "@google-cloud/storage": "^6.4.1", "@supabase/storage-js": "^2.3.0", + "fast-blob-stream": "^1.1.1", "payload": "^1.0.27" }, "peerDependenciesMeta": { @@ -35,6 +36,9 @@ }, "@supabase/storage-js": { "optional": true + }, + "fast-blob-stream": { + "optional": true } }, "files": [ @@ -59,6 +63,7 @@ "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "2.25.4", "eslint-plugin-prettier": "^4.0.0", + "fast-blob-stream": "^1.1.1", "nodemon": "^2.0.6", "payload": "^1.6.6", "prettier": "^2.7.1", diff --git a/yarn.lock b/yarn.lock index b4e4366..b8bda97 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3757,6 +3757,14 @@ extend@^3.0.2: resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +fast-blob-stream@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fast-blob-stream/-/fast-blob-stream-1.1.1.tgz#3ed549efb6cf302a20a409e32fda41f2ba6e4871" + integrity sha512-wdRazMMeM2pl8hq1lFG8fzix8p1VLAJunTTE2RADiFBwbUfZwybUm6IwPrmMS7qTthiayr166NoXeqWe3hfR5w== + dependencies: + fast-readable-async-iterator "^1.1.1" + streamx "^2.12.4" + fast-copy@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.0.tgz#875ebf33b13948ae012b6e51d33da5e6e7571ab8" @@ -3772,6 +3780,11 @@ fast-diff@^1.1.2: resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== +fast-fifo@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.1.0.tgz#17d1a3646880b9891dfa0c54e69c5fef33cad779" + integrity sha512-Kl29QoNbNvn4nhDsLYjyIAaIqaJB6rBx5p3sL9VjaefJ+eMFBWVZiaoguaoZfzEKr5RhAti0UgM8703akGPJ6g== + fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" @@ -3793,6 +3806,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-readable-async-iterator@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fast-readable-async-iterator/-/fast-readable-async-iterator-1.1.1.tgz#77dfbb5262b278bb123c4d8d3219b1bb881b857c" + integrity sha512-xEHkLUEmStETI+15zhglJLO9TjXxNkkp2ldEfYVZdcqxFhM172EfGl1irI6mVlTxXspYKH1/kjevnt/XSsPeFA== + fast-redact@^3.0.0: version "3.1.2" resolved "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa" @@ -6585,6 +6603,11 @@ queue-microtask@^1.2.2: resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +queue-tick@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" + integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag== + quick-format-unescaped@^4.0.3: version "4.0.4" resolved "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" @@ -7395,6 +7418,14 @@ streamsearch@^1.1.0: resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== +streamx@^2.12.4: + version "2.13.2" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.13.2.tgz#9de43569a1cd54980d128673b3c1429b79afff1c" + integrity sha512-+TWqixPhGDXEG9L/XczSbhfkmwAtGs3BJX5QNU6cvno+pOLKeszByWcnaTu6dg8efsTYqR8ZZuXWHhZfgrxMvA== + dependencies: + fast-fifo "^1.1.0" + queue-tick "^1.0.1" + string.prototype.trimend@^1.0.6: version "1.0.6" resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" From c3c5a98dbb51c011835c48a1b0985902f6f5b3e8 Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 19 Feb 2023 17:06:02 +0100 Subject: [PATCH 04/12] webpack config modified --- dev/src/payload.config.ts | 1 + src/adapters/supabase/webpack.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/dev/src/payload.config.ts b/dev/src/payload.config.ts index 83d215b..4e9d133 100644 --- a/dev/src/payload.config.ts +++ b/dev/src/payload.config.ts @@ -79,6 +79,7 @@ export default buildConfig({ '@aws-sdk/client-s3': path.resolve(__dirname, '../../src/adapters/s3/mock.js'), '@google-cloud/storage': path.resolve(__dirname, '../../src/adapters/gcs/mock.js'), '@supabase/storage-js': path.resolve(__dirname, '../../src/adapters/supabase/mock.js'), + 'fast-blob-stream': path.resolve(__dirname, '../../src/adapters/supabase/mock.js'), }, }, } diff --git a/src/adapters/supabase/webpack.ts b/src/adapters/supabase/webpack.ts index 16c9c1f..85e2a06 100644 --- a/src/adapters/supabase/webpack.ts +++ b/src/adapters/supabase/webpack.ts @@ -9,6 +9,7 @@ export const extendWebpackConfig = (existingWebpackConfig: WebpackConfig): Webpa alias: { ...(existingWebpackConfig.resolve?.alias ? existingWebpackConfig.resolve.alias : {}), '@supabase/storage-js': path.resolve(__dirname, './mock.js'), + 'fast-blob-stream': path.resolve(__dirname, './mock.js'), fs: path.resolve(__dirname, './fileStub.js'), }, }, From f82d9beb0bbcd52e6f06a20441ce5b9d0ac8cb5e Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 19 Feb 2023 17:07:27 +0100 Subject: [PATCH 05/12] mock files --- src/adapters/supabase/fileStub.js | 1 + src/adapters/supabase/mock.js | 1 + 2 files changed, 2 insertions(+) create mode 100644 src/adapters/supabase/fileStub.js diff --git a/src/adapters/supabase/fileStub.js b/src/adapters/supabase/fileStub.js new file mode 100644 index 0000000..e25c9a3 --- /dev/null +++ b/src/adapters/supabase/fileStub.js @@ -0,0 +1 @@ +export default 'file-stub' diff --git a/src/adapters/supabase/mock.js b/src/adapters/supabase/mock.js index 1ac1b20..2cdfe4d 100644 --- a/src/adapters/supabase/mock.js +++ b/src/adapters/supabase/mock.js @@ -1,3 +1,4 @@ exports.StorageClient = () => null exports.Upload = () => null exports.getBucket = () => null +exports.BlobReadStream = () => null From 82fa0f0a404b5cfcba7c5540d476a67308634d78 Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 19 Feb 2023 18:43:32 +0100 Subject: [PATCH 06/12] handlers working --- src/adapters/supabase/handleDelete.ts | 1 - src/adapters/supabase/handleUpload.ts | 17 +++++++++++++---- src/adapters/supabase/index.ts | 7 ++++--- src/adapters/supabase/staticHandler.ts | 11 +++++++++-- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/adapters/supabase/handleDelete.ts b/src/adapters/supabase/handleDelete.ts index 67fd2c5..d93c76c 100644 --- a/src/adapters/supabase/handleDelete.ts +++ b/src/adapters/supabase/handleDelete.ts @@ -10,7 +10,6 @@ interface Args { export const getHandleDelete = ({ getStorageClient, bucket }: Args): HandleDelete => { return async ({ filename, doc: { prefix = '' } }) => { const fileKey: string = path.posix.join(prefix, filename) - await getStorageClient().from(bucket).remove([fileKey]) } } diff --git a/src/adapters/supabase/handleUpload.ts b/src/adapters/supabase/handleUpload.ts index 8ed39ae..675d814 100644 --- a/src/adapters/supabase/handleUpload.ts +++ b/src/adapters/supabase/handleUpload.ts @@ -1,5 +1,8 @@ import type { StorageClient } from '@supabase/storage-js' +import fs from 'fs' import path from 'path' +import type stream from 'stream' +import type { HandleUpload } from '../../types' interface Args { getStorageClient: () => StorageClient @@ -7,11 +10,17 @@ interface Args { prefix?: string } -export const getHandleUpload = ({ getStorageClient, bucket, prefix = '' }: Args): any => { - return async ({ data, file }: any) => { - const fileKey: string = path.posix.join(prefix, file.filename) +export const getHandleUpload = ({ getStorageClient, bucket, prefix = '' }: Args): HandleUpload => { + return async ({ data, file }) => { + const fileKey = path.posix.join(prefix, file.filename) - await getStorageClient().from(bucket).upload(fileKey, file) + const fileBufferOrStream: Buffer | stream.Readable = file.tempFilePath + ? fs.createReadStream(file.tempFilePath) + : file.buffer + + await getStorageClient().from(bucket).upload(fileKey, fileBufferOrStream, { + contentType: file.mimeType, + }) return data } diff --git a/src/adapters/supabase/index.ts b/src/adapters/supabase/index.ts index 708593c..ea50ab6 100644 --- a/src/adapters/supabase/index.ts +++ b/src/adapters/supabase/index.ts @@ -1,19 +1,20 @@ import { StorageClient } from '@supabase/storage-js' +import type { Adapter, GeneratedAdapter } from '../../types' import { getGenerateURL } from './generateURL' import { getHandleDelete } from './handleDelete' import { getHandleUpload } from './handleUpload' import { getHandler } from './staticHandler' import { extendWebpackConfig } from './webpack' -interface Args { +export interface Args { url: string apiKey: string bucket: string } export const supabaseAdapter = - ({ url, apiKey, bucket }: Args): any => - ({ collection, prefix }: any): any => { + ({ url, apiKey, bucket }: Args): Adapter => + ({ collection, prefix }): GeneratedAdapter => { let storageClient: StorageClient | null = null const getStorageClient: () => StorageClient = () => { if (storageClient) return storageClient diff --git a/src/adapters/supabase/staticHandler.ts b/src/adapters/supabase/staticHandler.ts index 43db4bf..018a77a 100644 --- a/src/adapters/supabase/staticHandler.ts +++ b/src/adapters/supabase/staticHandler.ts @@ -1,4 +1,5 @@ import type { StorageClient } from '@supabase/storage-js' +import { BlobReadStream } from 'fast-blob-stream' import path from 'path' import type { CollectionConfig } from 'payload/types' import type { StaticHandler } from '../../types' @@ -24,13 +25,19 @@ export const getHandler = ({ getStorageClient, bucket, collection }: Args): Stat const file = data![0] const fileDownloaded = await getStorageClient().from(bucket).download(key) const blobFile = fileDownloaded.data + res.set({ 'Content-Length': file.metadata.contentLength, 'Content-Type': file.metadata.mimetype, ETag: file.metadata.eTag, }) - // NOT WORKING - return res + + if (blobFile) { + const readStream = new BlobReadStream(blobFile) + return readStream.pipe(res) + } + + return next() } catch (err: unknown) { req.payload.logger.error(err) return next() From ce0a1b530b696098d43fa0563eb86839ed61dc8c Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 19 Feb 2023 18:43:50 +0100 Subject: [PATCH 07/12] .env.example modified --- dev/.env.example | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dev/.env.example b/dev/.env.example index 7b69673..f6843b9 100644 --- a/dev/.env.example +++ b/dev/.env.example @@ -18,4 +18,8 @@ GCS_ENDPOINT=http://localhost:4443 GCS_PROJECT_ID=test GCS_BUCKET=payload-bucket +SUPABASE_SECRET_KEY=supabase-secret-key +SUPABASE_BUCKET_NAME=payload-bucket +SUPABASE_ENDPOINT=https://localhost:10000/your-endpoint + PAYLOAD_DROP_DATABASE=true From fa03f3f63d4a83b94c3db02dbf998ec90fab760b Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 19 Feb 2023 19:00:13 +0100 Subject: [PATCH 08/12] README modified --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index a844cff..4421629 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ This plugin supports the following adapters: - [Azure Blob Storage](#azure-blob-storage-adapter) - [AWS S3-style Storage](#s3-adapter) - [Google Cloud Storage](#gcs-adapter) +- [Supabase Storage Adapter](#supabase-adapter) However, you can create your own adapter for any third-party service you would like to use. @@ -151,6 +152,27 @@ const adapter = gcsAdapter({ // Now you can pass this adapter to the plugin ``` +### Supabase Adapter + +To use the Supabase adapter, some peer dependencies need to be installed: + +`yarn add @supabase/storage-js fast-blob-stream`. + +From there, create the adapter, passing in all of its required properties: + +```js +import { s3Adapter } from '@payloadcms/plugin-cloud-storage/supabase'; + +const adapter = supabaseAdapter({ + apiKey: process.env.SUPABASE_SECRET_KEY,// this env variable will have the service_role key of your supabase project + bucket: process.env.SUPABASE_BUCKET_NAME, + // this env variable will have the bucket name + url: process.env.SUPABASE_ENDPOINT,// this env variable will have the endpoint of your supabase project +}) + +// Now you can pass this adapter to the plugin +``` + ### Payload Access Control Payload ships with access control that runs _even on statically served files_. The same `read` access control property on your `upload`-enabled collections is used, and it allows you to restrict who can request your uploaded files. From d6b47d05961c953c3ea1e478dd234f684c1256a2 Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 19 Feb 2023 19:16:27 +0100 Subject: [PATCH 09/12] local-dev file modified --- docs/local-dev.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/local-dev.md b/docs/local-dev.md index 5e17487..fe462a0 100644 --- a/docs/local-dev.md +++ b/docs/local-dev.md @@ -8,6 +8,16 @@ This repository includes a local development environment for local testing and d 1. `cd` into `./dev` and run `cp .env.example .env` to create an `.env` file 1. Open your newly created `./dev/.env` file and _completely_ fill out each property +### Supabase Adapter Development + +By now, this repository does not come with a Docker emulator for Supabase Storage. + +If you would like to test locally this plugin, use the following steps: + +1. Sign up for a free plan in Supabase platform. +1. Make sure your environment variables within `./dev/.env` are configured for your Supabase connection. +1. Finally, run `yarn dev:supabase` and then open `http://localhost:3000/admin` in your browser. + ### Azure Adapter Development This repository comes with a Docker emulator for Azure Blob Storage. From 32cfd210773cf5fbe2e93e7d3e2876e4f1c002ea Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 19 Feb 2023 19:18:24 +0100 Subject: [PATCH 10/12] Small fixes in docs --- README.md | 2 +- docs/local-dev.md | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 4421629..01e1b32 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ To use the Supabase adapter, some peer dependencies need to be installed: From there, create the adapter, passing in all of its required properties: ```js -import { s3Adapter } from '@payloadcms/plugin-cloud-storage/supabase'; +import { supabaseAdapter } from '@payloadcms/plugin-cloud-storage/supabase'; const adapter = supabaseAdapter({ apiKey: process.env.SUPABASE_SECRET_KEY,// this env variable will have the service_role key of your supabase project diff --git a/docs/local-dev.md b/docs/local-dev.md index fe462a0..8c674da 100644 --- a/docs/local-dev.md +++ b/docs/local-dev.md @@ -8,16 +8,6 @@ This repository includes a local development environment for local testing and d 1. `cd` into `./dev` and run `cp .env.example .env` to create an `.env` file 1. Open your newly created `./dev/.env` file and _completely_ fill out each property -### Supabase Adapter Development - -By now, this repository does not come with a Docker emulator for Supabase Storage. - -If you would like to test locally this plugin, use the following steps: - -1. Sign up for a free plan in Supabase platform. -1. Make sure your environment variables within `./dev/.env` are configured for your Supabase connection. -1. Finally, run `yarn dev:supabase` and then open `http://localhost:3000/admin` in your browser. - ### Azure Adapter Development This repository comes with a Docker emulator for Azure Blob Storage. @@ -55,3 +45,13 @@ The default `./dev/.env.example` file comes pre-loaded with correct `env` variab Otherwise, if you are not using the emulator, make sure your environment variables within `./dev/.env` are configured for your Google connection. Finally, to start the Payload dev server with the GCS adapter, run `yarn dev:gcs` and then open `http://localhost:3000/admin` in your browser. + +### Supabase Adapter Development + +By now, this repository does not come with a Docker emulator for Supabase Storage. + +If you would like to test locally this plugin, use the following steps: + +1. Sign up for a free plan in Supabase platform. +1. Make sure your environment variables within `./dev/.env` are configured for your Supabase connection. +1. Finally, run `yarn dev:supabase` and then open `http://localhost:3000/admin` in your browser. From 7014272fd9c4af30517125836efc1f6886d2c2fa Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 19 Feb 2023 19:19:32 +0100 Subject: [PATCH 11/12] Small fix in README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 01e1b32..115b4ee 100644 --- a/README.md +++ b/README.md @@ -165,8 +165,7 @@ import { supabaseAdapter } from '@payloadcms/plugin-cloud-storage/supabase'; const adapter = supabaseAdapter({ apiKey: process.env.SUPABASE_SECRET_KEY,// this env variable will have the service_role key of your supabase project - bucket: process.env.SUPABASE_BUCKET_NAME, - // this env variable will have the bucket name + bucket: process.env.SUPABASE_BUCKET_NAME,// this env variable will have the bucket name url: process.env.SUPABASE_ENDPOINT,// this env variable will have the endpoint of your supabase project }) From af7afc865a11c76af6ddf5704f4a6309f8634f44 Mon Sep 17 00:00:00 2001 From: jorgeAgoiz Date: Sun, 19 Feb 2023 19:21:09 +0100 Subject: [PATCH 12/12] Small fix in package.json --- dev/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/package.json b/dev/package.json index bdeccff..448bd7f 100644 --- a/dev/package.json +++ b/dev/package.json @@ -5,7 +5,6 @@ "license": "MIT", "private": true, "scripts": { - "dev": "nodemon", "dev:azure": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER=azure nodemon", "dev:s3": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER=s3 nodemon", "dev:gcs": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER=gcs nodemon",