-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor: extract `BaseClient` from `Client` * feat: `WriteClient` * feat: `Migration` * test: type test migration types * refactor: `MigrationPrismicDocumentParams` * wip: `client.migrate` * feat: patch migration document data * feat: discover existing images automatically * fix: handle edge cases and log API responses properly * fix: use `JSON.parse` instead of `JSON.stringify` * docs: document new code * docs: document new warning messages * feat: validate assets metadata * refactor: skip initial delay on `pLimit` when possible * test: `Client` updated constructor * test: `Migration` class * test: `WriteClient` constructor * test: setup mocks for asset API and migration API * style: lint * test: `WriteClient` core methods * chore(deps): bump `@prismicio/mock` * fix tests on old node version * test: skip tests on specific node version * style: unused variable * refactor: `WriteClient.migrate` reporter * refactor: use more predictable asset API in tests * test: `WriteClient.migrateCreateAssets` * test: `WriteClient.migrateCreateDocuments` * test: ensure unique repository name for all tests * test: `WriteClient.fetchForeignAsset` * test: `WriteClient.migrateUpdateDocuments` (WIP) * test: `WriteClient.migrateUpdateDocuments` * test: `pLimit` * test: skip `WriteClient.fetchForeignAsset` tests on Node 18 * refactor: per self review * refactor: use random API key pool for migration API demo * docs: capitalize `Migration API` * docs: messages copy editing * chore: ignore all `.tgz` files * refactor: `apiEndpoint` to `documentAPIEndpoint` Co-authored-by: Angelo Ashmore <angeloashmore@users.noreply.github.com> * docs: wording Co-authored-by: Angelo Ashmore <angeloashmore@users.noreply.github.com> * refactor: per review (API, wording, tests) Co-authored-by: Angelo Ashmore <angeloashmore@users.noreply.github.com> * fix: stronger `is.richText` helper * refactor: per review (API, tests) * refactor: use classes to detect migration field * chore: rename file casing * refactor: rename `_prepare` to `_resolve` * refactor: abstract thunks under `Migration#createContentRelationship` * docs: document new types * refactor: simplify migration documents traversing * refactor: remove documents and assets maps * refactor: remove existing assets querying * refactor: remove `dependencies` concept * refactor: remove `MigrationContentRelationship` class * refactor: remove all child asset classes * refactor: remove `addThumbnail` method * refactor: tests naming * refactor: per review * fix: allow not updating document's title * fix: missing migration embed and slice types * docs: add `migrate` example --------- Co-authored-by: lihbr <lihbr@users.noreply.github.com> Co-authored-by: Angelo Ashmore <angeloashmore@users.noreply.github.com>
- Loading branch information
1 parent
088f9c5
commit 7dc2950
Showing
93 changed files
with
15,270 additions
and
2,078 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 |
---|---|---|
|
@@ -3,6 +3,7 @@ CHANGELOG.md | |
# .gitignore copy | ||
|
||
# custom | ||
*.tgz | ||
dist | ||
examples/**/package-lock.json | ||
|
||
|
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 |
---|---|---|
@@ -1,4 +1,5 @@ | ||
# custom | ||
*.tgz | ||
dist | ||
examples/**/package-lock.json | ||
|
||
|
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 |
---|---|---|
|
@@ -4,6 +4,7 @@ CHANGELOG.md | |
# .gitignore copy | ||
|
||
# custom | ||
*.tgz | ||
dist | ||
examples/**/package-lock.json | ||
|
||
|
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,26 @@ | ||
# Migrate | ||
|
||
This example shows a migration script leveraging `@prismicio/client`'s write client | ||
and the migration helper to migrate existing content to Prismic. `migrate.ts` is the | ||
TypeScript exact equivalent of `migrate.mjs`. | ||
|
||
Learn more about migrating to Prismic on the [migration documentation](https://prismic.io/docs/migration). | ||
|
||
## How to run the example | ||
|
||
> Scripts in this example uses an hypothetical WordPress client, therefore, they are not runnable as-is. | ||
```sh | ||
# Clone the repository to your computer | ||
git clone https://github.com/prismicio/prismic-client.git | ||
cd prismic-client/examples/migrate | ||
|
||
# Install the dependencies | ||
npm install | ||
|
||
# Run the example (TypeScript) | ||
npx tsx migrate.ts | ||
|
||
# Run the example (JavaScript) | ||
node migrate.mjs | ||
``` |
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,101 @@ | ||
import * as prismic from "@prismicio/client" | ||
import { htmlAsRichText } from "@prismicio/migrate" | ||
import "dotenv/config" | ||
// An hypothetical WordPress client | ||
import { createWordPressClient } from "wordpress" | ||
|
||
import { repositoryName } from "./slicemachine.config.json" | ||
|
||
// Prismic setup | ||
const writeClient = prismic.createWriteClient(repositoryName, { | ||
writeToken: process.env.PRISMIC_WRITE_TOKEN, | ||
}) | ||
|
||
const migration = prismic.createMigration() | ||
|
||
// Custom migration script logic | ||
|
||
const convertWPDocument = (wpDocument) => { | ||
switch (wpDocument.type) { | ||
case "page": | ||
return convertWPPage(wpDocument) | ||
case "settings": | ||
return convertWPSettings(wpDocument) | ||
} | ||
|
||
throw new Error(`Unsupported document type: ${wpDocument.type}`) | ||
} | ||
|
||
const convertWPPage = (wpPage) => { | ||
return migration.createDocument( | ||
{ | ||
type: "page", | ||
lang: wpPage.lang, | ||
uid: wpPage.slug, | ||
tags: ["wordpress"], | ||
data: { | ||
meta_title: wpPage.meta_title, | ||
meta_description: wpPage.meta_description, | ||
meta_image: migration.createAsset( | ||
wpPage.meta_image.url, | ||
wpPage.meta_image.name, | ||
), | ||
title: wpHTMLAsRichText(wpPage.title), | ||
body: wpHTMLAsRichText(wpPage.content), | ||
}, | ||
}, | ||
wpPage.name, | ||
{ | ||
masterLanguageDocument: () => | ||
migration.getByUID( | ||
wpPage.masterLanguageDocument.type, | ||
wpPage.masterLanguageDocument.uid, | ||
), | ||
}, | ||
) | ||
} | ||
|
||
const convertWPSettings = (wpSettings) => { | ||
return migration.createDocument( | ||
{ | ||
type: "settings", | ||
lang: wpSettings.lang, | ||
tags: ["wordpress"], | ||
data: { | ||
title: wpHTMLAsRichText(wpSettings.name), | ||
}, | ||
}, | ||
"Settings", | ||
) | ||
} | ||
|
||
const wpHTMLAsRichText = (html) => { | ||
return htmlAsRichText(html, { | ||
serializer: { | ||
img: ({ node }) => { | ||
const src = node.properties.src | ||
const filename = src.split("/").pop() | ||
const alt = node.properties.alt | ||
|
||
return { | ||
type: "image", | ||
id: migration.createAsset(src, filename, { alt }), | ||
} | ||
}, | ||
}, | ||
}).result | ||
} | ||
|
||
// Fetching and converting WordPress documents | ||
const wpClient = createWordPressClient("https://example.com/wp-json") | ||
|
||
const wpDocuments = await wpClient.dangerouslyGetAllDocuments() | ||
|
||
for (const wpDocument of wpDocuments) { | ||
convertWPDocument(wpDocument) | ||
} | ||
|
||
// Execute the prepared migration at the very end of the script | ||
await writeClient.migrate(migration, { | ||
reporter: (event) => console.info(event), | ||
}) |
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,102 @@ | ||
import * as prismic from "@prismicio/client" | ||
import { htmlAsRichText } from "@prismicio/migrate" | ||
import "dotenv/config" | ||
// An hypothetical WordPress client | ||
// @ts-expect-error - This is an hypothetical WordPress client | ||
import { type WPDocument, createWordPressClient } from "wordpress" | ||
|
||
import { repositoryName } from "./slicemachine.config.json" | ||
|
||
// Prismic setup | ||
const writeClient = prismic.createWriteClient(repositoryName, { | ||
writeToken: process.env.PRISMIC_WRITE_TOKEN!, | ||
}) | ||
|
||
const migration = prismic.createMigration() | ||
|
||
// Custom migration script logic | ||
|
||
const convertWPDocument = (wpDocument: WPDocument) => { | ||
switch (wpDocument.type) { | ||
case "page": | ||
return convertWPPage(wpDocument) | ||
case "settings": | ||
return convertWPSettings(wpDocument) | ||
} | ||
|
||
throw new Error(`Unsupported document type: ${wpDocument.type}`) | ||
} | ||
|
||
const convertWPPage = (wpPage: WPDocument) => { | ||
return migration.createDocument( | ||
{ | ||
type: "page", | ||
lang: wpPage.lang, | ||
uid: wpPage.slug, | ||
tags: ["wordpress"], | ||
data: { | ||
meta_title: wpPage.meta_title, | ||
meta_description: wpPage.meta_description, | ||
meta_image: migration.createAsset( | ||
wpPage.meta_image.url, | ||
wpPage.meta_image.name, | ||
), | ||
title: wpHTMLAsRichText(wpPage.title), | ||
body: wpHTMLAsRichText(wpPage.content), | ||
}, | ||
}, | ||
wpPage.name, | ||
{ | ||
masterLanguageDocument: () => | ||
migration.getByUID( | ||
wpPage.masterLanguageDocument.type, | ||
wpPage.masterLanguageDocument.uid, | ||
), | ||
}, | ||
) | ||
} | ||
|
||
const convertWPSettings = (wpSettings: WPDocument) => { | ||
return migration.createDocument( | ||
{ | ||
type: "settings", | ||
lang: wpSettings.lang, | ||
tags: ["wordpress"], | ||
data: { | ||
title: wpHTMLAsRichText(wpSettings.name), | ||
}, | ||
}, | ||
"Settings", | ||
) | ||
} | ||
|
||
const wpHTMLAsRichText = (html: string) => { | ||
return htmlAsRichText(html, { | ||
serializer: { | ||
img: ({ node }) => { | ||
const src = node.properties.src as string | ||
const filename = src.split("/").pop()! | ||
const alt = node.properties.alt as string | ||
|
||
return { | ||
type: "image", | ||
id: migration.createAsset(src, filename, { alt }), | ||
} | ||
}, | ||
}, | ||
}).result | ||
} | ||
|
||
// Fetching and converting WordPress documents | ||
const wpClient = createWordPressClient("https://example.com/wp-json") | ||
|
||
const wpDocuments = await wpClient.dangerouslyGetAllDocuments() | ||
|
||
for (const wpDocument of wpDocuments) { | ||
convertWPDocument(wpDocument) | ||
} | ||
|
||
// Execute the prepared migration at the very end of the script | ||
await writeClient.migrate(migration, { | ||
reporter: (event) => console.info(event), | ||
}) |
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,11 @@ | ||
{ | ||
"type": "module", | ||
"dependencies": { | ||
"@prismicio/client": "latest", | ||
"@prismicio/migrate": "latest" | ||
}, | ||
"devDependencies": { | ||
"tsx": "^4.19.1", | ||
"typescript": "^5.6.2" | ||
} | ||
} |
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,6 @@ | ||
{ | ||
"libraries": ["./slices"], | ||
"adapter": "@slicemachine/adapter-next", | ||
"repositoryName": "qwerty", | ||
"localSliceSimulatorURL": "http://localhost:3000/slice-simulator" | ||
} |
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,14 @@ | ||
{ | ||
"compilerOptions": { | ||
"target": "esnext", | ||
"lib": ["esnext"], | ||
"module": "esnext", | ||
"moduleResolution": "bundler", | ||
"resolveJsonModule": true, | ||
"strict": true, | ||
"strictNullChecks": true, | ||
"esModuleInterop": true, | ||
"skipDefaultLibCheck": true, | ||
"skipLibCheck": true | ||
} | ||
} |
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,23 @@ | ||
# Avoid write client in browser | ||
|
||
`@prismicio/client`'s write client uses credentials to authenticate write queries to a Prismic repository. | ||
|
||
The repository write token and Migration API key must be provided when creating a `@prismicio/client` write client like the following: | ||
|
||
```typescript | ||
import * as prismic from "@prismicio/client"; | ||
|
||
const writeClient = prismic.createWriteClient("example-prismic-repo", { | ||
writeToken: "xxx" | ||
}) | ||
``` | ||
|
||
If the write client is exposed to the browser, so are its tokens. Malicious actors will have write access to your repository. | ||
|
||
Use the non-write client when write actions are not needed. The non-write client only has read access to the repository and can safely be used in the browser. Be aware the client's access token, if used, will be exposed in the browser. | ||
|
||
```typescript | ||
import * as prismic from "@prismicio/client"; | ||
|
||
const client = prismic.createClient("example-prismic-repo") | ||
``` |
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
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,29 @@ | ||
# Prefer repository name | ||
|
||
`@prismicio/client` uses either a Prismic repository name or a repository-specific Document API endpoint to query content from Prismic. | ||
|
||
The repository name must be provided when creating a `@prismicio/client` like the following: | ||
|
||
```typescript | ||
import * as prismic from "@prismicio/client"; | ||
|
||
const client = prismic.createClient("example-prismic-repo") | ||
``` | ||
|
||
When proxying a Prismic API v2 repository endpoint (not recommended), the `documentAPIEndpoint` option can be used to specify that endpoint. | ||
|
||
```typescript | ||
import * as prismic from "@prismicio/client" | ||
|
||
// ✅ Correct | ||
const client = prismic.createClient("my-repo-name", { | ||
documentAPIEndpoint: "https://example.com/my-prismic-proxy" | ||
}) | ||
|
||
// ❌ Incorrect: repository name can't be inferred from a proxied endpoint | ||
const client = prismic.createClient("https://example.com/my-prismic-proxy", { | ||
documentAPIEndpoint: "https://example.com/my-prismic-proxy" | ||
}) | ||
``` | ||
|
||
Proxying a Prismic API v2 repository endpoint can have unexpected side-effects and cause performance issues when querying Prismic. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
Oops, something went wrong.