feat(storybook): migrator for webpack 5
This commit is contained in:
parent
0f85b49065
commit
fd3868c94e
@ -98,6 +98,12 @@
|
||||
"version": "13.0.0-beta.0",
|
||||
"description": "Update tsconfig.json to use `jsxImportSource` to support css prop",
|
||||
"factory": "./src/migrations/update-13-0-0/update-emotion-setup"
|
||||
},
|
||||
"migrate-storybook-to-webpack-5-13.0.0": {
|
||||
"cli": "nx",
|
||||
"version": "13.0.0-beta.0",
|
||||
"description": "Migrate Storybook to use webpack 5",
|
||||
"factory": "./src/migrations/update-13-0-0/migrate-storybook-to-webpack-5"
|
||||
}
|
||||
},
|
||||
"packageJsonUpdates": {
|
||||
|
||||
@ -0,0 +1,361 @@
|
||||
import { readJson, Tree, updateJson } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import { migrateStorybookToWebPack5 } from './migrate-storybook-to-webpack-5';
|
||||
|
||||
describe('migrateStorybookToWebPack5', () => {
|
||||
let tree: Tree;
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it('should add packages needed by Storybook if workspace has the @storybook/react package', async () => {
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
json.devDependencies = {
|
||||
'@storybook/react': '~6.3.0',
|
||||
};
|
||||
return json;
|
||||
});
|
||||
|
||||
await migrateStorybookToWebPack5(tree);
|
||||
|
||||
const json = readJson(tree, '/package.json');
|
||||
|
||||
expect(json.devDependencies['@storybook/builder-webpack5']).toBe('~6.3.0');
|
||||
expect(json.devDependencies['@storybook/manager-webpack5']).toBe('~6.3.0');
|
||||
});
|
||||
|
||||
it('should not add the webpack Storybook packages again if they already exist', async () => {
|
||||
let newTree = createTreeWithEmptyWorkspace();
|
||||
updateJson(newTree, 'package.json', (json) => {
|
||||
json.dependencies = {
|
||||
'@storybook/react': '~6.3.0',
|
||||
'@storybook/builder-webpack5': '~6.3.0',
|
||||
'@storybook/manager-webpack5': '~6.3.0',
|
||||
};
|
||||
return json;
|
||||
});
|
||||
await migrateStorybookToWebPack5(newTree);
|
||||
const json = readJson(newTree, '/package.json');
|
||||
expect(json.devDependencies['@storybook/builder-webpack5']).toBeUndefined();
|
||||
expect(json.devDependencies['@storybook/manager-webpack5']).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not add Storybook packages if @storybook/react does not exist', async () => {
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
json.devDependencies = {
|
||||
'@storybook/angular': '~6.3.0',
|
||||
};
|
||||
return json;
|
||||
});
|
||||
await migrateStorybookToWebPack5(tree);
|
||||
const json = readJson(tree, '/package.json');
|
||||
expect(json.devDependencies['@storybook/builder-webpack5']).toBeUndefined();
|
||||
expect(json.devDependencies['@storybook/manager-webpack5']).toBeUndefined();
|
||||
});
|
||||
|
||||
describe('updating project-level .storybook/main.js configurations for webpack 5', () => {
|
||||
beforeEach(async () => {
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
json.devDependencies = {
|
||||
'@storybook/react': '~6.3.0',
|
||||
};
|
||||
return json;
|
||||
});
|
||||
|
||||
updateJson(tree, 'workspace.json', (json) => {
|
||||
json = {
|
||||
...json,
|
||||
projects: {
|
||||
...json.projects,
|
||||
'test-one': {
|
||||
targets: {
|
||||
storybook: {
|
||||
options: {
|
||||
uiFramework: '@storybook/react',
|
||||
config: {
|
||||
configFolder: 'libs/test-one/.storybook',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'test-two': {
|
||||
targets: {
|
||||
storybook: {
|
||||
options: {
|
||||
uiFramework: '@storybook/react',
|
||||
config: {
|
||||
configFolder: 'libs/test-two/.storybook',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
return json;
|
||||
});
|
||||
|
||||
tree.write(
|
||||
`.storybook/main.js`,
|
||||
`module.exports = {
|
||||
stories: [],
|
||||
addons: ['@storybook/addon-essentials'],
|
||||
// uncomment the property below if you want to apply some webpack config globally
|
||||
// webpackFinal: async (config, { configType }) => {
|
||||
// // Make whatever fine-grained changes you need that should apply to all storybook configs
|
||||
|
||||
// // Return the altered config
|
||||
// return config;
|
||||
// },
|
||||
};
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
describe('when main.js uses new syntax', () => {
|
||||
it('should update the project-level .storybook/main.js if there is a core object', async () => {
|
||||
tree.write(
|
||||
`libs/test-one/.storybook/main.js`,
|
||||
`const rootMain = require('../../../.storybook/main');
|
||||
module.exports = {
|
||||
...rootMain,
|
||||
|
||||
core: { ...rootMain.core },
|
||||
stories: [
|
||||
...rootMain.stories,
|
||||
'../src/lib/**/*.stories.mdx',
|
||||
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)',
|
||||
],
|
||||
addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
|
||||
webpackFinal: async (config, { configType }) => {
|
||||
// apply any global webpack configs that might have been specified in .storybook/main.js
|
||||
if (rootMain.webpackFinal) {
|
||||
config = await rootMain.webpackFinal(config, { configType });
|
||||
}
|
||||
|
||||
// add your own webpack tweaks if needed
|
||||
|
||||
return config;
|
||||
},
|
||||
};`
|
||||
);
|
||||
|
||||
tree.write(
|
||||
`libs/test-two/.storybook/main.js`,
|
||||
`const rootMain = require('../../../.storybook/main');
|
||||
module.exports = {
|
||||
...rootMain,
|
||||
core: { ...rootMain.core },
|
||||
stories: [
|
||||
...rootMain.stories,
|
||||
'../src/lib/**/*.stories.mdx',
|
||||
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)',
|
||||
],
|
||||
addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
|
||||
webpackFinal: async (config, { configType }) => {
|
||||
// apply any global webpack configs that might have been specified in .storybook/main.js
|
||||
if (rootMain.webpackFinal) {
|
||||
config = await rootMain.webpackFinal(config, { configType });
|
||||
}
|
||||
|
||||
// add your own webpack tweaks if needed
|
||||
|
||||
return config;
|
||||
},
|
||||
};`
|
||||
);
|
||||
|
||||
await migrateStorybookToWebPack5(tree);
|
||||
|
||||
const projectOne = tree.read(
|
||||
`libs/test-one/.storybook/main.js`,
|
||||
'utf-8'
|
||||
);
|
||||
expect(projectOne).toContain(`builder: 'webpack5'`);
|
||||
const projectTwo = tree.read(
|
||||
`libs/test-two/.storybook/main.js`,
|
||||
'utf-8'
|
||||
);
|
||||
expect(projectTwo).toContain(`builder: 'webpack5'`);
|
||||
});
|
||||
|
||||
it('should update the project-level .storybook/main.js if there is not a core object', async () => {
|
||||
tree.write(
|
||||
`libs/test-one/.storybook/main.js`,
|
||||
`const rootMain = require('../../../.storybook/main');
|
||||
module.exports = {
|
||||
...rootMain,
|
||||
|
||||
stories: [
|
||||
...rootMain.stories,
|
||||
'../src/lib/**/*.stories.mdx',
|
||||
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)',
|
||||
],
|
||||
addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
|
||||
webpackFinal: async (config, { configType }) => {
|
||||
// apply any global webpack configs that might have been specified in .storybook/main.js
|
||||
if (rootMain.webpackFinal) {
|
||||
config = await rootMain.webpackFinal(config, { configType });
|
||||
}
|
||||
|
||||
// add your own webpack tweaks if needed
|
||||
|
||||
return config;
|
||||
},
|
||||
};`
|
||||
);
|
||||
|
||||
tree.write(
|
||||
`libs/test-two/.storybook/main.js`,
|
||||
`const rootMain = require('../../../.storybook/main');
|
||||
module.exports = {
|
||||
...rootMain,
|
||||
|
||||
stories: [
|
||||
...rootMain.stories,
|
||||
'../src/lib/**/*.stories.mdx',
|
||||
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)',
|
||||
],
|
||||
addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
|
||||
webpackFinal: async (config, { configType }) => {
|
||||
// apply any global webpack configs that might have been specified in .storybook/main.js
|
||||
if (rootMain.webpackFinal) {
|
||||
config = await rootMain.webpackFinal(config, { configType });
|
||||
}
|
||||
|
||||
// add your own webpack tweaks if needed
|
||||
|
||||
return config;
|
||||
},
|
||||
};`
|
||||
);
|
||||
|
||||
await migrateStorybookToWebPack5(tree);
|
||||
const projectOne = tree.read(
|
||||
`libs/test-one/.storybook/main.js`,
|
||||
'utf-8'
|
||||
);
|
||||
expect(projectOne).toContain(`builder: 'webpack5'`);
|
||||
const projectTwo = tree.read(
|
||||
`libs/test-two/.storybook/main.js`,
|
||||
'utf-8'
|
||||
);
|
||||
expect(projectTwo).toContain(`builder: 'webpack5'`);
|
||||
});
|
||||
|
||||
it('should not do anything if project-level .storybook/main.js is invalid', async () => {
|
||||
tree.write(
|
||||
`libs/test-one/.storybook/main.js`,
|
||||
`const rootMain = require('../../../.storybook/main');
|
||||
module.exports = {
|
||||
};`
|
||||
);
|
||||
|
||||
tree.write(
|
||||
`libs/test-two/.storybook/main.js`,
|
||||
`const rootMain = require('../../../.storybook/main');
|
||||
module.exports = {
|
||||
...rootMain,
|
||||
},
|
||||
};`
|
||||
);
|
||||
|
||||
await migrateStorybookToWebPack5(tree);
|
||||
const projectOne = tree.read(
|
||||
`libs/test-one/.storybook/main.js`,
|
||||
'utf-8'
|
||||
);
|
||||
expect(projectOne).not.toContain(`builder: 'webpack5'`);
|
||||
const projectTwo = tree.read(
|
||||
`libs/test-two/.storybook/main.js`,
|
||||
'utf-8'
|
||||
);
|
||||
expect(projectTwo).not.toContain(`builder: 'webpack5'`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when main.js uses old syntax', () => {
|
||||
it('should update the project-level .storybook/main.js if there is a core object', async () => {
|
||||
tree.write(
|
||||
`libs/test-one/.storybook/main.js`,
|
||||
`const rootMain = require('../../../.storybook/main');
|
||||
|
||||
rootMain.core = {
|
||||
...rootMain.core
|
||||
};
|
||||
// Use the following syntax to add addons!
|
||||
// rootMain.addons.push('');
|
||||
rootMain.stories.push(
|
||||
...['../src/lib/**/*.stories.mdx', '../src/lib/**/*.stories.@(js|jsx|ts|tsx)']
|
||||
);
|
||||
module.exports = rootMain;`
|
||||
);
|
||||
|
||||
tree.write(
|
||||
`libs/test-two/.storybook/main.js`,
|
||||
`const rootMain = require('../../../.storybook/main');
|
||||
|
||||
rootMain.core = { ...rootMain.core, builder: 'webpack5' };
|
||||
// Use the following syntax to add addons!
|
||||
// rootMain.addons.push('');
|
||||
rootMain.stories.push(
|
||||
...['../src/lib/**/*.stories.mdx', '../src/lib/**/*.stories.@(js|jsx|ts|tsx)']
|
||||
);
|
||||
module.exports = rootMain;`
|
||||
);
|
||||
|
||||
await migrateStorybookToWebPack5(tree);
|
||||
|
||||
const projectOne = tree.read(
|
||||
`libs/test-one/.storybook/main.js`,
|
||||
'utf-8'
|
||||
);
|
||||
expect(projectOne).toContain(`builder: 'webpack5'`);
|
||||
const projectTwo = tree.read(
|
||||
`libs/test-two/.storybook/main.js`,
|
||||
'utf-8'
|
||||
);
|
||||
expect(projectTwo).toContain(`builder: 'webpack5'`);
|
||||
});
|
||||
|
||||
it('should update the project-level .storybook/main.js if there is not a core object', async () => {
|
||||
tree.write(
|
||||
`libs/test-one/.storybook/main.js`,
|
||||
`const rootMain = require('../../../.storybook/main');
|
||||
|
||||
// Use the following syntax to add addons!
|
||||
// rootMain.addons.push('');
|
||||
rootMain.stories.push(
|
||||
...['../src/lib/**/*.stories.mdx', '../src/lib/**/*.stories.@(js|jsx|ts|tsx)']
|
||||
);
|
||||
module.exports = rootMain;`
|
||||
);
|
||||
|
||||
tree.write(
|
||||
`libs/test-two/.storybook/main.js`,
|
||||
`const rootMain = require('../../../.storybook/main');
|
||||
|
||||
// Use the following syntax to add addons!
|
||||
// rootMain.addons.push('');
|
||||
rootMain.stories.push(
|
||||
...['../src/lib/**/*.stories.mdx', '../src/lib/**/*.stories.@(js|jsx|ts|tsx)']
|
||||
);
|
||||
module.exports = rootMain;`
|
||||
);
|
||||
|
||||
await migrateStorybookToWebPack5(tree);
|
||||
const projectOne = tree.read(
|
||||
`libs/test-one/.storybook/main.js`,
|
||||
'utf-8'
|
||||
);
|
||||
expect(projectOne).toContain(`builder: 'webpack5'`);
|
||||
const projectTwo = tree.read(
|
||||
`libs/test-two/.storybook/main.js`,
|
||||
'utf-8'
|
||||
);
|
||||
expect(projectTwo).toContain(`builder: 'webpack5'`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,46 @@
|
||||
import { Tree, logger, updateJson, readJson } from '@nrwl/devkit';
|
||||
import {
|
||||
migrateToWebPack5,
|
||||
workspaceHasStorybookForReact,
|
||||
} from './webpack5-changes-utils';
|
||||
|
||||
let needsInstall = false;
|
||||
|
||||
export async function migrateStorybookToWebPack5(tree: Tree) {
|
||||
const packageJson = readJson(tree, 'package.json');
|
||||
if (workspaceHasStorybookForReact(packageJson)) {
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
json.dependencies = json.dependencies || {};
|
||||
json.devDependencies = json.devDependencies || {};
|
||||
|
||||
if (
|
||||
!json.dependencies['@storybook/builder-webpack5'] &&
|
||||
!json.devDependencies['@storybook/builder-webpack5']
|
||||
) {
|
||||
needsInstall = true;
|
||||
json.devDependencies['@storybook/builder-webpack5'] =
|
||||
workspaceHasStorybookForReact(packageJson);
|
||||
}
|
||||
|
||||
if (
|
||||
!json.dependencies['@storybook/manager-webpack5'] &&
|
||||
!json.devDependencies['@storybook/manager-webpack5']
|
||||
) {
|
||||
needsInstall = true;
|
||||
json.devDependencies['@storybook/manager-webpack5'] =
|
||||
workspaceHasStorybookForReact(packageJson);
|
||||
}
|
||||
|
||||
return json;
|
||||
});
|
||||
await migrateToWebPack5(tree);
|
||||
|
||||
if (needsInstall) {
|
||||
logger.info(
|
||||
'Please make sure to run npm install or yarn install to get the latest packages added by this migration'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default migrateStorybookToWebPack5;
|
||||
@ -0,0 +1,322 @@
|
||||
import { getProjects, Tree } from '@nrwl/devkit';
|
||||
import {
|
||||
logger,
|
||||
formatFiles,
|
||||
applyChangesToString,
|
||||
ChangeType,
|
||||
} from '@nrwl/devkit';
|
||||
|
||||
import ts = require('typescript');
|
||||
import { findNodes } from '@nrwl/workspace/src/utilities/typescript/find-nodes';
|
||||
|
||||
export async function migrateToWebPack5(tree: Tree) {
|
||||
allReactProjectsWithStorybookConfiguration(tree).forEach((project) => {
|
||||
editProjectMainJs(
|
||||
tree,
|
||||
`${project.storybookConfigPath}/main.js`,
|
||||
project.projectName
|
||||
);
|
||||
});
|
||||
await formatFiles(tree);
|
||||
}
|
||||
|
||||
export function workspaceHasStorybookForReact(
|
||||
packageJson: any
|
||||
): string | undefined {
|
||||
return (
|
||||
packageJson.dependencies['@storybook/react'] ||
|
||||
packageJson.devDependencies['@storybook/react']
|
||||
);
|
||||
}
|
||||
|
||||
export function allReactProjectsWithStorybookConfiguration(tree: Tree): {
|
||||
projectName: string;
|
||||
storybookConfigPath: string;
|
||||
}[] {
|
||||
const projects = getProjects(tree);
|
||||
const reactProjectsThatHaveStorybookConfiguration: {
|
||||
projectName: string;
|
||||
storybookConfigPath: string;
|
||||
}[] = [...projects.entries()]
|
||||
?.filter(
|
||||
([_, projectConfig]) =>
|
||||
projectConfig.targets &&
|
||||
projectConfig.targets.storybook &&
|
||||
projectConfig.targets.storybook.options
|
||||
)
|
||||
?.map(([projectName, projectConfig]) => {
|
||||
if (
|
||||
projectConfig.targets &&
|
||||
projectConfig.targets.storybook &&
|
||||
projectConfig.targets.storybook.options?.config?.configFolder &&
|
||||
projectConfig.targets.storybook.options?.uiFramework ===
|
||||
'@storybook/react'
|
||||
) {
|
||||
return {
|
||||
projectName,
|
||||
storybookConfigPath:
|
||||
projectConfig.targets.storybook.options.config.configFolder,
|
||||
};
|
||||
}
|
||||
});
|
||||
return reactProjectsThatHaveStorybookConfiguration;
|
||||
}
|
||||
|
||||
export function editProjectMainJs(
|
||||
tree: Tree,
|
||||
projectMainJsFile: string,
|
||||
projectName: string
|
||||
) {
|
||||
let newContents: string;
|
||||
let moduleExportsIsEmptyOrNonExistentOrInvalid = false;
|
||||
let alreadyHasBuilder: any;
|
||||
const rootMainJsExists = tree.exists(projectMainJsFile);
|
||||
let moduleExportsFull: ts.Node[] = [];
|
||||
|
||||
if (rootMainJsExists) {
|
||||
const file = getTsSourceFile(tree, projectMainJsFile);
|
||||
const appFileContent = tree.read(projectMainJsFile, 'utf-8');
|
||||
newContents = appFileContent;
|
||||
moduleExportsFull = findNodes(file, [ts.SyntaxKind.ExpressionStatement]);
|
||||
|
||||
if (moduleExportsFull && moduleExportsFull[0]) {
|
||||
const moduleExports = moduleExportsFull[0];
|
||||
|
||||
const listOfStatements = findNodes(moduleExports, [
|
||||
ts.SyntaxKind.SyntaxList,
|
||||
]);
|
||||
|
||||
/**
|
||||
* Keep the index of the stories node
|
||||
* to put the core object before it
|
||||
* if it does not exist already
|
||||
*/
|
||||
|
||||
let indexOfStoriesNode = -1;
|
||||
|
||||
const hasCoreObject = listOfStatements[0]?.getChildren()?.find((node) => {
|
||||
if (
|
||||
node &&
|
||||
node.getText().length > 0 &&
|
||||
indexOfStoriesNode < 0 &&
|
||||
node?.getText().startsWith('stories')
|
||||
) {
|
||||
indexOfStoriesNode = node.getStart();
|
||||
}
|
||||
return (
|
||||
node?.kind === ts.SyntaxKind.PropertyAssignment &&
|
||||
node?.getText().startsWith('core')
|
||||
);
|
||||
});
|
||||
|
||||
if (hasCoreObject) {
|
||||
const contentsOfCoreNode = hasCoreObject.getChildren().find((node) => {
|
||||
return node.kind === ts.SyntaxKind.ObjectLiteralExpression;
|
||||
});
|
||||
const everyAttributeInsideCoreNode = contentsOfCoreNode
|
||||
.getChildren()
|
||||
.find((node) => node.kind === ts.SyntaxKind.SyntaxList);
|
||||
|
||||
alreadyHasBuilder = everyAttributeInsideCoreNode
|
||||
.getChildren()
|
||||
.find((node) => node.getText() === "builder: 'webpack5'");
|
||||
|
||||
if (!alreadyHasBuilder) {
|
||||
newContents = applyChangesToString(newContents, [
|
||||
{
|
||||
type: ChangeType.Insert,
|
||||
index: contentsOfCoreNode.getEnd() - 1,
|
||||
text: ", builder: 'webpack5'",
|
||||
},
|
||||
]);
|
||||
}
|
||||
} else if (indexOfStoriesNode >= 0) {
|
||||
/**
|
||||
* Does not have core object,
|
||||
* so just write one, at the start.
|
||||
*/
|
||||
newContents = applyChangesToString(newContents, [
|
||||
{
|
||||
type: ChangeType.Insert,
|
||||
index: indexOfStoriesNode - 1,
|
||||
text: "core: { ...rootMain.core, builder: 'webpack5' }, ",
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
/**
|
||||
* Module exports is empty or does not
|
||||
* contain stories - most probably invalid
|
||||
*/
|
||||
moduleExportsIsEmptyOrNonExistentOrInvalid = true;
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* module.exports does not exist
|
||||
*/
|
||||
moduleExportsIsEmptyOrNonExistentOrInvalid = true;
|
||||
}
|
||||
} else {
|
||||
moduleExportsIsEmptyOrNonExistentOrInvalid = true;
|
||||
}
|
||||
|
||||
if (moduleExportsIsEmptyOrNonExistentOrInvalid) {
|
||||
const usesOldSyntax = checkMainJsForOldSyntax(
|
||||
moduleExportsFull,
|
||||
newContents
|
||||
);
|
||||
if (moduleExportsFull.length > 0 && usesOldSyntax) {
|
||||
newContents = usesOldSyntax;
|
||||
tree.write(projectMainJsFile, newContents);
|
||||
return;
|
||||
} else {
|
||||
logger.info(
|
||||
`Please configure Storybook for project "${projectName}"", since it has not been configured properly.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyHasBuilder) {
|
||||
tree.write(projectMainJsFile, newContents);
|
||||
}
|
||||
}
|
||||
|
||||
export function checkMainJsForOldSyntax(
|
||||
nodeList: ts.Node[],
|
||||
fileContent: string
|
||||
): string | undefined {
|
||||
let alreadyContainsBuilder = false;
|
||||
let coreNode: ts.Node | undefined;
|
||||
let hasCoreNode = false;
|
||||
const lastIndexOfFirstNode = nodeList[0].getEnd();
|
||||
|
||||
if (!fileContent.includes('stories.push') || nodeList.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Go through the node list and find if the core object exists
|
||||
// If it does, then we need to check if it has the builder property
|
||||
// If it does not, then we need to add it
|
||||
for (let topNode of nodeList) {
|
||||
if (
|
||||
topNode.kind === ts.SyntaxKind.ExpressionStatement &&
|
||||
topNode.getChildren()?.length > 0
|
||||
) {
|
||||
for (let node of topNode.getChildren()) {
|
||||
if (
|
||||
node.kind === ts.SyntaxKind.BinaryExpression &&
|
||||
node.getChildren()?.length
|
||||
) {
|
||||
for (let childNode of node.getChildren()) {
|
||||
if (
|
||||
childNode.kind === ts.SyntaxKind.PropertyAccessExpression &&
|
||||
childNode.getChildren()?.length
|
||||
) {
|
||||
for (let grandChildNode of childNode.getChildren()) {
|
||||
if (
|
||||
grandChildNode.kind === ts.SyntaxKind.Identifier &&
|
||||
grandChildNode.getText() === 'core'
|
||||
) {
|
||||
coreNode = node;
|
||||
hasCoreNode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasCoreNode) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasCoreNode) {
|
||||
if (coreNode.getChildren()?.length) {
|
||||
for (let coreChildNode of coreNode.getChildren()) {
|
||||
if (
|
||||
coreChildNode.kind === ts.SyntaxKind.ObjectLiteralExpression &&
|
||||
coreChildNode.getChildren()?.length
|
||||
) {
|
||||
for (let coreChildNodeChild of coreChildNode.getChildren()) {
|
||||
if (coreChildNodeChild.kind === ts.SyntaxKind.SyntaxList) {
|
||||
for (let coreChildNodeGrandChild of coreChildNodeChild.getChildren()) {
|
||||
if (
|
||||
coreChildNodeGrandChild.kind ===
|
||||
ts.SyntaxKind.PropertyAssignment &&
|
||||
coreChildNodeGrandChild.getText().startsWith('builder')
|
||||
) {
|
||||
for (let coreChildNodeGrandChildChild of coreChildNodeGrandChild.getChildren()) {
|
||||
if (
|
||||
coreChildNodeGrandChildChild.kind ===
|
||||
ts.SyntaxKind.StringLiteral &&
|
||||
coreChildNodeGrandChildChild.getText() ===
|
||||
'webpack5'
|
||||
) {
|
||||
alreadyContainsBuilder = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (alreadyContainsBuilder) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (alreadyContainsBuilder) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (alreadyContainsBuilder) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasCoreNode) {
|
||||
if (alreadyContainsBuilder) {
|
||||
break;
|
||||
} else {
|
||||
// Add builder
|
||||
const indexOfCoreNodeEnd = coreNode.getEnd();
|
||||
fileContent = applyChangesToString(fileContent, [
|
||||
{
|
||||
type: ChangeType.Insert,
|
||||
index: indexOfCoreNodeEnd - 1,
|
||||
text: ", builder: 'webpack5'",
|
||||
},
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasCoreNode) {
|
||||
fileContent = applyChangesToString(fileContent, [
|
||||
{
|
||||
type: ChangeType.Insert,
|
||||
index: lastIndexOfFirstNode + 1,
|
||||
text: "rootMain.core = { ...rootMain.core, builder: 'webpack5' };\n",
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
export function getTsSourceFile(host: Tree, path: string): ts.SourceFile {
|
||||
const buffer = host.read(path);
|
||||
if (!buffer) {
|
||||
throw new Error(`Could not read TS file (${path}).`);
|
||||
}
|
||||
const content = buffer.toString();
|
||||
const source = ts.createSourceFile(
|
||||
path,
|
||||
content,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
|
||||
return source;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user