diff --git a/code/lib/create-storybook/package.json b/code/lib/create-storybook/package.json index 0af48115489f..762dd2366431 100644 --- a/code/lib/create-storybook/package.json +++ b/code/lib/create-storybook/package.json @@ -54,6 +54,7 @@ "find-up": "^7.0.0", "ora": "^5.4.1", "picocolors": "^1.1.0", + "process-ancestry": "^0.0.2", "prompts": "^2.4.0", "react": "^18.2.0", "tiny-invariant": "^1.3.1", diff --git a/code/lib/create-storybook/src/initiate.test.ts b/code/lib/create-storybook/src/initiate.test.ts index a301c13fb064..6a84e7a5f80f 100644 --- a/code/lib/create-storybook/src/initiate.test.ts +++ b/code/lib/create-storybook/src/initiate.test.ts @@ -5,7 +5,7 @@ import { telemetry } from 'storybook/internal/telemetry'; import prompts from 'prompts'; -import { promptInstallType, promptNewUser } from './initiate'; +import { getStorybookVersionFromAncestry, promptInstallType, promptNewUser } from './initiate'; vi.mock('prompts', { spy: true }); vi.mock('storybook/internal/telemetry'); @@ -155,3 +155,66 @@ describe('promptInstallType', () => { `); }); }); + +describe('getStorybookVersionFromAncestry', () => { + it('possible storybook path', () => { + const ancestry = [{ command: 'node' }, { command: 'storybook@7.0.0' }, { command: 'npm' }]; + expect(getStorybookVersionFromAncestry(ancestry as any)).toBeUndefined(); + }); + + it('create storybook', () => { + const ancestry = [ + { command: 'node' }, + { command: 'npm create storybook@7.0.0-alpha.3' }, + { command: 'npm' }, + ]; + expect(getStorybookVersionFromAncestry(ancestry as any)).toBe('7.0.0-alpha.3'); + }); + + it('storybook init', () => { + const ancestry = [ + { command: 'node' }, + { command: 'npx storybook@7.0.0 init' }, + { command: 'npm' }, + ]; + expect(getStorybookVersionFromAncestry(ancestry as any)).toBe('7.0.0'); + }); + + it('storybook init no version', () => { + const ancestry = [{ command: 'node' }, { command: 'npx storybook init' }, { command: 'npm' }]; + expect(getStorybookVersionFromAncestry(ancestry as any)).toBeUndefined(); + }); + + it('create-storybook with latest', () => { + const ancestry = [ + { command: 'node' }, + { command: 'npx create-storybook@latest' }, + { command: 'npm' }, + ]; + expect(getStorybookVersionFromAncestry(ancestry as any)).toBe('latest'); + }); + + it('foo-storybook with latest', () => { + const ancestry = [ + { command: 'node' }, + { command: 'npx foo-storybook@latest' }, + { command: 'npm' }, + ]; + expect(getStorybookVersionFromAncestry(ancestry as any)).toBeUndefined(); + }); + + it('multiple matches', () => { + const ancestry = [ + { command: 'node' }, + { command: 'npx create-storybook@foo' }, + { command: 'npm' }, + { command: 'npx create-storybook@bar' }, + ]; + expect(getStorybookVersionFromAncestry(ancestry as any)).toBe('bar'); + }); + + it('returns undefined if no storybook version found', () => { + const ancestry = [{ command: 'node' }, { command: 'npm' }]; + expect(getStorybookVersionFromAncestry(ancestry as any)).toBeUndefined(); + }); +}); diff --git a/code/lib/create-storybook/src/initiate.ts b/code/lib/create-storybook/src/initiate.ts index 0e7fb817efcc..2954870a73a8 100644 --- a/code/lib/create-storybook/src/initiate.ts +++ b/code/lib/create-storybook/src/initiate.ts @@ -33,6 +33,7 @@ import { telemetry } from 'storybook/internal/telemetry'; import boxen from 'boxen'; import { findUp } from 'find-up'; import picocolors from 'picocolors'; +import { getProcessAncestry } from 'process-ancestry'; import prompts from 'prompts'; import { lt, prerelease } from 'semver'; import { dedent } from 'ts-dedent'; @@ -382,6 +383,18 @@ export const promptInstallType = async ({ return installType; }; +export function getStorybookVersionFromAncestry( + ancestry: ReturnType +): string | undefined { + for (const ancestor of ancestry.toReversed()) { + const match = ancestor.command?.match(/\s(?:create-storybook|storybook)@([^\s]+)/); + if (match) { + return match[1]; + } + } + return undefined; +} + export async function doInitiate(options: CommandOptions): Promise< | { shouldRunDev: true; @@ -425,6 +438,13 @@ export async function doInitiate(options: CommandOptions): Promise< const isPrerelease = prerelease(currentVersion); const isOutdated = lt(currentVersion, latestVersion); const borderColor = isOutdated ? '#FC521F' : '#F1618C'; + let versionSpecifier = undefined; + try { + const ancestry = getProcessAncestry(); + versionSpecifier = getStorybookVersionFromAncestry(ancestry); + } catch (err) { + // + } const messages = { welcome: `Adding Storybook version ${picocolors.bold(currentVersion)} to your project..`, @@ -635,7 +655,12 @@ export async function doInitiate(options: CommandOptions): Promise< } if (!options.disableTelemetry) { - await telemetry('init', { projectType, features: telemetryFeatures, newUser }); + await telemetry('init', { + projectType, + features: telemetryFeatures, + newUser, + versionSpecifier, + }); } if ([ProjectType.REACT_NATIVE, ProjectType.REACT_NATIVE_AND_RNW].includes(projectType)) { diff --git a/code/yarn.lock b/code/yarn.lock index 843aa86b95f6..969d541d8a13 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -11822,6 +11822,7 @@ __metadata: find-up: "npm:^7.0.0" ora: "npm:^5.4.1" picocolors: "npm:^1.1.0" + process-ancestry: "npm:^0.0.2" prompts: "npm:^2.4.0" react: "npm:^18.2.0" semver: "npm:^7.6.2" @@ -21725,6 +21726,13 @@ __metadata: languageName: node linkType: hard +"process-ancestry@npm:^0.0.2": + version: 0.0.2 + resolution: "process-ancestry@npm:0.0.2" + checksum: 10c0/bca0290b7d3bd35da3a30bb958b2b0f2724f468b80d1b41e58d9a6a49fc42ff466faf49c2d085e94b7b660fee654be26e047b43f6b6065613ca123432bd409a9 + languageName: node + linkType: hard + "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1"