-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migration Guide from v4 to v5 (#1406)
Co-authored-by: Johannes Obermair <48853629+johnnyomair@users.noreply.github.com>
- Loading branch information
1 parent
cde6c8c
commit 02ac607
Showing
2 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
title: Migration | ||
sidebar_position: 12 | ||
--- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
--- | ||
title: Migrating from v4 to v5 | ||
sidebar_position: 1 | ||
--- | ||
|
||
# Migrating from v4 to v5 | ||
|
||
## API | ||
|
||
### blocks-meta.json | ||
|
||
The key (type) of OneOfBlocks is now included in the `blocks-meta.json`. | ||
|
||
This is only a problem if you still have your own `generate-block-types.ts` in your project. In that case, you must switch to `@comet/cli`: | ||
|
||
1. Install `@comet/cli` as a dev dependency | ||
2. Replace the scripts in the package.json of your admin: | ||
|
||
```diff | ||
- "generate-block-types": "dotenv -c -- ts-node generate-block-types.ts", | ||
+ "generate-block-types": "comet generate-block-types --inputs", | ||
``` | ||
|
||
3. Replace the scripts in the package.json of your site: | ||
|
||
```diff | ||
- "generate-block-types": "dotenv -c -- ts-node generate-block-types.ts", | ||
+ "generate-block-types": "comet generate-block-types", | ||
``` | ||
|
||
### indexData() | ||
|
||
Previously, `BlockIndexData` had one field: `damFileIds`. It could only represent dependencies to DAM files. Now, `BlockIndexData` has a generic `dependencies` field. It can represent dependencies to any entity. | ||
|
||
The `indexData()` method of a block must be refactored | ||
|
||
```diff | ||
indexData(): BlockIndexData { | ||
- return { | ||
- damFileIds: this.damFileId ? [this.damFileId] : [], | ||
- }; | ||
+ if (this.damFileId === undefined) { | ||
+ return {}; | ||
+ } | ||
+ | ||
+ return { | ||
+ dependencies: [ | ||
+ { | ||
+ targetEntityName: File.name, | ||
+ id: this.damFileId, | ||
+ }, | ||
+ ], | ||
+ }; | ||
} | ||
``` | ||
|
||
### FilesService.upload() | ||
|
||
The method signature changed. | ||
The second argument is now an options object. | ||
You may have to adjust this in your fixtures. | ||
|
||
```diff | ||
- await filesService.upload(file, folderId); | ||
+ await filesService.upload(file, { folderId }); | ||
``` | ||
|
||
### @IsOptional() -> @IsUndefinable() and @IsNullable() | ||
|
||
`class-validator` offers the `@IsOptional()` decorator that allows `undefined` and `null`. | ||
COMET now offers the more specific `@IsUndefinable()` and `@IsNullable()` decorators to avoid bugs. | ||
Use these decorators from now on and (if possible) replace existing `@IsOptional()` with `@IsUndefinable()` or `@IsNullable()`. | ||
|
||
### PartialType | ||
|
||
COMET now has an own implementation of `PartialType` using `@IsUndefinable()` (instead of `@IsOptional()`). | ||
Uses of `PartialType` from `@nestjs/mapped-types` should be replaced with `PartialType` from `@comet/cms-api`. | ||
|
||
## Admin | ||
|
||
### Admin Generator | ||
|
||
Add the following command to the `package.json` of your admin app: | ||
|
||
```diff | ||
+ "admin-generator": "rimraf 'src/*/generated' && comet-admin-generator generate crud-generator-config.ts", | ||
``` | ||
|
||
### Documents (DocumentInterface) | ||
|
||
The `DocumentInterface` now requires a `dependencies()` and a `replaceDependenciesInOutput()` method. However, you don't have to implement them yourself. | ||
|
||
**Instead, use the new `createDocumentRootBlocksMethods()` to generate the methods.** | ||
It further generates `anchors()` and `inputToOutput()`. | ||
|
||
```diff | ||
export const Page: DocumentInterface<Pick<GQLPage, "content" | "seo">, GQLPageInput> = { | ||
// ... | ||
- inputToOutput: (input) => {}, | ||
- anchors: (input) => {}, | ||
+ ...createDocumentRootBlocksMethods({ | ||
+ content: PageContentBlock, | ||
+ seo: SeoBlock, | ||
+ }), | ||
}; | ||
``` | ||
|
||
### Blocks (BlockInterface) | ||
|
||
The `BlockInterface` now has the methods `dependencies()` and `replaceDependenciesInOutput()`. | ||
However, you usually don't have to implement them. Only if your block has dependencies to some entity (e.g. a link to a `PageTreeNode` or uses a `DamFile`). | ||
|
||
`dependencies()` returns the dependency information for the block. It could look like this: | ||
|
||
```tsx | ||
dependencies: (state) => { | ||
const dependencies: BlockDependency[] = []; | ||
|
||
if (state.damFile?.id) { | ||
dependencies.push({ | ||
targetGraphqlObjectType: "DamFile", | ||
id: state.damFile.id, | ||
data: { | ||
damFile: state.damFile, | ||
}, | ||
}); | ||
} | ||
|
||
return dependencies; | ||
}; | ||
``` | ||
|
||
`replaceDependenciesInOutput()` replaces the IDs of your dependencies when copying the block to another scope: | ||
|
||
```tsx | ||
replaceDependenciesInOutput: (output, replacements) => { | ||
const clonedOutput: PixelImageBlockInput = deepClone(output); | ||
const replacement = replacements.find((replacement) => replacement.type === "DamFile" && replacement.originalId === output.damFileId); | ||
|
||
if (replacement) { | ||
clonedOutput.damFileId = replacement.replaceWithId; | ||
} | ||
|
||
return clonedOutput; | ||
}; | ||
``` | ||
|
||
### BlockPreview | ||
|
||
The `BlockPreview` component was removed. Instead, use `BlockPreviewContent`: | ||
|
||
```diff | ||
- const state = linkBlock.input2State(params.value); | ||
|
||
- return <BlockPreview title={linkBlock.dynamicDisplayName?.(state) ?? linkBlock.displayName} content={linkBlock.previewContent(state)} />; | ||
+ return <BlockPreviewContent block={linkBlock} input={params.value} />; | ||
``` | ||
|
||
### @comet/admin | ||
|
||
#### Loading | ||
|
||
The `Loading` component now uses our `BallTriangle` instead of MUI's `CircularProgress`. If you use the `size` prop, you must now use `sx` instead: | ||
|
||
```diff | ||
- <Loading behavior="fillParent" size={20} color="inherit" /> | ||
+ <Loading behavior="fillParent" sx={{ fontSize: 20 }} color="inherit" /> | ||
``` | ||
|
||
#### FinalFormSelect | ||
|
||
The `getOptionSelected()` prop was removed from `FinalFormSelect` and replaced with `getOptionValue()` in order to support multi-select. | ||
|
||
If you had a custom implementation of `getOptionSelected()`, you may need to replace it with a custom `getOptionValue()`. However, for most cases the [default implementation](https://github.com/vivid-planet/comet/commit/fe5e0735#diff-ef93179fe4c6d99e9e776fb1e928ac8b5af12c27fa2d2a6ea124e46028fb8b95R28-R31) will be sufficient. | ||
|
||
#### FilterBarMoreFilters | ||
|
||
The `textWrapper` class of `FilterBarMoreFilters` was removed. Use the new `button` class instead. | ||
|
||
## ESLint | ||
|
||
### no-private-sibling-import | ||
|
||
The new rule `no-private-sibling-import` bans imports of private sibling files. | ||
Meaning, a file called `Foo.gql.ts` next to a `Foo.ts` can only be imported by `Foo.ts` and no other file. |