diff --git a/addons/links/src/preview.test.js b/addons/links/src/preview.test.js index 04bdeb2730f1..88008541f0d2 100644 --- a/addons/links/src/preview.test.js +++ b/addons/links/src/preview.test.js @@ -17,6 +17,8 @@ jest.mock('global', () => ({ kind: 'kind', })), }, + window: global, + __STORYBOOK_LOGGER: console, __STORYBOOK_CLIENT_API__: { raw: jest.fn(() => [ { diff --git a/addons/links/src/react/components/link.test.js b/addons/links/src/react/components/link.test.js index b38b6bf2bc9d..fd174ebe9d11 100644 --- a/addons/links/src/react/components/link.test.js +++ b/addons/links/src/react/components/link.test.js @@ -14,6 +14,7 @@ jest.mock('global', () => ({ search: 'search', }, }, + window: global, __STORYBOOK_STORY_STORE__: { getSelection: jest.fn(() => ({ id: 1 })), fromId: jest.fn(() => ({})), diff --git a/app/react/src/client/preview/index.test.ts b/app/react/src/client/preview/index.test.ts index bd25fc3ca828..6bd053669e7e 100644 --- a/app/react/src/client/preview/index.test.ts +++ b/app/react/src/client/preview/index.test.ts @@ -18,7 +18,7 @@ describe('preview', () => { () => ({ document: undefined, - window: undefined, + window: {}, } as any) ); const api = require('.'); diff --git a/docs/src/pages/configurations/overview/index.md b/docs/src/pages/configurations/overview/index.md index 0c8de1bc57d6..5c9de8814fb8 100644 --- a/docs/src/pages/configurations/overview/index.md +++ b/docs/src/pages/configurations/overview/index.md @@ -26,6 +26,8 @@ module.exports = { `stories` is a list of [glob](https://www.npmjs.com/package/glob) patterns that tells where your stories are located, relative to the configuration file. +`logLevel` is a setting that tells storybook to only log to a specific level. Options are: `trace`, `debug`, `info`, `warn`, `error` and `silent`. + The `addons` field can refer to traditional [addons](../../addons/introduction), but it can also include [presets](/docs/presets/introduction/), which are able to extend the config further. ### `main.js` is a Preset diff --git a/lib/client-logger/package.json b/lib/client-logger/package.json index 9c536ceef5e7..2def2c41b23b 100644 --- a/lib/client-logger/package.json +++ b/lib/client-logger/package.json @@ -28,7 +28,9 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "core-js": "^3.0.1" + "core-js": "^3.0.1", + "global": "^4.3.2", + "loglevel": "^1.6.7" }, "publishConfig": { "access": "public" diff --git a/lib/client-logger/src/index.test.ts b/lib/client-logger/src/index.test.ts index 0d2bc5782bcf..3272d11bf949 100644 --- a/lib/client-logger/src/index.test.ts +++ b/lib/client-logger/src/index.test.ts @@ -1,8 +1,11 @@ import { logger } from '.'; +jest.mock('loglevel', () => global.console); + describe('client-logger', () => { const initialConsole = { ...global.console }; beforeEach(() => { + global.console.trace = jest.fn(); global.console.debug = jest.fn(); global.console.log = jest.fn(); global.console.info = jest.fn(); diff --git a/lib/client-logger/src/index.ts b/lib/client-logger/src/index.ts index 335ae378f3dd..6dedb9df4991 100644 --- a/lib/client-logger/src/index.ts +++ b/lib/client-logger/src/index.ts @@ -1,14 +1,27 @@ -const { console } = global; +import { window, LOGLEVEL } from 'global'; +import console from 'loglevel'; export const logger = { + trace: (message: any, ...rest: any[]): void => console.trace(message, ...rest), debug: (message: any, ...rest: any[]): void => console.debug(message, ...rest), - log: (message: any, ...rest: any[]): void => console.log(message, ...rest), + log: (message: any, ...rest: any[]): void => window.console.log(message, ...rest), info: (message: any, ...rest: any[]): void => console.info(message, ...rest), warn: (message: any, ...rest: any[]): void => console.warn(message, ...rest), error: (message: any, ...rest: any[]): void => console.error(message, ...rest), }; -export const pretty = (type: keyof typeof logger) => (...args: string[]) => { +if (LOGLEVEL) { + console.setLevel(LOGLEVEL); +} + +if (window) { + // eslint-disable-next-line no-underscore-dangle + window.__STORYBOOK_LOGGER = console; +} + +export const pretty = (type: 'trace' | 'debug' | 'info' | 'warn' | 'error') => ( + ...args: string[] +) => { const argArray = []; if (args.length) { @@ -34,8 +47,8 @@ export const pretty = (type: keyof typeof logger) => (...args: string[]) => { console[type].apply(console, argArray); }; +pretty.trace = pretty('trace'); pretty.debug = pretty('debug'); -pretty.log = pretty('log'); pretty.info = pretty('info'); pretty.warn = pretty('warn'); pretty.error = pretty('error'); diff --git a/lib/client-logger/src/typings.d.ts b/lib/client-logger/src/typings.d.ts new file mode 100644 index 000000000000..2f4eb9cf4fd9 --- /dev/null +++ b/lib/client-logger/src/typings.d.ts @@ -0,0 +1 @@ +declare module 'global'; diff --git a/lib/core/src/server/cli/dev.js b/lib/core/src/server/cli/dev.js index ab37a045b608..050b4f9de5b5 100644 --- a/lib/core/src/server/cli/dev.js +++ b/lib/core/src/server/cli/dev.js @@ -25,6 +25,7 @@ async function getCLI(packageJson) { .option('--ssl-key ', 'Provide an SSL key. (Required with --https)') .option('--smoke-test', 'Exit after successful start') .option('--ci', "CI mode (skip interactive prompts, don't open browser)") + .option('--loglevel [level]', 'Control level of logging during build') .option('--quiet', 'Suppress verbose build output') .option('--no-version-updates', 'Suppress update check', true) .option('--no-dll', 'Do not use dll reference') @@ -36,6 +37,8 @@ async function getCLI(packageJson) { .option('--docs', 'Build a documentation-only site using addon-docs') .parse(process.argv); + logger.setLevel(program.loglevel); + // Workaround the `-h` shorthand conflict. // Output the help if `-h` is called without any value. // See storybookjs/storybook#5360 diff --git a/lib/core/src/server/common/common-preset.js b/lib/core/src/server/common/common-preset.js index 20b574b85ecf..8ef5e36fa30f 100644 --- a/lib/core/src/server/common/common-preset.js +++ b/lib/core/src/server/common/common-preset.js @@ -9,3 +9,5 @@ export const babel = async (_, options) => { presets.apply('babelDefault', babelConfig(), options) ); }; + +export const logLevel = (previous, options) => previous || options.loglevel || 'info'; diff --git a/lib/core/src/server/manager/manager-webpack.config.js b/lib/core/src/server/manager/manager-webpack.config.js index d1a8c5a097ac..488f33b31db0 100644 --- a/lib/core/src/server/manager/manager-webpack.config.js +++ b/lib/core/src/server/manager/manager-webpack.config.js @@ -24,7 +24,7 @@ const context = coreDirName.includes('node_modules') ? path.join(coreDirName, '../../') // Real life case, already in node_modules : path.join(coreDirName, '../../node_modules'); // SB Monorepo -export default ({ +export default async ({ configDir, configType, docsMode, @@ -35,8 +35,10 @@ export default ({ cache, previewUrl, versionCheck, + presets, }) => { const { raw, stringified } = loadEnv(); + const logLevel = await presets.apply('logLevel', undefined); const isProd = configType === 'PRODUCTION'; const refsTemplate = fse.readFileSync(path.join(__dirname, 'virtualModuleRef.template.js'), { encoding: 'utf8', @@ -81,6 +83,7 @@ export default ({ version, dlls: dll ? ['./sb_dll/storybook_ui_dll.js'] : [], globals: { + LOGLEVEL: logLevel, VERSIONCHECK: JSON.stringify(versionCheck), DOCS_MODE: docsMode, // global docs mode PREVIEW_URL: previewUrl, // global preview URL diff --git a/lib/core/src/server/preview/iframe-webpack.config.js b/lib/core/src/server/preview/iframe-webpack.config.js index 7a665c530f9e..3453f3d1ffa6 100644 --- a/lib/core/src/server/preview/iframe-webpack.config.js +++ b/lib/core/src/server/preview/iframe-webpack.config.js @@ -42,6 +42,7 @@ export default async ({ typescriptOptions, }) => { const dlls = await presets.apply('webpackDlls', []); + const logLevel = await presets.apply('logLevel', undefined); const { raw, stringified } = loadEnv({ production: true }); const babelLoader = createBabelLoader(babelOptions, framework); const isProd = configType === 'PRODUCTION'; @@ -112,7 +113,9 @@ export default async ({ files, options, version: packageJson.version, - globals: {}, + globals: { + LOGLEVEL: logLevel, + }, headHtmlSnippet: getPreviewHeadHtml(configDir, process.env), dlls, bodyHtmlSnippet: getPreviewBodyHtml(configDir, process.env), diff --git a/yarn.lock b/yarn.lock index dd8a457f1108..6b256865698a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21681,7 +21681,7 @@ loglevel-plugin-prefix@^0.8.4: resolved "https://registry.yarnpkg.com/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz#2fe0e05f1a820317d98d8c123e634c1bd84ff644" integrity sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g== -loglevel@^1.4.1, loglevel@^1.6.4, loglevel@^1.6.6, loglevel@^1.6.8: +loglevel@^1.4.1, loglevel@^1.6.4, loglevel@^1.6.6, loglevel@^1.6.7, loglevel@^1.6.8: version "1.6.8" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==