diff --git a/.circleci/config.yml b/.circleci/config.yml index dac362b5530b..6db12bf41959 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -614,22 +614,22 @@ workflows: requires: - build - create-sandboxes: - parallelism: 35 + parallelism: 36 requires: - build # - smoke-test-sandboxes: # disabled for now # requires: # - create-sandboxes - build-sandboxes: - parallelism: 35 + parallelism: 36 requires: - create-sandboxes - chromatic-sandboxes: - parallelism: 32 + parallelism: 33 requires: - build-sandboxes - e2e-production: - parallelism: 30 + parallelism: 31 requires: - build-sandboxes - e2e-dev: @@ -637,7 +637,7 @@ workflows: requires: - create-sandboxes - test-runner-production: - parallelism: 30 + parallelism: 31 requires: - build-sandboxes # TODO: reenable once we find out the source of flakyness diff --git a/code/e2e-tests/addon-actions.spec.ts b/code/e2e-tests/addon-actions.spec.ts index 520c2b5dc41f..a9f32e61c022 100644 --- a/code/e2e-tests/addon-actions.spec.ts +++ b/code/e2e-tests/addon-actions.spec.ts @@ -3,9 +3,16 @@ import process from 'process'; import { SbPage } from './util'; const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; +const templateName = process.env.STORYBOOK_TEMPLATE_NAME || ''; test.describe('addon-actions', () => { test('should trigger an action', async ({ page }) => { + // eslint-disable-next-line jest/no-disabled-tests + test.skip( + // eslint-disable-next-line jest/valid-title + templateName.includes('svelte') && templateName.includes('prerelease'), + 'Svelte 5 prerelase does not support automatic actions with our current example components yet' + ); await page.goto(storybookUrl); const sbPage = new SbPage(page); sbPage.waitUntilLoaded(); diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index 585a77752bed..4cfe87214037 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -52,18 +52,18 @@ "@storybook/svelte": "workspace:*", "@sveltejs/vite-plugin-svelte": "^2.4.2", "magic-string": "^0.30.0", - "svelte-preprocess": "^5.0.4", + "svelte-preprocess": "^5.1.1", "sveltedoc-parser": "^4.2.1", "ts-dedent": "^2.2.0" }, "devDependencies": { "@types/node": "^18.0.0", - "svelte": "^4.0.0", + "svelte": "^5.0.0-next.16", "typescript": "^5.3.2", "vite": "^4.0.0" }, "peerDependencies": { - "svelte": "^3.0.0 || ^4.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.16", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" }, "engines": { diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index 9e47d3bb34ee..4885a726417b 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -59,7 +59,7 @@ }, "peerDependencies": { "@babel/core": "*", - "svelte": "^3.48.0 || ^4.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.16", "svelte-loader": "*" }, "engines": { diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json index f952e2515b07..162fb8229411 100644 --- a/code/frameworks/sveltekit/package.json +++ b/code/frameworks/sveltekit/package.json @@ -64,7 +64,7 @@ "vite": "^4.0.0" }, "peerDependencies": { - "svelte": "^3.0.0 || ^4.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.16", "vite": "^4.0.0" }, "engines": { diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ButtonTypeScript.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ButtonTypeScript.svelte new file mode 100644 index 000000000000..cd00f38a3d57 --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ButtonTypeScript.svelte @@ -0,0 +1,38 @@ +<script lang="ts"> + /** + * @component Button TypeScript + * @wrapper + */ + import { global as globalThis } from '@storybook/global'; + // @ts-ignore + const Button = globalThis.Components?.Button; + + /** + * Rounds the button + */ + export let primary: boolean = false; + + /** + * Displays the count + */ + export let count: number = 0; + + /** + * Button text + * @slot + */ + export let text: string = 'You clicked'; + + function handleClick(_event: MouseEvent) { + count += 1; + } +</script> + +<h1>Button TypeScript</h1> + +<Button {primary} on:click on:click={handleClick} label="{text}: {count}" /> + +<p>A little text to show this is a view.</p> +<p>If we need to test components in a Svelte environment, for instance to test slot behaviour,</p> +<p>then wrapping the component up in a view</p> +<p>made just for the story is the simplest way to achieve this.</p> diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Forms.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Forms.svelte new file mode 100644 index 000000000000..371a17656bea --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Forms.svelte @@ -0,0 +1,7 @@ +<script> + import { enhance } from '$app/forms'; +</script> + +<form use:enhance> + <button>enhance</button> +</form> \ No newline at end of file diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Hrefs.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Hrefs.svelte new file mode 100644 index 000000000000..4e7d69e0e051 --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Hrefs.svelte @@ -0,0 +1,8 @@ +<ul> + <li><a href="/basic-href">Link to <code>/basic-href</code></a></li> + <li> + <a href="/deep/nested/link?with=true&multiple-params=200#and-an-id" + >Link to <code>/deep/nested/link?with=true&multiple-params=200#and-an-id</code></a + > + </li> +</ul> diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Navigation.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Navigation.svelte new file mode 100644 index 000000000000..4bcb7d0e6fc9 --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Navigation.svelte @@ -0,0 +1,25 @@ +<script> + import { goto, invalidate, invalidateAll, afterNavigate } from '$app/navigation'; + + export let afterNavigateFn; + + afterNavigate(afterNavigateFn); +</script> + +<button + on:click={() => { + goto('/storybook-goto'); + }}>goto</button +> + +<button + on:click={() => { + invalidate('/storybook-invalidate'); + }}>invalidate</button +> + +<button + on:click={() => { + invalidateAll(); + }}>invalidateAll</button +> diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Stores.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Stores.svelte new file mode 100644 index 000000000000..164b00f7fa8b --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/Stores.svelte @@ -0,0 +1,17 @@ +<script> + import { page, navigating, updated, getStores } from '$app/stores'; + + let { navigating: navigatingStore, page: pageStore, updated: updatedStore } = getStores(); + + updated.check(); +</script> + +<p>Directly importing</p> +<pre>{JSON.stringify($page, null, 2)}</pre> +<pre>{JSON.stringify($navigating, null, 2)}</pre> +<pre>{JSON.stringify($updated, null, 2)}</pre> + +<p>With getStores</p> +<pre>{JSON.stringify($pageStore, null, 2)}</pre> +<pre>{JSON.stringify($navigatingStore, null, 2)}</pre> +<pre>{JSON.stringify($updatedStore, null, 2)}</pre> diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js new file mode 100644 index 000000000000..72b584baef76 --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js @@ -0,0 +1,26 @@ +import { expect, fn, within } from '@storybook/test'; +import Forms from './Forms.svelte'; + +export default { + title: 'stories/sveltekit/modules/forms', + component: Forms, + tags: ['autodocs'], +}; + +const enhance = fn(); + +export const Enhance = { + async play({ canvasElement }) { + const canvas = within(canvasElement); + const button = canvas.getByText('enhance'); + button.click(); + expect(enhance).toHaveBeenCalled(); + }, + parameters: { + sveltekit_experimental: { + forms: { + enhance, + }, + }, + }, +}; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js new file mode 100644 index 000000000000..f1cbf4973534 --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js @@ -0,0 +1,53 @@ +import { expect, fn, within } from '@storybook/test'; +import Hrefs from './Hrefs.svelte'; + +export default { + title: 'stories/sveltekit/modules/hrefs', + component: Hrefs, + tags: ['autodocs'], +}; + +export const DefaultActions = { + async play({ canvasElement }) { + const canvas = within(canvasElement); + // eslint-disable-next-line no-undef + const initialUrl = window.location.toString(); + + const basicHref = canvas.getByText('/basic-href'); + basicHref.click(); + + const complexHref = canvas.getByText( + '/deep/nested/link?with=true&multiple-params=200#and-an-id' + ); + complexHref.click(); + + // eslint-disable-next-line no-undef + const finalUrl = window.location.toString(); + expect(finalUrl).toBe(initialUrl); + }, +}; + +const basicStringMatch = fn(); +const noMatch = fn(); +const exactStringMatch = fn(); +const regexMatch = fn(); + +export const Callbacks = { + parameters: { + sveltekit_experimental: { + hrefs: { + '/basic-href': basicStringMatch, + '/basic': noMatch, + '/deep/nested/link?with=true&multiple-params=200#and-an-id': exactStringMatch, + 'nested/link\\?with': { callback: regexMatch, asRegex: true }, + }, + }, + }, + play: async (ctx) => { + await DefaultActions.play(ctx); + expect(basicStringMatch).toHaveBeenCalledTimes(1); + expect(noMatch).not.toHaveBeenCalled(); + expect(exactStringMatch).toHaveBeenCalledTimes(1); + expect(regexMatch).toHaveBeenCalledTimes(1); + }, +}; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js new file mode 100644 index 000000000000..ded12268e03c --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js @@ -0,0 +1,84 @@ +import { expect, fn, within } from '@storybook/test'; +import Navigation from './Navigation.svelte'; + +export default { + title: 'stories/sveltekit/modules/navigation', + component: Navigation, + tags: ['autodocs'], +}; + +const goto = fn(); + +export const Goto = { + async play({ canvasElement }) { + const canvas = within(canvasElement); + const button = canvas.getByText('goto'); + button.click(); + expect(goto).toHaveBeenCalledWith('/storybook-goto'); + }, + parameters: { + sveltekit_experimental: { + navigation: { + goto, + }, + }, + }, +}; + +export const DefaultActions = {}; + +const invalidate = fn(); + +export const Invalidate = { + async play({ canvasElement }) { + const canvas = within(canvasElement); + const button = canvas.getByText('invalidate', { exact: true }); + button.click(); + expect(invalidate).toHaveBeenCalledWith('/storybook-invalidate'); + }, + parameters: { + sveltekit_experimental: { + navigation: { + invalidate, + }, + }, + }, +}; + +const invalidateAll = fn(); + +export const InvalidateAll = { + async play({ canvasElement }) { + const canvas = within(canvasElement); + const button = canvas.getByText('invalidateAll'); + button.click(); + expect(invalidateAll).toHaveBeenCalledWith(); + }, + parameters: { + sveltekit_experimental: { + navigation: { + invalidateAll, + }, + }, + }, +}; + +const afterNavigateFn = fn(); + +export const AfterNavigate = { + async play() { + expect(afterNavigateFn).toHaveBeenCalledWith({ test: 'passed' }); + }, + args: { + afterNavigateFn, + }, + parameters: { + sveltekit_experimental: { + navigation: { + afterNavigate: { + test: 'passed', + }, + }, + }, + }, +}; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/stores.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/stores.stories.js new file mode 100644 index 000000000000..7f7401cf8bee --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/stores.stories.js @@ -0,0 +1,116 @@ +import Stores from './Stores.svelte'; + +export default { + title: 'stories/sveltekit/modules/stores', + component: Stores, + tags: ['autodocs'], +}; + +export const AllUndefined = {}; + +export const PageStore = { + parameters: { + sveltekit_experimental: { + stores: { + page: { + data: { + test: 'passed', + }, + }, + }, + }, + }, +}; + +export const NavigatingStore = { + parameters: { + sveltekit_experimental: { + stores: { + navigating: { + route: { + id: '/storybook', + }, + }, + }, + }, + }, +}; + +export const UpdatedStore = { + parameters: { + sveltekit_experimental: { + stores: { + updated: true, + }, + }, + }, +}; + +export const PageAndNavigatingStore = { + parameters: { + sveltekit_experimental: { + stores: { + page: { + data: { + test: 'passed', + }, + }, + navigating: { + route: { + id: '/storybook', + }, + }, + }, + }, + }, +}; + +export const PageAndUpdatedStore = { + parameters: { + sveltekit_experimental: { + stores: { + page: { + data: { + test: 'passed', + }, + }, + updated: true, + }, + }, + }, +}; + +export const NavigatingAndUpdatedStore = { + parameters: { + sveltekit_experimental: { + stores: { + navigating: { + route: { + id: '/storybook', + }, + }, + updated: true, + }, + }, + }, +}; + +export const AllThreeStores = { + parameters: { + sveltekit_experimental: { + stores: { + page: { + data: { + test: 'passed', + }, + }, + navigating: { + route: { + id: '/storybook', + }, + }, + updated: true, + }, + }, + }, +}; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ts-docs.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ts-docs.stories.js new file mode 100644 index 000000000000..f33428810ee9 --- /dev/null +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/ts-docs.stories.js @@ -0,0 +1,12 @@ +import ButtonTypescript from './ButtonTypeScript.svelte'; + +export default { + title: 'stories/renderers/svelte/ts-docs', + component: ButtonTypescript, + args: { + primary: true, + }, + tags: ['autodocs'], +}; + +export const Primary = {}; diff --git a/code/lib/cli/src/sandbox-templates.ts b/code/lib/cli/src/sandbox-templates.ts index 6aeed1d585a3..1399da6bcef9 100644 --- a/code/lib/cli/src/sandbox-templates.ts +++ b/code/lib/cli/src/sandbox-templates.ts @@ -376,6 +376,17 @@ const baseTemplates = { }, skipTasks: ['e2e-tests-dev', 'bench'], }, + 'svelte-kit/prerelease-ts': { + name: 'SvelteKit Prerelease (Vite | TypeScript)', + script: + 'yarn create svelte-with-args --name=svelte-kit/prerelease-ts --directory={{beforeDir}} --template=skeleton --types=typescript --no-prettier --no-eslint --no-playwright --no-vitest --svelte5', + expected: { + framework: '@storybook/sveltekit', + renderer: '@storybook/svelte', + builder: '@storybook/builder-vite', + }, + skipTasks: ['e2e-tests-dev', 'bench'], + }, 'lit-vite/default-js': { name: 'Lit Latest (Vite | JavaScript)', script: @@ -619,6 +630,7 @@ export const daily: TemplateKey[] = [ 'vue-cli/default-js', 'lit-vite/default-js', 'svelte-kit/skeleton-js', + 'svelte-kit/prerelease-ts', 'svelte-vite/default-js', 'nextjs/13-ts', 'nextjs/default-js', diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json index fca64af0725c..2792fa28bc32 100644 --- a/code/presets/svelte-webpack/package.json +++ b/code/presets/svelte-webpack/package.json @@ -76,7 +76,7 @@ }, "peerDependencies": { "@babel/core": "*", - "svelte": "^3.1.0 || ^4.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.16", "svelte-loader": "*" }, "engines": { diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index 74eae303430f..c7b3ad589592 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -63,12 +63,12 @@ }, "devDependencies": { "expect-type": "^0.15.0", - "svelte": "^4.0.0", - "svelte-check": "3.4.6", + "svelte": "^5.0.0-next.15", + "svelte-check": "^3.6.1", "typescript": "^5.3.2" }, "peerDependencies": { - "svelte": "^3.1.0 || ^4.0.0" + "svelte": "^4.0.0 || ^5.0.0-next.16" }, "engines": { "node": ">=16.0.0" diff --git a/code/renderers/svelte/src/render.ts b/code/renderers/svelte/src/render.ts index cfde36047fa1..b1821b692358 100644 --- a/code/renderers/svelte/src/render.ts +++ b/code/renderers/svelte/src/render.ts @@ -1,6 +1,5 @@ /* eslint-disable no-param-reassign */ import type { RenderContext, ArgsStoryFn } from '@storybook/types'; -import type { SvelteComponentTyped } from 'svelte'; import { RESET_STORY_ARGS } from '@storybook/core-events'; // ! DO NOT change this PreviewRender import to a relative path, it will break it. // ! A relative import will be compiled at build time, and Svelte will be unable to @@ -10,10 +9,14 @@ import { RESET_STORY_ARGS } from '@storybook/core-events'; // eslint-disable-next-line import/no-extraneous-dependencies import PreviewRender from '@storybook/svelte/templates/PreviewRender.svelte'; import { addons } from '@storybook/preview-api'; +import * as svelte from 'svelte'; import type { SvelteRenderer } from './types'; -const componentsByDomElement = new Map<SvelteRenderer['canvasElement'], SvelteComponentTyped>(); +const componentsByDomElement = new Map< + SvelteRenderer['canvasElement'], + any // ReturnType<typeof createRoot | typeof mount> depends on the version of Svelte v4 or v5 +>(); function teardown(canvasElement: SvelteRenderer['canvasElement']) { if (!componentsByDomElement.has(canvasElement)) { @@ -26,6 +29,25 @@ function teardown(canvasElement: SvelteRenderer['canvasElement']) { componentsByDomElement.delete(canvasElement); } +/** + * Mount the PreviewRender component to the provided canvasElement + * Either using the Svelte v4 or v5 API + */ +function createRoot(target: HTMLElement, props: any) { + if ((svelte as any).createRoot) { + // Svelte v5 + return svelte.createRoot(PreviewRender, { + target, + props, + }); + } + // Svelte v4 + return new (PreviewRender as any)({ + target, + props, + }); +} + /** * This is a workaround for the issue that when resetting args, * the story needs to be remounted completely to revert to the component's default props. @@ -66,16 +88,13 @@ export function renderToCanvas( } if (!existingComponent || remount) { - const createdComponent = new PreviewRender({ - target: canvasElement, - props: { - storyFn, - storyContext, - name, - kind, - showError, - }, - }) as SvelteComponentTyped; + const createdComponent = createRoot(canvasElement, { + storyFn, + storyContext, + name, + kind, + showError, + }); componentsByDomElement.set(canvasElement, createdComponent); } else { existingComponent.$set({ diff --git a/code/renderers/svelte/src/typings.d.ts b/code/renderers/svelte/src/typings.d.ts index 109dcd62da0e..2e00d983aa34 100644 --- a/code/renderers/svelte/src/typings.d.ts +++ b/code/renderers/svelte/src/typings.d.ts @@ -1,2 +1,9 @@ declare var STORYBOOK_ENV: 'svelte'; declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined; + +declare module '*.svelte' { + import type { ComponentType } from 'svelte'; + + const component: ComponentType; + export default component; +} diff --git a/code/renderers/svelte/templates/SlotDecorator.svelte b/code/renderers/svelte/templates/SlotDecorator.svelte index 5bd0fdfe3455..9de64db04c3d 100644 --- a/code/renderers/svelte/templates/SlotDecorator.svelte +++ b/code/renderers/svelte/templates/SlotDecorator.svelte @@ -5,19 +5,19 @@ export let Component; export let props = {}; export let on = undefined; - + let instance; let decoratorInstance; - - function getInstance() { - // instance can be undefined if a decorator doesn't have <slot/> - return instance || decoratorInstance; - } - + if (on) { - // Attach svelte event listeners. - Object.keys(on).forEach((eventName) => { - onMount(() => getInstance().$on(eventName, on[eventName])); + // Attach Svelte event listeners in Svelte v4 + // In Svelte v5 this is not possible anymore as instances are no longer classes with $on() properties, so it will be a no-op + onMount(() => { + Object.entries(on).forEach(([eventName, eventCallback]) => { + // instance can be undefined if a decorator doesn't have <slot/> + const inst = instance ?? decoratorInstance; + inst?.$on?.(eventName, eventCallback) + }); }); } </script> diff --git a/code/yarn.lock b/code/yarn.lock index 551e676483a2..264293e08cea 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6201,7 +6201,7 @@ __metadata: typescript: "npm:^5.3.2" peerDependencies: "@babel/core": "*" - svelte: ^3.1.0 || ^4.0.0 + svelte: ^4.0.0 || ^5.0.0-next.16 svelte-loader: "*" languageName: unknown linkType: soft @@ -6679,14 +6679,14 @@ __metadata: "@sveltejs/vite-plugin-svelte": "npm:^2.4.2" "@types/node": "npm:^18.0.0" magic-string: "npm:^0.30.0" - svelte: "npm:^4.0.0" - svelte-preprocess: "npm:^5.0.4" + svelte: "npm:^5.0.0-next.16" + svelte-preprocess: "npm:^5.1.1" sveltedoc-parser: "npm:^4.2.1" ts-dedent: "npm:^2.2.0" typescript: "npm:^5.3.2" vite: "npm:^4.0.0" peerDependencies: - svelte: ^3.0.0 || ^4.0.0 + svelte: ^4.0.0 || ^5.0.0-next.16 vite: ^3.0.0 || ^4.0.0 || ^5.0.0 languageName: unknown linkType: soft @@ -6704,7 +6704,7 @@ __metadata: typescript: "npm:^5.3.2" peerDependencies: "@babel/core": "*" - svelte: ^3.48.0 || ^4.0.0 + svelte: ^4.0.0 || ^5.0.0-next.16 svelte-loader: "*" languageName: unknown linkType: soft @@ -6720,14 +6720,14 @@ __metadata: "@storybook/preview-api": "workspace:*" "@storybook/types": "workspace:*" expect-type: "npm:^0.15.0" - svelte: "npm:^4.0.0" - svelte-check: "npm:3.4.6" + svelte: "npm:^5.0.0-next.15" + svelte-check: "npm:^3.6.1" sveltedoc-parser: "npm:^4.2.1" ts-dedent: "npm:^2.0.0" type-fest: "npm:~2.19" typescript: "npm:^5.3.2" peerDependencies: - svelte: ^3.1.0 || ^4.0.0 + svelte: ^4.0.0 || ^5.0.0-next.16 languageName: unknown linkType: soft @@ -6743,7 +6743,7 @@ __metadata: typescript: "npm:^5.3.2" vite: "npm:^4.0.0" peerDependencies: - svelte: ^3.0.0 || ^4.0.0 + svelte: ^4.0.0 || ^5.0.0-next.16 vite: ^4.0.0 languageName: unknown linkType: soft @@ -9482,6 +9482,15 @@ __metadata: languageName: node linkType: hard +"acorn-typescript@npm:^1.4.11": + version: 1.4.12 + resolution: "acorn-typescript@npm:1.4.12" + peerDependencies: + acorn: ">=8.9.0" + checksum: a3b33ed0dc321e3364da507a3decec96423736384068c88fea5ea57aeae864ea115a6c4a20b3ace71b75f4901b0657bec82d83aab30a8ad0dfc4bfc0d8337546 + languageName: node + linkType: hard + "acorn-walk@npm:^7.2.0": version: 7.2.0 resolution: "acorn-walk@npm:7.2.0" @@ -10256,6 +10265,15 @@ __metadata: languageName: node linkType: hard +"axobject-query@npm:^4.0.0": + version: 4.0.0 + resolution: "axobject-query@npm:4.0.0" + dependencies: + dequal: "npm:^2.0.3" + checksum: 4d756b5c2ff099f1c7f99e55a5de9b2066cb2a13a3170185ff34bfec2d7bcab81eb820a4e7340d35c251341b61ebee6e705b7ce64db78224df1df5a4d68448fe + languageName: node + linkType: hard + "b4a@npm:^1.6.4": version: 1.6.4 resolution: "b4a@npm:1.6.4" @@ -14802,6 +14820,13 @@ __metadata: languageName: node linkType: hard +"esm-env@npm:^1.0.0": + version: 1.0.0 + resolution: "esm-env@npm:1.0.0" + checksum: 6ea0001410224ebc18de4a83ce97dbdca6abc83ea4bbe91625aa3aead70793bb98dfa089f38e2cc5c13b7b025668d0649d5e25f2f9e8cca0f4aa3ad3406870d0 + languageName: node + linkType: hard + "espree@npm:9.2.0": version: 9.2.0 resolution: "espree@npm:9.2.0" @@ -14843,6 +14868,16 @@ __metadata: languageName: node linkType: hard +"esrap@npm:^1.2.1": + version: 1.2.1 + resolution: "esrap@npm:1.2.1" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.4.15" + "@types/estree": "npm:^1.0.1" + checksum: 28d6e36adcf4342a844a938a736132269c33e9db6bbefc98c6af5ed06c14899afcc85391e7ce4824ce5066877fa10b0ed5c5007592cbc58012be95f13c66467f + languageName: node + linkType: hard + "esrecurse@npm:^4.3.0": version: 4.3.0 resolution: "esrecurse@npm:4.3.0" @@ -27215,9 +27250,9 @@ __metadata: languageName: node linkType: hard -"svelte-check@npm:3.4.6": - version: 3.4.6 - resolution: "svelte-check@npm:3.4.6" +"svelte-check@npm:^3.6.1": + version: 3.6.2 + resolution: "svelte-check@npm:3.6.2" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.17" chokidar: "npm:^3.4.1" @@ -27225,13 +27260,13 @@ __metadata: import-fresh: "npm:^3.2.1" picocolors: "npm:^1.0.0" sade: "npm:^1.7.4" - svelte-preprocess: "npm:^5.0.4" + svelte-preprocess: "npm:^5.1.0" typescript: "npm:^5.0.3" peerDependencies: - svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 + svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 bin: svelte-check: bin/svelte-check - checksum: 7f537831af8f2c47859ca72f4a929d24c58f2946f949f7c9721351be97ff9d0674c57db003e3ad3883fdd85761b7950c5c11513c2a917c91091f155e2d026350 + checksum: 3f389df29268d4df9b561d0b206566e827af84923c70150b2dadfd407bcbdaccbfd561bd8b93884597de62477d62826ff1a5108854641078b692130441a49a55 languageName: node linkType: hard @@ -27273,7 +27308,7 @@ __metadata: languageName: node linkType: hard -"svelte-preprocess@npm:^5.0.4": +"svelte-preprocess@npm:^5.1.0, svelte-preprocess@npm:^5.1.1": version: 5.1.1 resolution: "svelte-preprocess@npm:5.1.1" dependencies: @@ -27340,6 +27375,26 @@ __metadata: languageName: node linkType: hard +"svelte@npm:^5.0.0-next.15, svelte@npm:^5.0.0-next.16": + version: 5.0.0-next.19 + resolution: "svelte@npm:5.0.0-next.19" + dependencies: + "@ampproject/remapping": "npm:^2.2.1" + "@jridgewell/sourcemap-codec": "npm:^1.4.15" + acorn: "npm:^8.10.0" + acorn-typescript: "npm:^1.4.11" + aria-query: "npm:^5.3.0" + axobject-query: "npm:^4.0.0" + esm-env: "npm:^1.0.0" + esrap: "npm:^1.2.1" + is-reference: "npm:^3.0.1" + locate-character: "npm:^3.0.0" + magic-string: "npm:^0.30.4" + zimmerframe: "npm:^1.1.0" + checksum: 2efc415d3a51cd9094349aa0295e728ea74e10bad17dedd167b1fae64de8ee5d46cbd27b5cfb152e4af641e1326e233dfeb918d8fa0541f65cf149b85d00419a + languageName: node + linkType: hard + "sveltedoc-parser@npm:^4.2.1": version: 4.3.1 resolution: "sveltedoc-parser@npm:4.3.1" @@ -30221,6 +30276,13 @@ __metadata: languageName: node linkType: hard +"zimmerframe@npm:^1.1.0": + version: 1.1.0 + resolution: "zimmerframe@npm:1.1.0" + checksum: dffe3f555bb000176ed9c7577e0fb0c3eddeceb6df9bb3ff870995bac3a51b40fab5443bd3dc47ce91c1f8ecf07282742efb80771ae6a088edc0340bb217f93d + languageName: node + linkType: hard + "zod@npm:^3.22.2": version: 3.22.4 resolution: "zod@npm:3.22.4" diff --git a/scripts/task.ts b/scripts/task.ts index 20dad32716c3..1247cc89351a 100644 --- a/scripts/task.ts +++ b/scripts/task.ts @@ -496,7 +496,7 @@ async function run() { controller.abort(); }); - return 1; + throw err; } statuses.set(task, task.service ? 'serving' : 'complete'); diff --git a/scripts/tasks/generate.ts b/scripts/tasks/generate.ts index cbce6c66a1c5..f453fc3222e8 100644 --- a/scripts/tasks/generate.ts +++ b/scripts/tasks/generate.ts @@ -1,3 +1,4 @@ +/* eslint-disable import/extensions */ import { pathExists, remove } from 'fs-extra'; import { join } from 'path'; import { REPROS_DIRECTORY } from '../utils/constants'; @@ -27,7 +28,8 @@ export const generate: Task = { } // This uses an async import as it depends on `lib/cli` which requires `code` to be installed. - const { generate: generateRepro } = await import('../sandbox/generate'); + // @ts-expect-error Default import required for dynamic import processed by esbuild + const { generate: generateRepro } = (await import('../sandbox/generate.ts')).default; await generateRepro({ templates: [details.key], diff --git a/scripts/tasks/sandbox-parts.ts b/scripts/tasks/sandbox-parts.ts index d2f5748ce104..d35edced9abc 100644 --- a/scripts/tasks/sandbox-parts.ts +++ b/scripts/tasks/sandbox-parts.ts @@ -39,6 +39,7 @@ import { JsPackageManagerFactory } from '../../code/lib/cli/src/js-package-manag import { workspacePath } from '../utils/workspace'; import { babelParse } from '../../code/lib/csf-tools/src/babelParse'; import { CODE_DIRECTORY, REPROS_DIRECTORY } from '../utils/constants'; +import type { TemplateKey } from '../../code/lib/cli/src/sandbox-templates'; const logger = console; @@ -75,7 +76,7 @@ export const create: Task['run'] = async ({ key, template, sandboxDir }, { dryRu } }; -export const install: Task['run'] = async ({ sandboxDir }, { link, dryRun, debug }) => { +export const install: Task['run'] = async ({ sandboxDir, key }, { link, dryRun, debug }) => { const cwd = sandboxDir; await installYarn2({ cwd, dryRun, debug }); @@ -93,24 +94,22 @@ export const install: Task['run'] = async ({ sandboxDir }, { link, dryRun, debug // of any storybook packages as verdaccio is not able to both proxy to npm and publish over // the top. In theory this could mask issues where different versions cause problems. await addPackageResolutions({ cwd, dryRun, debug }); - await configureYarn2ForVerdaccio({ cwd, dryRun, debug }); + await configureYarn2ForVerdaccio({ cwd, dryRun, debug, key }); // Add vite plugin workarounds for frameworks that need it // (to support vite 5 without peer dep errors) - if ( - [ - 'bench-react-vite-default-ts', - 'bench-react-vite-default-ts-nodocs', - 'bench-react-vite-default-ts-test-build', - 'internal-ssv6-vite', - 'react-vite-default-js', - 'react-vite-default-ts', - 'svelte-vite-default-js', - 'svelte-vite-default-ts', - 'vue3-vite-default-js', - 'vue3-vite-default-ts', - ].includes(sandboxDir.split(sep).at(-1)) - ) { + const sandboxesNeedingWorkarounds: TemplateKey[] = [ + 'bench/react-vite-default-ts', + 'bench/react-vite-default-ts-nodocs', + 'bench/react-vite-default-ts-test-build', + 'react-vite/default-js', + 'react-vite/default-ts', + 'svelte-vite/default-js', + 'svelte-vite/default-ts', + 'vue3-vite/default-js', + 'vue3-vite/default-ts', + ]; + if (sandboxesNeedingWorkarounds.includes(key)) { await addWorkaroundResolutions({ cwd, dryRun, debug }); } diff --git a/scripts/utils/yarn.ts b/scripts/utils/yarn.ts index 19f87d1c0182..2f1fdc8b838e 100644 --- a/scripts/utils/yarn.ts +++ b/scripts/utils/yarn.ts @@ -1,6 +1,7 @@ import { pathExists, readJSON, writeJSON } from 'fs-extra'; import path from 'path'; +import type { TemplateKey } from 'get-template'; import { exec } from './exec'; // TODO -- should we generate this file a second time outside of CLI? import storybookVersions from '../../code/lib/cli/src/versions'; @@ -75,7 +76,12 @@ export const addWorkaroundResolutions = async ({ cwd, dryRun }: YarnOptions) => await writeJSON(packageJsonPath, packageJson, { spaces: 2 }); }; -export const configureYarn2ForVerdaccio = async ({ cwd, dryRun, debug }: YarnOptions) => { +export const configureYarn2ForVerdaccio = async ({ + cwd, + dryRun, + debug, + key, +}: YarnOptions & { key: TemplateKey }) => { const command = [ // We don't want to use the cache or we might get older copies of our built packages // (with identical versions), as yarn (correctly I guess) assumes the same version hasn't changed @@ -89,10 +95,20 @@ export const configureYarn2ForVerdaccio = async ({ cwd, dryRun, debug }: YarnOpt `yarn config set pnpFallbackMode none`, // We need to be able to update lockfile when bootstrapping the examples `yarn config set enableImmutableInstalls false`, + ]; + + if (key === 'svelte-kit/prerelease-ts') { + // Don't error with INCOMPATIBLE_PEER_DEPENDENCY for SvelteKit prerelease, it is expected + command.push( + `yarn config set logFilters --json '[ { "code": "YN0013", "level": "discard" } ]'` + ); + } else { // Discard all YN0013 - FETCH_NOT_CACHED messages // Error on YN0060 - INCOMPATIBLE_PEER_DEPENDENCY - `yarn config set logFilters --json '[ { "code": "YN0013", "level": "discard" }, { "code": "YN0060", "level": "error" } ]'`, - ]; + command.push( + `yarn config set logFilters --json '[ { "code": "YN0013", "level": "discard" }, { "code": "YN0060", "level": "error" } ]'` + ); + } await exec( command,