diff --git a/.changeset/loose-colts-sin.md b/.changeset/loose-colts-sin.md new file mode 100644 index 00000000..627bfd30 --- /dev/null +++ b/.changeset/loose-colts-sin.md @@ -0,0 +1,5 @@ +--- +'sv': patch +--- + +feat: expose `runsAfter` to add-ons diff --git a/packages/addons/storybook/index.ts b/packages/addons/storybook/index.ts index d75ffcf0..ad35e16d 100644 --- a/packages/addons/storybook/index.ts +++ b/packages/addons/storybook/index.ts @@ -6,6 +6,10 @@ export default defineAddon({ shortDescription: 'frontend workshop', homepage: 'https://storybook.js.org', options: {}, + setup: ({ runsAfter }) => { + runsAfter('vitest'); + runsAfter('eslint'); + }, run: async ({ sv }) => { await sv.execute(['storybook@latest', 'init', '--skip-install', '--no-dev'], 'inherit'); sv.devDependency(`@types/node`, getNodeTypesVersion()); diff --git a/packages/cli/lib/install.ts b/packages/cli/lib/install.ts index 9c0bfb7e..900bf5be 100644 --- a/packages/cli/lib/install.ts +++ b/packages/cli/lib/install.ts @@ -87,11 +87,15 @@ export function setupAddons( const addonSetupResults: Record = {}; for (const addon of addons) { - const setupResult: AddonSetupResult = { unsupported: [], dependsOn: [] }; + const setupResult: AddonSetupResult = { unsupported: [], dependsOn: [], runsAfter: [] }; addon.setup?.({ ...workspace, - dependsOn: (name) => setupResult.dependsOn.push(name), - unsupported: (reason) => setupResult.unsupported.push(reason) + dependsOn: (name) => { + setupResult.dependsOn.push(name); + setupResult.runsAfter.push(name); + }, + unsupported: (reason) => setupResult.unsupported.push(reason), + runsAfter: (name) => setupResult.runsAfter.push(name) }); addonSetupResults[addon.id] = setupResult; } @@ -181,13 +185,10 @@ async function runAddon({ addon, multiple, workspace }: RunAddon) { } // orders addons by putting addons that don't require any other addon in the front. -// This is a drastic simplification, as this could still cause some inconvenient cituations, +// This is a drastic simplification, as this could still cause some inconvenient circumstances, // but works for now in contrary to the previous implementation function orderAddons(addons: Array>, setupResults: Record) { return addons.sort((a, b) => { - // Adding storybook last means it will correctly detect and integrate with other addons like vitest and eslint - if (a.id === 'storybook') return 1; - if (b.id === 'storybook') return -1; - return setupResults[a.id]?.dependsOn?.length - setupResults[b.id]?.dependsOn?.length; + return setupResults[a.id]?.runsAfter?.length - setupResults[b.id]?.runsAfter?.length; }); } diff --git a/packages/core/addon/config.ts b/packages/core/addon/config.ts index be36f777..fbce3775 100644 --- a/packages/core/addon/config.ts +++ b/packages/core/addon/config.ts @@ -37,6 +37,7 @@ export type Addon = { workspace: Workspace & { dependsOn: (name: string) => void; unsupported: (reason: string) => void; + runsAfter: (addonName: string) => void; } ) => MaybePromise; run: (workspace: Workspace & { sv: SvApi }) => MaybePromise; @@ -59,7 +60,7 @@ export function defineAddon(config: Addon): return config; } -export type AddonSetupResult = { dependsOn: string[]; unsupported: string[] }; +export type AddonSetupResult = { dependsOn: string[]; unsupported: string[]; runsAfter: string[] }; export type AddonWithoutExplicitArgs = Addon>; export type AddonConfigWithoutExplicitArgs = Addon>;