From 183ab1bcb69b4c92aff6351c00918fc7d4ebf76c Mon Sep 17 00:00:00 2001
From: Josanghyeon <05lazy.dev@gmail.com>
Date: Sat, 27 May 2023 12:37:05 +0900
Subject: [PATCH 01/65] getting started add install cli yarn
---
docs/get-started/install.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/get-started/install.md b/docs/get-started/install.md
index 15861bb46364..94a53d5ab4e5 100644
--- a/docs/get-started/install.md
+++ b/docs/get-started/install.md
@@ -9,6 +9,7 @@ Use the Storybook CLI to install it in a single command. Run this inside your _e
From 16d0156fa17306ecfc94938dc425d75917ad9944 Mon Sep 17 00:00:00 2001
From: Gavin King
Date: Fri, 14 Jul 2023 11:42:28 +0200
Subject: [PATCH 02/65] search label for attribute doesn't match id of input
(fixes #23463)
The for attribute value was not set to match the hardcoded value
used for the search input id.
---
code/ui/manager/src/components/sidebar/Search.tsx | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/code/ui/manager/src/components/sidebar/Search.tsx b/code/ui/manager/src/components/sidebar/Search.tsx
index 9bd4b6839954..675351ddc552 100644
--- a/code/ui/manager/src/components/sidebar/Search.tsx
+++ b/code/ui/manager/src/components/sidebar/Search.tsx
@@ -345,9 +345,13 @@ export const Search = React.memo<{
onBlur: () => setPlaceholder('Find components'),
});
+ const labelProps = getLabelProps({
+ htmlFor: 'storybook-explorer-searchfield',
+ });
+
return (
<>
- Search for components
+ Search for components
Date: Sun, 20 Aug 2023 11:30:42 +0900
Subject: [PATCH 03/65] Make sure the Next.js Image Context is reused instead
of recreated when imported
---
code/frameworks/nextjs/package.json | 3 +++
1 file changed, 3 insertions(+)
diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json
index 14ec26a04924..3d1f45e1718a 100644
--- a/code/frameworks/nextjs/package.json
+++ b/code/frameworks/nextjs/package.json
@@ -141,12 +141,15 @@
"./src/preview.tsx",
"./src/next-image-loader-stub.ts",
"./src/images/context.ts",
+ "./src/images/decorator.tsx",
"./src/images/next-future-image.tsx",
"./src/images/next-legacy-image.tsx",
"./src/images/next-image.tsx",
"./src/font/webpack/loader/storybook-nextjs-font-loader.ts"
],
"externals": [
+ "./context",
+ "./images/decorator",
"sb-original/next/image",
"sb-original/next/future/image",
"sb-original/next/legacy/image"
From f4a1021902b903d2a1c425da3bb089e336b1ab53 Mon Sep 17 00:00:00 2001
From: Martin Nabhan <7613182+martinnabhan@users.noreply.github.com>
Date: Tue, 29 Aug 2023 18:13:39 +0900
Subject: [PATCH 04/65] Make sure the Next.js Image Context is reused instead
of recreated when imported
---
code/frameworks/nextjs/package.json | 8 +++++++-
.../src/{images/context.ts => image-context.ts} | 0
code/frameworks/nextjs/src/images/decorator.tsx | 3 ++-
.../nextjs/src/images/next-future-image.tsx | 11 ++++-------
code/frameworks/nextjs/src/images/next-image.tsx | 9 ++++-----
.../nextjs/src/images/next-legacy-image.tsx | 11 ++++-------
6 files changed, 21 insertions(+), 21 deletions(-)
rename code/frameworks/nextjs/src/{images/context.ts => image-context.ts} (100%)
diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json
index acdeb7177946..00afe2a336e5 100644
--- a/code/frameworks/nextjs/package.json
+++ b/code/frameworks/nextjs/package.json
@@ -27,6 +27,11 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
+ "./image-context": {
+ "types": "./dist/image-context.d.ts",
+ "require": "./dist/image-context.js",
+ "import": "./dist/image-context.mjs"
+ },
"./preset": {
"types": "./dist/preset.d.ts",
"require": "./dist/preset.js"
@@ -136,11 +141,12 @@
},
"bundler": {
"entries": [
+ "./src/image-context.ts",
"./src/index.ts",
"./src/preset.ts",
"./src/preview.tsx",
"./src/next-image-loader-stub.ts",
- "./src/images/context.ts",
+ "./src/images/decorator.tsx",
"./src/images/next-future-image.tsx",
"./src/images/next-legacy-image.tsx",
"./src/images/next-image.tsx",
diff --git a/code/frameworks/nextjs/src/images/context.ts b/code/frameworks/nextjs/src/image-context.ts
similarity index 100%
rename from code/frameworks/nextjs/src/images/context.ts
rename to code/frameworks/nextjs/src/image-context.ts
diff --git a/code/frameworks/nextjs/src/images/decorator.tsx b/code/frameworks/nextjs/src/images/decorator.tsx
index f0917b3a3b50..0ee445f8707b 100644
--- a/code/frameworks/nextjs/src/images/decorator.tsx
+++ b/code/frameworks/nextjs/src/images/decorator.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
import type { Addon_StoryContext } from '@storybook/types';
-import { ImageContext } from './context';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { ImageContext } from '@storybook/nextjs/dist/image-context';
export const ImageDecorator = (
Story: React.FC,
diff --git a/code/frameworks/nextjs/src/images/next-future-image.tsx b/code/frameworks/nextjs/src/images/next-future-image.tsx
index 559d2e857d39..0b841452d1fc 100644
--- a/code/frameworks/nextjs/src/images/next-future-image.tsx
+++ b/code/frameworks/nextjs/src/images/next-future-image.tsx
@@ -3,18 +3,15 @@ import type * as _NextImage from 'next/image';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore import is aliased in webpack config
import OriginalNextFutureImage from 'sb-original/next/future/image';
-import { ImageContext } from './context';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { ImageContext } from '@storybook/nextjs/dist/image-context';
import { defaultLoader } from './next-image-default-loader';
-function NextFutureImage(props: _NextImage.ImageProps) {
+function NextFutureImage({ loader, ...props }: _NextImage.ImageProps) {
const imageParameters = React.useContext(ImageContext);
return (
-
+
);
}
diff --git a/code/frameworks/nextjs/src/images/next-image.tsx b/code/frameworks/nextjs/src/images/next-image.tsx
index 74e252d93a7d..34cf6d242bc4 100644
--- a/code/frameworks/nextjs/src/images/next-image.tsx
+++ b/code/frameworks/nextjs/src/images/next-image.tsx
@@ -3,15 +3,14 @@
import OriginalNextImage from 'sb-original/next/image';
import type * as _NextImage from 'next/image';
import React from 'react';
-import { ImageContext } from './context';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { ImageContext } from '@storybook/nextjs/dist/image-context';
import { defaultLoader } from './next-image-default-loader';
-const MockedNextImage = (props: _NextImage.ImageProps) => {
+const MockedNextImage = ({ loader, ...props }: _NextImage.ImageProps) => {
const imageParameters = React.useContext(ImageContext);
- return (
-
- );
+ return ;
};
export default MockedNextImage;
diff --git a/code/frameworks/nextjs/src/images/next-legacy-image.tsx b/code/frameworks/nextjs/src/images/next-legacy-image.tsx
index 8d899cc341a5..1e2f8d9df20c 100644
--- a/code/frameworks/nextjs/src/images/next-legacy-image.tsx
+++ b/code/frameworks/nextjs/src/images/next-legacy-image.tsx
@@ -3,18 +3,15 @@
import OriginalNextLegacyImage from 'sb-original/next/legacy/image';
import type * as _NextLegacyImage from 'next/legacy/image';
import React from 'react';
-import { ImageContext } from './context';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { ImageContext } from '@storybook/nextjs/dist/image-context';
import { defaultLoader } from './next-image-default-loader';
-function NextLegacyImage(props: _NextLegacyImage.ImageProps) {
+function NextLegacyImage({ loader, ...props }: _NextLegacyImage.ImageProps) {
const imageParameters = React.useContext(ImageContext);
return (
-
+
);
}
From 3bd204616c4f6b4f44bf0763460e933dd25e09d2 Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Wed, 30 Aug 2023 22:56:15 +0200
Subject: [PATCH 05/65] add visual tests addon to storybook:ui
---
code/ui/.storybook/main.ts | 8 +
code/ui/components/package.json | 1 +
code/yarn.lock | 321 +++++++++++++++++++++++++++++++-
3 files changed, 322 insertions(+), 8 deletions(-)
diff --git a/code/ui/.storybook/main.ts b/code/ui/.storybook/main.ts
index 5f979898a5c2..190a5e4b84da 100644
--- a/code/ui/.storybook/main.ts
+++ b/code/ui/.storybook/main.ts
@@ -51,6 +51,14 @@ const config: StorybookConfig = {
'@storybook/addon-interactions',
'@storybook/addon-storysource',
'@storybook/addon-designs',
+ {
+ name: '@chromaui/addon-visual-tests',
+ options: {
+ projectId: 'Project:635781f3500dd2c49e189caf',
+ projectToken: '80b312430ec4',
+ buildScriptName: 'storybook:ui:build',
+ },
+ },
],
framework: {
name: '@storybook/react-vite',
diff --git a/code/ui/components/package.json b/code/ui/components/package.json
index 9b170beb3b75..9921b6ef1122 100644
--- a/code/ui/components/package.json
+++ b/code/ui/components/package.json
@@ -71,6 +71,7 @@
"util-deprecate": "^1.0.2"
},
"devDependencies": {
+ "@chromaui/addon-visual-tests": "^0.0.49",
"@popperjs/core": "^2.6.0",
"@storybook/icons": "^1.1.6",
"@types/react-syntax-highlighter": "11.0.5",
diff --git a/code/yarn.lock b/code/yarn.lock
index debf9c20cd8d..82f1d07dbd2d 100644
--- a/code/yarn.lock
+++ b/code/yarn.lock
@@ -5,6 +5,18 @@ __metadata:
version: 6
cacheKey: 8c0
+"@0no-co/graphql.web@npm:^1.0.1":
+ version: 1.0.4
+ resolution: "@0no-co/graphql.web@npm:1.0.4"
+ peerDependencies:
+ graphql: ^14.0.0 || ^15.0.0 || ^16.0.0
+ peerDependenciesMeta:
+ graphql:
+ optional: true
+ checksum: bf63cb5b017063363c9a9e06dc17532abc1c2da402c7ebcbc7b5ab2a0601ec93b02de93af9e50d9daffb3b747eddcf0b1e5418a46d1182c5b8087b7d7a1768ad
+ languageName: node
+ linkType: hard
+
"@aashutoshrathi/word-wrap@npm:^1.2.3":
version: 1.2.6
resolution: "@aashutoshrathi/word-wrap@npm:1.2.6"
@@ -2238,6 +2250,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/runtime@npm:^7.1.2":
+ version: 7.22.10
+ resolution: "@babel/runtime@npm:7.22.10"
+ dependencies:
+ regenerator-runtime: ^0.14.0
+ checksum: d3a006fe2cbaf4048b935fb18f55d9ed52c26292182537b442cee57bf524dbb483367c57f464b1a5a96648d9d8d0fdcda848d58a8a09e18ed3f8971dcd684c6c
+ languageName: node
+ linkType: hard
+
"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.14.8, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2":
version: 7.22.6
resolution: "@babel/runtime@npm:7.22.6"
@@ -2321,6 +2342,38 @@ __metadata:
languageName: node
linkType: hard
+"@chromaui/addon-visual-tests@npm:^0.0.49":
+ version: 0.0.49
+ resolution: "@chromaui/addon-visual-tests@npm:0.0.49"
+ dependencies:
+ "@storybook/csf-tools": 7.4.0
+ "@storybook/design-system": ^7.15.15
+ chromatic: 6.24.0
+ date-fns: ^2.30.0
+ pluralize: ^8.0.0
+ ts-dedent: ^2.2.0
+ urql: ^4.0.3
+ uuid: ^9.0.0
+ peerDependencies:
+ "@storybook/blocks": ^7.2.0
+ "@storybook/client-logger": ^7.2.0
+ "@storybook/components": ^7.2.0
+ "@storybook/core-events": ^7.2.0
+ "@storybook/manager-api": ^7.2.0
+ "@storybook/preview-api": ^7.2.0
+ "@storybook/theming": ^7.2.0
+ "@storybook/types": ^7.2.0
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
+ peerDependenciesMeta:
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ checksum: af5860520f2652d866017ca24d11fc38c18030c7452ba430c2f399c41ef5808af9187ded1f1fdcf936e97c68e821f8cce53495a54d8f40a75b07dfc7b94da3c4
+ languageName: node
+ linkType: hard
+
"@colors/colors@npm:1.5.0":
version: 1.5.0
resolution: "@colors/colors@npm:1.5.0"
@@ -2614,7 +2667,7 @@ __metadata:
languageName: node
linkType: hard
-"@emotion/weak-memoize@npm:^0.3.1":
+"@emotion/weak-memoize@npm:^0.3.0, @emotion/weak-memoize@npm:^0.3.1":
version: 0.3.1
resolution: "@emotion/weak-memoize@npm:0.3.1"
checksum: ed514b3cb94bbacece4ac2450d98898066c0a0698bdeda256e312405ca53634cb83c75889b25cd8bbbe185c80f4c05a1f0a0091e1875460ba6be61d0334f0b8a
@@ -3347,6 +3400,19 @@ __metadata:
languageName: node
linkType: hard
+"@hypnosphi/create-react-context@npm:^0.3.1":
+ version: 0.3.1
+ resolution: "@hypnosphi/create-react-context@npm:0.3.1"
+ dependencies:
+ gud: ^1.0.0
+ warning: ^4.0.3
+ peerDependencies:
+ prop-types: ^15.0.0
+ react: ">=0.14.0"
+ checksum: e8072221f9f9c2c47c3ebc5bc6079f9a71938e181d2b4aa3e1d3922707bc097336d5260dad088cf47c1d6e1ff34839fa21f2505a95bddda0d7548c5a955b5691
+ languageName: node
+ linkType: hard
+
"@isaacs/cliui@npm:^8.0.2":
version: 8.0.2
resolution: "@isaacs/cliui@npm:8.0.2"
@@ -6665,6 +6731,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@storybook/components@workspace:ui/components"
dependencies:
+ "@chromaui/addon-visual-tests": ^0.0.49
"@popperjs/core": ^2.6.0
"@radix-ui/react-select": ^1.2.2
"@radix-ui/react-toolbar": ^1.0.4
@@ -6833,7 +6900,7 @@ __metadata:
languageName: unknown
linkType: soft
-"@storybook/csf-tools@workspace:*, @storybook/csf-tools@workspace:lib/csf-tools":
+"@storybook/csf-tools@7.4.0, @storybook/csf-tools@workspace:*, @storybook/csf-tools@workspace:lib/csf-tools":
version: 0.0.0-use.local
resolution: "@storybook/csf-tools@workspace:lib/csf-tools"
dependencies:
@@ -6871,6 +6938,32 @@ __metadata:
languageName: node
linkType: hard
+"@storybook/design-system@npm:^7.15.15":
+ version: 7.15.15
+ resolution: "@storybook/design-system@npm:7.15.15"
+ dependencies:
+ "@emotion/weak-memoize": ^0.3.0
+ "@storybook/theming": ^7.0.2
+ "@types/pluralize": ^0.0.29
+ "@types/prismjs": ^1.16.6
+ "@types/react-modal": ^3.12.1
+ "@types/uuid": ^8.3.1
+ copy-to-clipboard: ^3.3.1
+ human-format: ^0.11.0
+ pluralize: ^8.0.0
+ polished: ^3.6.4
+ prismjs: 1.25.0
+ react-github-button: ^0.1.11
+ react-modal: ^3.11.2
+ react-popper-tooltip: ^2.11.1
+ uuid: ^3.3.3
+ peerDependencies:
+ react: ^15.0.0 || ^16.0.0 || ^17.0.0
+ react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0
+ checksum: 3f2ea63556aed966e906b8e56fa0ef12fd67f919426a63350a7ecba5a6cff277b8e18362d680530f7fdfa7240c8ceb890984a0594f5129f2b9d972e991b297cf
+ languageName: node
+ linkType: hard
+
"@storybook/docs-mdx@npm:^0.1.0":
version: 0.1.0
resolution: "@storybook/docs-mdx@npm:0.1.0"
@@ -8003,7 +8096,7 @@ __metadata:
languageName: node
linkType: hard
-"@storybook/theming@workspace:*, @storybook/theming@workspace:lib/theming":
+"@storybook/theming@^7.0.2, @storybook/theming@workspace:*, @storybook/theming@workspace:lib/theming":
version: 0.0.0-use.local
resolution: "@storybook/theming@workspace:lib/theming"
dependencies:
@@ -9193,6 +9286,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/pluralize@npm:^0.0.29":
+ version: 0.0.29
+ resolution: "@types/pluralize@npm:0.0.29"
+ checksum: 840796fa1db158eb4d9787758d134736e29d9a8035f5b0cbad06e3801fc64b79112ba944c83f9a1a5b94da08703f505b8315b7e0f28bfc0f8e9e1ccfead7b083
+ languageName: node
+ linkType: hard
+
"@types/prettier@npm:2.7.2":
version: 2.7.2
resolution: "@types/prettier@npm:2.7.2"
@@ -9214,6 +9314,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/prismjs@npm:^1.16.6":
+ version: 1.26.0
+ resolution: "@types/prismjs@npm:1.26.0"
+ checksum: dce1388a626c20b95fa2715917deef5a401eec33e9e181f202840ee3b3c7d8a84d5558c834af4c29b8e007741a6a18639b074db8ecccdd6e7de15280fc4dfdd2
+ languageName: node
+ linkType: hard
+
"@types/prompts@npm:^2.0.9":
version: 2.4.4
resolution: "@types/prompts@npm:2.4.4"
@@ -9288,6 +9395,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/react-modal@npm:^3.12.1":
+ version: 3.16.0
+ resolution: "@types/react-modal@npm:3.16.0"
+ dependencies:
+ "@types/react": "*"
+ checksum: ee65eb9f47e6c953bed23d716442ee1fcac3c2d586409924317043c8df2e38475c2232ef04e3c57d7d7387d7a319a97732278e92864d7363596e54fc5ebcd0cb
+ languageName: node
+ linkType: hard
+
"@types/react-syntax-highlighter@npm:11.0.5":
version: 11.0.5
resolution: "@types/react-syntax-highlighter@npm:11.0.5"
@@ -9500,6 +9616,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/uuid@npm:^8.3.1":
+ version: 8.3.4
+ resolution: "@types/uuid@npm:8.3.4"
+ checksum: b9ac98f82fcf35962317ef7dc44d9ac9e0f6fdb68121d384c88fe12ea318487d5585d3480fa003cf28be86a3bbe213ca688ba786601dce4a97724765eb5b1cf2
+ languageName: node
+ linkType: hard
+
"@types/uuid@npm:^9.0.1":
version: 9.0.2
resolution: "@types/uuid@npm:9.0.2"
@@ -9743,6 +9866,16 @@ __metadata:
languageName: node
linkType: hard
+"@urql/core@npm:^4.1.0":
+ version: 4.1.1
+ resolution: "@urql/core@npm:4.1.1"
+ dependencies:
+ "@0no-co/graphql.web": ^1.0.1
+ wonka: ^6.3.2
+ checksum: 1f2077a0ce6cc7e34f03107f6e51f7b4ae77a9ef8f81ac37a81d61828b8ec4fa7b937eb315ead84108164ecd01e442b21f8ad3701fb8df881fa1c63cba114e68
+ languageName: node
+ linkType: hard
+
"@vitejs/plugin-basic-ssl@npm:1.0.1":
version: 1.0.1
resolution: "@vitejs/plugin-basic-ssl@npm:1.0.1"
@@ -12721,6 +12854,17 @@ __metadata:
languageName: node
linkType: hard
+"chromatic@npm:6.24.0":
+ version: 6.24.0
+ resolution: "chromatic@npm:6.24.0"
+ bin:
+ chroma: dist/bin.js
+ chromatic: dist/bin.js
+ chromatic-cli: dist/bin.js
+ checksum: e5ebc1ff78076e5112d79fd5f4f133febf789cb4713149507f755741cd069daf3f0a2c7f13b7b176becde7734cf010d1d7628a22f3e28087a6faa17f28ffd798
+ languageName: node
+ linkType: hard
+
"chrome-trace-event@npm:^1.0.2":
version: 1.0.3
resolution: "chrome-trace-event@npm:1.0.3"
@@ -13966,7 +14110,7 @@ __metadata:
languageName: node
linkType: hard
-"date-fns@npm:^2.0.1":
+"date-fns@npm:^2.0.1, date-fns@npm:^2.30.0":
version: 2.30.0
resolution: "date-fns@npm:2.30.0"
dependencies:
@@ -14075,6 +14219,20 @@ __metadata:
languageName: node
linkType: hard
+"deep-equal@npm:^1.1.1":
+ version: 1.1.1
+ resolution: "deep-equal@npm:1.1.1"
+ dependencies:
+ is-arguments: ^1.0.4
+ is-date-object: ^1.0.1
+ is-regex: ^1.0.4
+ object-is: ^1.0.1
+ object-keys: ^1.1.1
+ regexp.prototype.flags: ^1.2.0
+ checksum: 473d5dd1d707afd5ad3068864765590591b049d0e0d9a01931599dbbd820e35f09d0a42faa6e4644deb7cf6b7dc90f7bfdf5559f42279d67f714209b62036212
+ languageName: node
+ linkType: hard
+
"deep-equal@npm:^2.0.5":
version: 2.2.2
resolution: "deep-equal@npm:2.2.2"
@@ -16155,6 +16313,13 @@ __metadata:
languageName: node
linkType: hard
+"exenv@npm:^1.2.0":
+ version: 1.2.2
+ resolution: "exenv@npm:1.2.2"
+ checksum: 4e96b355a6b9b9547237288ca779dd673b2e698458b409e88b50df09feb7c85ef94c07354b6b87bc3ed0193a94009a6f7a3c71956da12f45911c0d0f5aa3caa0
+ languageName: node
+ linkType: hard
+
"exit@npm:^0.1.2":
version: 0.1.2
resolution: "exit@npm:0.1.2"
@@ -17826,6 +17991,13 @@ __metadata:
languageName: node
linkType: hard
+"gud@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "gud@npm:1.0.0"
+ checksum: a4db6edc18e2c4e3a22dc9e639e40a4e5650d53dae9cf384a96d5380dfa17ddda376cf6b7797a5c30d140d2532e5a69d167bdb70c2c151dd673253bac6b027f3
+ languageName: node
+ linkType: hard
+
"gunzip-maybe@npm:^1.4.2":
version: 1.4.2
resolution: "gunzip-maybe@npm:1.4.2"
@@ -18496,6 +18668,13 @@ __metadata:
languageName: node
linkType: hard
+"human-format@npm:^0.11.0":
+ version: 0.11.0
+ resolution: "human-format@npm:0.11.0"
+ checksum: 83cc87af67036b4abb6dc585533fcc232279373f8a3a7a4fc1f6d988f6aa35664f986adb818d04d9de3dee240648ec94a9944a8ab1852df21eb67c254e991ea7
+ languageName: node
+ linkType: hard
+
"human-signals@npm:^2.1.0":
version: 2.1.0
resolution: "human-signals@npm:2.1.0"
@@ -19359,7 +19538,7 @@ __metadata:
languageName: node
linkType: hard
-"is-regex@npm:^1.0.3, is-regex@npm:^1.0.5, is-regex@npm:^1.1.0, is-regex@npm:^1.1.4":
+"is-regex@npm:^1.0.3, is-regex@npm:^1.0.4, is-regex@npm:^1.0.5, is-regex@npm:^1.1.0, is-regex@npm:^1.1.4":
version: 1.1.4
resolution: "is-regex@npm:1.1.4"
dependencies:
@@ -25162,6 +25341,15 @@ __metadata:
languageName: node
linkType: hard
+"polished@npm:^3.6.4":
+ version: 3.7.2
+ resolution: "polished@npm:3.7.2"
+ dependencies:
+ "@babel/runtime": ^7.12.5
+ checksum: c36439946b5bfbac16c06dd7b00a89f45e07410427344e909c540ce3ddeb9b44d2ae9cc035a9d77f4551e07b9803419ae77767aec85958a0978158a95c0115d8
+ languageName: node
+ linkType: hard
+
"polished@npm:^4.2.2":
version: 4.2.2
resolution: "polished@npm:4.2.2"
@@ -25171,6 +25359,13 @@ __metadata:
languageName: node
linkType: hard
+"popper.js@npm:^1.14.4":
+ version: 1.16.1
+ resolution: "popper.js@npm:1.16.1"
+ checksum: 1c1a826f757edb5b8c2049dfd7a9febf6ae1e9d0e51342fc715b49a0c1020fced250d26484619883651e097c5764bbcacd2f31496e3646027f079dd83e072681
+ languageName: node
+ linkType: hard
+
"portfinder@npm:^1.0.28":
version: 1.0.32
resolution: "portfinder@npm:1.0.32"
@@ -25520,6 +25715,13 @@ __metadata:
languageName: node
linkType: hard
+"prismjs@npm:1.25.0":
+ version: 1.25.0
+ resolution: "prismjs@npm:1.25.0"
+ checksum: 0c3853a6c815b23a07bef77700f60a40b2a12018a383a75cd7d108718717b73927c809e7dd08ac0ae9f16fbe1e005b337262bc95952cf9cfc91914f986b07bd3
+ languageName: node
+ linkType: hard
+
"prismjs@npm:^1.27.0":
version: 1.29.0
resolution: "prismjs@npm:1.29.0"
@@ -25662,7 +25864,7 @@ __metadata:
languageName: node
linkType: hard
-"prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1":
+"prop-types@npm:^15.5.10, prop-types@npm:^15.6.1, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1":
version: 15.8.1
resolution: "prop-types@npm:15.8.1"
dependencies:
@@ -26247,6 +26449,15 @@ __metadata:
languageName: node
linkType: hard
+"react-github-button@npm:^0.1.11":
+ version: 0.1.11
+ resolution: "react-github-button@npm:0.1.11"
+ dependencies:
+ prop-types: ^15.5.10
+ checksum: e00fa4f3b2dee74f45fff0c9d68d7d75eefa495d27a56ef2e2391f9600623d16b8a9f99c1d35a7b4f620dfb95dd8ed0b1a76fbbfece4be0843cd507c17a37dfa
+ languageName: node
+ linkType: hard
+
"react-helmet-async@npm:^1.0.7":
version: 1.3.0
resolution: "react-helmet-async@npm:1.3.0"
@@ -26300,6 +26511,13 @@ __metadata:
languageName: node
linkType: hard
+"react-lifecycles-compat@npm:^3.0.0":
+ version: 3.0.4
+ resolution: "react-lifecycles-compat@npm:3.0.4"
+ checksum: 1d0df3c85af79df720524780f00c064d53a9dd1899d785eddb7264b378026979acbddb58a4b7e06e7d0d12aa1494fd5754562ee55d32907b15601068dae82c27
+ languageName: node
+ linkType: hard
+
"react-merge-refs@npm:^1.0.0":
version: 1.1.0
resolution: "react-merge-refs@npm:1.1.0"
@@ -26307,6 +26525,34 @@ __metadata:
languageName: node
linkType: hard
+"react-modal@npm:^3.11.2":
+ version: 3.16.1
+ resolution: "react-modal@npm:3.16.1"
+ dependencies:
+ exenv: ^1.2.0
+ prop-types: ^15.7.2
+ react-lifecycles-compat: ^3.0.0
+ warning: ^4.0.3
+ peerDependencies:
+ react: ^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18
+ react-dom: ^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18
+ checksum: 7b56e2c505b2b924736c471a34754a4211df40ac2d6fb0949cf095aea5e65d3326bd9f111fa7898acf40afa54f526809ad8aa47e02b8328663d11422568dc7b1
+ languageName: node
+ linkType: hard
+
+"react-popper-tooltip@npm:^2.11.1":
+ version: 2.11.1
+ resolution: "react-popper-tooltip@npm:2.11.1"
+ dependencies:
+ "@babel/runtime": ^7.9.2
+ react-popper: ^1.3.7
+ peerDependencies:
+ react: ^16.6.0
+ react-dom: ^16.6.0
+ checksum: f81278f1ea87899ffa57fed85c2531fa583ebca424ae5522e3a1b05c5635c014b3467391e77fb9c48bbc8e7b9f1050fa9302e8ee6134a9333858b5a6e0ae1b49
+ languageName: node
+ linkType: hard
+
"react-popper-tooltip@npm:^4.4.2":
version: 4.4.2
resolution: "react-popper-tooltip@npm:4.4.2"
@@ -26321,6 +26567,23 @@ __metadata:
languageName: node
linkType: hard
+"react-popper@npm:^1.3.7":
+ version: 1.3.11
+ resolution: "react-popper@npm:1.3.11"
+ dependencies:
+ "@babel/runtime": ^7.1.2
+ "@hypnosphi/create-react-context": ^0.3.1
+ deep-equal: ^1.1.1
+ popper.js: ^1.14.4
+ prop-types: ^15.6.1
+ typed-styles: ^0.0.7
+ warning: ^4.0.2
+ peerDependencies:
+ react: 0.14.x || ^15.0.0 || ^16.0.0 || ^17.0.0
+ checksum: d5dd1d0d4b5a3407134681b42a079fce525c94bce892ad177515d54a8cf64203eecbc30231476367e916aaff91221f5b6abd5afc207a86c698f35b7254178488
+ languageName: node
+ linkType: hard
+
"react-popper@npm:^2.3.0":
version: 2.3.0
resolution: "react-popper@npm:2.3.0"
@@ -26815,6 +27078,13 @@ __metadata:
languageName: node
linkType: hard
+"regenerator-runtime@npm:^0.14.0":
+ version: 0.14.0
+ resolution: "regenerator-runtime@npm:0.14.0"
+ checksum: e25f062c1a183f81c99681691a342760e65c55e8d3a4d4fe347ebe72433b123754b942b70b622959894e11f8a9131dc549bd3c9a5234677db06a4af42add8d12
+ languageName: node
+ linkType: hard
+
"regenerator-transform@npm:^0.15.1":
version: 0.15.1
resolution: "regenerator-transform@npm:0.15.1"
@@ -26841,7 +27111,7 @@ __metadata:
languageName: node
linkType: hard
-"regexp.prototype.flags@npm:^1.4.3, regexp.prototype.flags@npm:^1.5.0":
+"regexp.prototype.flags@npm:^1.2.0, regexp.prototype.flags@npm:^1.4.3, regexp.prototype.flags@npm:^1.5.0":
version: 1.5.0
resolution: "regexp.prototype.flags@npm:1.5.0"
dependencies:
@@ -30162,6 +30432,13 @@ __metadata:
languageName: node
linkType: hard
+"typed-styles@npm:^0.0.7":
+ version: 0.0.7
+ resolution: "typed-styles@npm:0.0.7"
+ checksum: ec159f0e538364750cf9b8f19136375df64ad364fda355e6f7a7216ebffc67f18b436722c5c6853c89f70e6507eb69e5061ceb9334fa1f54902c0f6be1b985fe
+ languageName: node
+ linkType: hard
+
"typedarray@npm:^0.0.6":
version: 0.0.6
resolution: "typedarray@npm:0.0.6"
@@ -30723,6 +31000,18 @@ __metadata:
languageName: node
linkType: hard
+"urql@npm:^4.0.3":
+ version: 4.0.5
+ resolution: "urql@npm:4.0.5"
+ dependencies:
+ "@urql/core": ^4.1.0
+ wonka: ^6.3.2
+ peerDependencies:
+ react: ">= 16.8.0"
+ checksum: 9560d04b3c2fe72c921bdb21e969039b776e07999704d23bce35f815eb537c9357b6c7322a1b8cd43957550798c30cd15f5130ddd054dfd8a890d17d2be85282
+ languageName: node
+ linkType: hard
+
"use-callback-ref@npm:^1.3.0":
version: 1.3.0
resolution: "use-callback-ref@npm:1.3.0"
@@ -30867,6 +31156,15 @@ __metadata:
languageName: node
linkType: hard
+"uuid@npm:^3.3.3":
+ version: 3.4.0
+ resolution: "uuid@npm:3.4.0"
+ bin:
+ uuid: ./bin/uuid
+ checksum: 1c13950df865c4f506ebfe0a24023571fa80edf2e62364297a537c80af09c618299797bbf2dbac6b1f8ae5ad182ba474b89db61e0e85839683991f7e08795347
+ languageName: node
+ linkType: hard
+
"uuid@npm:^9.0.0":
version: 9.0.0
resolution: "uuid@npm:9.0.0"
@@ -31480,7 +31778,7 @@ __metadata:
languageName: node
linkType: hard
-"warning@npm:^4.0.2":
+"warning@npm:^4.0.2, warning@npm:^4.0.3":
version: 4.0.3
resolution: "warning@npm:4.0.3"
dependencies:
@@ -31952,6 +32250,13 @@ __metadata:
languageName: node
linkType: hard
+"wonka@npm:^6.3.2":
+ version: 6.3.4
+ resolution: "wonka@npm:6.3.4"
+ checksum: 77329eea673da07717476e1b8f1a22f1e1a4f261bb9a58fa446c03d3da13dbd5b254664f8aded5928d953f33ee5b399a17a4f70336e8b236e478209c0e78cda4
+ languageName: node
+ linkType: hard
+
"wordwrap@npm:^1.0.0":
version: 1.0.0
resolution: "wordwrap@npm:1.0.0"
From 15b8f838be36f30a6783b9a17ccbb98ecdab6590 Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Thu, 31 Aug 2023 11:58:11 +0200
Subject: [PATCH 06/65] sanitize ansi codes in error message and stack
---
code/lib/telemetry/src/sanitize.test.ts | 16 ++++++++++++++++
code/lib/telemetry/src/sanitize.ts | 15 ++++++++++++++-
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/code/lib/telemetry/src/sanitize.test.ts b/code/lib/telemetry/src/sanitize.test.ts
index f5b3a742d3e6..a3389c83df79 100644
--- a/code/lib/telemetry/src/sanitize.test.ts
+++ b/code/lib/telemetry/src/sanitize.test.ts
@@ -1,7 +1,23 @@
+/* eslint-disable local-rules/no-uncategorized-errors */
import { sanitizeError, cleanPaths } from './sanitize';
describe(`Errors Helpers`, () => {
describe(`sanitizeError`, () => {
+ it(`Sanitizes ansi codes in error`, () => {
+ const errorMessage = `\u001B[4mStorybook\u001B[0m`;
+ let e: any;
+ try {
+ throw new Error(errorMessage);
+ } catch (error) {
+ e = error;
+ }
+
+ const sanitizedError = sanitizeError(e);
+
+ expect(sanitizedError.message).toEqual('Storybook');
+ expect(sanitizedError.stack).toContain('Error: Storybook');
+ });
+
it(`Sanitizes current path from error stacktraces`, () => {
const errorMessage = `this is a test`;
let e: any;
diff --git a/code/lib/telemetry/src/sanitize.ts b/code/lib/telemetry/src/sanitize.ts
index 4c68ed50db94..a611dbea1a13 100644
--- a/code/lib/telemetry/src/sanitize.ts
+++ b/code/lib/telemetry/src/sanitize.ts
@@ -12,6 +12,11 @@ function regexpEscape(str: string): string {
return str.replace(/[-[/{}()*+?.\\^$|]/g, `\\$&`);
}
+export function removeAnsiEscapeCodes(input: string): string {
+ // eslint-disable-next-line no-control-regex
+ return input.replace(/\u001B\[[0-9;]*m/g, '');
+}
+
export function cleanPaths(str: string, separator: string = sep): string {
if (!str) return str;
@@ -35,7 +40,15 @@ export function cleanPaths(str: string, separator: string = sep): string {
export function sanitizeError(error: Error, pathSeparator: string = sep) {
try {
// Hack because Node
- error = JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)));
+ error = JSON.parse(
+ JSON.stringify(error, [...Object.getOwnPropertyNames(error), 'message', 'name'])
+ );
+ if (error.message) {
+ error.message = removeAnsiEscapeCodes(error.message);
+ }
+ if (error.stack) {
+ error.stack = removeAnsiEscapeCodes(error.stack);
+ }
// Removes all user paths
const errorString = cleanPaths(JSON.stringify(error), pathSeparator);
From e2e9c24ba9c454c6fcfc8c5958ce1b65ad9a07e3 Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 15:03:03 +0200
Subject: [PATCH 07/65] use node 18 to generate angular sandboxes
---
.github/workflows/generate-sandboxes-main.yml | 57 -------------------
...dboxes-next.yml => generate-sandboxes.yml} | 25 ++++++--
scripts/sandbox/generate.ts | 25 +++++++-
3 files changed, 42 insertions(+), 65 deletions(-)
delete mode 100644 .github/workflows/generate-sandboxes-main.yml
rename .github/workflows/{generate-sandboxes-next.yml => generate-sandboxes.yml} (69%)
diff --git a/.github/workflows/generate-sandboxes-main.yml b/.github/workflows/generate-sandboxes-main.yml
deleted file mode 100644
index 66cd1b800d37..000000000000
--- a/.github/workflows/generate-sandboxes-main.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-name: Generate and push sandboxes (main)
-
-on:
- schedule:
- - cron: '2 2 */1 * *'
- workflow_dispatch:
- # To test fixes on push rather than wait for the scheduling, do the following:
- # 1. Uncomment the lines below and add your branch.
- # push:
- # branches:
- # -
- # 2. change the "ref" value to in the actions/checkout step below.
- # 3. 👉 DON'T FORGET TO UNDO THE VALUES BACK TO `main` BEFORE YOU MERGE YOUR CHANGES!
-
-jobs:
- generate:
- runs-on: ubuntu-latest
- env:
- YARN_ENABLE_IMMUTABLE_INSTALLS: false
- CLEANUP_SANDBOX_NODE_MODULES: true
- steps:
- - uses: actions/setup-node@v3
- with:
- node-version: 16
- - uses: actions/checkout@v3
- with:
- ref: main
- - name: Setup git user
- run: |
- git config --global user.name "Storybook Bot"
- git config --global user.email "bot@storybook.js.org"
- - name: Install dependencies
- run: node ./scripts/check-dependencies.js
- - name: Compile Storybook libraries
- run: yarn task --task compile --start-from=auto --no-link
- - name: Publishing to local registry
- run: yarn local-registry --publish
- working-directory: ./code
- - name: Running local registry
- run: yarn local-registry --open &
- working-directory: ./code
- - name: Wait for registry
- run: yarn wait-on http://localhost:6001
- working-directory: ./code
- - name: Generate
- run: yarn generate-sandboxes --local-registry
- working-directory: ./code
- - name: Publish
- run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=main
- working-directory: ./code
- - name: The job has failed
- if: ${{ failure() || cancelled() }}
- env:
- DISCORD_WEBHOOK: ${{ secrets.DISCORD_MONITORING_URL }}
- uses: Ilshidur/action-discord@master
- with:
- args: 'The generation of sandboxes in the **main** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})'
diff --git a/.github/workflows/generate-sandboxes-next.yml b/.github/workflows/generate-sandboxes.yml
similarity index 69%
rename from .github/workflows/generate-sandboxes-next.yml
rename to .github/workflows/generate-sandboxes.yml
index f22e7cb4a50b..c37ecb643fa8 100644
--- a/.github/workflows/generate-sandboxes-next.yml
+++ b/.github/workflows/generate-sandboxes.yml
@@ -1,4 +1,4 @@
-name: Generate and push sandboxes (next)
+name: Generate and push sandboxes
on:
schedule:
@@ -18,13 +18,26 @@ jobs:
env:
YARN_ENABLE_IMMUTABLE_INSTALLS: false
CLEANUP_SANDBOX_NODE_MODULES: true
+ strategy:
+ matrix:
+ node_version:
+ - 16
+ - 18
+ branch:
+ - main
+ - next
+ include:
+ - node_version: 16
+ excludeTemplates: 'angular-cli/prerelease'
+ - node_version: 18
+ includeTemplates: 'angular-cli/prerelease'
steps:
- uses: actions/setup-node@v3
with:
- node-version: 16
+ node-version: ${{ matrix.node_version }}
- uses: actions/checkout@v3
with:
- ref: next
+ ref: ${{ matrix.branch }}
- name: Setup git user
run: |
git config --global user.name "Storybook Bot"
@@ -43,10 +56,10 @@ jobs:
run: yarn wait-on http://localhost:6001
working-directory: ./code
- name: Generate
- run: yarn generate-sandboxes --local-registry
+ run: yarn generate-sandboxes --local-registry --includeTemplates "${{matrix.includeTemplates}}" --excludeTemplates "${{matrix.excludeTemplates}}"
working-directory: ./code
- name: Publish
- run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=next
+ run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=${{ matrix.branch }}}
working-directory: ./code
- name: The job has failed
if: ${{ failure() || cancelled() }}
@@ -54,4 +67,4 @@ jobs:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_MONITORING_URL }}
uses: Ilshidur/action-discord@master
with:
- args: 'The generation of sandboxes in the **next** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})'
+ args: 'The generation of sandboxes in the **${{ matrix.branch }}** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})'
diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts
index b74ae5a28d03..6c2455d0d937 100755
--- a/scripts/sandbox/generate.ts
+++ b/scripts/sandbox/generate.ts
@@ -207,6 +207,17 @@ export const options = createOptions({
description: 'Which template would you like to create?',
values: Object.keys(sandboxTemplates),
},
+ includeTemplates: {
+ type: 'string',
+ description: 'Comma-delimited list of templates to include',
+ promptType: false,
+ },
+ excludeTemplates: {
+ type: 'string',
+ description:
+ 'Comma-delimited list of templates to exclude. Takes precedence over --includedTemplates',
+ promptType: false,
+ },
localRegistry: {
type: 'boolean',
description: 'Generate reproduction from local registry?',
@@ -221,6 +232,8 @@ export const options = createOptions({
export const generate = async ({
template,
+ includeTemplates,
+ excludeTemplates,
localRegistry,
debug,
}: OptionValues) => {
@@ -233,8 +246,11 @@ export const generate = async ({
if (template) {
return dirName === template;
}
-
- return true;
+ let include = includeTemplates ? includeTemplates.split(',').includes(dirName) : true;
+ if (excludeTemplates && include) {
+ include = !excludeTemplates.split(',').includes(dirName);
+ }
+ return include;
});
await runGenerators(generatorConfigs, localRegistry, debug);
@@ -244,6 +260,11 @@ if (require.main === module) {
program
.description('Generate sandboxes from a set of possible templates')
.option('--template ', 'Create a single template')
+ .option('--includeTemplates ', 'Comma-delimited list of templates to include')
+ .option(
+ '--excludeTemplates ',
+ 'Comma-delimited list of templates to exclude. Takes precedence over --includedTemplates'
+ )
.option('--debug', 'Print all the logs to the console')
.option('--local-registry', 'Use local registry', false)
.action((optionValues) => {
From 07b6e3e0adee7783d2a168e77d6ee8203ef9275f Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 15:06:00 +0200
Subject: [PATCH 08/65] temp workflow rename
---
.../{generate-sandboxes.yml => generate-sandboxes-next.yml} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename .github/workflows/{generate-sandboxes.yml => generate-sandboxes-next.yml} (100%)
diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes-next.yml
similarity index 100%
rename from .github/workflows/generate-sandboxes.yml
rename to .github/workflows/generate-sandboxes-next.yml
From 3c17f4b71f6fea045e7c6a3f81e6a2d20459cb52 Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 15:08:42 +0200
Subject: [PATCH 09/65] debug strategy
---
.github/workflows/generate-sandboxes-next.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/generate-sandboxes-next.yml b/.github/workflows/generate-sandboxes-next.yml
index c37ecb643fa8..32cc6e4dd793 100644
--- a/.github/workflows/generate-sandboxes-next.yml
+++ b/.github/workflows/generate-sandboxes-next.yml
@@ -42,6 +42,8 @@ jobs:
run: |
git config --global user.name "Storybook Bot"
git config --global user.email "bot@storybook.js.org"
+ - name: debug strategy
+ run: echo ${{ toJSON(matrix) }}
- name: Install dependencies
run: node ./scripts/check-dependencies.js
- name: Compile Storybook libraries
From ce6c6f57f9213f530ecff8e21a1d7940c2d441d5 Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 15:10:14 +0200
Subject: [PATCH 10/65] improve error message
---
.github/workflows/generate-sandboxes-next.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/generate-sandboxes-next.yml b/.github/workflows/generate-sandboxes-next.yml
index 32cc6e4dd793..c425218cbdb6 100644
--- a/.github/workflows/generate-sandboxes-next.yml
+++ b/.github/workflows/generate-sandboxes-next.yml
@@ -69,4 +69,4 @@ jobs:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_MONITORING_URL }}
uses: Ilshidur/action-discord@master
with:
- args: 'The generation of sandboxes in the **${{ matrix.branch }}** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})'
+ args: 'The generation of sandboxes with Node version **${{ matrix.node_version }}** in the **${{ matrix.branch }}** branch has failed. [View Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})'
From 123bcb4191faf3f2b1fe4aea4bc1d0ff78395f7f Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 15:13:38 +0200
Subject: [PATCH 11/65] remove debug
---
.github/workflows/generate-sandboxes-next.yml | 2 --
1 file changed, 2 deletions(-)
diff --git a/.github/workflows/generate-sandboxes-next.yml b/.github/workflows/generate-sandboxes-next.yml
index c425218cbdb6..4b6003231d67 100644
--- a/.github/workflows/generate-sandboxes-next.yml
+++ b/.github/workflows/generate-sandboxes-next.yml
@@ -42,8 +42,6 @@ jobs:
run: |
git config --global user.name "Storybook Bot"
git config --global user.email "bot@storybook.js.org"
- - name: debug strategy
- run: echo ${{ toJSON(matrix) }}
- name: Install dependencies
run: node ./scripts/check-dependencies.js
- name: Compile Storybook libraries
From 1e9c34fed3b40bc12229ffecfb1fbc5997cddabc Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 15:14:11 +0200
Subject: [PATCH 12/65] rename gh workflow back
---
.../{generate-sandboxes-next.yml => generate-sandboxes.yml} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename .github/workflows/{generate-sandboxes-next.yml => generate-sandboxes.yml} (100%)
diff --git a/.github/workflows/generate-sandboxes-next.yml b/.github/workflows/generate-sandboxes.yml
similarity index 100%
rename from .github/workflows/generate-sandboxes-next.yml
rename to .github/workflows/generate-sandboxes.yml
From 73810cd07476293b36c61163ebb2af2ea07d8e87 Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 15:30:23 +0200
Subject: [PATCH 13/65] extract angular prerelease to separate CI run
---
.circleci/config.yml | 37 +++++++++++++++++++++++----
code/lib/cli/src/sandbox-templates.ts | 1 -
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 5e7cc4a22d24..e285eb919f21 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -262,6 +262,33 @@ jobs:
- report-workflow-on-failure
- store_test_results:
path: test-results
+ angular-prerelease-sandbox:
+ executor:
+ class: large
+ name: sb_playwright
+ steps:
+ - git-shallow-clone/checkout_advanced:
+ clone_options: '--depth 1 --verbose'
+ - attach_workspace:
+ at: .
+ - run:
+ name: Angular Prerelease Sandbox
+ command: |
+ yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task sandbox
+ yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task build
+ yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task chromatic
+ yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task e2e-tests
+ yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task e2e-tests-dev
+ yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task test-runner
+ - report-workflow-on-failure:
+ template: angular-cli/prerelease
+ - persist_to_workspace:
+ root: .
+ paths:
+ - sandbox
+ - store_test_results:
+ path: test-results
+
## new workflow
create-sandboxes:
parameters:
@@ -609,22 +636,22 @@ workflows:
requires:
- build
- create-sandboxes:
- parallelism: 35
+ parallelism: 34
requires:
- build
# - smoke-test-sandboxes: # disabled for now
# requires:
# - create-sandboxes
- build-sandboxes:
- parallelism: 35
+ parallelism: 34
requires:
- create-sandboxes
- chromatic-sandboxes:
- parallelism: 32
+ parallelism: 31
requires:
- build-sandboxes
- e2e-production:
- parallelism: 32
+ parallelism: 31
requires:
- build-sandboxes
- e2e-dev:
@@ -632,7 +659,7 @@ workflows:
requires:
- create-sandboxes
- test-runner-production:
- parallelism: 32
+ parallelism: 31
requires:
- build-sandboxes
# TODO: reenable once we find out the source of flakyness
diff --git a/code/lib/cli/src/sandbox-templates.ts b/code/lib/cli/src/sandbox-templates.ts
index bbfdaef49ef6..64916eddab3a 100644
--- a/code/lib/cli/src/sandbox-templates.ts
+++ b/code/lib/cli/src/sandbox-templates.ts
@@ -573,7 +573,6 @@ export const merged: TemplateKey[] = [
];
export const daily: TemplateKey[] = [
...merged,
- 'angular-cli/prerelease',
'cra/default-js',
'react-vite/default-js',
'vue3-vite/default-js',
From 7a4bad6cd76e87fc1dab109b943025802221eb53 Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 15:30:57 +0200
Subject: [PATCH 14/65] add node version log to angular prerelease ci
---
.circleci/config.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index e285eb919f21..09d93db647ba 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -274,6 +274,7 @@ jobs:
- run:
name: Angular Prerelease Sandbox
command: |
+ node -v
yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task sandbox
yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task build
yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task chromatic
From 36370f912fd16cfe067f1f242e0dac945e541e7e Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 15:35:50 +0200
Subject: [PATCH 15/65] add angular job to ci workflow
---
.circleci/config.yml | 78 +++++++++++++++++++++++---------------------
1 file changed, 40 insertions(+), 38 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 09d93db647ba..a5796c773b7f 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -619,50 +619,52 @@ workflows:
when:
equal: [daily, << pipeline.parameters.workflow >>]
jobs:
- - pretty-docs
+ # - pretty-docs
- build
- - lint:
- requires:
- - build
- - check:
- requires:
- - build
- - unit-tests:
- requires:
- - build
- - script-checks:
- requires:
- - build
- - chromatic-internal-storybooks:
- requires:
- - build
- - create-sandboxes:
- parallelism: 34
+ # - lint:
+ # requires:
+ # - build
+ # - check:
+ # requires:
+ # - build
+ # - unit-tests:
+ # requires:
+ # - build
+ # - script-checks:
+ # requires:
+ # - build
+ # - chromatic-internal-storybooks:
+ # requires:
+ # - build
+ # - chromatic-internal-storybooks:
+ # requires:
+ # - build
+ - angular-prerelease-sandbox:
requires:
- build
# - smoke-test-sandboxes: # disabled for now
# requires:
# - create-sandboxes
- - build-sandboxes:
- parallelism: 34
- requires:
- - create-sandboxes
- - chromatic-sandboxes:
- parallelism: 31
- requires:
- - build-sandboxes
- - e2e-production:
- parallelism: 31
- requires:
- - build-sandboxes
- - e2e-dev:
- parallelism: 4
- requires:
- - create-sandboxes
- - test-runner-production:
- parallelism: 31
- requires:
- - build-sandboxes
+ # - build-sandboxes:
+ # parallelism: 34
+ # requires:
+ # - create-sandboxes
+ # - chromatic-sandboxes:
+ # parallelism: 31
+ # requires:
+ # - build-sandboxes
+ # - e2e-production:
+ # parallelism: 31
+ # requires:
+ # - build-sandboxes
+ # - e2e-dev:
+ # parallelism: 4
+ # requires:
+ # - create-sandboxes
+ # - test-runner-production:
+ # parallelism: 31
+ # requires:
+ # - build-sandboxes
# TODO: reenable once we find out the source of flakyness
# - test-runner-dev:
# parallelism: 4
From 52ecb89bc74896f1e4fc56e99c5d36004d212f92 Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Thu, 31 Aug 2023 16:00:24 +0200
Subject: [PATCH 16/65] treat empty error messages in telemetry reports and
allow non-error instances
---
.../lib/core-server/src/withTelemetry.test.ts | 542 +++++++++++++-----
code/lib/core-server/src/withTelemetry.ts | 23 +-
2 files changed, 406 insertions(+), 159 deletions(-)
diff --git a/code/lib/core-server/src/withTelemetry.test.ts b/code/lib/core-server/src/withTelemetry.test.ts
index 519de40c1458..2d511ea7663a 100644
--- a/code/lib/core-server/src/withTelemetry.test.ts
+++ b/code/lib/core-server/src/withTelemetry.test.ts
@@ -1,10 +1,11 @@
+/* eslint-disable local-rules/no-uncategorized-errors */
/// ;
import prompts from 'prompts';
import { loadAllPresets, cache } from '@storybook/core-common';
-import { telemetry } from '@storybook/telemetry';
+import { telemetry, oneWayHash } from '@storybook/telemetry';
-import { withTelemetry } from './withTelemetry';
+import { getErrorLevel, sendTelemetryError, withTelemetry } from './withTelemetry';
jest.mock('prompts');
jest.mock('@storybook/core-common');
@@ -12,222 +13,463 @@ jest.mock('@storybook/telemetry');
const cliOptions = {};
-it('works in happy path', async () => {
- const run = jest.fn();
+describe('withTelemetry', () => {
+ it('works in happy path', async () => {
+ const run = jest.fn();
- await withTelemetry('dev', { cliOptions }, run);
+ await withTelemetry('dev', { cliOptions }, run);
- expect(telemetry).toHaveBeenCalledTimes(1);
- expect(telemetry).toHaveBeenCalledWith('boot', { eventType: 'dev' }, { stripMetadata: true });
-});
-
-it('does not send boot when cli option is passed', async () => {
- const run = jest.fn();
+ expect(telemetry).toHaveBeenCalledTimes(1);
+ expect(telemetry).toHaveBeenCalledWith('boot', { eventType: 'dev' }, { stripMetadata: true });
+ });
- await withTelemetry('dev', { cliOptions: { disableTelemetry: true } }, run);
+ it('does not send boot when cli option is passed', async () => {
+ const run = jest.fn();
- expect(telemetry).toHaveBeenCalledTimes(0);
-});
+ await withTelemetry('dev', { cliOptions: { disableTelemetry: true } }, run);
-describe('when command fails', () => {
- const error = new Error('An Error!');
- const run = jest.fn(async () => {
- throw error;
+ expect(telemetry).toHaveBeenCalledTimes(0);
});
- it('sends boot message', async () => {
- await expect(async () => withTelemetry('dev', { cliOptions }, run)).rejects.toThrow(error);
+ describe('when command fails', () => {
+ const error = new Error('An Error!');
+ const run = jest.fn(async () => {
+ throw error;
+ });
- expect(telemetry).toHaveBeenCalledWith('boot', { eventType: 'dev' }, { stripMetadata: true });
- });
+ it('sends boot message', async () => {
+ await expect(async () =>
+ withTelemetry('dev', { cliOptions, printError: jest.fn() }, run)
+ ).rejects.toThrow(error);
- it('does not send boot when cli option is passed', async () => {
- await expect(async () =>
- withTelemetry('dev', { cliOptions: { disableTelemetry: true } }, run)
- ).rejects.toThrow(error);
+ expect(telemetry).toHaveBeenCalledWith('boot', { eventType: 'dev' }, { stripMetadata: true });
+ });
- expect(telemetry).toHaveBeenCalledTimes(0);
+ it('does not send boot when cli option is passed', async () => {
+ await expect(async () =>
+ withTelemetry('dev', { cliOptions: { disableTelemetry: true }, printError: jest.fn() }, run)
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(0);
+ });
+
+ it('sends error message when no options are passed', async () => {
+ await expect(async () =>
+ withTelemetry('dev', { cliOptions, printError: jest.fn() }, run)
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(2);
+ expect(telemetry).toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({ eventType: 'dev', error }),
+ expect.objectContaining({})
+ );
+ });
+
+ it('does not send error message when cli opt out is passed', async () => {
+ await expect(async () =>
+ withTelemetry('dev', { cliOptions: { disableTelemetry: true }, printError: jest.fn() }, run)
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(0);
+ expect(telemetry).not.toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({}),
+ expect.objectContaining({})
+ );
+ });
+
+ it('does not send full error message when crash reports are disabled', async () => {
+ jest.mocked(loadAllPresets).mockResolvedValueOnce({
+ apply: async () => ({ enableCrashReports: false } as any),
+ });
+ await expect(async () =>
+ withTelemetry(
+ 'dev',
+ { cliOptions: {} as any, presetOptions: {} as any, printError: jest.fn() },
+ run
+ )
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(2);
+ expect(telemetry).toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({ eventType: 'dev' }),
+ expect.objectContaining({})
+ );
+ });
+
+ it('does send error message when crash reports are enabled', async () => {
+ jest.mocked(loadAllPresets).mockResolvedValueOnce({
+ apply: async () => ({ enableCrashReports: true } as any),
+ });
+
+ await expect(async () =>
+ withTelemetry(
+ 'dev',
+ { cliOptions: {} as any, presetOptions: {} as any, printError: jest.fn() },
+ run
+ )
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(2);
+ expect(telemetry).toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({ eventType: 'dev', error }),
+ expect.objectContaining({})
+ );
+ });
+
+ it('does not send any error message when telemetry is disabled', async () => {
+ jest.mocked(loadAllPresets).mockResolvedValueOnce({
+ apply: async () => ({ disableTelemetry: true } as any),
+ });
+
+ await expect(async () =>
+ withTelemetry(
+ 'dev',
+ { cliOptions: {} as any, presetOptions: {} as any, printError: jest.fn() },
+ run
+ )
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(1);
+ expect(telemetry).not.toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({}),
+ expect.objectContaining({})
+ );
+ });
+
+ it('does send error messages when telemetry is disabled, but crash reports are enabled', async () => {
+ jest.mocked(loadAllPresets).mockResolvedValueOnce({
+ apply: async () => ({ disableTelemetry: true, enableCrashReports: true } as any),
+ });
+
+ await expect(async () =>
+ withTelemetry(
+ 'dev',
+ { cliOptions: {} as any, presetOptions: {} as any, printError: jest.fn() },
+ run
+ )
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(2);
+ expect(telemetry).toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({ eventType: 'dev', error }),
+ expect.objectContaining({})
+ );
+ });
+
+ it('does not send full error messages when disabled crash reports are cached', async () => {
+ jest.mocked(loadAllPresets).mockResolvedValueOnce({
+ apply: async () => ({} as any),
+ });
+ jest.mocked(cache.get).mockResolvedValueOnce(false);
+
+ await expect(async () =>
+ withTelemetry(
+ 'dev',
+ { cliOptions: {} as any, presetOptions: {} as any, printError: jest.fn() },
+ run
+ )
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(2);
+ expect(telemetry).toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({ eventType: 'dev' }),
+ expect.objectContaining({})
+ );
+ });
+
+ it('does send error messages when enabled crash reports are cached', async () => {
+ jest.mocked(loadAllPresets).mockResolvedValueOnce({
+ apply: async () => ({} as any),
+ });
+ jest.mocked(cache.get).mockResolvedValueOnce(true);
+
+ await expect(async () =>
+ withTelemetry(
+ 'dev',
+ { cliOptions: {} as any, presetOptions: {} as any, printError: jest.fn() },
+ run
+ )
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(2);
+ expect(telemetry).toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({ eventType: 'dev', error }),
+ expect.objectContaining({})
+ );
+ });
+
+ it('does not send full error messages when disabled crash reports are prompted', async () => {
+ jest.mocked(loadAllPresets).mockResolvedValueOnce({
+ apply: async () => ({} as any),
+ });
+ jest.mocked(cache.get).mockResolvedValueOnce(undefined);
+ jest.mocked(prompts).mockResolvedValueOnce({ enableCrashReports: false });
+
+ await expect(async () =>
+ withTelemetry(
+ 'dev',
+ { cliOptions: {} as any, presetOptions: {} as any, printError: jest.fn() },
+ run
+ )
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(2);
+ expect(telemetry).toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({ eventType: 'dev' }),
+ expect.objectContaining({})
+ );
+ });
+
+ it('does send error messages when enabled crash reports are prompted', async () => {
+ jest.mocked(loadAllPresets).mockResolvedValueOnce({
+ apply: async () => ({} as any),
+ });
+ jest.mocked(cache.get).mockResolvedValueOnce(undefined);
+ jest.mocked(prompts).mockResolvedValueOnce({ enableCrashReports: true });
+
+ await expect(async () =>
+ withTelemetry(
+ 'dev',
+ { cliOptions: {} as any, presetOptions: {} as any, printError: jest.fn() },
+ run
+ )
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(2);
+ expect(telemetry).toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({ eventType: 'dev', error }),
+ expect.objectContaining({})
+ );
+ });
+
+ // if main.js has errors, we have no way to tell if they've disabled error reporting,
+ // so we assume they have.
+ it('does not send full error messages when presets fail to evaluate', async () => {
+ jest.mocked(loadAllPresets).mockRejectedValueOnce(error);
+
+ await expect(async () =>
+ withTelemetry(
+ 'dev',
+ { cliOptions: {} as any, presetOptions: {} as any, printError: jest.fn() },
+ run
+ )
+ ).rejects.toThrow(error);
+
+ expect(telemetry).toHaveBeenCalledTimes(2);
+ expect(telemetry).toHaveBeenCalledWith(
+ 'error',
+ expect.objectContaining({ eventType: 'dev' }),
+ expect.objectContaining({})
+ );
+ });
});
+});
+
+describe('sendTelemetryError', () => {
+ it('handles error instances and sends telemetry', async () => {
+ const options: any = {
+ cliOptions: {},
+ skipPrompt: false,
+ };
+ const mockError = new Error('Test error');
+ const eventType: any = 'testEventType';
+
+ jest.mocked(oneWayHash).mockReturnValueOnce('some-hash');
- it('sends error message when no options are passed', async () => {
- await expect(async () => withTelemetry('dev', { cliOptions }, run)).rejects.toThrow(error);
+ await sendTelemetryError(mockError, eventType, options);
- expect(telemetry).toHaveBeenCalledTimes(2);
expect(telemetry).toHaveBeenCalledWith(
'error',
- { eventType: 'dev', error },
- expect.objectContaining({})
+ expect.objectContaining({
+ error: mockError,
+ eventType,
+ isErrorInstance: true,
+ errorHash: 'some-hash',
+ }),
+ expect.any(Object)
);
});
- it('does not send error message when cli opt out is passed', async () => {
- await expect(async () =>
- withTelemetry('dev', { cliOptions: { disableTelemetry: true } }, run)
- ).rejects.toThrow(error);
+ it('handles non-error instances and sends telemetry with no-message hash', async () => {
+ const options: any = {
+ cliOptions: {},
+ skipPrompt: false,
+ };
+ const mockError = { error: new Error('Test error') };
+ const eventType: any = 'testEventType';
- expect(telemetry).toHaveBeenCalledTimes(0);
- expect(telemetry).not.toHaveBeenCalledWith(
+ await sendTelemetryError(mockError, eventType, options);
+
+ expect(telemetry).toHaveBeenCalledWith(
'error',
- expect.objectContaining({}),
- expect.objectContaining({})
+ expect.objectContaining({
+ error: mockError,
+ eventType,
+ isErrorInstance: false,
+ errorHash: 'no-message',
+ }),
+ expect.any(Object)
);
});
- it('does not send full error message when crash reports are disabled', async () => {
- jest.mocked(loadAllPresets).mockResolvedValueOnce({
- apply: async () => ({ enableCrashReports: false } as any),
- });
- await expect(async () =>
- withTelemetry('dev', { cliOptions: {} as any, presetOptions: {} as any }, run)
- ).rejects.toThrow(error);
+ it('handles error with empty message and sends telemetry with empty-message hash', async () => {
+ const options: any = {
+ cliOptions: {},
+ skipPrompt: false,
+ };
+ const mockError = new Error();
+ const eventType: any = 'testEventType';
+
+ await sendTelemetryError(mockError, eventType, options);
- expect(telemetry).toHaveBeenCalledTimes(2);
expect(telemetry).toHaveBeenCalledWith(
'error',
- { eventType: 'dev' },
- expect.objectContaining({})
+ expect.objectContaining({
+ error: mockError,
+ eventType,
+ isErrorInstance: true,
+ errorHash: 'empty-message',
+ }),
+ expect.any(Object)
);
});
+});
- it('does send error message when crash reports are enabled', async () => {
- jest.mocked(loadAllPresets).mockResolvedValueOnce({
- apply: async () => ({ enableCrashReports: true } as any),
- });
+describe('getErrorLevel', () => {
+ beforeEach(() => {
+ jest.resetAllMocks();
+ });
- await expect(async () =>
- withTelemetry('dev', { cliOptions: {} as any, presetOptions: {} as any }, run)
- ).rejects.toThrow(error);
+ it('returns "none" when cliOptions.disableTelemetry is true', async () => {
+ const options: any = {
+ cliOptions: {
+ disableTelemetry: true,
+ },
+ presetOptions: undefined,
+ skipPrompt: false,
+ };
- expect(telemetry).toHaveBeenCalledTimes(2);
- expect(telemetry).toHaveBeenCalledWith(
- 'error',
- { eventType: 'dev', error },
- expect.objectContaining({})
- );
+ const errorLevel = await getErrorLevel(options);
+
+ expect(errorLevel).toBe('none');
});
- it('does not send any error message when telemetry is disabled', async () => {
- jest.mocked(loadAllPresets).mockResolvedValueOnce({
- apply: async () => ({ disableTelemetry: true } as any),
- });
+ it('returns "full" when presetOptions is not provided', async () => {
+ const options: any = {
+ cliOptions: {
+ disableTelemetry: false,
+ },
+ presetOptions: undefined,
+ skipPrompt: false,
+ };
- await expect(async () =>
- withTelemetry('dev', { cliOptions: {} as any, presetOptions: {} as any }, run)
- ).rejects.toThrow(error);
+ const errorLevel = await getErrorLevel(options);
- expect(telemetry).toHaveBeenCalledTimes(1);
- expect(telemetry).not.toHaveBeenCalledWith(
- 'error',
- expect.objectContaining({}),
- expect.objectContaining({})
- );
+ expect(errorLevel).toBe('full');
});
- it('does send error messages when telemetry is disabled, but crash reports are enabled', async () => {
+ it('returns "full" when core.enableCrashReports is true', async () => {
+ const options: any = {
+ cliOptions: {
+ disableTelemetry: false,
+ },
+ presetOptions: {},
+ skipPrompt: false,
+ };
+
jest.mocked(loadAllPresets).mockResolvedValueOnce({
- apply: async () => ({ disableTelemetry: true, enableCrashReports: true } as any),
+ apply: async () => ({ enableCrashReports: true } as any),
});
+ jest.mocked(cache.get).mockResolvedValueOnce(false);
- await expect(async () =>
- withTelemetry('dev', { cliOptions: {} as any, presetOptions: {} as any }, run)
- ).rejects.toThrow(error);
+ const errorLevel = await getErrorLevel(options);
- expect(telemetry).toHaveBeenCalledTimes(2);
- expect(telemetry).toHaveBeenCalledWith(
- 'error',
- { eventType: 'dev', error },
- expect.objectContaining({})
- );
+ expect(errorLevel).toBe('full');
});
- it('does not send full error messages when disabled crash reports are cached', async () => {
+ it('returns "error" when core.enableCrashReports is false', async () => {
+ const options: any = {
+ cliOptions: {
+ disableTelemetry: false,
+ },
+ presetOptions: {},
+ skipPrompt: false,
+ };
+
jest.mocked(loadAllPresets).mockResolvedValueOnce({
- apply: async () => ({} as any),
+ apply: async () => ({ enableCrashReports: false } as any),
});
jest.mocked(cache.get).mockResolvedValueOnce(false);
- await expect(async () =>
- withTelemetry('dev', { cliOptions: {} as any, presetOptions: {} as any }, run)
- ).rejects.toThrow(error);
+ const errorLevel = await getErrorLevel(options);
- expect(telemetry).toHaveBeenCalledTimes(2);
- expect(telemetry).toHaveBeenCalledWith(
- 'error',
- { eventType: 'dev' },
- expect.objectContaining({})
- );
+ expect(errorLevel).toBe('error');
});
- it('does send error messages when enabled crash reports are cached', async () => {
+ it('returns "none" when core.disableTelemetry is true', async () => {
+ const options: any = {
+ cliOptions: {
+ disableTelemetry: false,
+ },
+ presetOptions: {},
+ skipPrompt: false,
+ };
+
jest.mocked(loadAllPresets).mockResolvedValueOnce({
- apply: async () => ({} as any),
+ apply: async () => ({ disableTelemetry: true } as any),
});
- jest.mocked(cache.get).mockResolvedValueOnce(true);
+ jest.mocked(cache.get).mockResolvedValueOnce(false);
- await expect(async () =>
- withTelemetry('dev', { cliOptions: {} as any, presetOptions: {} as any }, run)
- ).rejects.toThrow(error);
+ const errorLevel = await getErrorLevel(options);
- expect(telemetry).toHaveBeenCalledTimes(2);
- expect(telemetry).toHaveBeenCalledWith(
- 'error',
- { eventType: 'dev', error },
- expect.objectContaining({})
- );
+ expect(errorLevel).toBe('none');
});
- it('does not send full error messages when disabled crash reports are prompted', async () => {
+ it('returns "full" if cache contains crashReports true', async () => {
+ const options: any = {
+ cliOptions: {
+ disableTelemetry: false,
+ },
+ presetOptions: {},
+ skipPrompt: false,
+ };
+
+ jest.mocked(cache.get).mockResolvedValueOnce(true);
jest.mocked(loadAllPresets).mockResolvedValueOnce({
apply: async () => ({} as any),
});
- jest.mocked(cache.get).mockResolvedValueOnce(undefined);
- jest.mocked(prompts).mockResolvedValueOnce({ enableCrashReports: false });
- await expect(async () =>
- withTelemetry('dev', { cliOptions: {} as any, presetOptions: {} as any }, run)
- ).rejects.toThrow(error);
+ const errorLevel = await getErrorLevel(options);
- expect(telemetry).toHaveBeenCalledTimes(2);
- expect(telemetry).toHaveBeenCalledWith(
- 'error',
- { eventType: 'dev' },
- expect.objectContaining({})
- );
+ expect(errorLevel).toBe('full');
});
- it('does send error messages when enabled crash reports are prompted', async () => {
+ it('returns "error" when skipPrompt is true', async () => {
+ const options: any = {
+ cliOptions: {
+ disableTelemetry: false,
+ },
+ presetOptions: {},
+ skipPrompt: true,
+ };
+
jest.mocked(loadAllPresets).mockResolvedValueOnce({
apply: async () => ({} as any),
});
jest.mocked(cache.get).mockResolvedValueOnce(undefined);
- jest.mocked(prompts).mockResolvedValueOnce({ enableCrashReports: true });
-
- await expect(async () =>
- withTelemetry('dev', { cliOptions: {} as any, presetOptions: {} as any }, run)
- ).rejects.toThrow(error);
-
- expect(telemetry).toHaveBeenCalledTimes(2);
- expect(telemetry).toHaveBeenCalledWith(
- 'error',
- { eventType: 'dev', error },
- expect.objectContaining({})
- );
- });
-
- // if main.js has errors, we have no way to tell if they've disabled error reporting,
- // so we assume they have.
- it('does not send full error messages when presets fail to evaluate', async () => {
- jest.mocked(loadAllPresets).mockRejectedValueOnce(error);
- await expect(async () =>
- withTelemetry('dev', { cliOptions: {} as any, presetOptions: {} as any }, run)
- ).rejects.toThrow(error);
+ const errorLevel = await getErrorLevel(options);
- expect(telemetry).toHaveBeenCalledTimes(2);
- expect(telemetry).toHaveBeenCalledWith(
- 'error',
- { eventType: 'dev' },
- expect.objectContaining({})
- );
+ expect(errorLevel).toBe('error');
});
});
diff --git a/code/lib/core-server/src/withTelemetry.ts b/code/lib/core-server/src/withTelemetry.ts
index 0baebb8d97cb..086ee991e5ec 100644
--- a/code/lib/core-server/src/withTelemetry.ts
+++ b/code/lib/core-server/src/withTelemetry.ts
@@ -4,7 +4,6 @@ import { loadAllPresets, cache } from '@storybook/core-common';
import { telemetry, getPrecedingUpgrade, oneWayHash } from '@storybook/telemetry';
import type { EventType } from '@storybook/telemetry';
import { logger } from '@storybook/node-logger';
-import invariant from 'tiny-invariant';
type TelemetryOptions = {
cliOptions: CLIOptions;
@@ -32,7 +31,7 @@ const promptCrashReports = async () => {
type ErrorLevel = 'none' | 'error' | 'full';
-async function getErrorLevel({
+export async function getErrorLevel({
cliOptions,
presetOptions,
skipPrompt,
@@ -67,7 +66,7 @@ async function getErrorLevel({
}
export async function sendTelemetryError(
- error: unknown,
+ _error: unknown,
eventType: EventType,
options: TelemetryOptions
) {
@@ -81,10 +80,7 @@ export async function sendTelemetryError(
if (errorLevel !== 'none') {
const precedingUpgrade = await getPrecedingUpgrade();
- invariant(
- error instanceof Error,
- 'The error passed to sendTelemetryError was not an Error, please only send Errors'
- );
+ const error = _error as Error | Record;
let storybookErrorProperties = {};
// if it's an UNCATEGORIZED error, it won't have a coded name, so we just pass the category and source
@@ -104,14 +100,23 @@ export async function sendTelemetryError(
};
}
+ let errorHash;
+ if ('message' in error) {
+ errorHash = error.message ? oneWayHash(error.message) : 'empty-message';
+ } else {
+ errorHash = 'no-message';
+ }
+
await telemetry(
'error',
{
+ ...storybookErrorProperties,
eventType,
precedingUpgrade,
error: errorLevel === 'full' ? error : undefined,
- errorHash: oneWayHash(error.message),
- ...storybookErrorProperties,
+ errorHash,
+ // if we ever end up sending a non-error instance, we'd like to know
+ isErrorInstance: error instanceof Error,
},
{
immediate: true,
From d72e96860388eaaf827b9ca5d1209ef13958e712 Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 16:33:15 +0200
Subject: [PATCH 17/65] enable daily jobs again
---
.circleci/config.yml | 78 ++++++++++++++++++++++----------------------
1 file changed, 39 insertions(+), 39 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index a5796c773b7f..c09dee33503d 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -619,52 +619,52 @@ workflows:
when:
equal: [daily, << pipeline.parameters.workflow >>]
jobs:
- # - pretty-docs
+ - pretty-docs
- build
- # - lint:
- # requires:
- # - build
- # - check:
- # requires:
- # - build
- # - unit-tests:
- # requires:
- # - build
- # - script-checks:
- # requires:
- # - build
- # - chromatic-internal-storybooks:
- # requires:
- # - build
- # - chromatic-internal-storybooks:
- # requires:
- # - build
+ - lint:
+ requires:
+ - build
+ - check:
+ requires:
+ - build
+ - unit-tests:
+ requires:
+ - build
+ - script-checks:
+ requires:
+ - build
+ - chromatic-internal-storybooks:
+ requires:
+ - build
+ - chromatic-internal-storybooks:
+ requires:
+ - build
- angular-prerelease-sandbox:
requires:
- build
# - smoke-test-sandboxes: # disabled for now
# requires:
# - create-sandboxes
- # - build-sandboxes:
- # parallelism: 34
- # requires:
- # - create-sandboxes
- # - chromatic-sandboxes:
- # parallelism: 31
- # requires:
- # - build-sandboxes
- # - e2e-production:
- # parallelism: 31
- # requires:
- # - build-sandboxes
- # - e2e-dev:
- # parallelism: 4
- # requires:
- # - create-sandboxes
- # - test-runner-production:
- # parallelism: 31
- # requires:
- # - build-sandboxes
+ - build-sandboxes:
+ parallelism: 34
+ requires:
+ - create-sandboxes
+ - chromatic-sandboxes:
+ parallelism: 31
+ requires:
+ - build-sandboxes
+ - e2e-production:
+ parallelism: 31
+ requires:
+ - build-sandboxes
+ - e2e-dev:
+ parallelism: 4
+ requires:
+ - create-sandboxes
+ - test-runner-production:
+ parallelism: 31
+ requires:
+ - build-sandboxes
# TODO: reenable once we find out the source of flakyness
# - test-runner-dev:
# parallelism: 4
From 6f219e96b3e29c4a5375c3951cfdf3f63592a2e1 Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 16:43:45 +0200
Subject: [PATCH 18/65] fix bad circleci config
---
.circleci/config.yml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index c09dee33503d..3e5ec294d0a9 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -636,10 +636,11 @@ workflows:
- chromatic-internal-storybooks:
requires:
- build
- - chromatic-internal-storybooks:
+ - angular-prerelease-sandbox:
requires:
- build
- - angular-prerelease-sandbox:
+ - create-sandboxes:
+ parallelism: 34
requires:
- build
# - smoke-test-sandboxes: # disabled for now
From dd9722dceb0add4bd54a62046b6cb01d2c31e269 Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Thu, 31 Aug 2023 18:17:20 +0200
Subject: [PATCH 19/65] make cleanpaths case insensitive
---
code/lib/telemetry/src/sanitize.test.ts | 14 +++++---------
code/lib/telemetry/src/sanitize.ts | 4 ++--
2 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/code/lib/telemetry/src/sanitize.test.ts b/code/lib/telemetry/src/sanitize.test.ts
index a3389c83df79..934695e1e70b 100644
--- a/code/lib/telemetry/src/sanitize.test.ts
+++ b/code/lib/telemetry/src/sanitize.test.ts
@@ -85,14 +85,12 @@ describe(`Errors Helpers`, () => {
`should clean path on unix: %s`,
(filePath) => {
const cwdMockPath = `/Users/username/storybook-app`;
- const fullPath = `${cwdMockPath}/${filePath}`;
-
const mockCwd = jest.spyOn(process, `cwd`).mockImplementation(() => cwdMockPath);
- const errorMessage = `This path should be sanitized ${fullPath}`;
+ const errorMessage = `Path 1 /Users/Username/storybook-app/${filePath} Path 2 /Users/username/storybook-app/${filePath}`;
expect(cleanPaths(errorMessage, `/`)).toBe(
- `This path should be sanitized $SNIP/${filePath}`
+ `Path 1 $SNIP/${filePath} Path 2 $SNIP/${filePath}`
);
mockCwd.mockRestore();
}
@@ -102,14 +100,12 @@ describe(`Errors Helpers`, () => {
`should clean path on windows: %s`,
(filePath) => {
const cwdMockPath = `C:\\Users\\username\\storybook-app`;
- const fullPath = `${cwdMockPath}\\${filePath}`;
-
- const mockCwd = jest.spyOn(process, `cwd`).mockImplementation(() => cwdMockPath);
- const errorMessage = `This path should be sanitized ${fullPath}`;
+ const mockCwd = jest.spyOn(process, `cwd`).mockImplementationOnce(() => cwdMockPath);
+ const errorMessage = `Path 1 C:\\Users\\username\\storybook-app\\${filePath} Path 2 c:\\Users\\username\\storybook-app\\${filePath}`;
expect(cleanPaths(errorMessage, `\\`)).toBe(
- `This path should be sanitized $SNIP\\${filePath}`
+ `Path 1 $SNIP\\${filePath} Path 2 $SNIP\\${filePath}`
);
mockCwd.mockRestore();
}
diff --git a/code/lib/telemetry/src/sanitize.ts b/code/lib/telemetry/src/sanitize.ts
index a611dbea1a13..839ebd9368d2 100644
--- a/code/lib/telemetry/src/sanitize.ts
+++ b/code/lib/telemetry/src/sanitize.ts
@@ -24,11 +24,11 @@ export function cleanPaths(str: string, separator: string = sep): string {
while (stack.length > 1) {
const currentPath = stack.join(separator);
- const currentRegex = new RegExp(regexpEscape(currentPath), `g`);
+ const currentRegex = new RegExp(regexpEscape(currentPath), `gi`);
str = str.replace(currentRegex, `$SNIP`);
const currentPath2 = stack.join(separator + separator);
- const currentRegex2 = new RegExp(regexpEscape(currentPath2), `g`);
+ const currentRegex2 = new RegExp(regexpEscape(currentPath2), `gi`);
str = str.replace(currentRegex2, `$SNIP`);
stack.pop();
From d6be6ba3720fcf11e801ebf55894d0253208647d Mon Sep 17 00:00:00 2001
From: j3rem1e
Date: Thu, 31 Aug 2023 22:24:26 +0200
Subject: [PATCH 20/65] Fix generated properties on Svelte event handler
---
.../svelte/src/docs/sourceDecorator.test.ts | 36 +++++++++++++++++++
.../svelte/src/docs/sourceDecorator.ts | 28 +++++++++++----
2 files changed, 57 insertions(+), 7 deletions(-)
diff --git a/code/renderers/svelte/src/docs/sourceDecorator.test.ts b/code/renderers/svelte/src/docs/sourceDecorator.test.ts
index 86b30788f462..6123b45d8b94 100644
--- a/code/renderers/svelte/src/docs/sourceDecorator.test.ts
+++ b/code/renderers/svelte/src/docs/sourceDecorator.test.ts
@@ -7,6 +7,9 @@ expect.addSnapshotSerializer({
test: (val: unknown) => typeof val === 'string',
});
+const loremIpsum = 'Lorem ipsum dolor sit amet';
+const lotOfProperties = { property1: loremIpsum, property2: loremIpsum, property3: loremIpsum };
+
function generateForArgs(args: Args, slotProperty: string | null = null) {
return generateSvelteSource({ name: 'Component' }, args, {}, slotProperty);
}
@@ -35,6 +38,14 @@ describe('generateSvelteSource', () => {
test('multiple properties', () => {
expect(generateForArgs({ a: 1, b: 2 })).toMatchInlineSnapshot(``);
});
+ test('lot of properties', () => {
+ expect(generateForArgs(lotOfProperties)).toMatchInlineSnapshot(`
+
+ `);
+ });
test('slot property', () => {
expect(generateForArgs({ content: 'xyz', myProp: 'abc' }, 'content')).toMatchInlineSnapshot(`
@@ -42,7 +53,32 @@ describe('generateSvelteSource', () => {
`);
});
+ test('slot property with lot of properties', () => {
+ expect(generateForArgs({ content: 'xyz', ...lotOfProperties }, 'content'))
+ .toMatchInlineSnapshot(`
+
+ xyz
+
+ `);
+ });
test('component is not set', () => {
expect(generateSvelteSource(null, {}, {}, null)).toBeNull();
});
+ test('Skip event property', () => {
+ expect(
+ generateSvelteSource(
+ { name: 'Component' },
+ { event_click: () => {} },
+ { event_click: { action: 'click' } }
+ )
+ ).toMatchInlineSnapshot(``);
+ });
+ test('Property value is a function', () => {
+ expect(
+ generateSvelteSource({ name: 'Component' }, { myHandler: () => {} }, {})
+ ).toMatchInlineSnapshot(`}/>`);
+ });
});
diff --git a/code/renderers/svelte/src/docs/sourceDecorator.ts b/code/renderers/svelte/src/docs/sourceDecorator.ts
index 9f16caf80162..7b61eea6a7e9 100644
--- a/code/renderers/svelte/src/docs/sourceDecorator.ts
+++ b/code/renderers/svelte/src/docs/sourceDecorator.ts
@@ -38,8 +38,15 @@ function toSvelteProperty(key: string, value: any, argTypes: ArgTypes): string |
return null;
}
+ const argType = argTypes[key];
+
// default value ?
- if (argTypes[key] && argTypes[key].defaultValue === value) {
+ if (argType && argType.defaultValue === value) {
+ return null;
+ }
+
+ // event should be skipped
+ if (argType && argType.action) {
return null;
}
@@ -51,6 +58,11 @@ function toSvelteProperty(key: string, value: any, argTypes: ArgTypes): string |
return `${key}=${JSON.stringify(value)}`;
}
+ // handle function
+ if (typeof value === 'function') {
+ return `${key}={}`;
+ }
+
return `${key}={${JSON.stringify(value)}}`;
}
@@ -98,19 +110,21 @@ export function generateSvelteSource(
return null;
}
- const props = Object.entries(args)
+ const propsArray = Object.entries(args)
.filter(([k]) => k !== slotProperty)
.map(([k, v]) => toSvelteProperty(k, v, argTypes))
- .filter((p) => p)
- .join(' ');
+ .filter((p) => p);
+ const props = propsArray.join(' ');
+
+ const multiline = props.length > 50;
const slotValue = slotProperty ? args[slotProperty] : null;
+ const srcStart = multiline ? `<${name}\n ${propsArray.join('\n ')}` : `<${name} ${props}`;
if (slotValue) {
- return `<${name} ${props}>\n ${slotValue}\n${name}>`;
+ return `${srcStart}>\n ${slotValue}\n${name}>`;
}
-
- return `<${name} ${props}/>`;
+ return `${srcStart}/>`;
}
/**
From d5e10e482ab7072ad7d46cd30ba6b002c0e50b5c Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 23:03:29 +0200
Subject: [PATCH 21/65] improvements to generate script
---
.circleci/config.yml | 18 +++++++++--
.github/workflows/generate-sandboxes.yml | 18 +++++++++--
scripts/sandbox/generate.ts | 39 +++++++++---------------
3 files changed, 45 insertions(+), 30 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 3e5ec294d0a9..8eb90e39c6cd 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -272,14 +272,28 @@ jobs:
- attach_workspace:
at: .
- run:
- name: Angular Prerelease Sandbox
+ name: Create Sandbox
command: |
- node -v
yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task sandbox
+ - run:
+ name: Build Sandbox
+ command: |
yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task build
+ - run:
+ name: Chromatic
+ command: |
yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task chromatic
+ - run:
+ name: E2E Tests Production
+ command: |
yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task e2e-tests
+ - run:
+ name: E2E Tests Development
+ command: |
yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task e2e-tests-dev
+ - run:
+ name: Test Runner
+ command: |
yarn task --template angular-cli/prerelease --no-link --start-from=never --junit --task test-runner
- report-workflow-on-failure:
template: angular-cli/prerelease
diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml
index 4b6003231d67..24adf2c90dea 100644
--- a/.github/workflows/generate-sandboxes.yml
+++ b/.github/workflows/generate-sandboxes.yml
@@ -28,39 +28,51 @@ jobs:
- next
include:
- node_version: 16
- excludeTemplates: 'angular-cli/prerelease'
+ # space-delimited list of templates
+ exclude: 'angular-cli/prerelease'
- node_version: 18
- includeTemplates: 'angular-cli/prerelease'
+ # space-delimited list of templates
+ templates: 'angular-cli/prerelease'
steps:
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node_version }}
+
- uses: actions/checkout@v3
with:
ref: ${{ matrix.branch }}
+
- name: Setup git user
run: |
git config --global user.name "Storybook Bot"
git config --global user.email "bot@storybook.js.org"
+
- name: Install dependencies
run: node ./scripts/check-dependencies.js
+
- name: Compile Storybook libraries
run: yarn task --task compile --start-from=auto --no-link
+
- name: Publishing to local registry
run: yarn local-registry --publish
working-directory: ./code
+
- name: Running local registry
run: yarn local-registry --open &
working-directory: ./code
+
- name: Wait for registry
run: yarn wait-on http://localhost:6001
working-directory: ./code
+
- name: Generate
- run: yarn generate-sandboxes --local-registry --includeTemplates "${{matrix.includeTemplates}}" --excludeTemplates "${{matrix.excludeTemplates}}"
+ run: yarn generate-sandboxes --local-registry --templates ${{matrix.templates}} --exclude ${{matrix.exclude}}
working-directory: ./code
+
- name: Publish
run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=${{ matrix.branch }}}
working-directory: ./code
+
- name: The job has failed
if: ${{ failure() || cancelled() }}
env:
diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts
index 6c2455d0d937..0e477b1a6220 100755
--- a/scripts/sandbox/generate.ts
+++ b/scripts/sandbox/generate.ts
@@ -202,20 +202,14 @@ const runGenerators = async (
};
export const options = createOptions({
- template: {
- type: 'string',
- description: 'Which template would you like to create?',
+ templates: {
+ type: 'string[]',
+ description: 'Which templates would you like to create?',
values: Object.keys(sandboxTemplates),
},
- includeTemplates: {
- type: 'string',
- description: 'Comma-delimited list of templates to include',
- promptType: false,
- },
- excludeTemplates: {
- type: 'string',
- description:
- 'Comma-delimited list of templates to exclude. Takes precedence over --includedTemplates',
+ exclude: {
+ type: 'string[]',
+ description: 'Space-delimited list of templates to exclude. Takes precedence over --templates',
promptType: false,
},
localRegistry: {
@@ -231,9 +225,8 @@ export const options = createOptions({
});
export const generate = async ({
- template,
- includeTemplates,
- excludeTemplates,
+ templates,
+ exclude,
localRegistry,
debug,
}: OptionValues) => {
@@ -243,12 +236,9 @@ export const generate = async ({
...configuration,
}))
.filter(({ dirName }) => {
- if (template) {
- return dirName === template;
- }
- let include = includeTemplates ? includeTemplates.split(',').includes(dirName) : true;
- if (excludeTemplates && include) {
- include = !excludeTemplates.split(',').includes(dirName);
+ let include = Array.isArray(templates) ? templates.includes(dirName) : true;
+ if (Array.isArray(exclude) && include) {
+ include = !exclude.includes(dirName);
}
return include;
});
@@ -259,11 +249,10 @@ export const generate = async ({
if (require.main === module) {
program
.description('Generate sandboxes from a set of possible templates')
- .option('--template ', 'Create a single template')
- .option('--includeTemplates ', 'Comma-delimited list of templates to include')
+ .option('--templates [templates...]', 'Space-delimited list of templates to include')
.option(
- '--excludeTemplates ',
- 'Comma-delimited list of templates to exclude. Takes precedence over --includedTemplates'
+ '--exclude [templates...]',
+ 'Space-delimited list of templates to exclude. Takes precedence over --templates'
)
.option('--debug', 'Print all the logs to the console')
.option('--local-registry', 'Use local registry', false)
From 25e7e8d0fa0723b3b8a9ec53784991bce6dc7b92 Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Thu, 31 Aug 2023 23:06:57 +0200
Subject: [PATCH 22/65] test gh workflow
---
.github/workflows/generate-sandboxes.yml | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml
index 24adf2c90dea..4a5a0b606cb9 100644
--- a/.github/workflows/generate-sandboxes.yml
+++ b/.github/workflows/generate-sandboxes.yml
@@ -6,11 +6,11 @@ on:
workflow_dispatch:
# To test fixes on push rather than wait for the scheduling, do the following:
# 1. Uncomment the lines below and add your branch.
- # push:
- # branches:
- # -
+ push:
+ branches:
+ - fix-angular-prerelease-sandbox
# 2. change the "ref" value to in the actions/checkout step below.
- # 3. 👉 DON'T FORGET TO UNDO THE VALUES BACK TO `next` BEFORE YOU MERGE YOUR CHANGES!
+ # 3. 👉 DON'T FORGET TO UNDO THE VALUES BACK BEFORE YOU MERGE YOUR CHANGES!
jobs:
generate:
@@ -19,6 +19,7 @@ jobs:
YARN_ENABLE_IMMUTABLE_INSTALLS: false
CLEANUP_SANDBOX_NODE_MODULES: true
strategy:
+ fail-fast: false
matrix:
node_version:
- 16
@@ -40,7 +41,7 @@ jobs:
- uses: actions/checkout@v3
with:
- ref: ${{ matrix.branch }}
+ ref: fix-angular-prerelease-sandbox
- name: Setup git user
run: |
From 4610e4a8562b6c3212812906ea10857eaac9e977 Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Fri, 1 Sep 2023 08:55:59 +0200
Subject: [PATCH 23/65] remove test workflow
---
.github/workflows/generate-sandboxes.yml | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/generate-sandboxes.yml b/.github/workflows/generate-sandboxes.yml
index 4a5a0b606cb9..bfcd791de4d7 100644
--- a/.github/workflows/generate-sandboxes.yml
+++ b/.github/workflows/generate-sandboxes.yml
@@ -6,9 +6,9 @@ on:
workflow_dispatch:
# To test fixes on push rather than wait for the scheduling, do the following:
# 1. Uncomment the lines below and add your branch.
- push:
- branches:
- - fix-angular-prerelease-sandbox
+ # push:
+ # branches:
+ # -
# 2. change the "ref" value to in the actions/checkout step below.
# 3. 👉 DON'T FORGET TO UNDO THE VALUES BACK BEFORE YOU MERGE YOUR CHANGES!
@@ -41,7 +41,7 @@ jobs:
- uses: actions/checkout@v3
with:
- ref: fix-angular-prerelease-sandbox
+ ref: ${{ matrix.branch }}
- name: Setup git user
run: |
@@ -71,7 +71,7 @@ jobs:
working-directory: ./code
- name: Publish
- run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=${{ matrix.branch }}}
+ run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=${{ matrix.branch }}
working-directory: ./code
- name: The job has failed
From c48ba157753f50e5344710abeee3d838f220d006 Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Fri, 1 Sep 2023 18:50:04 +0200
Subject: [PATCH 24/65] remove node hack from sanitization
---
code/lib/telemetry/src/sanitize.ts | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/code/lib/telemetry/src/sanitize.ts b/code/lib/telemetry/src/sanitize.ts
index 839ebd9368d2..77e0c1fbda0e 100644
--- a/code/lib/telemetry/src/sanitize.ts
+++ b/code/lib/telemetry/src/sanitize.ts
@@ -12,7 +12,7 @@ function regexpEscape(str: string): string {
return str.replace(/[-[/{}()*+?.\\^$|]/g, `\\$&`);
}
-export function removeAnsiEscapeCodes(input: string): string {
+export function removeAnsiEscapeCodes(input = ''): string {
// eslint-disable-next-line no-control-regex
return input.replace(/\u001B\[[0-9;]*m/g, '');
}
@@ -39,16 +39,13 @@ export function cleanPaths(str: string, separator: string = sep): string {
// Takes an Error and returns a sanitized JSON String
export function sanitizeError(error: Error, pathSeparator: string = sep) {
try {
- // Hack because Node
- error = JSON.parse(
- JSON.stringify(error, [...Object.getOwnPropertyNames(error), 'message', 'name'])
- );
- if (error.message) {
- error.message = removeAnsiEscapeCodes(error.message);
- }
- if (error.stack) {
- error.stack = removeAnsiEscapeCodes(error.stack);
- }
+ error = {
+ ...JSON.parse(JSON.stringify(error)),
+ message: removeAnsiEscapeCodes(error.message),
+ stack: removeAnsiEscapeCodes(error.stack),
+ cause: error.cause,
+ name: error.name,
+ };
// Removes all user paths
const errorString = cleanPaths(JSON.stringify(error), pathSeparator);
From acbcacf1c9c1bf7ee2e6efd4cb1a156e09f155af Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Thu, 31 Aug 2023 14:49:04 +0200
Subject: [PATCH 25/65] treat empty error messages in telemetry reports and
allow non-error instances
---
code/lib/core-server/src/withTelemetry.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/lib/core-server/src/withTelemetry.ts b/code/lib/core-server/src/withTelemetry.ts
index 086ee991e5ec..e07387d1a918 100644
--- a/code/lib/core-server/src/withTelemetry.ts
+++ b/code/lib/core-server/src/withTelemetry.ts
@@ -5,7 +5,7 @@ import { telemetry, getPrecedingUpgrade, oneWayHash } from '@storybook/telemetry
import type { EventType } from '@storybook/telemetry';
import { logger } from '@storybook/node-logger';
-type TelemetryOptions = {
+export type TelemetryOptions = {
cliOptions: CLIOptions;
presetOptions?: Parameters[0];
printError?: (err: any) => void;
From e92d8747ba7274a1b8a47d8a1d7922d5f3b1254d Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Fri, 1 Sep 2023 07:34:14 +0200
Subject: [PATCH 26/65] categorize webpack builder error
---
code/builders/builder-webpack5/src/index.ts | 4 +-
.../src/errors/server-errors.test.ts | 80 +++++++++++++++++++
.../core-events/src/errors/server-errors.ts | 45 +++++++++++
code/lib/core-server/src/withTelemetry.ts | 2 +-
4 files changed, 128 insertions(+), 3 deletions(-)
create mode 100644 code/lib/core-events/src/errors/server-errors.test.ts
diff --git a/code/builders/builder-webpack5/src/index.ts b/code/builders/builder-webpack5/src/index.ts
index 0106cfea091d..45775dc7d04f 100644
--- a/code/builders/builder-webpack5/src/index.ts
+++ b/code/builders/builder-webpack5/src/index.ts
@@ -9,6 +9,7 @@ import { dirname, join, parse } from 'path';
import express from 'express';
import fs from 'fs-extra';
import { PREVIEW_BUILDER_PROGRESS } from '@storybook/core-events';
+import { WebpackCompilationError } from '@storybook/core-events/server-errors';
import prettyTime from 'pretty-hrtime';
@@ -195,8 +196,7 @@ const starter: StarterFunction = async function* starterGeneratorFn({
}
if (stats.hasErrors()) {
- // eslint-disable-next-line @typescript-eslint/no-throw-literal
- throw stats;
+ throw new WebpackCompilationError({ error: stats });
}
return {
diff --git a/code/lib/core-events/src/errors/server-errors.test.ts b/code/lib/core-events/src/errors/server-errors.test.ts
new file mode 100644
index 000000000000..bff920656ad4
--- /dev/null
+++ b/code/lib/core-events/src/errors/server-errors.test.ts
@@ -0,0 +1,80 @@
+/* eslint-disable local-rules/no-uncategorized-errors */
+import { WebpackCompilationError } from './server-errors';
+
+describe('WebpackCompilationError', () => {
+ it('should correctly handle error with error property', () => {
+ const error = new Error('Custom error message');
+ const data = {
+ error,
+ };
+
+ const webpackError = new WebpackCompilationError(data);
+
+ expect(webpackError.message).toBe(error.message);
+ });
+
+ it('should correctly handle error with error within error', () => {
+ const error = new Error('Custom error message');
+ const data = {
+ error: new Error() as Error & { error: Error },
+ };
+ data.error.error = error;
+
+ const webpackError = new WebpackCompilationError(data);
+
+ expect(webpackError.message).toBe(error.message);
+ });
+
+ it('should correctly handle error with stats.compilation.errors', () => {
+ const compilationErrors = [new Error('Error 1 message'), new Error('Error 2 message')];
+ const data = new Error() as Error & {
+ error: Error & { stats?: { compilation: { errors: Error[] } } };
+ };
+ data.error = new Error();
+ data.error.stats = {
+ compilation: {
+ errors: compilationErrors,
+ },
+ };
+
+ const webpackError = new WebpackCompilationError(data);
+
+ expect(webpackError.message).toMatchInlineSnapshot(`
+ "Error: Error 1 message
+
+ Error: Error 2 message"
+ `);
+ });
+
+ it('should correctly handle object with compilation.errors', () => {
+ const compilationErrors = [new Error('Error 1 message'), new Error('Error 2 message')];
+ const data = {
+ error: {
+ compilation: {
+ errors: compilationErrors,
+ },
+ },
+ };
+
+ const webpackError = new WebpackCompilationError(data);
+
+ expect(webpackError.message).toMatchInlineSnapshot(`
+ "Error: Error 1 message
+
+ Error: Error 2 message"
+ `);
+ });
+
+ it('should correctly handle error without specific format', () => {
+ const errorMessage = 'Generic error message';
+ const data = new Error() as Error & {
+ error: Error;
+ };
+
+ data.error = new Error(errorMessage);
+
+ const webpackError = new WebpackCompilationError(data);
+
+ expect(webpackError.message).toBe(errorMessage);
+ });
+});
diff --git a/code/lib/core-events/src/errors/server-errors.ts b/code/lib/core-events/src/errors/server-errors.ts
index 93f7355a3024..5c1eb801ee57 100644
--- a/code/lib/core-events/src/errors/server-errors.ts
+++ b/code/lib/core-events/src/errors/server-errors.ts
@@ -137,3 +137,48 @@ export class InvalidStoriesEntryError extends StorybookError {
`;
}
}
+
+export class WebpackCompilationError extends StorybookError {
+ readonly category = Category.BUILDER_WEBPACK5;
+
+ readonly code = 1;
+
+ private errorMessage = '';
+
+ constructor(
+ public data: {
+ error:
+ | (Error & {
+ error?: Error;
+ stats?: { compilation: { errors: Error[] } };
+ compilation?: { errors: Error[] };
+ })
+ | {
+ compilation?: { errors: Error[] };
+ };
+ }
+ ) {
+ super();
+
+ if (data.error instanceof Error) {
+ if (data.error.error) {
+ this.errorMessage = data.error.error.message;
+ this.stack = data.error.error.stack;
+ } else if (data.error.stats && data.error.stats.compilation.errors) {
+ data.error.stats.compilation.errors.forEach((e: Error) => {
+ this.errorMessage += `${e.name}: ${e.message}\n\n`;
+ });
+ } else {
+ this.errorMessage = data.error.message;
+ }
+ } else if (data.error.compilation?.errors) {
+ data.error.compilation.errors.forEach((e: Error) => {
+ this.errorMessage += `${e.name}: ${e.message}\n\n`;
+ });
+ }
+ }
+
+ template() {
+ return this.errorMessage.trim();
+ }
+}
diff --git a/code/lib/core-server/src/withTelemetry.ts b/code/lib/core-server/src/withTelemetry.ts
index e07387d1a918..086ee991e5ec 100644
--- a/code/lib/core-server/src/withTelemetry.ts
+++ b/code/lib/core-server/src/withTelemetry.ts
@@ -5,7 +5,7 @@ import { telemetry, getPrecedingUpgrade, oneWayHash } from '@storybook/telemetry
import type { EventType } from '@storybook/telemetry';
import { logger } from '@storybook/node-logger';
-export type TelemetryOptions = {
+type TelemetryOptions = {
cliOptions: CLIOptions;
presetOptions?: Parameters[0];
printError?: (err: any) => void;
From 553789e83af83c57179659c26223d87f043f8460 Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Fri, 1 Sep 2023 18:48:17 +0200
Subject: [PATCH 27/65] standardize errors thrown in webpack builder
- also bring back error logging on dev mode, which seemed to be lost in Storybook 7.0.0
---
code/builders/builder-webpack5/src/index.ts | 131 +++++++++---------
.../core-events/src/errors/server-errors.ts | 85 ++++++++----
code/lib/core-server/src/build-static.ts | 12 +-
code/lib/core-server/src/dev-server.ts | 5 +
4 files changed, 140 insertions(+), 93 deletions(-)
diff --git a/code/builders/builder-webpack5/src/index.ts b/code/builders/builder-webpack5/src/index.ts
index 45775dc7d04f..582c3156c71b 100644
--- a/code/builders/builder-webpack5/src/index.ts
+++ b/code/builders/builder-webpack5/src/index.ts
@@ -9,7 +9,11 @@ import { dirname, join, parse } from 'path';
import express from 'express';
import fs from 'fs-extra';
import { PREVIEW_BUILDER_PROGRESS } from '@storybook/core-events';
-import { WebpackCompilationError } from '@storybook/core-events/server-errors';
+import {
+ WebpackCompilationError,
+ WebpackInvocationError,
+ WebpackMissingStatsError,
+} from '@storybook/core-events/server-errors';
import prettyTime from 'pretty-hrtime';
@@ -118,21 +122,19 @@ const starter: StarterFunction = async function* starterGeneratorFn({
yield;
const config = await getConfig(options);
+
+ if (config.stats === 'none' || config.stats === 'summary') {
+ throw new WebpackMissingStatsError();
+ }
yield;
+
const compiler = webpackInstance(config);
if (!compiler) {
- const err = `${config.name}: missing webpack compiler at runtime!`;
- logger.error(err);
- return {
- bail,
- totalTime: process.hrtime(startTime),
- stats: {
- hasErrors: () => true,
- hasWarnings: () => false,
- toJson: () => ({ warnings: [] as any[], errors: [err] }),
- } as any as Stats,
- };
+ throw new WebpackInvocationError({
+ // eslint-disable-next-line local-rules/no-uncategorized-errors
+ error: new Error(`Missing Webpack compiler at runtime!`),
+ });
}
yield;
@@ -173,6 +175,7 @@ const starter: StarterFunction = async function* starterGeneratorFn({
const middlewareOptions: Parameters[1] = {
publicPath: config.output?.publicPath as string,
writeToDisk: true,
+ stats: 'errors-only',
};
compilation = webpackDevMiddleware(compiler, middlewareOptions);
@@ -185,18 +188,24 @@ const starter: StarterFunction = async function* starterGeneratorFn({
router.use(compilation);
router.use(webpackHotMiddleware(compiler, { log: false }));
- const stats = await new Promise((ready, stop) => {
- compilation?.waitUntilValid(ready as any);
- reject = stop;
+ const stats = await new Promise((res, rej) => {
+ compilation?.waitUntilValid(res as any);
+ reject = rej;
});
yield;
if (!stats) {
- throw new Error('no stats after building preview');
+ throw new WebpackMissingStatsError();
}
- if (stats.hasErrors()) {
- throw new WebpackCompilationError({ error: stats });
+ const { warnings, errors } = getWebpackStats({ config, stats });
+
+ if (warnings.length > 0) {
+ warnings?.forEach((e) => logger.error(e.message));
+ }
+
+ if (errors.length > 0) {
+ throw new WebpackCompilationError({ errors });
}
return {
@@ -206,6 +215,22 @@ const starter: StarterFunction = async function* starterGeneratorFn({
};
};
+function getWebpackStats({ config, stats }: { config: Configuration; stats: Stats }) {
+ const statsOptions =
+ typeof config.stats === 'string'
+ ? config.stats
+ : {
+ ...(config.stats as StatsOptions),
+ warnings: true,
+ errors: true,
+ };
+ const { warnings = [], errors = [] } = stats?.toJson(statsOptions) || {};
+ return {
+ warnings,
+ errors,
+ };
+}
+
/**
* This function is a generator so that we can abort it mid process
* in case of failure coming from other processes e.g. manager builder
@@ -215,73 +240,47 @@ const starter: StarterFunction = async function* starterGeneratorFn({
const builder: BuilderFunction = async function* builderGeneratorFn({ startTime, options }) {
const webpackInstance = await executor.get(options);
yield;
- logger.info('=> Compiling preview..');
const config = await getConfig(options);
+
+ if (config.stats === 'none' || config.stats === 'summary') {
+ throw new WebpackMissingStatsError();
+ }
yield;
const compiler = webpackInstance(config);
if (!compiler) {
- const err = `${config.name}: missing webpack compiler at runtime!`;
- logger.error(err);
- return {
- hasErrors: () => true,
- hasWarnings: () => false,
- toJson: () => ({ warnings: [] as any[], errors: [err] }),
- } as any as Stats;
+ throw new WebpackInvocationError({
+ // eslint-disable-next-line local-rules/no-uncategorized-errors
+ error: new Error(`Missing Webpack compiler at runtime!`),
+ });
}
const webpackCompilation = new Promise((succeed, fail) => {
compiler.run((error, stats) => {
- if (error || !stats || stats.hasErrors()) {
- logger.error('=> Failed to build the preview');
- process.exitCode = 1;
-
- if (error) {
- logger.error(error.message);
+ if (error) {
+ compiler.close(() => fail(new WebpackInvocationError({ error })));
+ return;
+ }
- compiler.close(() => fail(error));
+ if (!stats) {
+ throw new WebpackMissingStatsError();
+ }
- return;
- }
+ const { warnings, errors } = getWebpackStats({ config, stats });
- if (stats && (stats.hasErrors() || stats.hasWarnings())) {
- const { warnings = [], errors = [] } = stats.toJson(
- typeof config.stats === 'string'
- ? config.stats
- : {
- warnings: true,
- errors: true,
- ...(config.stats as StatsOptions),
- }
- );
-
- errors.forEach((e) => logger.error(e.message));
- warnings.forEach((e) => logger.error(e.message));
-
- compiler.close(() =>
- options.debugWebpack
- ? fail(stats)
- : fail(new Error('=> Webpack failed, learn more with --debug-webpack'))
- );
-
- return;
- }
+ if (warnings.length > 0) {
+ warnings?.forEach((e) => logger.error(e.message));
}
- logger.trace({ message: '=> Preview built', time: process.hrtime(startTime) });
- if (stats && stats.hasWarnings()) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- we know it has warnings because of hasWarnings()
- stats
- .toJson({ warnings: true } as StatsOptions)
- .warnings!.forEach((e) => logger.warn(e.message));
+ if (errors.length > 0) {
+ compiler.close(() => fail(new WebpackCompilationError({ errors })));
+ return;
}
- // https://webpack.js.org/api/node/#run
- // #15227
compiler.close((closeErr) => {
if (closeErr) {
- return fail(closeErr);
+ return fail(new WebpackInvocationError({ error: closeErr }));
}
return succeed(stats as Stats);
diff --git a/code/lib/core-events/src/errors/server-errors.ts b/code/lib/core-events/src/errors/server-errors.ts
index 5c1eb801ee57..4c3e10abf8e4 100644
--- a/code/lib/core-events/src/errors/server-errors.ts
+++ b/code/lib/core-events/src/errors/server-errors.ts
@@ -138,47 +138,80 @@ export class InvalidStoriesEntryError extends StorybookError {
}
}
-export class WebpackCompilationError extends StorybookError {
+export class WebpackMissingStatsError extends StorybookError {
readonly category = Category.BUILDER_WEBPACK5;
readonly code = 1;
+ public documentation = [
+ 'https://webpack.js.org/configuration/stats/',
+ 'https://storybook.js.org/docs/react/builders/webpack#configure',
+ ];
+
+ template() {
+ return dedent`
+ No Webpack stats found. Did you turn off stats reporting in your webpack config?
+ Storybook needs Webpack stats (including errors) in order to build correctly.
+ `;
+ }
+}
+
+export class WebpackInvocationError extends StorybookError {
+ readonly category = Category.BUILDER_WEBPACK5;
+
+ readonly code = 2;
+
private errorMessage = '';
constructor(
public data: {
- error:
- | (Error & {
- error?: Error;
- stats?: { compilation: { errors: Error[] } };
- compilation?: { errors: Error[] };
- })
- | {
- compilation?: { errors: Error[] };
- };
+ error: Error;
}
) {
super();
+ this.errorMessage = data.error.message;
+ }
+
+ template() {
+ return this.errorMessage.trim();
+ }
+}
+function removeAnsiEscapeCodes(input = '') {
+ // eslint-disable-next-line no-control-regex
+ return input.replace(/\u001B\[[0-9;]*m/g, '');
+}
+
+export class WebpackCompilationError extends StorybookError {
+ readonly category = Category.BUILDER_WEBPACK5;
+
+ readonly code = 3;
- if (data.error instanceof Error) {
- if (data.error.error) {
- this.errorMessage = data.error.error.message;
- this.stack = data.error.error.stack;
- } else if (data.error.stats && data.error.stats.compilation.errors) {
- data.error.stats.compilation.errors.forEach((e: Error) => {
- this.errorMessage += `${e.name}: ${e.message}\n\n`;
- });
- } else {
- this.errorMessage = data.error.message;
- }
- } else if (data.error.compilation?.errors) {
- data.error.compilation.errors.forEach((e: Error) => {
- this.errorMessage += `${e.name}: ${e.message}\n\n`;
- });
+ constructor(
+ public data: {
+ errors: {
+ message: string;
+ stack?: string;
+ name?: string;
+ }[];
}
+ ) {
+ super();
+
+ this.data.errors = data.errors.map((e, i) => {
+ return {
+ ...e,
+ message: removeAnsiEscapeCodes(e.message),
+ stack: removeAnsiEscapeCodes(e.stack),
+ name: e.name,
+ };
+ });
}
template() {
- return this.errorMessage.trim();
+ // This error message is a followup of errors logged by Webpack to the user
+ return dedent`
+ There were problems when compiling your code with Webpack.
+ Run Storybook with --debug-webpack for more information.
+ `;
}
}
diff --git a/code/lib/core-server/src/build-static.ts b/code/lib/core-server/src/build-static.ts
index 810c871724fd..b8ca4a95fa6c 100644
--- a/code/lib/core-server/src/build-static.ts
+++ b/code/lib/core-server/src/build-static.ts
@@ -199,23 +199,33 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption
if (options.ignorePreview) {
logger.info(`=> Not building preview`);
+ } else {
+ logger.info('=> Building preview..');
}
+ const startTime = process.hrtime();
await Promise.all([
...(options.ignorePreview
? []
: [
previewBuilder
.build({
- startTime: process.hrtime(),
+ startTime,
options: fullOptions,
})
.then(async (previewStats) => {
+ logger.trace({ message: '=> Preview built', time: process.hrtime(startTime) });
+
if (options.webpackStatsJson) {
const target =
options.webpackStatsJson === true ? options.outputDir : options.webpackStatsJson;
await outputStats(target, previewStats);
}
+ })
+ .catch((error) => {
+ logger.error('=> Failed to build the preview');
+ process.exitCode = 1;
+ throw error;
}),
]),
...effects,
diff --git a/code/lib/core-server/src/dev-server.ts b/code/lib/core-server/src/dev-server.ts
index 2eb1ea420cda..50d4c8dd4cdc 100644
--- a/code/lib/core-server/src/dev-server.ts
+++ b/code/lib/core-server/src/dev-server.ts
@@ -6,6 +6,7 @@ import type { CoreConfig, Options, StorybookConfig } from '@storybook/types';
import { logConfig } from '@storybook/core-common';
+import { logger } from '@storybook/node-logger';
import { getMiddleware } from './utils/middleware';
import { getServerAddresses } from './utils/server-address';
import { getServer } from './utils/server-init';
@@ -90,6 +91,7 @@ export async function storybookDevServer(options: Options) {
let previewStarted: Promise = Promise.resolve();
if (!options.ignorePreview) {
+ logger.info('=> Starting preview..');
previewStarted = previewBuilder
.start({
startTime: process.hrtime(),
@@ -99,6 +101,9 @@ export async function storybookDevServer(options: Options) {
channel: serverChannel,
})
.catch(async (e: any) => {
+ logger.error('=> Failed to build the preview');
+ process.exitCode = 1;
+
await managerBuilder?.bail().catch();
// For some reason, even when Webpack fails e.g. wrong main.js config,
// the preview may continue to print to stdout, which can affect output
From ea268a9879272c0663e0b8fa76613746da04e7f6 Mon Sep 17 00:00:00 2001
From: Jeppe Reinhold
Date: Fri, 1 Sep 2023 23:51:30 +0200
Subject: [PATCH 28/65] fix generate sandbox task
---
scripts/tasks/generate.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/tasks/generate.ts b/scripts/tasks/generate.ts
index 77ecdd336620..cbce6c66a1c5 100644
--- a/scripts/tasks/generate.ts
+++ b/scripts/tasks/generate.ts
@@ -30,7 +30,8 @@ export const generate: Task = {
const { generate: generateRepro } = await import('../sandbox/generate');
await generateRepro({
- template: details.key,
+ templates: [details.key],
+ exclude: [],
localRegistry: true,
debug: options.debug,
});
From d607118a1569c20ccbab005c0a251c08f1afa941 Mon Sep 17 00:00:00 2001
From: omahs <73983677+omahs@users.noreply.github.com>
Date: Sat, 2 Sep 2023 09:19:27 +0200
Subject: [PATCH 29/65] fix typo
---
docs/faq.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/faq.md b/docs/faq.md
index 9be3455a3be9..a936a3dbc8ed 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -373,7 +373,7 @@ Yes, with the release of version 6.2, Storybook now includes support for Vue 3.
## Why aren't my code blocks highlighted with Storybook MDX
-Out of the box, Storybook provides syntax highlighting for a set of languages (e.g., Javascript, Markdown, CSS, HTML, Typescript, GraphQL) you can use with your code blocks. Currently, there's a know limitation when you try and register a custom language to get syntax highlighting. We're working on a fix for this And will update this section once it's available.
+Out of the box, Storybook provides syntax highlighting for a set of languages (e.g., Javascript, Markdown, CSS, HTML, Typescript, GraphQL) you can use with your code blocks. Currently, there's a known limitation when you try and register a custom language to get syntax highlighting. We're working on a fix for this And will update this section once it's available.
## Why aren't my MDX 2 stories working in Storybook?
From 623dfda004448c9d38bed01abb59f52e10d5848c Mon Sep 17 00:00:00 2001
From: omahs <73983677+omahs@users.noreply.github.com>
Date: Sat, 2 Sep 2023 09:23:10 +0200
Subject: [PATCH 30/65] fix typo
---
docs/essentials/controls.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/essentials/controls.md b/docs/essentials/controls.md
index cc0f937ec97b..893661782e90 100644
--- a/docs/essentials/controls.md
+++ b/docs/essentials/controls.md
@@ -347,7 +347,7 @@ The previous example also removed the prop documentation from the table. In some
### Conditional controls
-In some cases, it's useful to be able to conditionally exclude a control based on the value of another control. Controls supports basic versions of these use cases with the `if`, which can takes a simple query object to determine whether to include the control.
+In some cases, it's useful to be able to conditionally exclude a control based on the value of another control. Controls supports basic versions of these use cases with the `if`, which can take a simple query object to determine whether to include the control.
Consider a collection of "advanced" settings that are only visible when the user toggles an "advanced" toggle.
From a5e0b3c0c55c9f2fb360a27e630ecd62bc7491cb Mon Sep 17 00:00:00 2001
From: omahs <73983677+omahs@users.noreply.github.com>
Date: Sat, 2 Sep 2023 09:27:02 +0200
Subject: [PATCH 31/65] fix typo
---
docs/configure/frameworks.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/configure/frameworks.md b/docs/configure/frameworks.md
index 80ebc224932e..fc9010251423 100644
--- a/docs/configure/frameworks.md
+++ b/docs/configure/frameworks.md
@@ -64,7 +64,7 @@ Storybook is a framework-agnostic tool. It can be used with any framework. Howev
### Legacy framework support
-We're deprecating support for several frameworks, including [Aurelia](https://github.com/aurelia/framework), [Marionette](https://github.com/marionettejs/backbone.marionette), [Mithril](https://github.com/MithrilJS/mithril.js), [Rax](https://github.com/alibaba/rax), and [Riot](https://github.com/riot/riot). Nevertheless, we're always looking for help maintaining these frameworks. If you're working with one of them and you want to continue supporting them, visit the dedicated [Storybook End-of-Life repository](https://github.com/storybook-eol) to learn more about the sunsetting process and for instructions on how to contribute our visit our [Discord server](https://discord.gg/storybook).
+We're deprecating support for several frameworks, including [Aurelia](https://github.com/aurelia/framework), [Marionette](https://github.com/marionettejs/backbone.marionette), [Mithril](https://github.com/MithrilJS/mithril.js), [Rax](https://github.com/alibaba/rax), and [Riot](https://github.com/riot/riot). Nevertheless, we're always looking for help maintaining these frameworks. If you're working with one of them and you want to continue supporting them, visit the dedicated [Storybook End-of-Life repository](https://github.com/storybook-eol) to learn more about the sunsetting process and for instructions on how to contribute visit our [Discord server](https://discord.gg/storybook).
### Learn about configuring Storybook
From 8b3c2e3a2a3c5320c0e1b6d361a1ec6eac24d7bb Mon Sep 17 00:00:00 2001
From: masaya48
Date: Mon, 4 Sep 2023 12:32:16 +0900
Subject: [PATCH 32/65] Docs: Fix page router path to pathname
---
code/frameworks/nextjs/README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/code/frameworks/nextjs/README.md b/code/frameworks/nextjs/README.md
index 4d9ea8542470..756c93732e23 100644
--- a/code/frameworks/nextjs/README.md
+++ b/code/frameworks/nextjs/README.md
@@ -295,7 +295,7 @@ export const Example = {
parameters: {
nextjs: {
router: {
- path: '/profile/[id]',
+ pathname: '/profile/[id]',
asPath: '/profile/1',
query: {
id: '1',
@@ -316,7 +316,7 @@ Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/c
export const parameters = {
nextjs: {
router: {
- path: '/some-default-path',
+ pathname: '/some-default-path',
asPath: '/some-default-path',
query: {},
},
From 1903fc6a7ef32afa1a1e1868be14a6707c5b4346 Mon Sep 17 00:00:00 2001
From: Voronoy Sergey
Date: Mon, 4 Sep 2023 09:48:56 +0300
Subject: [PATCH 33/65] Remove parasite "console.log" sourceDecorator.ts
When we use Vue3 in StoryBook in console always show parasite log for rendered.
---
code/renderers/vue3/src/docs/sourceDecorator.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/code/renderers/vue3/src/docs/sourceDecorator.ts b/code/renderers/vue3/src/docs/sourceDecorator.ts
index 5c1e9e51b0e5..f0e254f082ae 100644
--- a/code/renderers/vue3/src/docs/sourceDecorator.ts
+++ b/code/renderers/vue3/src/docs/sourceDecorator.ts
@@ -247,7 +247,6 @@ export function generateTemplateSource(
.map((child) => child.content)
.join('')
: '';
- console.log(' vnode ', vnode, ' childSources ', childSources, ' attributes ', attributes);
const name =
typeof type === 'string'
? type
From 24b837c4a1ece4d163310c0b597dd68ff006ffd3 Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Mon, 4 Sep 2023 08:51:18 +0200
Subject: [PATCH 34/65] add more context to explanation in core-events errors
---
code/lib/core-events/manager-errors.js | 6 ++++--
code/lib/core-events/preview-errors.js | 6 ++++--
code/lib/core-events/server-errors.js | 6 ++++--
3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/code/lib/core-events/manager-errors.js b/code/lib/core-events/manager-errors.js
index 6a1ce1522c1b..f94cf725de3c 100644
--- a/code/lib/core-events/manager-errors.js
+++ b/code/lib/core-events/manager-errors.js
@@ -1,4 +1,6 @@
-// This is required for projects that require paths such as `@storybook/core-events/manager-errors`
-// but in CJS, while not in ESM mode. Else an error like this will occur:
+// This is required for compatibility in projects that don't support the exports map field (e.g. Jest 27),
+// so when require paths such as `@storybook/core-events/manager-errors`,
+// An error like this will occur:
// ENOENT: no such file or directory, open '/xyz/node_modules/@storybook/core-events/manager-errors.js'
+// https://github.com/storybookjs/storybook/pull/24038#issuecomment-1704684432
module.exports = require('./dist/errors/manager-errors');
diff --git a/code/lib/core-events/preview-errors.js b/code/lib/core-events/preview-errors.js
index a98055ba796d..1a144b6c7e20 100644
--- a/code/lib/core-events/preview-errors.js
+++ b/code/lib/core-events/preview-errors.js
@@ -1,4 +1,6 @@
-// This is required for projects that require paths such as `@storybook/core-events/preview-errors`
-// but in CJS, while not in ESM mode. Else an error like this will occur:
+// This is required for compatibility in projects that don't support the exports map field (e.g. Jest 27),
+// so when require paths such as `@storybook/core-events/preview-errors`,
+// An error like this will occur:
// ENOENT: no such file or directory, open '/xyz/node_modules/@storybook/core-events/preview-errors.js'
+// https://github.com/storybookjs/storybook/pull/24038#issuecomment-1704684432
module.exports = require('./dist/errors/preview-errors');
diff --git a/code/lib/core-events/server-errors.js b/code/lib/core-events/server-errors.js
index 5f4eb31a408c..6aa7a95fd223 100644
--- a/code/lib/core-events/server-errors.js
+++ b/code/lib/core-events/server-errors.js
@@ -1,4 +1,6 @@
-// This is required for projects that require paths such as `@storybook/core-events/server-errors`
-// but in CJS, while not in ESM mode. Else an error like this will occur:
+// This is required for compatibility in projects that don't support the exports map field (e.g. Jest 27),
+// so when require paths such as `@storybook/core-events/server-errors`,
+// An error like this will occur:
// ENOENT: no such file or directory, open '/xyz/node_modules/@storybook/core-events/server-errors.js'
+// https://github.com/storybookjs/storybook/pull/24038#issuecomment-1704684432
module.exports = require('./dist/errors/server-errors');
From 6947671ef5d368a39e159323da0e6d09054707df Mon Sep 17 00:00:00 2001
From: Norbert de Langen
Date: Mon, 4 Sep 2023 09:29:15 +0200
Subject: [PATCH 35/65] fix types and ignore linting problem
---
code/frameworks/nextjs/package.json | 17 +++++++++++++++--
code/frameworks/nextjs/src/images/decorator.tsx | 1 +
.../nextjs/src/images/next-future-image.tsx | 1 +
.../frameworks/nextjs/src/images/next-image.tsx | 1 +
.../nextjs/src/images/next-legacy-image.tsx | 1 +
5 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json
index 3f29369e1617..a459eab4607a 100644
--- a/code/frameworks/nextjs/package.json
+++ b/code/frameworks/nextjs/package.json
@@ -32,6 +32,11 @@
"require": "./dist/image-context.js",
"import": "./dist/image-context.mjs"
},
+ "./dist/image-context": {
+ "types": "./dist/image-context.d.ts",
+ "require": "./dist/image-context.js",
+ "import": "./dist/image-context.mjs"
+ },
"./preset": {
"types": "./dist/preset.d.ts",
"require": "./dist/preset.js"
@@ -51,6 +56,16 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
+ "typesVersions": {
+ "*": {
+ "*": [
+ "dist/index.d.ts"
+ ],
+ "dist/image-context": [
+ "dist/image-context.d.ts"
+ ]
+ }
+ },
"files": [
"dist/**/*",
"template/cli/**/*",
@@ -153,8 +168,6 @@
"./src/font/webpack/loader/storybook-nextjs-font-loader.ts"
],
"externals": [
- "./context",
- "./images/decorator",
"sb-original/next/image",
"sb-original/next/future/image",
"sb-original/next/legacy/image"
diff --git a/code/frameworks/nextjs/src/images/decorator.tsx b/code/frameworks/nextjs/src/images/decorator.tsx
index bfed3d281e1d..c3ca76aecc49 100644
--- a/code/frameworks/nextjs/src/images/decorator.tsx
+++ b/code/frameworks/nextjs/src/images/decorator.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
import type { Addon_StoryContext } from '@storybook/types';
+// eslint-disable-next-line import/no-extraneous-dependencies
import { ImageContext } from '@storybook/nextjs/dist/image-context';
export const ImageDecorator = (
diff --git a/code/frameworks/nextjs/src/images/next-future-image.tsx b/code/frameworks/nextjs/src/images/next-future-image.tsx
index 46ea6445e689..20f260b0335d 100644
--- a/code/frameworks/nextjs/src/images/next-future-image.tsx
+++ b/code/frameworks/nextjs/src/images/next-future-image.tsx
@@ -4,6 +4,7 @@ import type * as _NextImage from 'next/image';
// @ts-ignore import is aliased in webpack config
import OriginalNextFutureImage from 'sb-original/next/future/image';
+// eslint-disable-next-line import/no-extraneous-dependencies
import { ImageContext } from '@storybook/nextjs/dist/image-context';
import { defaultLoader } from './next-image-default-loader';
diff --git a/code/frameworks/nextjs/src/images/next-image.tsx b/code/frameworks/nextjs/src/images/next-image.tsx
index 557790f3d924..8f4e9a7957e3 100644
--- a/code/frameworks/nextjs/src/images/next-image.tsx
+++ b/code/frameworks/nextjs/src/images/next-image.tsx
@@ -4,6 +4,7 @@ import OriginalNextImage from 'sb-original/next/image';
import type * as _NextImage from 'next/image';
import React from 'react';
+// eslint-disable-next-line import/no-extraneous-dependencies
import { ImageContext } from '@storybook/nextjs/dist/image-context';
import { defaultLoader } from './next-image-default-loader';
diff --git a/code/frameworks/nextjs/src/images/next-legacy-image.tsx b/code/frameworks/nextjs/src/images/next-legacy-image.tsx
index ada69d607be7..c9b727d0145c 100644
--- a/code/frameworks/nextjs/src/images/next-legacy-image.tsx
+++ b/code/frameworks/nextjs/src/images/next-legacy-image.tsx
@@ -4,6 +4,7 @@ import OriginalNextLegacyImage from 'sb-original/next/legacy/image';
import type * as _NextLegacyImage from 'next/legacy/image';
import React from 'react';
+// eslint-disable-next-line import/no-extraneous-dependencies
import { ImageContext } from '@storybook/nextjs/dist/image-context';
import { defaultLoader } from './next-image-default-loader';
From a4973a4cf81185760291f9e8bad1fb24e98157c3 Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Fri, 1 Sep 2023 19:06:22 +0200
Subject: [PATCH 36/65] cleanup tests
---
.../src/errors/server-errors.test.ts | 78 ++-----------------
.../core-events/src/errors/server-errors.ts | 11 +--
2 files changed, 13 insertions(+), 76 deletions(-)
diff --git a/code/lib/core-events/src/errors/server-errors.test.ts b/code/lib/core-events/src/errors/server-errors.test.ts
index bff920656ad4..0eb5fa4ad21d 100644
--- a/code/lib/core-events/src/errors/server-errors.test.ts
+++ b/code/lib/core-events/src/errors/server-errors.test.ts
@@ -2,79 +2,15 @@
import { WebpackCompilationError } from './server-errors';
describe('WebpackCompilationError', () => {
- it('should correctly handle error with error property', () => {
- const error = new Error('Custom error message');
- const data = {
- error,
- };
-
- const webpackError = new WebpackCompilationError(data);
-
- expect(webpackError.message).toBe(error.message);
- });
-
- it('should correctly handle error with error within error', () => {
- const error = new Error('Custom error message');
- const data = {
- error: new Error() as Error & { error: Error },
- };
- data.error.error = error;
-
- const webpackError = new WebpackCompilationError(data);
-
- expect(webpackError.message).toBe(error.message);
- });
-
it('should correctly handle error with stats.compilation.errors', () => {
- const compilationErrors = [new Error('Error 1 message'), new Error('Error 2 message')];
- const data = new Error() as Error & {
- error: Error & { stats?: { compilation: { errors: Error[] } } };
- };
- data.error = new Error();
- data.error.stats = {
- compilation: {
- errors: compilationErrors,
- },
- };
-
- const webpackError = new WebpackCompilationError(data);
-
- expect(webpackError.message).toMatchInlineSnapshot(`
- "Error: Error 1 message
-
- Error: Error 2 message"
- `);
- });
-
- it('should correctly handle object with compilation.errors', () => {
- const compilationErrors = [new Error('Error 1 message'), new Error('Error 2 message')];
- const data = {
- error: {
- compilation: {
- errors: compilationErrors,
- },
- },
- };
-
- const webpackError = new WebpackCompilationError(data);
-
- expect(webpackError.message).toMatchInlineSnapshot(`
- "Error: Error 1 message
-
- Error: Error 2 message"
- `);
- });
-
- it('should correctly handle error without specific format', () => {
- const errorMessage = 'Generic error message';
- const data = new Error() as Error & {
- error: Error;
- };
-
- data.error = new Error(errorMessage);
+ const errors = [
+ new Error('Error 1 \u001B[4mmessage\u001B[0m'),
+ new Error('\u001B[4mError\u001B[0m 2 message'),
+ ];
- const webpackError = new WebpackCompilationError(data);
+ const webpackError = new WebpackCompilationError({ errors });
- expect(webpackError.message).toBe(errorMessage);
+ expect(webpackError.data.errors[0].message).toEqual('Error 1 message');
+ expect(webpackError.data.errors[1].message).toEqual('Error 2 message');
});
});
diff --git a/code/lib/core-events/src/errors/server-errors.ts b/code/lib/core-events/src/errors/server-errors.ts
index 4c3e10abf8e4..bba1faec306f 100644
--- a/code/lib/core-events/src/errors/server-errors.ts
+++ b/code/lib/core-events/src/errors/server-errors.ts
@@ -176,6 +176,7 @@ export class WebpackInvocationError extends StorybookError {
return this.errorMessage.trim();
}
}
+
function removeAnsiEscapeCodes(input = '') {
// eslint-disable-next-line no-control-regex
return input.replace(/\u001B\[[0-9;]*m/g, '');
@@ -197,12 +198,12 @@ export class WebpackCompilationError extends StorybookError {
) {
super();
- this.data.errors = data.errors.map((e, i) => {
+ this.data.errors = data.errors.map((err) => {
return {
- ...e,
- message: removeAnsiEscapeCodes(e.message),
- stack: removeAnsiEscapeCodes(e.stack),
- name: e.name,
+ ...err,
+ message: removeAnsiEscapeCodes(err.message),
+ stack: removeAnsiEscapeCodes(err.stack),
+ name: err.name,
};
});
}
From 183ad26b4d6c1304910837579d441e86d2718bdc Mon Sep 17 00:00:00 2001
From: Norbert de Langen
Date: Mon, 4 Sep 2023 09:56:12 +0200
Subject: [PATCH 37/65] fix types via a bit convoluted work-around
---
code/frameworks/nextjs/src/images/decorator.tsx | 7 ++++++-
code/frameworks/nextjs/src/images/next-future-image.tsx | 7 ++++++-
code/frameworks/nextjs/src/images/next-image.tsx | 7 ++++++-
code/frameworks/nextjs/src/images/next-legacy-image.tsx | 7 ++++++-
4 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/code/frameworks/nextjs/src/images/decorator.tsx b/code/frameworks/nextjs/src/images/decorator.tsx
index c3ca76aecc49..342f49d32b9a 100644
--- a/code/frameworks/nextjs/src/images/decorator.tsx
+++ b/code/frameworks/nextjs/src/images/decorator.tsx
@@ -1,8 +1,13 @@
import * as React from 'react';
import type { Addon_StoryContext } from '@storybook/types';
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore-error (this only errors during compilation for production)
// eslint-disable-next-line import/no-extraneous-dependencies
-import { ImageContext } from '@storybook/nextjs/dist/image-context';
+import { ImageContext as ImageContextValue } from '@storybook/nextjs/dist/image-context';
+import { type ImageContext as ImageContextType } from '../image-context';
+
+const ImageContext = ImageContextValue as typeof ImageContextType;
export const ImageDecorator = (
Story: React.FC,
diff --git a/code/frameworks/nextjs/src/images/next-future-image.tsx b/code/frameworks/nextjs/src/images/next-future-image.tsx
index 20f260b0335d..306518079b38 100644
--- a/code/frameworks/nextjs/src/images/next-future-image.tsx
+++ b/code/frameworks/nextjs/src/images/next-future-image.tsx
@@ -4,10 +4,15 @@ import type * as _NextImage from 'next/image';
// @ts-ignore import is aliased in webpack config
import OriginalNextFutureImage from 'sb-original/next/future/image';
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore-error (this only errors during compilation for production)
// eslint-disable-next-line import/no-extraneous-dependencies
-import { ImageContext } from '@storybook/nextjs/dist/image-context';
+import { ImageContext as ImageContextValue } from '@storybook/nextjs/dist/image-context';
+import { type ImageContext as ImageContextType } from '../image-context';
import { defaultLoader } from './next-image-default-loader';
+const ImageContext = ImageContextValue as typeof ImageContextType;
+
function NextFutureImage({ loader, ...props }: _NextImage.ImageProps) {
const imageParameters = React.useContext(ImageContext);
diff --git a/code/frameworks/nextjs/src/images/next-image.tsx b/code/frameworks/nextjs/src/images/next-image.tsx
index 8f4e9a7957e3..8fc964785f6b 100644
--- a/code/frameworks/nextjs/src/images/next-image.tsx
+++ b/code/frameworks/nextjs/src/images/next-image.tsx
@@ -4,10 +4,15 @@ import OriginalNextImage from 'sb-original/next/image';
import type * as _NextImage from 'next/image';
import React from 'react';
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore-error (this only errors during compilation for production)
// eslint-disable-next-line import/no-extraneous-dependencies
-import { ImageContext } from '@storybook/nextjs/dist/image-context';
+import { ImageContext as ImageContextValue } from '@storybook/nextjs/dist/image-context';
+import { type ImageContext as ImageContextType } from '../image-context';
import { defaultLoader } from './next-image-default-loader';
+const ImageContext = ImageContextValue as typeof ImageContextType;
+
const MockedNextImage = ({ loader, ...props }: _NextImage.ImageProps) => {
const imageParameters = React.useContext(ImageContext);
diff --git a/code/frameworks/nextjs/src/images/next-legacy-image.tsx b/code/frameworks/nextjs/src/images/next-legacy-image.tsx
index c9b727d0145c..33dfc0e0068a 100644
--- a/code/frameworks/nextjs/src/images/next-legacy-image.tsx
+++ b/code/frameworks/nextjs/src/images/next-legacy-image.tsx
@@ -4,10 +4,15 @@ import OriginalNextLegacyImage from 'sb-original/next/legacy/image';
import type * as _NextLegacyImage from 'next/legacy/image';
import React from 'react';
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore-error (this only errors during compilation for production)
// eslint-disable-next-line import/no-extraneous-dependencies
-import { ImageContext } from '@storybook/nextjs/dist/image-context';
+import { ImageContext as ImageContextValue } from '@storybook/nextjs/dist/image-context';
+import { type ImageContext as ImageContextType } from '../image-context';
import { defaultLoader } from './next-image-default-loader';
+const ImageContext = ImageContextValue as typeof ImageContextType;
+
function NextLegacyImage({ loader, ...props }: _NextLegacyImage.ImageProps) {
const imageParameters = React.useContext(ImageContext);
From 1219a423738106da5bb6778e233d69c7a8085461 Mon Sep 17 00:00:00 2001
From: John Hunter
Date: Tue, 29 Aug 2023 15:04:02 +0100
Subject: [PATCH 38/65] Replace volta node version config
Add .nvmrc config for latest node 16
---
.gitignore | 1 -
.nvmrc | 1 +
package.json | 6 +-----
3 files changed, 2 insertions(+), 6 deletions(-)
create mode 100644 .nvmrc
diff --git a/.gitignore b/.gitignore
index 29c025aadf26..63f9445af854 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,7 +37,6 @@ coverage/
/**/LICENSE
code/docs/public
package-lock.json
-.nvmrc
storybook-static
.jest-test-results.json
*.jar
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 000000000000..59ea99ee63cb
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+16.20
diff --git a/package.json b/package.json
index 7c606bfbed07..562cce14091e 100644
--- a/package.json
+++ b/package.json
@@ -12,9 +12,5 @@
"test": "cd code; yarn test",
"upload-bench": "cd scripts; yarn upload-bench"
},
- "packageManager": "yarn@3.5.1",
- "volta": {
- "node": "16.20.1",
- "yarn": "3.5.1"
- }
+ "packageManager": "yarn@3.5.1"
}
From e4e08362a44d1be9b4b091bd2da9a91705ff9190 Mon Sep 17 00:00:00 2001
From: John Hunter
Date: Tue, 29 Aug 2023 15:04:44 +0100
Subject: [PATCH 39/65] Update docs with fnm instructions
---
CONTRIBUTING.md | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index cc26a6bff211..b6e215ded3af 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,13 +1,24 @@
# Getting started
-Storybook is developed against a specific node version. We recommend using [Volta](https://volta.sh/) as it will automatically install the correct node and yarn version when you first use the repo. If you chose not to use Volta please ensure you you have node version 16 installed (suggestion: v16.5)
+Storybook is developed against a specific node version defined in `.nvmrc`. You can use any Node version manager that uses the `.nvmrc` configuration file. We recommend using [fnm](https://fnm.vercel.app/).
+
+## Using fnm as a Node version manager
+
+- Install fnm [as per instructions](https://github.com/Schniz/fnm/tree/master#installation)
+- In your shell setup include the `use-on-cd`, `corepack-enabled` and `version-file-strategy recursive` in the env command, e.g.
+
+ ```sh
+ eval "$(fnm env --use-on-cd --corepack-enabled --version-file-strategy recursive)"
+ ```
- Ensure if you are using Windows to use the Windows Subsystem for Linux (WSL).
- Run `yarn start` in the root directory to run a basic test Storybook "sandbox".
+## Running the local development environment
+
The `yarn start` script will generate a React Vite TypeScript sandbox with a set of test stories inside it, as well as taking all steps required to get it running (building the various packages we need etc). There is no need to run `yarn` or `yarn install` as `yarn start` will do this for you.
-## Issues
+### Issues
If you run `yarn start` and encounter the following error, try rerunning `yarn start` a second time:
From 2abcd06f7b14ff0635fab185326a989f2fb9d43e Mon Sep 17 00:00:00 2001
From: John Hunter
Date: Wed, 30 Aug 2023 13:33:49 +0100
Subject: [PATCH 40/65] Use .nvmrc file for node version
Non-publish actions
---
.github/workflows/danger-js.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/danger-js.yml b/.github/workflows/danger-js.yml
index f83519953b4b..eddb5dee1fe7 100644
--- a/.github/workflows/danger-js.yml
+++ b/.github/workflows/danger-js.yml
@@ -21,10 +21,10 @@ jobs:
name: Danger JS
runs-on: ubuntu-latest
steps:
+ - uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
- node-version: '16'
- - uses: actions/checkout@v3
+ node-version-file: '.nvmrc'
- name: Danger JS
uses: danger/danger-js@11.2.6
env:
From 9403f3cbc73c440b5a28202cd18555e4719477c3 Mon Sep 17 00:00:00 2001
From: John Hunter
Date: Wed, 30 Aug 2023 13:45:36 +0100
Subject: [PATCH 41/65] Use .nvmrc file for node version
Publish and release related but these actions already used hardcoded node 16 versions.
---
.github/workflows/canary-release-pr.yml | 3 +--
.github/workflows/prepare-patch-release.yml | 2 +-
.github/workflows/prepare-prerelease.yml | 2 +-
.github/workflows/publish.yml | 2 +-
4 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/canary-release-pr.yml b/.github/workflows/canary-release-pr.yml
index 4b1504cfd1bf..827f24a2c5f8 100644
--- a/.github/workflows/canary-release-pr.yml
+++ b/.github/workflows/canary-release-pr.yml
@@ -58,8 +58,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
- node-version: '16'
-
+ node-version-file: '.nvmrc'
- name: Cache dependencies
uses: actions/cache@v3
with:
diff --git a/.github/workflows/prepare-patch-release.yml b/.github/workflows/prepare-patch-release.yml
index c88022c7ea01..e4f8e38df502 100644
--- a/.github/workflows/prepare-patch-release.yml
+++ b/.github/workflows/prepare-patch-release.yml
@@ -33,7 +33,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
- node-version: '16'
+ node-version-file: '.nvmrc'
- name: Cache dependencies
uses: actions/cache@v3
diff --git a/.github/workflows/prepare-prerelease.yml b/.github/workflows/prepare-prerelease.yml
index 1250aedcfaa3..e68a7e1ef63a 100644
--- a/.github/workflows/prepare-prerelease.yml
+++ b/.github/workflows/prepare-prerelease.yml
@@ -54,7 +54,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
- node-version: '16'
+ node-version-file: '.nvmrc'
- name: Cache dependencies
uses: actions/cache@v3
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 18e23c174162..863b4e9ae7e2 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -45,7 +45,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
- node-version: '16'
+ node-version-file: '.nvmrc'
- name: Cache dependencies
uses: actions/cache@v3
From f534bc63a12e16210b4353f9534883a1f014940c Mon Sep 17 00:00:00 2001
From: John Hunter
Date: Wed, 30 Aug 2023 14:24:45 +0100
Subject: [PATCH 42/65] Minor docs changes
---
CONTRIBUTING.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b6e215ded3af..78993afd8386 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,21 +1,21 @@
# Getting started
-Storybook is developed against a specific node version defined in `.nvmrc`. You can use any Node version manager that uses the `.nvmrc` configuration file. We recommend using [fnm](https://fnm.vercel.app/).
+Storybook is developed against a specific node version which is defined in an `.nvmrc` file. You can use any Node version manager that uses the `.nvmrc` configuration file (we recommend [fnm](https://fnm.vercel.app/)).
## Using fnm as a Node version manager
- Install fnm [as per instructions](https://github.com/Schniz/fnm/tree/master#installation)
-- In your shell setup include the `use-on-cd`, `corepack-enabled` and `version-file-strategy recursive` in the env command, e.g.
+- In your shell setup include the `use-on-cd`, `corepack-enabled` and `version-file-strategy recursive` parameters in the `fnm env` command, e.g.
```sh
eval "$(fnm env --use-on-cd --corepack-enabled --version-file-strategy recursive)"
```
+## Running the local development environment
+
- Ensure if you are using Windows to use the Windows Subsystem for Linux (WSL).
- Run `yarn start` in the root directory to run a basic test Storybook "sandbox".
-## Running the local development environment
-
The `yarn start` script will generate a React Vite TypeScript sandbox with a set of test stories inside it, as well as taking all steps required to get it running (building the various packages we need etc). There is no need to run `yarn` or `yarn install` as `yarn start` will do this for you.
### Issues
From 3648a0e11f808d1593b37042d59f46e101f475c2 Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Wed, 30 Aug 2023 14:51:01 +0200
Subject: [PATCH 43/65] categorize angular legacy build options error
---
MIGRATION.md | 6 +-
code/frameworks/angular/README.md | 6 +-
.../server/framework-preset-angular-cli.ts | 15 +----
.../src/automigrate/fixes/angular-builders.ts | 4 +-
.../lib/cli/src/generators/ANGULAR/helpers.ts | 5 +-
.../core-events/src/errors/preview-errors.ts | 19 -------
.../core-events/src/errors/server-errors.ts | 55 +++++++++++++++++++
7 files changed, 71 insertions(+), 39 deletions(-)
diff --git a/MIGRATION.md b/MIGRATION.md
index 5022eefb59bd..d7c47af924b3 100644
--- a/MIGRATION.md
+++ b/MIGRATION.md
@@ -1044,7 +1044,11 @@ Starting in 7.0, we drop support for Angular < 14
#### Angular: Drop support for calling Storybook directly
-In Storybook 6.4 we have deprecated calling Storybook directly (`npm run storybook`) for Angular. In Storybook 7.0, we've removed it entirely. Instead you have to set up the Storybook builder in your `angular.json` and execute `ng run :storybook` to start Storybook. Please visit https://github.com/storybookjs/storybook/tree/next/code/frameworks/angular to set up Storybook for Angular correctly.
+_Has automigration_
+
+In Storybook 6.4 we deprecated calling Storybook directly (e.g. `npm run storybook`) for Angular. In Storybook 7.0, we've removed it entirely. Instead, you have to set up the Storybook builder in your `angular.json` and execute `ng run :storybook` to start Storybook.
+
+You can run `npx storybook@next automigrate` to automatically fix your configuration, or visit https://github.com/storybookjs/storybook/tree/next/code/frameworks/angular/README.md#how-do-i-migrate-to-an-angular-storybook-builder for instructions on how to set up Storybook for Angular manually.
#### Angular: Application providers and ModuleWithProviders
diff --git a/code/frameworks/angular/README.md b/code/frameworks/angular/README.md
index 3158060f3f9a..d97e1ab93f2a 100644
--- a/code/frameworks/angular/README.md
+++ b/code/frameworks/angular/README.md
@@ -10,7 +10,7 @@
- [moduleMetadata decorator](#modulemetadata-decorator)
- [applicationConfig decorator](#applicationconfig-decorator)
- [FAQ](#faq)
- - [How do I migrate to a Angular Storybook builder?](#how-do-i-migrate-to-a-angular-storybook-builder)
+ - [How do I migrate to an Angular Storybook builder?](#how-do-i-migrate-to-an-angular-storybook-builder)
- [Do you have only one Angular project in your workspace?](#do-you-have-only-one-angular-project-in-your-workspace)
- [Adjust your `package.json`](#adjust-your-packagejson)
- [I have multiple projects in my Angular workspace](#i-have-multiple-projects-in-my-angular-workspace)
@@ -252,10 +252,12 @@ export const WithCustomApplicationProvider: Story = {
## FAQ
-### How do I migrate to a Angular Storybook builder?
+### How do I migrate to an Angular Storybook builder?
The Storybook [Angular builder](https://angular.io/guide/glossary#builder) is a new way to run Storybook in an Angular workspace. It is a drop-in replacement for running `storybook dev` and `storybook build` directly.
+You can run `npx storybook@next automigrate` to try let Storybook detect and automatically fix your configuration. Otherwise, you can follow the next steps to manually adjust your configuration.
+
#### Do you have only one Angular project in your workspace?
In this case go to your `angular.json` and add `storybook` and `build-storybook` entries in `architect` section of your project like shown above.
diff --git a/code/frameworks/angular/src/server/framework-preset-angular-cli.ts b/code/frameworks/angular/src/server/framework-preset-angular-cli.ts
index f8f78996c366..059d8b30f4d1 100644
--- a/code/frameworks/angular/src/server/framework-preset-angular-cli.ts
+++ b/code/frameworks/angular/src/server/framework-preset-angular-cli.ts
@@ -1,10 +1,10 @@
import webpack from 'webpack';
import { logger } from '@storybook/node-logger';
+import { AngularLegacyBuildOptionsError } from '@storybook/core-events/server-errors';
import { BuilderContext, targetFromTargetString } from '@angular-devkit/architect';
import { sync as findUpSync } from 'find-up';
-import { dedent } from 'ts-dedent';
-
import { JsonObject, logging } from '@angular-devkit/core';
+
import { getWebpackConfig as getCustomWebpackConfig } from './angular-cli-webpack';
import { moduleIsAvailable } from './utils/module-is-available';
import { PresetOptions } from './preset-options';
@@ -85,13 +85,6 @@ async function getBuilderOptions(
return builderOptions;
}
-export const migrationToBuilderReferrenceMessage = dedent`Your Storybook startup uses a solution that is not supported.
- You must use angular builder to have an explicit configuration on the project used in angular.json
- Read more at:
- - https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#sb-angular-builder)
- - https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#angular13)
- `;
-
/**
* Checks if using legacy configuration that doesn't use builder and logs message referring to migration docs.
*/
@@ -101,7 +94,5 @@ function checkForLegacyBuildOptions(options: PresetOptions) {
return;
}
- logger.error(migrationToBuilderReferrenceMessage);
-
- throw Error('angularBrowserTarget is undefined.');
+ throw new AngularLegacyBuildOptionsError();
}
diff --git a/code/lib/cli/src/automigrate/fixes/angular-builders.ts b/code/lib/cli/src/automigrate/fixes/angular-builders.ts
index 626723f091ff..3bdc9da5062c 100644
--- a/code/lib/cli/src/automigrate/fixes/angular-builders.ts
+++ b/code/lib/cli/src/automigrate/fixes/angular-builders.ts
@@ -59,14 +59,14 @@ export const angularBuilders: Fix = {
prompt() {
return dedent`
- We have detected that your project does not use the Storybook Angular builder yet. In Storybook 6.4 we have deprecated calling Storybook directly (npm run storybook) for Angular. In Storybook 7.0, we've removed it entirely.
+ We have detected that your project does not use the Storybook Angular builder yet. In Storybook 6.4 we deprecated calling Storybook directly (npm run storybook) for Angular. In Storybook 7.0, we've removed it entirely.
In order to use the Storybook Angular builder, we need to add a few entries to your angular.json file. Additionally, we will add the @compodoc/compodoc package to your devDependencies if you want and we will add a few scripts to your package.json file.
Also feel free to remove the Compodoc script from your package.json file if you don't use it apart from Storybook anymore. Storybook uses Compodoc internally and you don't have to call in separately anymore.
Read more about the Angular builder here: ${chalk.yellow(
- 'https://storybook.js.org/docs/angular/configure/storybook-builders'
+ 'https://github.com/storybookjs/storybook/tree/next/code/frameworks/angular#how-do-i-migrate-to-an-angular-storybook-builder'
)}
`;
},
diff --git a/code/lib/cli/src/generators/ANGULAR/helpers.ts b/code/lib/cli/src/generators/ANGULAR/helpers.ts
index d1774e583017..459cbeac8165 100644
--- a/code/lib/cli/src/generators/ANGULAR/helpers.ts
+++ b/code/lib/cli/src/generators/ANGULAR/helpers.ts
@@ -1,6 +1,7 @@
import fs from 'fs';
import prompts from 'prompts';
import dedent from 'ts-dedent';
+import { MissingAngularJsonError } from '@storybook/core-events/server-errors';
export const ANGULAR_JSON_PATH = 'angular.json';
@@ -27,9 +28,7 @@ export class AngularJSON {
constructor() {
if (!fs.existsSync(ANGULAR_JSON_PATH)) {
- throw new Error(
- 'An angular.json file was not found in the current working directory. Storybook needs it to work properly, so please rerun the command at the root of your project, where the angular.json file is located. More info: https://storybook.js.org/docs/angular/faq#error-no-angularjson-file-found'
- );
+ throw new MissingAngularJsonError();
}
const jsonContent = fs.readFileSync(ANGULAR_JSON_PATH, 'utf8');
diff --git a/code/lib/core-events/src/errors/preview-errors.ts b/code/lib/core-events/src/errors/preview-errors.ts
index 3a2fe93aecf5..84161db505b8 100644
--- a/code/lib/core-events/src/errors/preview-errors.ts
+++ b/code/lib/core-events/src/errors/preview-errors.ts
@@ -19,25 +19,6 @@ export enum Category {
PREVIEW_REACT_DOM_SHIM = 'PREVIEW_REACT-DOM-SHIM',
PREVIEW_ROUTER = 'PREVIEW_ROUTER',
PREVIEW_THEMING = 'PREVIEW_THEMING',
- FRAMEWORK_ANGULAR = 'FRAMEWORK_ANGULAR',
- FRAMEWORK_EMBER = 'FRAMEWORK_EMBER',
- FRAMEWORK_HTML_VITE = 'FRAMEWORK_HTML-VITE',
- FRAMEWORK_HTML_WEBPACK5 = 'FRAMEWORK_HTML-WEBPACK5',
- FRAMEWORK_NEXTJS = 'FRAMEWORK_NEXTJS',
- FRAMEWORK_PREACT_VITE = 'FRAMEWORK_PREACT-VITE',
- FRAMEWORK_PREACT_WEBPACK5 = 'FRAMEWORK_PREACT-WEBPACK5',
- FRAMEWORK_REACT_VITE = 'FRAMEWORK_REACT-VITE',
- FRAMEWORK_REACT_WEBPACK5 = 'FRAMEWORK_REACT-WEBPACK5',
- FRAMEWORK_SERVER_WEBPACK5 = 'FRAMEWORK_SERVER-WEBPACK5',
- FRAMEWORK_SVELTE_VITE = 'FRAMEWORK_SVELTE-VITE',
- FRAMEWORK_SVELTE_WEBPACK5 = 'FRAMEWORK_SVELTE-WEBPACK5',
- FRAMEWORK_SVELTEKIT = 'FRAMEWORK_SVELTEKIT',
- FRAMEWORK_VUE_VITE = 'FRAMEWORK_VUE-VITE',
- FRAMEWORK_VUE_WEBPACK5 = 'FRAMEWORK_VUE-WEBPACK5',
- FRAMEWORK_VUE3_VITE = 'FRAMEWORK_VUE3-VITE',
- FRAMEWORK_VUE3_WEBPACK5 = 'FRAMEWORK_VUE3-WEBPACK5',
- FRAMEWORK_WEB_COMPONENTS_VITE = 'FRAMEWORK_WEB-COMPONENTS-VITE',
- FRAMEWORK_WEB_COMPONENTS_WEBPACK5 = 'FRAMEWORK_WEB-COMPONENTS-WEBPACK5',
RENDERER_HTML = 'RENDERER_HTML',
RENDERER_PREACT = 'RENDERER_PREACT',
RENDERER_REACT = 'RENDERER_REACT',
diff --git a/code/lib/core-events/src/errors/server-errors.ts b/code/lib/core-events/src/errors/server-errors.ts
index bba1faec306f..5d7068a10912 100644
--- a/code/lib/core-events/src/errors/server-errors.ts
+++ b/code/lib/core-events/src/errors/server-errors.ts
@@ -28,6 +28,25 @@ export enum Category {
POSTINSTALL = 'POSTINSTALL',
DOCS_TOOLS = 'DOCS-TOOLS',
CORE_WEBPACK = 'CORE-WEBPACK',
+ FRAMEWORK_ANGULAR = 'FRAMEWORK_ANGULAR',
+ FRAMEWORK_EMBER = 'FRAMEWORK_EMBER',
+ FRAMEWORK_HTML_VITE = 'FRAMEWORK_HTML-VITE',
+ FRAMEWORK_HTML_WEBPACK5 = 'FRAMEWORK_HTML-WEBPACK5',
+ FRAMEWORK_NEXTJS = 'FRAMEWORK_NEXTJS',
+ FRAMEWORK_PREACT_VITE = 'FRAMEWORK_PREACT-VITE',
+ FRAMEWORK_PREACT_WEBPACK5 = 'FRAMEWORK_PREACT-WEBPACK5',
+ FRAMEWORK_REACT_VITE = 'FRAMEWORK_REACT-VITE',
+ FRAMEWORK_REACT_WEBPACK5 = 'FRAMEWORK_REACT-WEBPACK5',
+ FRAMEWORK_SERVER_WEBPACK5 = 'FRAMEWORK_SERVER-WEBPACK5',
+ FRAMEWORK_SVELTE_VITE = 'FRAMEWORK_SVELTE-VITE',
+ FRAMEWORK_SVELTE_WEBPACK5 = 'FRAMEWORK_SVELTE-WEBPACK5',
+ FRAMEWORK_SVELTEKIT = 'FRAMEWORK_SVELTEKIT',
+ FRAMEWORK_VUE_VITE = 'FRAMEWORK_VUE-VITE',
+ FRAMEWORK_VUE_WEBPACK5 = 'FRAMEWORK_VUE-WEBPACK5',
+ FRAMEWORK_VUE3_VITE = 'FRAMEWORK_VUE3-VITE',
+ FRAMEWORK_VUE3_WEBPACK5 = 'FRAMEWORK_VUE3-WEBPACK5',
+ FRAMEWORK_WEB_COMPONENTS_VITE = 'FRAMEWORK_WEB-COMPONENTS-VITE',
+ FRAMEWORK_WEB_COMPONENTS_WEBPACK5 = 'FRAMEWORK_WEB-COMPONENTS-WEBPACK5',
}
export class NxProjectDetectedError extends StorybookError {
@@ -216,3 +235,39 @@ export class WebpackCompilationError extends StorybookError {
`;
}
}
+
+export class MissingAngularJsonError extends StorybookError {
+ readonly category = Category.CLI_INIT;
+
+ readonly code = 2;
+
+ public readonly documentation =
+ 'https://storybook.js.org/docs/angular/faq#error-no-angularjson-file-found';
+
+ template() {
+ return dedent`
+ An angular.json file was not found in the current working directory.
+ Storybook needs it to work properly, so please rerun the command at the root of your project, where the angular.json file is located.
+ `;
+ }
+}
+
+export class AngularLegacyBuildOptionsError extends StorybookError {
+ readonly category = Category.FRAMEWORK_ANGULAR;
+
+ readonly code = 1;
+
+ public readonly documentation = [
+ 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#angular-drop-support-for-calling-storybook-directly',
+ 'https://github.com/storybookjs/storybook/tree/next/code/frameworks/angular#how-do-i-migrate-to-an-angular-storybook-builder',
+ ];
+
+ template() {
+ return dedent`
+ Your Storybook startup script uses a solution that is not supported anymore.
+ You must use Angular builder to have an explicit configuration on the project used in angular.json.
+
+ Please run 'npx storybook@next automigrate' to automatically fix your config.
+ `;
+ }
+}
From 248a6c530726762e721a984cc9f865b504b8b878 Mon Sep 17 00:00:00 2001
From: Egor Pronin <42776347+MrZillaGold@users.noreply.github.com>
Date: Mon, 4 Sep 2023 16:08:59 +0300
Subject: [PATCH 44/65] fix(traverse-helpers): validate property key
---
.../source-loader/src/abstract-syntax-tree/traverse-helpers.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/lib/source-loader/src/abstract-syntax-tree/traverse-helpers.js b/code/lib/source-loader/src/abstract-syntax-tree/traverse-helpers.js
index 798e8a1ca7cf..a908bf618c9a 100644
--- a/code/lib/source-loader/src/abstract-syntax-tree/traverse-helpers.js
+++ b/code/lib/source-loader/src/abstract-syntax-tree/traverse-helpers.js
@@ -239,7 +239,7 @@ export function popParametersObjectFromDefaultExport(source, ast) {
(targetNode.properties || []).length
) {
const parametersProperty = targetNode.properties.find(
- (p) => p.key.name === 'parameters' && p.value.type === 'ObjectExpression'
+ (p) => p.key && p.key.name === 'parameters' && p.value.type === 'ObjectExpression'
);
foundParametersProperty = !!parametersProperty;
From 95bdc7e8e4761dd69ae631b377a0db4723194083 Mon Sep 17 00:00:00 2001
From: Yann Braga
Date: Mon, 4 Sep 2023 16:48:21 +0200
Subject: [PATCH 45/65] small refactor
---
code/ui/manager/src/components/sidebar/Search.tsx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/code/ui/manager/src/components/sidebar/Search.tsx b/code/ui/manager/src/components/sidebar/Search.tsx
index 5f13898c79c5..d9d03217db38 100644
--- a/code/ui/manager/src/components/sidebar/Search.tsx
+++ b/code/ui/manager/src/components/sidebar/Search.tsx
@@ -348,8 +348,9 @@ export const Search = React.memo<{
}
}
+ const inputId = 'storybook-explorer-searchfield';
const inputProps = getInputProps({
- id: 'storybook-explorer-searchfield',
+ id: inputId,
ref: inputRef,
required: true,
type: 'search',
@@ -362,7 +363,7 @@ export const Search = React.memo<{
});
const labelProps = getLabelProps({
- htmlFor: 'storybook-explorer-searchfield',
+ htmlFor: inputId,
});
return (
From 911aee2fec21ce0cafbbfcf53a67f64304347734 Mon Sep 17 00:00:00 2001
From: jonniebigodes
Date: Mon, 4 Sep 2023 20:49:55 +0100
Subject: [PATCH 46/65] Adds action video to the documentation
---
docs/essentials/actions.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/docs/essentials/actions.md b/docs/essentials/actions.md
index 130b05a2e307..2ffc18444046 100644
--- a/docs/essentials/actions.md
+++ b/docs/essentials/actions.md
@@ -2,6 +2,8 @@
title: 'Actions'
---
+
+
The actions addon is used to display data received by event handler (callback) arguments in your stories.