Files
payload/packages/plugin-cloud-storage
Dan Ribbens edfa85bcd5 feat(db-postgres)!: relationship column (#6339)
BREAKING CHANGE:

Moves `upload` field and `relationship` fields with `hasMany: false` &
`relationTo: string` from the many-to-many `_rels` join table to simple
columns. This only affects Postgres database users.

## TL;DR

We have dramatically simplified the storage of simple relationships in
relational databases to boost performance and align with more expected
relational paradigms. If you are using the beta Postgres adapter, and
you need to keep simple relationship data, you'll need to run a
migration script that we provide you.

### Background

For example, prior to this update, a collection of "posts" with a simple
`hasMany: false` and `relationTo: 'categories'` field would have a
`posts_rels` table where the category relations would be stored.

This was somewhat unnecessary as simple relations like this can be
expressed with a `category_id` column which is configured as a foreign
key. This also introduced added complexity for dealing directly with the
database if all you have are simple relations.

### Who needs to migrate

You need to migrate if you are using the beta Postgres database adapter
and any of the following applies to you.

- If you have versions enabled on any collection / global
- If you use the `upload` field 
- If you have relationship fields that are `hasMany: false` (default)
and `relationTo` to a single category ([has
one](https://payloadcms.com/docs/fields/relationship#has-one)) relations

### We have a migration for you

Even though the Postgres adapter is in beta, we've prepared a predefined
migration that will work out of the box for you to migrate from an
earlier version of the adapter to the most recent version easily.

It makes the schema changes in step with actually moving the data from
the old locations to the new before adding any null constraints and
dropping the old columns and tables.

### How to migrate

The steps to preserve your data while making this update are as follows.
These steps are the same whether you are moving from Payload v2 to v3 or
a previous version of v3 beta to the most recent v3 beta.

**Important: during these steps, don't start the dev server unless you
have `push: false` set on your Postgres adapter.**

#### Step 1 - backup

Always back up your database before performing big changes, especially
in production cases.

#### Step 2 - create a pre-update migration 
Before updating to new Payload and Postgres adapter versions, run
`payload migrate:create` without any other config changes to have a
prior snapshot of the schema from the previous adapter version

#### Step 3 - if you're migrating a dev DB, delete the dev `push` row
from your `payload_migrations` table

If you're migrating a dev database where you have the default setting to
push database changes directly to your DB, and you need to preserve data
in your development database, then you need to delete a `dev` migration
record from your database.

Connect directly to your database in any tool you'd like and delete the
dev push record from the `payload_migrations` table using the following
SQL statement:

```sql
DELETE FROM payload_migrations where batch = -1`
```

#### Step 4 - update Payload and Postgres versions to most recent

Update packages, making sure you have matching versions across all
`@payloadcms/*` and `payload` packages (including
`@payloadcms/db-postgres`)

#### Step 5 - create the predefined migration

Run the following command to create the predefined migration we've
provided:

```
payload migrate:create --file @payloadcms/db-postgres/relationships-v2-v3
```

#### Step 6 - migrate!

Run migrations with the following command: 

```
payload migrate
```

Assuming the migration worked, you can proceed to commit this change and
distribute it to be run on all other environments.

Note that if two servers connect to the same database, only one should
be running migrations to avoid transaction conflicts.

Related discussion:
https://github.com/payloadcms/payload/discussions/4163

---------

Co-authored-by: James <james@trbl.design>
Co-authored-by: PatrikKozak <patrik@payloadcms.com>
2024-05-30 14:09:11 -04:00
..
2024-04-12 11:39:08 -04:00
2024-03-10 13:53:37 -04:00

Payload Cloud Storage Plugin

This repository contains the officially supported Payload Cloud Storage plugin. It extends Payload to allow you to store all uploaded media in third-party permanent storage.

NOTE: If you are using Payload 3.0 and one of the following storage services, you should use one of following packages instead of this one:

Service Package
Vercel Blob @payloadcms/storage-vercel-blob
AWS S3 @payloadcms/storage-s3
Azure @payloadcms/storage-azure
Google Cloud Storage @payloadcms/storage-gcs

This package is now best used for implementing custom storage solutions or third-party storage services that do not have @payloadcms/storage-* packages.

Installation

pnpm add @payloadcms/plugin-cloud-storage

Usage

import { buildConfig } from 'payload/config'
import { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage'

export default buildConfig({
  plugins: [
    cloudStoragePlugin({
      collections: {
        'my-collection-slug': {
          adapter: theAdapterToUse, // see docs for the adapter you want to use
        },
      },
    }),
  ],
  // The rest of your config goes here
})

Conditionally Enabling/Disabling

The proper way to conditionally enable/disable this plugin is to use the enabled property.

cloudStoragePlugin({
  enabled: process.env.MY_CONDITION === 'true',
  collections: {
    'my-collection-slug': {
      adapter: theAdapterToUse, // see docs for the adapter you want to use
    },
  },
}),

If the code is included in any way in your config but conditionally disabled in another fashion, you may run into issues such as Webpack Build Error: Can't Resolve 'fs' and 'stream' or similar because the plugin must be run at all times in order to properly extend the webpack config.

Features

Adapter-based Implementation

This plugin supports the following adapters:

However, you can create your own adapter for any third-party service you would like to use.

All adapters are implemented dev directory's Payload Config. See this file for examples.

Plugin options

This plugin is configurable to work across many different Payload collections. A * denotes that the property is required.

Option Type Description
collections * Record<string, CollectionOptions> Object with keys set to the slug of collections you want to enable the plugin for, and values set to collection-specific options.
enabled boolean to conditionally enable/disable plugin. Default: true.

Collection-specific options:

Option Type Description
adapter * Adapter Pass in the adapter that you'd like to use for this collection. You can also set this field to null for local development if you'd like to bypass cloud storage in certain scenarios and use local storage.
disableLocalStorage boolean Choose to disable local storage on this collection. Defaults to true.
disablePayloadAccessControl true Set to true to disable Payload's access control. More
prefix string Set to media/images to upload files inside media/images folder in the bucket.
generateFileURL GenerateFileURL Override the generated file URL with one that you create.

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.

To preserve this feature, by default, this plugin keeps all file URLs exactly the same. Your file URLs won't be updated to point directly to your cloud storage source, as in that case, Payload's access control will be completely bypassed and you would need public readability on your cloud-hosted files.

Instead, all uploads will still be reached from the default /collectionSlug/staticURL/filename path. This plugin will "pass through" all files that are hosted on your third-party cloud service—with the added benefit of keeping your existing access control in place.

If this does not apply to you (your upload collection has read: () => true or similar) you can disable this functionality by setting disablePayloadAccessControl to true. When this setting is in place, this plugin will update your file URLs to point directly to your cloud host.

Credit

This plugin was created with significant help, and code, from Alex Bechmann and Richard VanBergen. Thank you!!