Skip to content

Commit

Permalink
Merge branch 'main' of github.com:redwoodjs/redwood into docs/rw-uplo…
Browse files Browse the repository at this point in the history
…ads-storage

* 'main' of github.com:redwoodjs/redwood: (32 commits)
  chore(uploads): Reorganise, change uploads package to storage (redwoodjs#11411)
  fix(cli-helpers): Don't add spaces around `=` for env vars (redwoodjs#11414)
  feat(uploads): Increase default fastify body limit to 100MB (redwoodjs#11412)
  chore: Rebuild fixture (redwoodjs#11413)
  chore(rsc): Refactor: Rename RscFetcher -> RscRoutes (redwoodjs#11409)
  chore(test-project): Update postcss to 8.4.42 (redwoodjs#11408)
  chore(rsc): Rename rscFetch to rscFetchRoutes and hardcode the rscId (redwoodjs#11407)
  feat(rsc): Initial support for RSA rerender (redwoodjs#11406)
  chore(router): Switch to experimental types (redwoodjs#11405)
  chore(router): Make React a normal dependency (redwoodjs#11404)
  feat(rsc): Return flight from RSAs (redwoodjs#11403)
  rscRequestHandler.ts: Make BASE_PATH naming match client.ts (redwoodjs#11401)
  fix(template): api type declaration merging for scripts (redwoodjs#11367)
  RSC: Disable client side flight caching for now (redwoodjs#11400)
  chore(fixtures): Use proper name for AuthLayout component (redwoodjs#11399)
  feat(storage): Add support for createMany, updateMany and upsert (redwoodjs#11390)
  feat(codegen): support sdl generation for model with compound id (redwoodjs#8556)
  chore(ci): Follow up to workflow permissions (redwoodjs#11397)
  chore(deps): Bump 'loader-utils' within docs (redwoodjs#11396)
  chore(ci): Pin action dependencies by digest (redwoodjs#11395)
  ...
  • Loading branch information
dac09 committed Sep 2, 2024
2 parents a384ea5 + f9978fc commit 512bb59
Show file tree
Hide file tree
Showing 89 changed files with 3,337 additions and 337 deletions.
124 changes: 124 additions & 0 deletions .changesets/11154.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
- feat(rw-uploads): Create uploads package with prisma extension and upload processor (#11154) by @dac09

Introduces `@redwoodjs/uploads` package which houses

- Prisma extension for handling uploads. Currently
a) Query Extension: will save, delete, replace files on disk during CRUD
b) Result Extension: gives you functions like `.withSignedUri` on configured prisma results - which will take the paths, and convert it to a signed url
- Storage adapters e.g. FS and Memory to use with the prisma extension
- Processors - i.e. utility functions which will take [`Files`](https://developer.mozilla.org/en-US/docs/Web/API/File) and save them to storage

## Usage

In `api/src/uploads.ts` - setup uploads - processors, storage and the prisma extension.

```ts
// api/src/lib/uploads.ts

import { UploadsConfig } from '@redwoodjs/uploads'
import { setupUploads } from '@redwoodjs/uploads'
import { FileSystemStorage } from '@redwoodjs/uploads/FileSystemStorage'
import { UrlSigner } from '@redwoodjs/uploads/signedUrl'

const uploadConfig: UploadsConfig = {
// 👇 prisma model
profile: {
// 👇 pass in fields that are going to be File uploads
// these should be configured as string in the Prisma.schema
fields: ['avatar', 'coverPhoto'],
},
}

// 👇 exporting these allows you access elsewhere on the api side
export const storage = new FileSystemStorage({
baseDir: './uploads',
})

// Optional
export const urlSigner = new UrlSigner({
secret: process.env.UPLOADS_SECRET,
endpoint: '/signedUrl',
})

const { uploadsProcessors, prismaExtension, fileListProcessor } = setupUploads(
uploadConfig,
storage,
urlSigner,
)

export { uploadsProcessors, prismaExtension, fileListProcessor }
```

### Configuring db to use the prisma extension

```ts
// api/src/lib/db.ts

import { PrismaClient } from '@prisma/client'

import { emitLogLevels, handlePrismaLogging } from '@redwoodjs/api/logger'

import { logger } from './logger'
import { prismaExtension } from './uploads'

// 👇 Notice here we create prisma client, and don't export it yet
export const prismaClient = new PrismaClient({
log: emitLogLevels(['info', 'warn', 'error']),
})

handlePrismaLogging({
db: prismaClient,
logger,
logLevels: ['info', 'warn', 'error'],
})

// 👇 Export db after adding uploads extension
export const db = prismaClient.$extends(prismaExtension)
```

## Using Prisma extension

### A) CRUD operations

No need to do anything here, but you have to use processors to supply Prisma with data in the correct format.

### B) Result extensions

```ts
// api/src/services/profiles/profiles.ts

export const profile: QueryResolvers['profile'] = async ({ id }) => {
// 👇 await the result from your prisma query
const profile = await db.profile.findUnique({
where: { id },
})

// Convert the avatar and coverPhoto fields to signed URLs
// Note that you still need to add a api endpoint to handle these signed urls
return profile?.withSignedUrl()
}
```

## Using processors

In your services, you can use the preconfigured "processors" to convert Files to strings for Prisma to save into the database. The processors, and storage adapters determine where the file is saved.

```ts
// api/src/services/profiles/profiles.ts

export const updateProfile: MutationResolvers['updateProfile'] = async ({
id,
input,
}) => {
const processedInput = await uploadsProcessors.processProfileUploads(input)

// This becomes a string 👇
// The configuration on where it was saved is passed when we setup uploads in src/lib/uploads.ts
// processedInput.avatar = '/mySavePath/profile/avatar/generatedId.jpg'

return db.profile.update({
data: processedInput,
where: { id },
})
}
```
6 changes: 6 additions & 0 deletions .changesets/11367.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- fix(template): api type declaration merging for scripts (#11367) by @Tobbe

Make imports in scripts (files in `scripts/`) find our mirror types used for declaration merging also for `api/src/` imports (not just web imports)

Users upgrading are adviced to manually upgrade their tsconfig files to match
what is now in the template.
5 changes: 5 additions & 0 deletions .changesets/11378.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- feat(uploads): Add File scalar to rootSchema (#11378) by @dac09

Adds `File` scalar to rootSchema, to enable parsing fields set to File as a https://developer.mozilla.org/en-US/docs/Web/API/File

The parsing and scalar is actually built in to GraphQL Yoga, this change just enables it by default instead of having to add `scalar File` to one or more of your SDLs.
29 changes: 29 additions & 0 deletions .changesets/11379.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
- template(db): Update `api/src/lib/db` template (#11379) by @dac09

Updates the template in `api/src/lib/db.{js,ts}` to export `db` differently.

In your existing projects, you can make the following changes:

```diff

import { PrismaClient } from '@prisma/client'

import { emitLogLevels, handlePrismaLogging } from '@redwoodjs/api/logger'

import { logger } from './logger'
import { prismaExtension } from './uploads'

- export const db = new PrismaClient({
+ const prismaClient = new PrismaClient({
log: emitLogLevels(['info', 'warn', 'error']),
})

handlePrismaLogging({
- db
+ db: prismaClient,
logger,
logLevels: ['info', 'warn', 'error'],
})

+ export const db = prismaClient
```
3 changes: 3 additions & 0 deletions .changesets/11383.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- few Flightcontrol template & doc updates (#11383) by @flybayer

Updates the flight control deployment command and documentation. Corrects issue #10754 which is to do with an outdated database setup.
9 changes: 9 additions & 0 deletions .changesets/11390.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- feat(storage): Add support for createMany, updateMany and upsert (#11390) by @dac09

Extends the uploads Prisma client extension with the following:

1. `createMany`: support for bulk creation with automatic cleanup of uploaded files if the operation fails.

2. `updateMany`: bulk update functionality that manages file uploads across multiple records, including removal of old files after successful updates.

3. `upsert`: determining whether it's an insert or update and managing file uploads accordingly - delete files on creation fail, and replace files on update
7 changes: 7 additions & 0 deletions .changesets/11406.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
- feat(rsc): Initial support for RSA rerender (#11406) by @Tobbe

This PR makes it so that the entire page is re-rendered when a React Server Action returns.
Previously when calling an RSA you'd only get the result of the action back.
Now, when calling an RSA you'll still get the result back, and in addition to that the page will update.
What this means is that if you for example update a counter on the server that a server component is displaying that counter will now immediately update.
Also, if some data has been updated by something external to the app the new data will be displayed (like if someone used an external CMS to update some .md file you're rendering)
38 changes: 38 additions & 0 deletions .changesets/11411.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
- chore(uploads): Reorganise, change uploads package to storage (#11411) by @dac09

This PR does the following:

- renames `@redwoodjs/uploads` -> `@redwoodjs/storage`
- Renames `processors` -> `savers`

They now look like this:

```ts
// reads much nicer ✅
const processedInput = await saveFiles.forProfile(input)

// avatar is a File becomes a string
// processedInput.avatar =
// '/basePath/uploads/profile-avatar-01J6ACDPWAER8B1SAXPKQK5YA1.png'

const profile = await db.profile.update({
data: processedInput,
where: { id },
})
```

even though when you export it, it looks weird

```ts
// api/src/lib/uploads.ts
const { saveFiles, storagePrismaExtension } = setupStorage({
//...
})

export { saveFiles, storagePrismaExtension }
```

The naming convention is:
`for<Model>` - takes inputs in the shape of a Prisma data for that model but with Files instead of strings. The files get saved to storage, and a key/path is replaced in the value.

`inList` - does the same, but only takes an array of File, and returns an array of stored paths/keys
15 changes: 15 additions & 0 deletions .changesets/11412.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
- feat(uploads): Increase default fastify body limit to 100MB (#11412) by @dac09

Increases the default limit for receiving requests to 100MB (instead of 15MB). This number is arbitrary really, but it is the TOTAL size of the request, not of each file being uploaded.

The user can override this in their server file.

```jsx
// api/server.js
const server = await createServer({
logger,
fastifyServerOptions: {
bodyLimit: 1048576 * 2, // 2 MiB
},
})
```
3 changes: 3 additions & 0 deletions .changesets/11414.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- fix(cli-helpers): Don't add spaces around `=` for env vars (#11414) by @Tobbe

The `addEnvVar` helper function in `packages/cli-helpers` no longer adds spaces around `=` when setting environment variables.
22 changes: 22 additions & 0 deletions .changesets/8556.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
- feat(codegen): support sdl generation for model with compound id (#8556) by @russell-dot-js

The SDL generator will no longer error when handling a table with a composite id, like so:

```prisma
model Order {
tenantId String
id String @unique @default(uuid())
@@id([tenantId, id])
}
```

It will now generate code in the SDL that handles input of both these variables:

```gql
input TempIdInput {
tenantId: String!
id: String!
}
```

If you are using a custom `sdl.{j,t}s.template` then you may have to update it to support the new `idInput`.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ module.exports = {
'packages/babel-config/src/__tests__/__fixtures__/**/*',
'packages/codemods/**/__testfixtures__/**/*',
'packages/cli/**/__testfixtures__/**/*',
'packages/storage/src/__tests__/prisma-client/*',
],
rules: {
curly: 'error',
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/check-changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions: {}

jobs:
check-changesets:
name: 📝 Check changesets
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- name: Set up job
uses: ./.github/actions/set-up-job
with:
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/check-create-redwood-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions: {}

jobs:
check-create-redwood-app:
name: Check create redwood app
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- name: Set up job
uses: ./.github/actions/set-up-job
with:
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/check-test-project-fixture.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions: {}

jobs:
detect-changes:
if: github.repository == 'redwoodjs/redwood'
Expand All @@ -22,7 +24,7 @@ jobs:
ssr: ${{ steps.detect-changes.outputs.ssr }}

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- name: Set up job
uses: ./.github/actions/set-up-job
with:
Expand All @@ -40,7 +42,7 @@ jobs:
name: Check test project fixture
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

- name: Set up job
if: "!contains(github.event.pull_request.labels.*.name, 'fixture-ok')"
Expand Down
Loading

0 comments on commit 512bb59

Please sign in to comment.