diff --git a/code/.storybook/manager.tsx b/code/.storybook/manager.tsx index b6c5ed75c34..1a06234f6e2 100644 --- a/code/.storybook/manager.tsx +++ b/code/.storybook/manager.tsx @@ -1,6 +1,6 @@ import { addons } from 'storybook/internal/manager-api'; -import startCase from 'lodash/startCase.js'; +import { startCase } from 'es-toolkit/compat'; addons.setConfig({ sidebar: { diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json index 83a5e8b395c..2fb4f39c27b 100644 --- a/code/addons/a11y/package.json +++ b/code/addons/a11y/package.json @@ -62,7 +62,6 @@ "@storybook/global": "^5.0.0", "@storybook/icons": "^1.2.10", "@testing-library/react": "^14.0.0", - "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", "react-resize-detector": "^7.1.2", diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index 3eb2df92434..b2f1b6e2184 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -52,7 +52,6 @@ "dependencies": { "@storybook/global": "^5.0.0", "dequal": "^2.0.2", - "lodash": "^4.17.21", "ts-dedent": "^2.0.0" }, "devDependencies": { diff --git a/code/core/package.json b/code/core/package.json index c0027461358..27b66345dda 100644 --- a/code/core/package.json +++ b/code/core/package.json @@ -323,7 +323,6 @@ "@types/ejs": "^3.1.1", "@types/find-cache-dir": "^5.0.0", "@types/js-yaml": "^4.0.5", - "@types/lodash": "^4.14.167", "@types/node": "^22.0.0", "@types/npmlog": "^7.0.0", "@types/picomatch": "^2.3.0", @@ -361,6 +360,7 @@ "diff": "^5.2.0", "downshift": "^9.0.4", "ejs": "^3.1.10", + "es-toolkit": "^1.21.0", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0", "esbuild-plugin-alias": "^0.2.1", "execa": "^8.0.1", @@ -380,7 +380,6 @@ "js-yaml": "^4.1.0", "lazy-universal-dotenv": "^4.0.0", "leven": "^4.0.0", - "lodash": "^4.17.21", "markdown-to-jsx": "^7.4.5", "memfs": "^4.11.1", "memoizerific": "^1.11.3", diff --git a/code/core/src/core-server/utils/get-component-variable-name.ts b/code/core/src/core-server/utils/get-component-variable-name.ts index bc29ff9e51d..34f72352afc 100644 --- a/code/core/src/core-server/utils/get-component-variable-name.ts +++ b/code/core/src/core-server/utils/get-component-variable-name.ts @@ -6,6 +6,7 @@ */ export const getComponentVariableName = async (name: string) => { const camelCase = await import('camelcase'); + const camelCased = camelCase.default(name.replace(/^[^a-zA-Z_$]*/, ''), { pascalCase: true }); const sanitized = camelCased.replace(/[^a-zA-Z_$]+/, ''); return sanitized; diff --git a/code/core/src/core-server/utils/stories-json.test.ts b/code/core/src/core-server/utils/stories-json.test.ts index e9f5e73a737..3faa5da2fe1 100644 --- a/code/core/src/core-server/utils/stories-json.test.ts +++ b/code/core/src/core-server/utils/stories-json.test.ts @@ -6,8 +6,8 @@ import { normalizeStoriesEntry } from '@storybook/core/common'; import { STORY_INDEX_INVALIDATED } from '@storybook/core/core-events'; +import { debounce } from 'es-toolkit/compat'; import type { Request, Response, Router } from 'express'; -import debounce from 'lodash/debounce.js'; import Watchpack from 'watchpack'; import { csfIndexer } from '../presets/common-preset'; @@ -17,7 +17,7 @@ import type { ServerChannel } from './get-server-channel'; import { DEBOUNCE, useStoriesJson } from './stories-json'; vi.mock('watchpack'); -vi.mock('lodash/debounce'); +vi.mock('es-toolkit/compat'); vi.mock('@storybook/core/node-logger'); const workingDir = join(__dirname, '__mockdata__'); @@ -471,8 +471,7 @@ describe('useStoriesJson', () => { it('debounces invalidation events', async () => { vi.mocked(debounce).mockImplementation( - // @ts-expect-error it doesn't think default exists - (await vi.importActual('lodash/debounce.js')).default + (await vi.importActual('es-toolkit/compat')).debounce ); const mockServerChannel = { emit: vi.fn() } as any as ServerChannel; diff --git a/code/core/src/core-server/utils/stories-json.ts b/code/core/src/core-server/utils/stories-json.ts index d34ba9d7218..3426aa689de 100644 --- a/code/core/src/core-server/utils/stories-json.ts +++ b/code/core/src/core-server/utils/stories-json.ts @@ -5,8 +5,8 @@ import type { NormalizedStoriesSpecifier, StoryIndex } from '@storybook/core/typ import { STORY_INDEX_INVALIDATED } from '@storybook/core/core-events'; +import { debounce } from 'es-toolkit/compat'; import type { Request, Response, Router } from 'express'; -import debounce from 'lodash/debounce.js'; import type { StoryIndexGenerator } from './StoryIndexGenerator'; import type { ServerChannel } from './get-server-channel'; diff --git a/code/core/src/docs-tools/argTypes/convert/convert.test.ts b/code/core/src/docs-tools/argTypes/convert/convert.test.ts index 25d1b04f01a..11ca3529195 100644 --- a/code/core/src/docs-tools/argTypes/convert/convert.test.ts +++ b/code/core/src/docs-tools/argTypes/convert/convert.test.ts @@ -4,7 +4,7 @@ import { describe, expect, it } from 'vitest'; import { transformSync } from '@storybook/core/babel'; -import mapValues from 'lodash/mapValues.js'; +import { mapValues } from 'es-toolkit'; import requireFromString from 'require-from-string'; import { normalizeNewlines } from '../utils'; diff --git a/code/core/src/docs-tools/argTypes/convert/proptypes/convert.ts b/code/core/src/docs-tools/argTypes/convert/proptypes/convert.ts index 710ddfa449d..c3426ecfd3e 100644 --- a/code/core/src/docs-tools/argTypes/convert/proptypes/convert.ts +++ b/code/core/src/docs-tools/argTypes/convert/proptypes/convert.ts @@ -1,6 +1,6 @@ import type { SBType } from '@storybook/core/types'; -import mapValues from 'lodash/mapValues.js'; +import { mapValues } from 'es-toolkit'; import { parseLiteral } from '../utils'; import type { PTType } from './types'; diff --git a/code/core/src/manager-api/lib/merge.ts b/code/core/src/manager-api/lib/merge.ts index ec4c474942b..f00195c304b 100644 --- a/code/core/src/manager-api/lib/merge.ts +++ b/code/core/src/manager-api/lib/merge.ts @@ -1,10 +1,13 @@ import { logger } from '@storybook/core/client-logger'; -import isEqual from 'lodash/isEqual.js'; -import mergeWith from 'lodash/mergeWith.js'; +import { isEqual, mergeWith, omitBy, pick } from 'es-toolkit'; -export default (a: TObj, b: Partial) => - mergeWith({}, a, b, (objValue: TObj, srcValue: Partial) => { +export default (a: TObj, ...b: Partial[]): TObj => { + // start with empty object + let target = {}; + + // merge object a unto target + target = mergeWith({}, a, (objValue: TObj, srcValue: Partial) => { if (Array.isArray(srcValue) && Array.isArray(objValue)) { srcValue.forEach((s) => { const existing = objValue.find((o) => o === s || isEqual(o, s)); @@ -19,5 +22,52 @@ export default (a: TObj, b: Partial) => logger.log(['the types mismatch, picking', objValue]); return objValue; } - return undefined; }); + + for (const obj of b) { + // merge object b unto target + target = mergeWith(target, obj, (objValue: TObj, srcValue: Partial) => { + if (Array.isArray(srcValue) && Array.isArray(objValue)) { + srcValue.forEach((s) => { + const existing = objValue.find((o) => o === s || isEqual(o, s)); + if (!existing) { + objValue.push(s); + } + }); + + return objValue; + } + if (Array.isArray(objValue)) { + logger.log(['the types mismatch, picking', objValue]); + return objValue; + } + }); + } + + return target as TObj; +}; + +export const noArrayMerge = (a: TObj, ...b: Partial[]): TObj => { + // start with empty object + let target = {}; + + // merge object a unto target + target = mergeWith({}, a, (objValue: TObj, srcValue: Partial) => { + // Treat arrays as scalars: + if (Array.isArray(srcValue)) { + return srcValue; + } + }); + + for (const obj of b) { + // merge object b unto target + target = mergeWith(target, obj, (objValue: TObj, srcValue: Partial) => { + // Treat arrays as scalars: + if (Array.isArray(srcValue)) { + return srcValue; + } + }); + } + + return target as TObj; +}; diff --git a/code/core/src/manager-api/lib/stories.ts b/code/core/src/manager-api/lib/stories.ts index a4ff209c324..556acba0076 100644 --- a/code/core/src/manager-api/lib/stories.ts +++ b/code/core/src/manager-api/lib/stories.ts @@ -19,8 +19,7 @@ import type { } from '@storybook/core/types'; import { sanitize } from '@storybook/csf'; -import countBy from 'lodash/countBy.js'; -import mapValues from 'lodash/mapValues.js'; +import { countBy, mapValues } from 'es-toolkit'; import memoize from 'memoizerific'; import { dedent } from 'ts-dedent'; @@ -41,7 +40,7 @@ export const denormalizeStoryParameters = ({ kindParameters[storyData.kind], storyData.parameters as unknown as Parameters ), - })); + })) as SetStoriesStoryData; }; export const transformSetStoriesStoryDataToStoriesHash = ( @@ -112,7 +111,7 @@ export const transformStoryIndexV2toV3 = (index: StoryIndexV2): StoryIndexV3 => }; export const transformStoryIndexV3toV4 = (index: StoryIndexV3): API_PreparedStoryIndex => { - const countByTitle = countBy(Object.values(index.stories), 'title'); + const countByTitle = countBy(Object.values(index.stories), (item) => item.title); return { v: 4, entries: Object.values(index.stories).reduce( diff --git a/code/core/src/manager-api/modules/layout.ts b/code/core/src/manager-api/modules/layout.ts index 642f78fc581..468d51af1b8 100644 --- a/code/core/src/manager-api/modules/layout.ts +++ b/code/core/src/manager-api/modules/layout.ts @@ -5,8 +5,7 @@ import { global } from '@storybook/global'; import { SET_CONFIG } from '@storybook/core/core-events'; -import { dequal as deepEqual } from 'dequal'; -import pick from 'lodash/pick.js'; +import { isEqual as deepEqual, pick, toMerged } from 'es-toolkit'; import merge from '../lib/merge'; import type { ModuleFn } from '../lib/types'; @@ -319,14 +318,13 @@ export const init: ModuleFn = ({ store, provider, singleStory return { ...defaultLayoutState, layout: { - ...defaultLayoutState.layout, - ...pick(options, Object.keys(defaultLayoutState.layout)), + ...toMerged( + defaultLayoutState.layout, + pick(options, Object.keys(defaultLayoutState.layout)) + ), ...(singleStory && { navSize: 0 }), }, - ui: { - ...defaultLayoutState.ui, - ...pick(options, Object.keys(defaultLayoutState.ui)), - }, + ui: toMerged(defaultLayoutState.ui, pick(options, Object.keys(defaultLayoutState.ui))), selectedPanel: selectedPanel || defaultLayoutState.selectedPanel, theme: theme || defaultLayoutState.theme, }; @@ -351,7 +349,7 @@ export const init: ModuleFn = ({ store, provider, singleStory const updatedLayout = { ...layout, - ...options.layout, + ...(options.layout || {}), ...pick(options, Object.keys(layout)), ...(singleStory && { navSize: 0 }), }; @@ -359,7 +357,7 @@ export const init: ModuleFn = ({ store, provider, singleStory const updatedUi = { ...ui, ...options.ui, - ...pick(options, Object.keys(ui)), + ...toMerged(options.ui || {}, pick(options, Object.keys(ui))), }; const updatedTheme = { @@ -388,7 +386,7 @@ export const init: ModuleFn = ({ store, provider, singleStory }, }; - const persisted = pick(store.getState(), 'layout', 'selectedPanel'); + const persisted = pick(store.getState(), ['layout', 'selectedPanel']); provider.channel?.on(SET_CONFIG, () => { api.setOptions(merge(api.getInitialOptions(), persisted)); diff --git a/code/core/src/manager-api/modules/notifications.ts b/code/core/src/manager-api/modules/notifications.ts index cda1025001a..c1410cfbeb7 100644 --- a/code/core/src/manager-api/modules/notifications.ts +++ b/code/core/src/manager-api/modules/notifications.ts @@ -1,6 +1,6 @@ import type { API_Notification } from '@storybook/core/types'; -import partition from 'lodash/partition.js'; +import { partition } from 'es-toolkit'; import type { ModuleFn } from '../lib/types'; diff --git a/code/core/src/manager-api/root.tsx b/code/core/src/manager-api/root.tsx index bf992f1907a..1c150b47f4b 100644 --- a/code/core/src/manager-api/root.tsx +++ b/code/core/src/manager-api/root.tsx @@ -41,11 +41,12 @@ import { STORY_CHANGED, } from '@storybook/core/core-events'; -import mergeWith from 'lodash/mergeWith.js'; +import { mergeWith } from 'es-toolkit'; import { createContext } from './context'; import getInitialState from './initial-state'; import { types } from './lib/addons'; +import { noArrayMerge } from './lib/merge'; import type { ModuleFn } from './lib/types'; import * as addons from './modules/addons'; import * as channel from './modules/channel'; @@ -129,14 +130,7 @@ export type ManagerProviderProps = RouterData & // This is duplicated from @storybook/preview-api for the reasons mentioned in lib-addons/types.js export const combineParameters = (...parameterSets: Parameters[]) => - mergeWith({}, ...parameterSets, (objValue: any, srcValue: any) => { - // Treat arrays as scalars: - if (Array.isArray(srcValue)) { - return srcValue; - } - - return undefined; - }); + noArrayMerge({}, ...parameterSets); class ManagerProvider extends Component { api: API = {} as API; diff --git a/code/core/src/manager/components/mobile/navigation/MobileNavigation.stories.tsx b/code/core/src/manager/components/mobile/navigation/MobileNavigation.stories.tsx index e445d73dea2..37e18b66a1f 100644 --- a/code/core/src/manager/components/mobile/navigation/MobileNavigation.stories.tsx +++ b/code/core/src/manager/components/mobile/navigation/MobileNavigation.stories.tsx @@ -5,7 +5,7 @@ import { within } from '@storybook/test'; import { ManagerContext } from '@storybook/core/manager-api'; -import { startCase } from 'lodash'; +import { startCase } from 'es-toolkit'; import { LayoutProvider, useLayout } from '../../layout/LayoutProvider'; import { MobileNavigation } from './MobileNavigation'; diff --git a/code/core/src/manager/components/preview/Preview.tsx b/code/core/src/manager/components/preview/Preview.tsx index 8a459276f0e..ed73a059951 100644 --- a/code/core/src/manager/components/preview/Preview.tsx +++ b/code/core/src/manager/components/preview/Preview.tsx @@ -202,7 +202,7 @@ export function filterTabs(panels: Addon_BaseType[], parameters?: Record ({ index, ...(typeof tabs[key] === 'string' ? { title: tabs[key] } : tabs[key]), diff --git a/code/core/src/manager/components/preview/Toolbar.tsx b/code/core/src/manager/components/preview/Toolbar.tsx index 2f81f309435..5dd460e80e6 100644 --- a/code/core/src/manager/components/preview/Toolbar.tsx +++ b/code/core/src/manager/components/preview/Toolbar.tsx @@ -188,7 +188,10 @@ function toolbarItemHasBeenExcluded(item: Partial, entry: LeafEn const toolbarItemsFromStoryParameters = 'toolbar' in parameters ? parameters.toolbar : undefined; const { toolbar: toolbarItemsFromAddonsConfig } = addons.getConfig(); - const toolbarItems = merge(toolbarItemsFromAddonsConfig, toolbarItemsFromStoryParameters); + const toolbarItems = merge( + toolbarItemsFromAddonsConfig || {}, + toolbarItemsFromStoryParameters || {} + ); // @ts-expect-error (non strict) return toolbarItems ? !!toolbarItems[item?.id]?.hidden : false; diff --git a/code/core/src/manager/components/sidebar/useExpanded.ts b/code/core/src/manager/components/sidebar/useExpanded.ts index 5f9a479b330..e216c2b2e0c 100644 --- a/code/core/src/manager/components/sidebar/useExpanded.ts +++ b/code/core/src/manager/components/sidebar/useExpanded.ts @@ -7,7 +7,7 @@ import { STORIES_COLLAPSE_ALL, STORIES_EXPAND_ALL } from '@storybook/core/core-e import type { StoriesHash } from '@storybook/core/manager-api'; import { useStorybookApi } from '@storybook/core/manager-api'; -import throttle from 'lodash/throttle.js'; +import { throttle } from 'es-toolkit'; import { matchesKeyCode, matchesModifiers } from '../../keybinding'; import { getAncestorIds, getDescendantIds, isAncestor, scrollIntoView } from '../../utils/tree'; diff --git a/code/core/src/manager/components/sidebar/useLastViewed.ts b/code/core/src/manager/components/sidebar/useLastViewed.ts index da53f6645ba..48aa8e10cf1 100644 --- a/code/core/src/manager/components/sidebar/useLastViewed.ts +++ b/code/core/src/manager/components/sidebar/useLastViewed.ts @@ -1,6 +1,6 @@ import { useCallback, useEffect, useMemo, useRef } from 'react'; -import debounce from 'lodash/debounce.js'; +import { debounce } from 'es-toolkit/compat'; import store from 'store2'; import type { Selection, StoryRef } from './types'; diff --git a/code/core/src/preview-api/modules/preview-web/PreviewWeb.test.ts b/code/core/src/preview-api/modules/preview-web/PreviewWeb.test.ts index 7994173c2d0..57e3b0357a4 100644 --- a/code/core/src/preview-api/modules/preview-web/PreviewWeb.test.ts +++ b/code/core/src/preview-api/modules/preview-web/PreviewWeb.test.ts @@ -31,7 +31,7 @@ import { UPDATE_STORY_ARGS, } from '@storybook/core/core-events'; -import merge from 'lodash/merge.js'; +import { merge, toMerged } from 'es-toolkit'; import { addons } from '../addons'; import type { StoryStore } from '../store'; @@ -308,7 +308,7 @@ describe('PreviewWeb', () => { expect(mockChannel.emit).toHaveBeenCalledWith(STORY_MISSING, 'component-one--missing'); mockChannel.emit.mockClear(); - const newComponentOneExports = merge({}, componentOneExports, { + const newComponentOneExports = toMerged(componentOneExports, { d: { args: { foo: 'd' }, play: vi.fn() }, }); const newImportFn = vi.fn(async (path) => { @@ -362,7 +362,7 @@ describe('PreviewWeb', () => { }); await waitForSetCurrentStory(); - const newComponentOneExports = merge({}, componentOneExports, { + const newComponentOneExports = toMerged(componentOneExports, { d: { args: { foo: 'd' }, play: vi.fn() }, }); const newImportFn = vi.fn(async (path) => { @@ -2927,7 +2927,7 @@ describe('PreviewWeb', () => { }); describe('when the current story changes', () => { - const newComponentOneExports = merge({}, componentOneExports, { + const newComponentOneExports = toMerged(componentOneExports, { a: { args: { foo: 'edited' } }, }); const newImportFn = vi.fn(async (path) => { @@ -3282,7 +3282,7 @@ describe('PreviewWeb', () => { afterEach(() => { vi.useRealTimers(); }); - const newComponentOneExports = merge({}, componentOneExports, { + const newComponentOneExports = toMerged(componentOneExports, { a: { args: { bar: 'edited' }, argTypes: { bar: { type: { name: 'string' } } } }, }); const newImportFn = vi.fn(async (path) => { diff --git a/code/core/src/preview-api/modules/preview-web/parseArgsParam.ts b/code/core/src/preview-api/modules/preview-web/parseArgsParam.ts index 6cdffe7eae1..75be5bfb57e 100644 --- a/code/core/src/preview-api/modules/preview-web/parseArgsParam.ts +++ b/code/core/src/preview-api/modules/preview-web/parseArgsParam.ts @@ -2,7 +2,7 @@ import type { Args } from '@storybook/core/types'; import { once } from '@storybook/core/client-logger'; -import isPlainObject from 'lodash/isPlainObject.js'; +import { isPlainObject } from 'es-toolkit'; import qs from 'qs'; import { dedent } from 'ts-dedent'; diff --git a/code/core/src/preview-api/modules/store/StoryStore.ts b/code/core/src/preview-api/modules/store/StoryStore.ts index 510373177fa..cd7dc40a6ed 100644 --- a/code/core/src/preview-api/modules/store/StoryStore.ts +++ b/code/core/src/preview-api/modules/store/StoryStore.ts @@ -31,8 +31,7 @@ import { MissingStoryFromCsfFileError, } from '@storybook/core/preview-errors'; -import mapValues from 'lodash/mapValues.js'; -import pick from 'lodash/pick.js'; +import { mapValues, omitBy, pick, toMerged } from 'es-toolkit'; import memoize from 'memoizerific'; import { HooksContext } from '../addons'; @@ -47,6 +46,13 @@ import { processCSFFile, } from './csf'; +export function picky, K extends keyof T>( + obj: T, + keys: K[] +): Partial> { + return omitBy(pick(obj, keys), (v) => v === undefined); +} + // TODO -- what are reasonable values for these? const CSF_CACHE_SIZE = 1000; const STORY_CACHE_SIZE = 10000; @@ -354,7 +360,7 @@ export class StoryStore { const stories: Record = mapValues(value.stories, (story) => { const { importPath } = this.storyIndex.entries[story.id]; return { - ...pick(story, ['id', 'name', 'title']), + ...picky(story, ['id', 'name', 'title']), importPath, // These 3 fields were going to be dropped in v7, but instead we will keep them for the // 7.x cycle so that v7 Storybooks can be composed successfully in v6 Storybook. @@ -362,10 +368,10 @@ export class StoryStore { kind: story.title, story: story.name, parameters: { - ...pick(story.parameters, allowedParameters), + ...picky(story.parameters, allowedParameters), fileName: importPath, }, - }; + } as V3CompatIndexEntry; }); return { diff --git a/code/core/src/preview-api/modules/store/args.ts b/code/core/src/preview-api/modules/store/args.ts index e34df974c42..ea678dd4d2d 100644 --- a/code/core/src/preview-api/modules/store/args.ts +++ b/code/core/src/preview-api/modules/store/args.ts @@ -9,8 +9,7 @@ import type { import { once } from '@storybook/core/client-logger'; -import { dequal as deepEqual } from 'dequal'; -import isPlainObject from 'lodash/isPlainObject.js'; +import { isEqual as deepEqual, isPlainObject } from 'es-toolkit'; import { dedent } from 'ts-dedent'; const INCOMPATIBLE = Symbol('incompatible'); diff --git a/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.ts b/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.ts index d0bdaabdfe1..f4685dc8309 100644 --- a/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.ts +++ b/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.ts @@ -7,7 +7,7 @@ import type { StrictInputType, } from '@storybook/core/types'; -import mapValues from 'lodash/mapValues.js'; +import { mapValues } from 'es-toolkit'; const normalizeType = (type: InputType['type']): StrictInputType['type'] => { return typeof type === 'string' ? { name: type } : type; diff --git a/code/core/src/preview-api/modules/store/filterArgTypes.ts b/code/core/src/preview-api/modules/store/filterArgTypes.ts index 274489a67cf..16c2dd3a6c5 100644 --- a/code/core/src/preview-api/modules/store/filterArgTypes.ts +++ b/code/core/src/preview-api/modules/store/filterArgTypes.ts @@ -1,6 +1,6 @@ import type { StrictArgTypes } from '@storybook/core/types'; -import pickBy from 'lodash/pickBy.js'; +import { pickBy } from 'es-toolkit'; export type PropDescriptor = string[] | RegExp; @@ -18,8 +18,8 @@ export const filterArgTypes = ( return ( argTypes && pickBy(argTypes, (argType, key) => { - const name = argType.name || key; - return (!include || matches(name, include)) && (!exclude || !matches(name, exclude)); + const name = argType.name || key.toString(); + return !!(!include || matches(name, include)) && (!exclude || !matches(name, exclude)); }) ); }; diff --git a/code/core/src/preview-api/modules/store/inferArgTypes.ts b/code/core/src/preview-api/modules/store/inferArgTypes.ts index ea8b45b7560..007b4971a17 100644 --- a/code/core/src/preview-api/modules/store/inferArgTypes.ts +++ b/code/core/src/preview-api/modules/store/inferArgTypes.ts @@ -2,7 +2,7 @@ import type { ArgTypesEnhancer, Renderer, SBType } from '@storybook/core/types'; import { logger } from '@storybook/core/client-logger'; -import mapValues from 'lodash/mapValues.js'; +import { mapValues } from 'es-toolkit'; import { dedent } from 'ts-dedent'; import { combineParameters } from './parameters'; diff --git a/code/core/src/preview-api/modules/store/inferControls.ts b/code/core/src/preview-api/modules/store/inferControls.ts index b4408d85921..92447845cc9 100644 --- a/code/core/src/preview-api/modules/store/inferControls.ts +++ b/code/core/src/preview-api/modules/store/inferControls.ts @@ -7,7 +7,7 @@ import type { import { logger } from '@storybook/core/client-logger'; -import mapValues from 'lodash/mapValues.js'; +import { mapValues } from 'es-toolkit'; import { filterArgTypes } from './filterArgTypes'; import { combineParameters } from './parameters'; @@ -77,7 +77,7 @@ export const inferControls: ArgTypesEnhancer = (context) => { const filteredArgTypes = filterArgTypes(argTypes, include, exclude); const withControls = mapValues(filteredArgTypes, (argType, name) => { - return argType?.type && inferControl(argType, name, matchers); + return argType?.type && inferControl(argType, name.toString(), matchers); }); return combineParameters(withControls, filteredArgTypes); diff --git a/code/core/src/preview-api/modules/store/parameters.ts b/code/core/src/preview-api/modules/store/parameters.ts index 43dee876d71..3b607761480 100644 --- a/code/core/src/preview-api/modules/store/parameters.ts +++ b/code/core/src/preview-api/modules/store/parameters.ts @@ -1,7 +1,7 @@ // Utilities for handling parameters import type { Parameters } from '@storybook/core/types'; -import isPlainObject from 'lodash/isPlainObject.js'; +import { isPlainObject } from 'es-toolkit'; /** * Safely combine parameters recursively. Only copy objects when needed. Algorithm = always diff --git a/code/core/src/router/utils.ts b/code/core/src/router/utils.ts index 3859668c175..c9cb7985266 100644 --- a/code/core/src/router/utils.ts +++ b/code/core/src/router/utils.ts @@ -1,7 +1,6 @@ import { once } from '@storybook/core/client-logger'; -import { dequal as deepEqual } from 'dequal'; -import isPlainObject from 'lodash/isPlainObject.js'; +import { isEqual as deepEqual, isPlainObject } from 'es-toolkit'; import memoize from 'memoizerific'; import type { IStringifyOptions } from 'qs'; import qs from 'qs'; diff --git a/code/core/template/stories/args.stories.ts b/code/core/template/stories/args.stories.ts index 4f3b766b5a3..4c83a98ca0a 100644 --- a/code/core/template/stories/args.stories.ts +++ b/code/core/template/stories/args.stories.ts @@ -8,7 +8,13 @@ import { UPDATE_STORY_ARGS, } from '@storybook/core/core-events'; -import pick from 'lodash/pick'; +function pick(obj, keys) { + const result = {}; + for (const key of keys) { + result[key] = obj[key]; + } + return result; +} export default { component: globalThis.Components.Pre, diff --git a/code/lib/blocks/package.json b/code/lib/blocks/package.json index ec2042de6a4..bc598ece7ab 100644 --- a/code/lib/blocks/package.json +++ b/code/lib/blocks/package.json @@ -46,10 +46,9 @@ "@storybook/csf": "^0.1.11", "@storybook/global": "^5.0.0", "@storybook/icons": "^1.2.10", - "@types/lodash": "^4.14.167", "color-convert": "^2.0.1", "dequal": "^2.0.2", - "lodash": "^4.17.21", + "es-toolkit": "^1.21.0", "markdown-to-jsx": "^7.4.5", "memoizerific": "^1.11.3", "polished": "^4.2.2", diff --git a/code/lib/blocks/src/components/ArgsTable/ArgValue.tsx b/code/lib/blocks/src/components/ArgsTable/ArgValue.tsx index 0df1accdada..3b97b757e49 100644 --- a/code/lib/blocks/src/components/ArgsTable/ArgValue.tsx +++ b/code/lib/blocks/src/components/ArgsTable/ArgValue.tsx @@ -6,7 +6,7 @@ import { styled } from 'storybook/internal/theming'; import { ChevronSmallDownIcon, ChevronSmallUpIcon } from '@storybook/icons'; -import uniq from 'lodash/uniq.js'; +import { uniq } from 'es-toolkit/compat'; import memoize from 'memoizerific'; import type { PropSummaryValue } from './types'; diff --git a/code/lib/blocks/src/components/ArgsTable/ArgsTable.tsx b/code/lib/blocks/src/components/ArgsTable/ArgsTable.tsx index e0dab71a171..5a1c71b36a2 100644 --- a/code/lib/blocks/src/components/ArgsTable/ArgsTable.tsx +++ b/code/lib/blocks/src/components/ArgsTable/ArgsTable.tsx @@ -8,7 +8,7 @@ import { styled } from 'storybook/internal/theming'; import { includeConditionalArg } from '@storybook/csf'; import { DocumentIcon, UndoIcon } from '@storybook/icons'; -import pickBy from 'lodash/pickBy.js'; +import { pickBy } from 'es-toolkit/compat'; import { transparentize } from 'polished'; import { EmptyBlock } from '..'; @@ -346,7 +346,7 @@ export const ArgsTable: FC = (props) => { const { rows, args, globals } = 'rows' in props && props; const groups = groupRows( pickBy( - rows, + rows || {}, (row) => !row?.table?.disable && safeIncludeConditionalArg(row, args || {}, globals || {}) ), sort diff --git a/code/lib/blocks/src/controls/Color.tsx b/code/lib/blocks/src/controls/Color.tsx index 2feafd97d14..82b95aa95f2 100644 --- a/code/lib/blocks/src/controls/Color.tsx +++ b/code/lib/blocks/src/controls/Color.tsx @@ -7,7 +7,7 @@ import { styled } from 'storybook/internal/theming'; import { MarkupIcon } from '@storybook/icons'; import convert from 'color-convert'; -import debounce from 'lodash/debounce.js'; +import { debounce } from 'es-toolkit/compat'; import { HexColorPicker, HslaStringColorPicker, RgbaStringColorPicker } from 'react-colorful'; import { getControlId } from './helpers'; diff --git a/code/lib/blocks/src/controls/Object.tsx b/code/lib/blocks/src/controls/Object.tsx index 50b5b9891d5..382dca01a57 100644 --- a/code/lib/blocks/src/controls/Object.tsx +++ b/code/lib/blocks/src/controls/Object.tsx @@ -7,7 +7,7 @@ import { type Theme, styled, useTheme } from 'storybook/internal/theming'; import { global } from '@storybook/global'; import { AddIcon, EyeCloseIcon, EyeIcon, SubtractIcon } from '@storybook/icons'; -import cloneDeep from 'lodash/cloneDeep.js'; +import { cloneDeep } from 'es-toolkit/compat'; import { getControlId, getControlSetterButtonId } from './helpers'; import { JsonTree } from './react-editable-json-tree'; diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index 0d933878b1f..7ac6639aad6 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -61,9 +61,9 @@ "@storybook/csf": "^0.1.11", "@types/cross-spawn": "^6.0.2", "cross-spawn": "^7.0.3", + "es-toolkit": "^1.21.0", "globby": "^14.0.1", "jscodeshift": "^0.15.1", - "lodash": "^4.17.21", "prettier": "^3.1.1", "recast": "^0.23.5", "tiny-invariant": "^1.3.1" @@ -71,6 +71,7 @@ "devDependencies": { "@types/jscodeshift": "^0.11.10", "ansi-regex": "^6.0.1", + "camelcase": "^8.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.1", "remark": "^15.0.1", diff --git a/code/lib/codemod/src/lib/utils.ts b/code/lib/codemod/src/lib/utils.ts index 529c87efe73..a89002e1078 100644 --- a/code/lib/codemod/src/lib/utils.ts +++ b/code/lib/codemod/src/lib/utils.ts @@ -1,5 +1,4 @@ -import camelCase from 'lodash/camelCase.js'; -import upperFirst from 'lodash/upperFirst.js'; +import { camelCase, upperFirst } from 'es-toolkit/compat'; export const sanitizeName = (name: string) => { let key = upperFirst(camelCase(name)); diff --git a/code/lib/codemod/src/transforms/mdx-to-csf.ts b/code/lib/codemod/src/transforms/mdx-to-csf.ts index 15a6ae49e7b..c83f900d0d8 100644 --- a/code/lib/codemod/src/transforms/mdx-to-csf.ts +++ b/code/lib/codemod/src/transforms/mdx-to-csf.ts @@ -11,8 +11,8 @@ import { types as t, } from '@storybook/core/babel'; +import { camelCase } from 'es-toolkit'; import type { FileInfo } from 'jscodeshift'; -import camelCase from 'lodash/camelCase'; import type { MdxFlowExpression } from 'mdast-util-mdx-expression'; import type { MdxJsxAttribute, @@ -410,7 +410,7 @@ function addStoriesImport( } export function nameToValidExport(name: string) { - const [first, ...rest] = Array.from(camelCase(name)); + const [first, ...rest] = Array.from(camelCase(name).replace(/\s/g, '')); return `${first.match(/[a-zA-Z_$]/) ? first.toUpperCase() : `$${first}`}${rest.join('')}`; } diff --git a/code/lib/source-loader/package.json b/code/lib/source-loader/package.json index 7ee6a46a1ed..d7882750db5 100644 --- a/code/lib/source-loader/package.json +++ b/code/lib/source-loader/package.json @@ -45,8 +45,8 @@ }, "dependencies": { "@storybook/csf": "^0.1.11", + "es-toolkit": "^1.21.0", "estraverse": "^5.2.0", - "lodash": "^4.17.21", "prettier": "^3.1.1" }, "devDependencies": { diff --git a/code/lib/source-loader/src/abstract-syntax-tree/generate-helpers.js b/code/lib/source-loader/src/abstract-syntax-tree/generate-helpers.js index da737063db1..39c667804ae 100644 --- a/code/lib/source-loader/src/abstract-syntax-tree/generate-helpers.js +++ b/code/lib/source-loader/src/abstract-syntax-tree/generate-helpers.js @@ -1,6 +1,6 @@ import { sanitize, storyNameFromExport } from '@storybook/csf'; -import mapKeys from 'lodash/mapKeys.js'; +import { mapKeys } from 'es-toolkit/compat'; import { extractSource } from '../extract-source'; import { patchNode } from './parse-helpers'; diff --git a/code/package.json b/code/package.json index 247d6630af9..01e77911a0f 100644 --- a/code/package.json +++ b/code/package.json @@ -168,7 +168,6 @@ "@testing-library/user-event": "^14.5.2", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/express": "^4.17.21", - "@types/lodash": "^4.14.167", "@types/mock-require": "^2.0.3", "@types/node": "^22.0.0", "@types/react": "^18.0.37", @@ -185,6 +184,7 @@ "create-storybook": "workspace:*", "cross-env": "^7.0.3", "danger": "^12.3.3", + "es-toolkit": "^1.21.0", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0", "esbuild-loader": "^4.2.0", "esbuild-plugin-alias": "^0.2.1", @@ -199,7 +199,6 @@ "http-server": "^14.1.1", "husky": "^4.3.7", "lint-staged": "^13.2.2", - "lodash": "^4.17.21", "mock-require": "^3.0.3", "nx": "18.0.6", "prettier": "^3.1.1", diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json index 0af622fe37b..ea77fec881a 100644 --- a/code/renderers/react/package.json +++ b/code/renderers/react/package.json @@ -89,8 +89,8 @@ "@types/semver": "^7.3.4", "@types/util-deprecate": "^1.0.0", "babel-plugin-react-docgen": "^4.2.1", + "es-toolkit": "^1.21.0", "expect-type": "^0.15.0", - "lodash": "^4.17.21", "require-from-string": "^2.0.2" }, "peerDependencies": { diff --git a/code/renderers/react/src/docs/lib/defaultValues/createFromRawDefaultProp.ts b/code/renderers/react/src/docs/lib/defaultValues/createFromRawDefaultProp.ts index fa8ae48e3c8..96b052a07dd 100644 --- a/code/renderers/react/src/docs/lib/defaultValues/createFromRawDefaultProp.ts +++ b/code/renderers/react/src/docs/lib/defaultValues/createFromRawDefaultProp.ts @@ -6,9 +6,7 @@ import { isTooLongForDefaultValueSummary, } from 'storybook/internal/docs-tools'; -import isFunction from 'lodash/isFunction.js'; -import isPlainObject from 'lodash/isPlainObject.js'; -import isString from 'lodash/isString.js'; +import { isFunction, isPlainObject, isString } from 'es-toolkit/compat'; import reactElementToJSXString from 'react-element-to-jsx-string'; import { ELEMENT_CAPTION, FUNCTION_CAPTION, OBJECT_CAPTION } from '../captions'; diff --git a/code/renderers/react/template/stories/js-argtypes.stories.jsx b/code/renderers/react/template/stories/js-argtypes.stories.jsx index 0d884f27951..f111f47f72e 100644 --- a/code/renderers/react/template/stories/js-argtypes.stories.jsx +++ b/code/renderers/react/template/stories/js-argtypes.stories.jsx @@ -5,7 +5,7 @@ import { ThemeProvider, convert, themes } from 'storybook/internal/theming'; import { PureArgsTable as ArgsTable } from '@storybook/blocks'; -import mapValues from 'lodash/mapValues.js'; +import { mapValues } from 'es-toolkit/compat'; import PropTypes from 'prop-types'; // import { component as JsStyledDocgenComponent } from './__testfixtures__/8279-js-styled-docgen/input'; diff --git a/code/renderers/react/template/stories/ts-argtypes.stories.tsx b/code/renderers/react/template/stories/ts-argtypes.stories.tsx index b3de474d395..0af26d5bbd8 100644 --- a/code/renderers/react/template/stories/ts-argtypes.stories.tsx +++ b/code/renderers/react/template/stories/ts-argtypes.stories.tsx @@ -7,7 +7,7 @@ import type { Args, Parameters, StoryContext } from 'storybook/internal/types'; import { PureArgsTable as ArgsTable } from '@storybook/blocks'; import type { StoryObj } from '@storybook/react'; -import mapValues from 'lodash/mapValues.js'; +import { mapValues } from 'es-toolkit/compat'; import { component as TsImportedTypesComponent } from './docgen-components/8143-ts-imported-types/input'; import { component as TsReactFcGenericsComponent } from './docgen-components/8143-ts-react-fc-generics/input'; diff --git a/code/renderers/vue3/package.json b/code/renderers/vue3/package.json index 7080f5e2cd0..3e06cfcc60e 100644 --- a/code/renderers/vue3/package.json +++ b/code/renderers/vue3/package.json @@ -76,7 +76,6 @@ "@testing-library/vue": "^8.0.0", "@types/prettier": "^3.0.0", "@vitejs/plugin-vue": "^4.4.0", - "lodash": "^4.17.21", "typescript": "^5.3.2", "vue": "^3.2.47", "vue-tsc": "latest" diff --git a/code/yarn.lock b/code/yarn.lock index 88c0807dcaf..aeda53a9977 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -5338,7 +5338,6 @@ __metadata: "@storybook/icons": "npm:^1.2.10" "@testing-library/react": "npm:^14.0.0" axe-core: "npm:^4.2.0" - lodash: "npm:^4.17.21" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" react-resize-detector: "npm:^7.1.2" @@ -5393,7 +5392,6 @@ __metadata: "@storybook/global": "npm:^5.0.0" "@storybook/icons": "npm:^1.2.10" dequal: "npm:^2.0.2" - lodash: "npm:^4.17.21" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" ts-dedent: "npm:^2.0.0" @@ -5757,10 +5755,9 @@ __metadata: "@storybook/react": "workspace:*" "@storybook/test": "workspace:*" "@types/color-convert": "npm:^2.0.0" - "@types/lodash": "npm:^4.14.167" color-convert: "npm:^2.0.1" dequal: "npm:^2.0.2" - lodash: "npm:^4.17.21" + es-toolkit: "npm:^1.21.0" markdown-to-jsx: "npm:^7.4.5" memoizerific: "npm:^1.11.3" polished: "npm:^4.2.2" @@ -5931,10 +5928,11 @@ __metadata: "@types/cross-spawn": "npm:^6.0.2" "@types/jscodeshift": "npm:^0.11.10" ansi-regex: "npm:^6.0.1" + camelcase: "npm:^8.0.0" cross-spawn: "npm:^7.0.3" + es-toolkit: "npm:^1.21.0" globby: "npm:^14.0.1" jscodeshift: "npm:^0.15.1" - lodash: "npm:^4.17.21" mdast-util-mdx-jsx: "npm:^3.0.0" mdast-util-mdxjs-esm: "npm:^2.0.1" prettier: "npm:^3.1.1" @@ -6035,7 +6033,6 @@ __metadata: "@types/express": "npm:^4.17.21" "@types/find-cache-dir": "npm:^5.0.0" "@types/js-yaml": "npm:^4.0.5" - "@types/lodash": "npm:^4.14.167" "@types/node": "npm:^22.0.0" "@types/npmlog": "npm:^7.0.0" "@types/picomatch": "npm:^2.3.0" @@ -6075,6 +6072,7 @@ __metadata: diff: "npm:^5.2.0" downshift: "npm:^9.0.4" ejs: "npm:^3.1.10" + es-toolkit: "npm:^1.21.0" esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0" esbuild-plugin-alias: "npm:^0.2.1" esbuild-register: "npm:^3.5.0" @@ -6096,7 +6094,6 @@ __metadata: jsdoc-type-pratt-parser: "npm:^4.0.0" lazy-universal-dotenv: "npm:^4.0.0" leven: "npm:^4.0.0" - lodash: "npm:^4.17.21" markdown-to-jsx: "npm:^7.4.5" memfs: "npm:^4.11.1" memoizerific: "npm:^1.11.3" @@ -6760,10 +6757,10 @@ __metadata: acorn-jsx: "npm:^5.3.1" acorn-walk: "npm:^7.2.0" babel-plugin-react-docgen: "npm:^4.2.1" + es-toolkit: "npm:^1.21.0" escodegen: "npm:^2.1.0" expect-type: "npm:^0.15.0" html-tags: "npm:^3.1.0" - lodash: "npm:^4.17.21" prop-types: "npm:^15.7.2" react-element-to-jsx-string: "npm:^15.0.0" require-from-string: "npm:^2.0.2" @@ -6868,7 +6865,6 @@ __metadata: "@testing-library/user-event": "npm:^14.5.2" "@trivago/prettier-plugin-sort-imports": "npm:^4.3.0" "@types/express": "npm:^4.17.21" - "@types/lodash": "npm:^4.14.167" "@types/mock-require": "npm:^2.0.3" "@types/node": "npm:^22.0.0" "@types/react": "npm:^18.0.37" @@ -6885,6 +6881,7 @@ __metadata: create-storybook: "workspace:*" cross-env: "npm:^7.0.3" danger: "npm:^12.3.3" + es-toolkit: "npm:^1.21.0" esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0" esbuild-loader: "npm:^4.2.0" esbuild-plugin-alias: "npm:^0.2.1" @@ -6899,7 +6896,6 @@ __metadata: http-server: "npm:^14.1.1" husky: "npm:^4.3.7" lint-staged: "npm:^13.2.2" - lodash: "npm:^4.17.21" mock-require: "npm:^3.0.3" nx: "npm:18.0.6" prettier: "npm:^3.1.1" @@ -6987,8 +6983,8 @@ __metadata: resolution: "@storybook/source-loader@workspace:lib/source-loader" dependencies: "@storybook/csf": "npm:^0.1.11" + es-toolkit: "npm:^1.21.0" estraverse: "npm:^5.2.0" - lodash: "npm:^4.17.21" prettier: "npm:^3.1.1" typescript: "npm:^5.3.2" peerDependencies: @@ -7188,7 +7184,6 @@ __metadata: "@types/prettier": "npm:^3.0.0" "@vitejs/plugin-vue": "npm:^4.4.0" "@vue/compiler-core": "npm:^3.0.0" - lodash: "npm:^4.17.21" ts-dedent: "npm:^2.0.0" type-fest: "npm:~2.19" typescript: "npm:^5.3.2" @@ -8008,13 +8003,6 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:^4.14.167": - version: 4.14.202 - resolution: "@types/lodash@npm:4.14.202" - checksum: 10c0/6064d43c8f454170841bd67c8266cc9069d9e570a72ca63f06bceb484cb4a3ee60c9c1f305c1b9e3a87826049fd41124b8ef265c4dd08b00f6766609c7fe9973 - languageName: node - linkType: hard - "@types/mdast@npm:^3.0.0": version: 3.0.15 resolution: "@types/mdast@npm:3.0.15" @@ -14072,6 +14060,13 @@ __metadata: languageName: node linkType: hard +"es-toolkit@npm:^1.21.0": + version: 1.21.0 + resolution: "es-toolkit@npm:1.21.0" + checksum: 10c0/894a63f8ce5b2e5c1be242c8e8eace6364ea1212d01cdf89594d2cc582c5e1574114ad2ee7022ad5206561c4d5170511d83b38853257249860e56178768854ea + languageName: node + linkType: hard + "es6-promise@npm:^3.1.2": version: 3.3.1 resolution: "es6-promise@npm:3.3.1" diff --git a/scripts/package.json b/scripts/package.json index 2cd8402ddcd..13351afb582 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -79,7 +79,6 @@ "@types/fs-extra": "^11.0.4", "@types/http-server": "^0.12.4", "@types/jest": "^29.5.12", - "@types/lodash": "^4.17.6", "@types/node": "^22.0.0", "@types/prettier": "^3.0.0", "@types/pretty-hrtime": "^1.0.3", @@ -108,6 +107,7 @@ "detect-port": "^1.6.1", "ejs": "^3.1.10", "ejs-lint": "^2.0.0", + "es-toolkit": "^1.21.0", "esbuild": "^0.23.0", "esbuild-plugin-alias": "^0.2.1", "eslint": "^8.57.0", @@ -136,7 +136,6 @@ "json5": "^2.2.3", "junit-xml": "^1.2.0", "lint-staged": "^15.2.7", - "lodash": "^4.17.21", "memoizerific": "^1.11.3", "node-gyp": "^9.3.1", "nx": "18.0.6", diff --git a/scripts/release/unreleased-changes-exists.ts b/scripts/release/unreleased-changes-exists.ts index 49c50ccd7d4..217bfa033a4 100644 --- a/scripts/release/unreleased-changes-exists.ts +++ b/scripts/release/unreleased-changes-exists.ts @@ -1,7 +1,7 @@ import { setOutput } from '@actions/core'; import chalk from 'chalk'; import { program } from 'commander'; -import { intersection } from 'lodash'; +import { intersection } from 'es-toolkit'; import { z } from 'zod'; import { esMain } from '../utils/esmain'; diff --git a/scripts/tasks/sandbox-parts.ts b/scripts/tasks/sandbox-parts.ts index 07c518a9986..a2df1e8e169 100644 --- a/scripts/tasks/sandbox-parts.ts +++ b/scripts/tasks/sandbox-parts.ts @@ -1,5 +1,6 @@ // This file requires many imports from `../code`, which requires both an install and bootstrap of // the repo to work properly. So we load it async in the task runner *after* those steps. +import { isFunction } from 'es-toolkit'; import { copy, ensureDir, @@ -12,7 +13,6 @@ import { writeJson, } from 'fs-extra'; import JSON5 from 'json5'; -import { isFunction } from 'lodash'; import { createRequire } from 'module'; import { join, relative, resolve, sep } from 'path'; import slash from 'slash'; @@ -717,7 +717,7 @@ export const extendMain: Task['run'] = async ({ template, sandboxDir, key }, { d addRefs(mainConfig); } - const templateConfig = isFunction(template.modifications?.mainConfig) + const templateConfig: any = isFunction(template.modifications?.mainConfig) ? template.modifications?.mainConfig(mainConfig) : template.modifications?.mainConfig || {}; const configToAdd = { diff --git a/scripts/utils/options.ts b/scripts/utils/options.ts index 5add8c25dd2..6bf48e80474 100644 --- a/scripts/utils/options.ts +++ b/scripts/utils/options.ts @@ -2,7 +2,7 @@ import chalk from 'chalk'; import { type Command, type Option as CommanderOption, program } from 'commander'; // eslint-disable-next-line import/extensions -import kebabCase from 'lodash/kebabCase.js'; +import { kebabCase } from 'es-toolkit/compat'; import prompts from 'prompts'; import type { Falsy, PrevCaller, PromptObject, PromptType } from 'prompts'; import { dedent } from 'ts-dedent'; diff --git a/scripts/yarn.lock b/scripts/yarn.lock index 204801ac47a..25f08bde9c9 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -1529,7 +1529,6 @@ __metadata: "@types/fs-extra": "npm:^11.0.4" "@types/http-server": "npm:^0.12.4" "@types/jest": "npm:^29.5.12" - "@types/lodash": "npm:^4.17.6" "@types/node": "npm:^22.0.0" "@types/prettier": "npm:^3.0.0" "@types/pretty-hrtime": "npm:^1.0.3" @@ -1559,6 +1558,7 @@ __metadata: detect-port: "npm:^1.6.1" ejs: "npm:^3.1.10" ejs-lint: "npm:^2.0.0" + es-toolkit: "npm:^1.21.0" esbuild: "npm:^0.23.0" esbuild-plugin-alias: "npm:^0.2.1" eslint: "npm:^8.57.0" @@ -1588,7 +1588,6 @@ __metadata: json5: "npm:^2.2.3" junit-xml: "npm:^1.2.0" lint-staged: "npm:^15.2.7" - lodash: "npm:^4.17.21" memoizerific: "npm:^1.11.3" node-gyp: "npm:^9.3.1" nx: "npm:18.0.6" @@ -1973,7 +1972,7 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:^4.14.175, @types/lodash@npm:^4.17.6": +"@types/lodash@npm:^4.14.175": version: 4.17.6 resolution: "@types/lodash@npm:4.17.6" checksum: 10c0/3b197ac47af9443fee8c4719c5ffde527d7febc018b827d44a6bc2523c728c7adfdd25196fdcfe3eed827993e0c41a917d0da6e78938b18b2be94164789f1117 @@ -5272,6 +5271,13 @@ __metadata: languageName: node linkType: hard +"es-toolkit@npm:^1.21.0": + version: 1.21.0 + resolution: "es-toolkit@npm:1.21.0" + checksum: 10c0/894a63f8ce5b2e5c1be242c8e8eace6364ea1212d01cdf89594d2cc582c5e1574114ad2ee7022ad5206561c4d5170511d83b38853257249860e56178768854ea + languageName: node + linkType: hard + "esbuild-plugin-alias@npm:^0.2.1": version: 0.2.1 resolution: "esbuild-plugin-alias@npm:0.2.1"