diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ada265a87f..2382dab2a6 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,4 +4,4 @@ # the repo. Unless a later match takes precedence, # @global-owner1 and @global-owner2 will be requested for # review when someone opens a pull request. -* @prismicio/devs \ No newline at end of file +* @prismicio/dev-tools diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 594b26b5c3..9e7dbb2322 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,56 +1,146 @@ -# Slice Machine Contributing Guide +# Contributing -Whether you're helping us fix bugs, improve the docs, or spread the word, we'd love to have you as part of the Prismic developer community! +This package is primarily maintained by [Prismic](https://prismic.io)[^1]. External contributions are welcome. Ask for help by [opening an issue](https://github.com/prismicio/slice-machine/issues/new/choose), or request a review by opening a pull request. -**Asking a question**: [Open a new topic][forum-question] on our community forum explaining what you want to achieve / your question. Our support team will get back to you shortly. +## :gear: Setup -**Reporting a bug**: [Open an issue][repo-bug-report] explaining your application's setup and the bug you're encountering. + -**Suggesting an improvement**: [Open an issue][repo-feature-request] explaining your improvement or feature so we can discuss and learn more. +The following setup is required to work on this project: -**Submitting code changes**: For small fixes, feel free to [open a PR][repo-pull-requests] with a description of your changes. For large changes, please first [open an issue][repo-feature-request] so we can discuss if and how the changes should be implemented. +- Node.js +- npm CLI +- Yarn -## Local development +## :memo: Project-specific notes -Clone the `slice-machine` repository to your local machine. + + -``` -git clone https://github.com/prismicio/slice-machine.git -``` +> [!TIP] +> Please update this section with helpful notes for contributors. -Move into the folder, enable [Corepack](https://nodejs.org/dist/latest/docs/api/corepack.html) and install the dependencies. +#### "SM" Types -``` +- Slice Machine contains Slice Machine-specific versions of some `@prismicio/types-internal` types. For example, Slice Machine's `GroupSM` is a modified version of `@prismicio/types-internal`'s `Group`. +- The "SM" types contain reshaped data that make it easy to perform Slice Machine-specific transformations. For example, `GroupSM` uses an array to define its fields while `Group` uses an object. The array makes it easy to change the order of fields. +- "SM" types have `fromSM` and `toSM` helpers to convert one data type into the other. +- The "SM" types will be removed at some point in the future to simplify cross-repository development. + +#### Tests + +##### Unit and integration with Vitest + +- `slice-machine-ui` contains unit and integration tests. The integration tests have been superseded by Playwright tests and will likely be removed in the future. Unit tests can be written as needed. +- All other packages in the monorepo contain integration tests written using Vitest. + +##### End-to-end with Playwright + +See [playwright/README.md](./playwright/README.md) for details. + +#### Sentry + +- Sentry monitors errors in production. +- Check Sentry regularly for errors. Especially check Sentry after publishing new package versions. + +## :construction_worker: Develop + +> [!NOTE] +> It's highly recommended to discuss your changes with the Prismic team before starting by [opening an issue](https://github.com/prismicio/slice-machine/issues/new/choose).[^2] +> +> A short discussion can accelerate your work and ship it faster. + +```sh +# Clone and prepare the project. +git clone git@github.com:prismicio/slice-machine.git cd slice-machine -corepack enable -yarn -``` +yarn install -Start up the dev server. +# Create a new branch for your changes (e.g. lh/fix-win32-paths). +git checkout -b / +# Start the development watcher. +# Run this command while you are working on your changes. +yarn run dev + +# Build the project for production. +# Run this command when you want to see the production version. +yarn run build + +# Lint your changes before requesting a review. No errors are allowed. +yarn run lint + +# Format your changes before requesting a review. No errors are allowed. +yarn run prettier:check +# Errors can be fixed automatically: +yarn run prettier:fix + +# Test your changes before requesting a review. +# All changes should be tested. No failing tests are allowed. +yarn run test ``` -yarn dev -``` -Now that the dev server is running you can start the Next.js project used for testing. Move into the `e2e-projects/next` folder and run the `slicemachine:dev` script. +To start the development version of Slice Machine with a Prismic repository, use the `play` script. + +`yarn play` requires the `yarn dev` script to be running in the background. + +```sh +# Start the most recent playground or create one if none exist. +yarn play + +# Start an existing playground or create one if it doesn't exist. +yarn play my-playground-name + +# Force create a new playground +yarn play --new +yarn play --new my-playground-name + +# Specify a framework (default: next) +yarn play -f sveltekit +yarn play --framework sveltekit +# If `-f` is passed with a playground name and the playground +# already exists, halt. If the playground does not exist, create +# a new one with that framework. +yarn play -f sveltekit my-playground-name + +# Don't start the project +yarn play --no-start + +# Dry run +yarn play -n +yarn play --dry-run ``` -cd e2e-projects/next -yarn slicemachine:dev + +## :building_construction: Submit a pull request + +> [!NOTE] +> Code will be reviewed by the Prismic team before merging.[^3] +> +> Request a review by opening a pull request. + +```sh +# Open a pull request. This example uses the GitHub CLI. +gh pr create + +# Someone from the Prismic team will review your work. This review will at +# least consider the PR's general direction, code style, and test coverage. + +# When ready, PRs should be merged using the "Squash and merge" option. ``` -Now you can go to your browser and open `localhost:9999` to see the Slice Machine app up and running with some demo slices and types. -You're now ready to start working on your changes and see them updated in the app. +## :rocket: Publish -## E2E tests +> [!CAUTION] +> Publishing is restricted to the Prismic team.[^4] -In order to contribute to Slice Machine you will need to maintain and write new e2e tests: +Use the [**Publish stable**](https://github.com/prismicio/slice-machine/actions/workflows/publish-stable.yml) GitHub Action to publish a new version of Slice Machine and its child packages. -- [Slice Machine e2e tests documentation](./playwright/README.md) +Version increment types can be specified for each package using the action's workflow form. For example, you can choose to increment `slice-machine-ui` by a major, minor, or patch version. Select "decline" to skip incrementing the version. - +The GitHub Action is powered by a purpose-built script: `script/publish.ts`. -[forum-question]: https://community.prismic.io -[repo-bug-report]: https://github.com/prismicio/slice-machine/issues/new?assignees=&labels=bug&template=bug_report.md&title= -[repo-feature-request]: https://github.com/prismicio/slice-machine/issues/new?assignees=&labels=enhancement&template=feature_request.md&title= -[repo-pull-requests]: https://github.com/prismicio/slice-machine/pulls +[^1]: This package is maintained by the DevTools team. Prismic employees can ask for help or a review in the [#team-dev-tools](https://prismic-team.slack.com/archives/CPG31MDL1) Slack channel. +[^2]: Prismic employees are highly encouraged to discuss changes with the DevTools team in the [#team-dev-tools](https://prismic-team.slack.com/archives/CPG31MDL1) Slack channel before starting. +[^3]: Code should be reviewed by the DevTools team before merging. Prismic employees can request a review in the [#team-dev-tools](https://prismic-team.slack.com/archives/CPG31MDL1) Slack channel. +[^4]: Prismic employees can ask the DevTools team for [npm](https://www.npmjs.com) publish access. diff --git a/README.md b/README.md index 47f686b69a..402562fc26 100644 --- a/README.md +++ b/README.md @@ -22,13 +22,16 @@ For the smoothest onboarding experience, go to [Prismic][prismic-dashboard], cre If you want to dive in without any guidance, follow these steps: -Create a Next.js or Nuxt app: +Create a Next.js, Nuxt, or SvelteKit app: ``` npx create-next-app@latest my-app ``` ``` npx nuxi@latest init my-app ``` +``` +npm create svelte@latest my-app +``` Open the folder: ``` @@ -77,19 +80,19 @@ Whether you're helping us fix bugs, improve the docs, or spread the word, we'd l ## License ``` - Copyright 2013-2021 Prismic (https://prismic.io) +Copyright 2013-2024 Prismic (https://prismic.io) - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. ``` diff --git a/package.json b/package.json index ee93faf733..da061c65bd 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "resolutions": { "connected-next-router/react-redux": "8.0.7", "react-beautiful-dnd/react-redux": "8.0.7", - "@prismicio/types-internal": "2.4.1" + "@prismicio/types-internal": "2.5.0" }, "workspaces": [ "e2e-projects/next", diff --git a/packages/adapter-next/package.json b/packages/adapter-next/package.json index 9cf3e817d5..b3fd5e26fc 100644 --- a/packages/adapter-next/package.json +++ b/packages/adapter-next/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-next", - "version": "0.3.40", + "version": "0.3.42", "description": "Slice Machine adapter for Next.js.", "keywords": [ "typescript", @@ -67,7 +67,7 @@ }, "dependencies": { "@prismicio/simulator": "^0.1.4", - "@prismicio/types-internal": "^2.4.1", + "@prismicio/types-internal": "^2.5.0", "@slicemachine/plugin-kit": "workspace:*", "common-tags": "^1.8.2", "fp-ts": "^2.13.1", @@ -76,8 +76,7 @@ "lz-string": "1.5.0", "monocle-ts": "^2.3.13", "newtype-ts": "^0.3.5", - "pascal-case": "^3.1.2", - "prismic-ts-codegen": "^0.1.17" + "pascal-case": "^3.1.2" }, "devDependencies": { "@prismicio/mock": "0.2.0", @@ -96,6 +95,7 @@ "next": "14.1.3", "prettier": "3.0.3", "prettier-plugin-jsdoc": "1.1.1", + "prismic-ts-codegen": "^0.1.21", "react": "18.2.0", "rollup-plugin-preserve-directives": "0.2.0", "size-limit": "8.2.4", diff --git a/packages/adapter-next/src/hooks/project-init.ts b/packages/adapter-next/src/hooks/project-init.ts index 6039197d69..c95cc7ad0e 100644 --- a/packages/adapter-next/src/hooks/project-init.ts +++ b/packages/adapter-next/src/hooks/project-init.ts @@ -1,4 +1,3 @@ -import * as path from "node:path"; import type { ProjectInitHook, ProjectInitHookData, @@ -10,8 +9,8 @@ import { } from "@slicemachine/plugin-kit/fs"; import { source } from "common-tags"; +import { buildSrcPath } from "../lib/buildSrcPath"; import { checkHasAppRouter } from "../lib/checkHasAppRouter"; -import { checkHasSrcDirectory } from "../lib/checkHasSrcDirectory"; import { checkIsTypeScriptProject } from "../lib/checkIsTypeScriptProject"; import { getJSFileExtension } from "../lib/getJSFileExtension"; import { rejectIfNecessary } from "../lib/rejectIfNecessary"; @@ -45,15 +44,17 @@ const createPrismicIOFile = async ({ helpers, options, }); - const hasSrcDirectory = await checkHasSrcDirectory({ helpers }); + const hasSrcDirectory = await checkHasProjectFile({ + filename: "src", + helpers, + }); const hasAppRouter = await checkHasAppRouter({ helpers }); const extension = await getJSFileExtension({ helpers, options }); - const filename = path.join( - ...[hasSrcDirectory ? "src" : undefined, `prismicio.${extension}`].filter( - (segment): segment is NonNullable => Boolean(segment), - ), - ); + const filename = await buildSrcPath({ + filename: `prismicio.${extension}`, + helpers, + }); if (await checkHasProjectFile({ filename, helpers })) { return; @@ -255,20 +256,15 @@ const createSliceSimulatorPage = async ({ helpers, options, }); - const hasSrcDirectory = await checkHasSrcDirectory({ helpers }); const hasAppRouter = await checkHasAppRouter({ helpers }); const extension = await getJSFileExtension({ helpers, options, jsx: true }); - const filename = path.join( - ...[ - hasSrcDirectory ? "src" : undefined, - hasAppRouter - ? `app/slice-simulator/page.${extension}` - : `pages/slice-simulator.${extension}`, - ].filter((segment): segment is NonNullable => - Boolean(segment), - ), - ); + const filename = await buildSrcPath({ + filename: hasAppRouter + ? `app/slice-simulator/page.${extension}` + : `pages/slice-simulator.${extension}`, + helpers, + }); if (await checkHasProjectFile({ filename, helpers })) { return; @@ -350,7 +346,6 @@ const createPreviewRoute = async ({ helpers, options, }: SliceMachineContext) => { - const hasSrcDirectory = await checkHasSrcDirectory({ helpers }); const hasAppRouter = await checkHasAppRouter({ helpers }); const isTypeScriptProject = await checkIsTypeScriptProject({ helpers, @@ -358,16 +353,12 @@ const createPreviewRoute = async ({ }); const extension = await getJSFileExtension({ helpers, options }); - const filename = path.join( - ...[ - hasSrcDirectory ? "src" : undefined, - hasAppRouter - ? `app/api/preview/route.${extension}` - : `pages/api/preview.${extension}`, - ].filter((segment): segment is NonNullable => - Boolean(segment), - ), - ); + const filename = await buildSrcPath({ + filename: hasAppRouter + ? `app/api/preview/route.${extension}` + : `pages/api/preview.${extension}`, + helpers, + }); if (await checkHasProjectFile({ filename, helpers })) { return; @@ -447,7 +438,6 @@ const createExitPreviewRoute = async ({ helpers, options, }: SliceMachineContext) => { - const hasSrcDirectory = await checkHasSrcDirectory({ helpers }); const hasAppRouter = await checkHasAppRouter({ helpers }); const isTypeScriptProject = await checkIsTypeScriptProject({ helpers, @@ -455,16 +445,12 @@ const createExitPreviewRoute = async ({ }); const extension = await getJSFileExtension({ helpers, options }); - const filename = path.join( - ...[ - hasSrcDirectory ? "src" : undefined, - hasAppRouter - ? `app/api/exit-preview/route.${extension}` - : `pages/api/exit-preview.${extension}`, - ].filter((segment): segment is NonNullable => - Boolean(segment), - ), - ); + const filename = await buildSrcPath({ + filename: hasAppRouter + ? `app/api/exit-preview/route.${extension}` + : `pages/api/exit-preview.${extension}`, + helpers, + }); if (await checkHasProjectFile({ filename, helpers })) { return; @@ -514,7 +500,10 @@ const modifySliceMachineConfig = async ({ options, actions, }: SliceMachineContext) => { - const hasSrcDirectory = await checkHasSrcDirectory({ helpers }); + const hasSrcDirectory = await checkHasProjectFile({ + filename: "src", + helpers, + }); const project = await helpers.getProject(); // Add Slice Simulator URL. @@ -552,17 +541,11 @@ const createRevalidateRoute = async ({ return; } - const hasSrcDirectory = await checkHasSrcDirectory({ helpers }); - const extension = await getJSFileExtension({ helpers, options }); - const filename = path.join( - ...[ - hasSrcDirectory ? "src" : undefined, - `app/api/revalidate/route.${extension}`, - ].filter((segment): segment is NonNullable => - Boolean(segment), - ), - ); + const filename = await buildSrcPath({ + filename: `app/api/revalidate/route.${extension}`, + helpers, + }); if (await checkHasProjectFile({ filename, helpers })) { return; diff --git a/packages/adapter-next/src/hooks/snippet-read.ts b/packages/adapter-next/src/hooks/snippet-read.ts index 2f2b52ccdd..552be5725b 100644 --- a/packages/adapter-next/src/hooks/snippet-read.ts +++ b/packages/adapter-next/src/hooks/snippet-read.ts @@ -28,7 +28,7 @@ export const snippetRead: SnippetReadHook = async ( data, { helpers }, ) => { - const { fieldPath } = data; + const { fieldPath, itemName } = data; const label = "React"; @@ -88,8 +88,8 @@ export const snippetRead: SnippetReadHook = async ( const code = await format( stripIndent` <> - {${dotPath(fieldPath)}.map((item) => { - // Render the item + {${dotPath(fieldPath)}.map((${itemName}) => { + // Render the ${itemName} })} `, diff --git a/packages/adapter-next/src/lib/buildSrcPath.ts b/packages/adapter-next/src/lib/buildSrcPath.ts new file mode 100644 index 0000000000..a04ba336cd --- /dev/null +++ b/packages/adapter-next/src/lib/buildSrcPath.ts @@ -0,0 +1,16 @@ +import * as path from "node:path"; + +import type { SliceMachineHelpers } from "@slicemachine/plugin-kit"; +import { checkHasProjectFile } from "@slicemachine/plugin-kit/fs"; + +export async function buildSrcPath(args: { + filename: string; + helpers: SliceMachineHelpers; +}): Promise { + const hasSrcDirectory = await checkHasProjectFile({ + filename: "src", + helpers: args.helpers, + }); + + return hasSrcDirectory ? path.join("src", args.filename) : args.filename; +} diff --git a/packages/adapter-next/src/lib/checkHasAppRouter.ts b/packages/adapter-next/src/lib/checkHasAppRouter.ts index 49fd47ce5f..e0219283c1 100644 --- a/packages/adapter-next/src/lib/checkHasAppRouter.ts +++ b/packages/adapter-next/src/lib/checkHasAppRouter.ts @@ -1,9 +1,9 @@ import { SliceMachineContext } from "@slicemachine/plugin-kit"; import { checkHasProjectFile } from "@slicemachine/plugin-kit/fs"; -import * as path from "node:path"; import { PluginOptions } from "../types"; -import { checkHasSrcDirectory } from "./checkHasSrcDirectory"; + +import { buildSrcPath } from "./buildSrcPath"; type CheckHasAppRouterArgs = Pick< SliceMachineContext, @@ -13,10 +13,13 @@ type CheckHasAppRouterArgs = Pick< export async function checkHasAppRouter( args: CheckHasAppRouterArgs, ): Promise { - const hasSrcDirectory = await checkHasSrcDirectory({ helpers: args.helpers }); + const appRouterPath = await buildSrcPath({ + filename: "app", + helpers: args.helpers, + }); return await checkHasProjectFile({ - filename: hasSrcDirectory ? path.join("src", "app") : "app", + filename: appRouterPath, helpers: args.helpers, }); } diff --git a/packages/adapter-next/src/lib/checkHasSrcDirectory.ts b/packages/adapter-next/src/lib/checkHasSrcDirectory.ts deleted file mode 100644 index 8c38cf321b..0000000000 --- a/packages/adapter-next/src/lib/checkHasSrcDirectory.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { SliceMachineContext } from "@slicemachine/plugin-kit"; -import { checkHasProjectFile } from "@slicemachine/plugin-kit/fs"; - -import { PluginOptions } from "../types"; - -type CheckHasSrcDirectoryArgs = Pick< - SliceMachineContext, - "helpers" ->; - -export async function checkHasSrcDirectory( - args: CheckHasSrcDirectoryArgs, -): Promise { - return await checkHasProjectFile({ - filename: "src", - helpers: args.helpers, - }); -} diff --git a/packages/adapter-next/test/plugin-snippet-read.test.ts b/packages/adapter-next/test/plugin-snippet-read.test.ts index 53a1d8d1aa..9519af1448 100644 --- a/packages/adapter-next/test/plugin-snippet-read.test.ts +++ b/packages/adapter-next/test/plugin-snippet-read.test.ts @@ -1,5 +1,6 @@ import { test, expect } from "vitest"; import { createMockFactory } from "@prismicio/mock"; +import { GroupFieldType } from "@prismicio/types-internal/lib/customtypes"; import { Snippet } from "@slicemachine/plugin-kit"; import prettier from "prettier"; @@ -36,6 +37,8 @@ const model = mock.model.customType({ }, }); +const itemName = "item"; + const testSnippet = ( fieldName: keyof typeof model.json.Main, expected: string | Snippet[], @@ -46,6 +49,10 @@ const testSnippet = ( } = await ctx.pluginRunner.callHook("snippet:read", { fieldPath: [model.id, "data", fieldName], model: model.json.Main[fieldName], + itemName: + model.json.Main[fieldName].type === GroupFieldType + ? itemName + : undefined, }); if (Array.isArray(expected)) { @@ -101,8 +108,8 @@ testSnippet( testSnippet( "group", - `<>{${model.id}.data.group.map((item) => { -// Render the item + `<>{${model.id}.data.group.map((${itemName}) => { +// Render the ${itemName} })}`, ); diff --git a/packages/adapter-nuxt/package.json b/packages/adapter-nuxt/package.json index 0074fc0a44..5cbf55fafa 100644 --- a/packages/adapter-nuxt/package.json +++ b/packages/adapter-nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@slicemachine/adapter-nuxt", - "version": "0.3.40", + "version": "0.3.42", "description": "Slice Machine adapter for Nuxt 3.", "keywords": [ "typescript", @@ -60,7 +60,7 @@ }, "dependencies": { "@prismicio/simulator": "^0.1.4", - "@prismicio/types-internal": "^2.4.1", + "@prismicio/types-internal": "^2.5.0", "@slicemachine/plugin-kit": "workspace:*", "common-tags": "^1.8.2", "fp-ts": "^2.13.1", @@ -69,8 +69,7 @@ "magicast": "^0.3.4", "monocle-ts": "^2.3.13", "newtype-ts": "^0.3.5", - "pascal-case": "^3.1.2", - "prismic-ts-codegen": "^0.1.17" + "pascal-case": "^3.1.2" }, "devDependencies": { "@prismicio/mock": "0.2.0", @@ -87,6 +86,7 @@ "nuxt": "3.3.3", "prettier": "3.0.3", "prettier-plugin-jsdoc": "1.1.1", + "prismic-ts-codegen": "^0.1.21", "size-limit": "8.2.4", "ts-morph": "17.0.1", "typescript": "4.9.5", diff --git a/packages/adapter-nuxt/src/hooks/project-init.ts b/packages/adapter-nuxt/src/hooks/project-init.ts index f3319e4dbd..8f5e51714b 100644 --- a/packages/adapter-nuxt/src/hooks/project-init.ts +++ b/packages/adapter-nuxt/src/hooks/project-init.ts @@ -13,9 +13,9 @@ import { import { stripIndent } from "common-tags"; import { builders, loadFile, writeFile } from "magicast"; +import { buildSrcPath } from "../lib/buildSrcPath"; import { rejectIfNecessary } from "../lib/rejectIfNecessary"; import { checkIsTypeScriptProject } from "../lib/checkIsTypeScriptProject"; -import { checkHasSrcDirectory } from "../lib/checkHasSrcDirectory"; import type { PluginOptions } from "../types"; @@ -28,23 +28,12 @@ type InstallDependenciesArgs = { const installDependencies = async ({ installDependencies, }: InstallDependenciesArgs) => { - try { - await installDependencies({ - dependencies: { - [NUXT_PRISMIC]: "^3.0.0", - }, - dev: true, - }); - } catch (error) { - // TODO: Remove when latest is published and documented - // Fallback to RC if latest is still not available - await installDependencies({ - dependencies: { - [NUXT_PRISMIC]: "rc", - }, - dev: true, - }); - } + await installDependencies({ + dependencies: { + [NUXT_PRISMIC]: "^3.3.0", + }, + dev: true, + }); }; type ConfigurePrismicModuleArgs = SliceMachineContext; @@ -125,15 +114,36 @@ const createSliceSimulatorPage = async ({ options, }); + const appPagesDirectoryExists = await checkHasProjectFile({ + filename: "app/pages", + helpers, + }); + const srcPagesDirectoryExists = await checkHasProjectFile({ filename: "src/pages", helpers, }); - const filename = path.join( - srcPagesDirectoryExists ? "src/pages" : "pages", - "slice-simulator.vue", - ); + const pagesDirectoryExists = await checkHasProjectFile({ + filename: "pages", + helpers, + }); + + let filename: string; + // We first give priority to existing `pages` directory, then to `srcDir` + // because there could be conflicts with legacy `app` directory. + if (appPagesDirectoryExists) { + filename = path.join("app/pages", "slice-simulator.vue"); + } else if (srcPagesDirectoryExists) { + filename = path.join("src/pages", "slice-simulator.vue"); + } else if (pagesDirectoryExists) { + filename = path.join("pages", "slice-simulator.vue"); + } else { + filename = await buildSrcPath({ + filename: path.join("pages", "slice-simulator.vue"), + helpers, + }); + } if (await checkHasProjectFile({ filename, helpers })) { return; @@ -169,14 +179,9 @@ const moveOrDeleteAppVue = async ({ helpers, options, }: CreateSliceSimulatorPageArgs) => { - const srcDirectoryExists = await checkHasProjectFile({ - filename: "src", - helpers, - }); + const filenameAppVue = await buildSrcPath({ filename: "app.vue", helpers }); - const filenameAppVue = path.join(srcDirectoryExists ? "src" : "", "app.vue"); - - // If there's not `app.vue`, there's nothing to do. + // If there's no `app.vue`, there's nothing to do. if (!(await checkHasProjectFile({ filename: filenameAppVue, helpers }))) { return; } @@ -187,21 +192,17 @@ const moveOrDeleteAppVue = async ({ encoding: "utf-8", }); - // We check for app.vue to contain Nuxt default welcome component to determine if we need to consider it as the default one or not. + // We check for app.vue to contain Nuxt default welcome component to determine + // if we need to consider it as the default one or not. if (!filecontentAppVue.includes(") => { - const hasSrcDirectory = await checkHasSrcDirectory({ helpers }); + const hasAppDirectory = await checkHasProjectFile({ + filename: "app", + helpers, + }); + const hasSrcDirectory = await checkHasProjectFile({ + filename: "src", + helpers, + }); const project = await helpers.getProject(); // Add Slice Simulator URL. project.config.localSliceSimulatorURL ||= "http://localhost:3000/slice-simulator"; - // Nest the default Slice Library in the src directory if it exists and - // is empty. + // Nest the default Slice Library in the `app` or `src` directory if it + // exists and is empty. if ( - hasSrcDirectory && + (hasAppDirectory || hasSrcDirectory) && project.config.libraries && JSON.stringify(project.config.libraries) === JSON.stringify(["./slices"]) ) { @@ -243,7 +251,9 @@ const modifySliceMachineConfig = async ({ }); if (sliceLibrary.sliceIDs.length < 1) { - project.config.libraries = ["./src/slices"]; + project.config.libraries = hasAppDirectory + ? ["./app/slices"] + : ["./src/slices"]; } } diff --git a/packages/adapter-nuxt/src/hooks/snippet-read.ts b/packages/adapter-nuxt/src/hooks/snippet-read.ts index 10c112f604..1ad7ef3554 100644 --- a/packages/adapter-nuxt/src/hooks/snippet-read.ts +++ b/packages/adapter-nuxt/src/hooks/snippet-read.ts @@ -27,7 +27,7 @@ export const snippetRead: SnippetReadHook = async ( data, { helpers }, ) => { - const { fieldPath } = data; + const { fieldPath, itemName } = data; const label = "Vue"; @@ -102,8 +102,8 @@ export const snippetRead: SnippetReadHook = async ( language: "vue", code: await format( stripIndent` -