Fixes
https://github.com/payloadcms/payload/issues/11731#issue-2923088087
Only 2 s3Storage() instances with `clientUploads: true` are currently
working. If you add a 3rd instance, uploading files errors with
"Collection credit-certificates was not found in S3 options".
There is already an implementation that changes the
`/storage-s3-generate-signed-url` URL for each new s3Storage plugin
instance so that multiple instances don't break each other. Currently
the code looks like this:
```ts
/**
* Tracks how many times the same handler was already applied.
* This allows to apply the same plugin multiple times, for example
* to use different buckets for different collections.
*/
let handlerCount = 0
for (const endpoint of config.endpoints) {
if (endpoint.path === serverHandlerPath) {
handlerCount++
}
}
if (handlerCount) {
serverHandlerPath = `${serverHandlerPath}-${handlerCount}`
}
```
When we print the endpoints generated by this code we get:
```ts
{
handler: [AsyncFunction (anonymous)],
method: 'post',
path: '/storage-s3-generate-signed-url'
},
{
handler: [AsyncFunction (anonymous)],
method: 'post',
path: '/storage-s3-generate-signed-url-1'
},
{
handler: [AsyncFunction (anonymous)],
method: 'post',
path: '/storage-s3-generate-signed-url-1'
}
```
As you can see, the path or the 3rd instance is the same as the 2nd
instance. Presumably this functionality was originally tested with 2
instances and not more, allowing this bug to slip through. This
completely breaks uploads for the 3rd instance.
We need to change the conditional that checks whether the plugin exists
already to use `.startsWith()`:
```ts
/**
* Tracks how many times the same handler was already applied.
* This allows to apply the same plugin multiple times, for example
* to use different buckets for different collections.
*/
let handlerCount = 0
for (const endpoint of config.endpoints) {
// We want to match on 'path', 'path-1', 'path-2', etc.
if (endpoint.path?.startsWith(serverHandlerPath)) {
handlerCount++
}
}
if (handlerCount) {
serverHandlerPath = `${serverHandlerPath}-${handlerCount}`
}
```
With the fix we can see that the endpoints increment correctly, allowing
for a true arbitrary number of s3Storage plugins with client uploads.
```ts
{
handler: [AsyncFunction (anonymous)],
method: 'post',
path: '/storage-s3-generate-signed-url'
},
{
handler: [AsyncFunction (anonymous)],
method: 'post',
path: '/storage-s3-generate-signed-url-1'
},
{
handler: [AsyncFunction (anonymous)],
method: 'post',
path: '/storage-s3-generate-signed-url-2'
}
```