diff --git a/packages/devextreme-cli/src/utility/ng-version.js b/packages/devextreme-cli/src/utility/ng-version.js index 5ad037250..4327a0129 100644 --- a/packages/devextreme-cli/src/utility/ng-version.js +++ b/packages/devextreme-cli/src/utility/ng-version.js @@ -2,12 +2,12 @@ const semver = require('semver').SemVer; const execSync = require('child_process').execSync; function parseNgCliVersion(stdout) { - return /angular.cli:\s*(\S+)/ig.exec(stdout)[1]; + return stdout.trim(); } const getLocalNgVersion = () => { try { - const version = parseNgCliVersion(execSync('ng v').toString()); + const version = parseNgCliVersion(execSync('ng --version').toString()); return new semver(version); } catch(e) { return ''; diff --git a/packages/devextreme-schematics/src/add-layout/files/src/app/app-navigation.ts b/packages/devextreme-schematics/src/add-layout/files/src/app/app-navigation.ts index 30dda8ae5..af9c63786 100644 --- a/packages/devextreme-schematics/src/add-layout/files/src/app/app-navigation.ts +++ b/packages/devextreme-schematics/src/add-layout/files/src/app/app-navigation.ts @@ -1 +1,3 @@ -export const navigation = []; +type NavigationItem = { path?: string, text: string, icon?: string, items?: NavigationItem[] }; +export const navigation: NavigationItem[] = []; + diff --git a/packages/devextreme-schematics/src/add-layout/index.ts b/packages/devextreme-schematics/src/add-layout/index.ts index 85fca74b3..7810eefd4 100644 --- a/packages/devextreme-schematics/src/add-layout/index.ts +++ b/packages/devextreme-schematics/src/add-layout/index.ts @@ -44,7 +44,8 @@ import { import { NodeDependencyType, - addPackageJsonDependency + addPackageJsonDependency, + getPackageJsonDependency, } from '@schematics/angular/utility/dependencies'; import { getSourceFile } from '../utility/source'; @@ -173,6 +174,28 @@ async function updateBudgets(host: Tree, options: any) { return host; } +async function addPolyfills(host: Tree, project: string, polyfills: string[]) { + const projectName = await getProjectName(host, project); + + modifyJSONFile(host, './angular.json', config => { + const buildOptions: Record = config.projects[projectName]['architect']['build']['options']; + + if (!buildOptions.polyfills) { + buildOptions.polyfills = []; + } + + polyfills.forEach((polyfill) => { + if (!buildOptions.polyfills.includes(polyfill)) { + buildOptions.polyfills.push(polyfill); + } + }); + + return config; + }); + + return host; +} + function addViewportToBody(sourcePath: string = '') { return (host: Tree) => { const indexPath = join(sourcePath, 'index.html'); @@ -199,8 +222,8 @@ function modifyFileRule(path: string, callback: (source: SourceFile) => Change[] }; } -function updateAppComponent(host: Tree, sourcePath: string, templateOptions: any = {}) { - const appMComponentPath = sourcePath + (isAngularVersionHigherThan(host, 20) ? 'app.ts' : 'app.component.ts'); +function updateAppComponent(sourcePath: string, templateOptions: any = {}) { + const appMComponentPath = sourcePath + templateOptions.name + '.ts'; const importSetter = (importName: string, path: string, alias: string) => { return (source: SourceFile) => { @@ -250,13 +273,25 @@ function hasRouting(host: Tree, sourcePath: string) { function addPackagesToDependency(globalNgCliVersion: string) { const version = new SemVer(globalNgCliVersion.replace(/\^|\~/g, '')); + return (host: Tree) => { + const zonejs = getPackageJsonDependency(host, 'zone.js'); + addPackageJsonDependency(host, { type: NodeDependencyType.Default, name: '@angular/cdk', - version: `~${version.major}.${version.minor}.0` + version: version.raw.includes('next') || version.raw.includes('-rc') + ? 'next' : `^${version.major}.0.0` }); + if (!zonejs) { + addPackageJsonDependency(host, { + type: NodeDependencyType.Default, + name: 'zone.js', + version: version.major > 18 ? '~0.15.0' : '~0.14.0' + }); + } + return host; }; } @@ -389,11 +424,12 @@ export default function(options: any): Rule { const rules = [ modifyContentByTemplate(sourcePath, projectFilesSource, null, templateOptions, modifyContent), updateDevextremeConfig(sourcePath), - updateAppComponent(host, appPath, templateOptions), + updateAppComponent(appPath, templateOptions), addBuildThemeScript(), () => addCustomThemeStyles(host, options, sourcePath) as any, addViewportToBody(sourcePath), - addPackagesToDependency(options.globalNgCliVersion) + addPackagesToDependency(options.globalNgCliVersion), + () => addPolyfills(host, options.project, ['zone.js']) ]; if (options.updateBudgets) { diff --git a/packages/devextreme-schematics/src/add-layout/index_spec.ts b/packages/devextreme-schematics/src/add-layout/index_spec.ts index d22f07c93..e15c91411 100644 --- a/packages/devextreme-schematics/src/add-layout/index_spec.ts +++ b/packages/devextreme-schematics/src/add-layout/index_spec.ts @@ -174,7 +174,7 @@ describe('layout', () => { const tree = await runner.runSchematic('add-layout', options, appTree); const packageConfig = JSON.parse(tree.readContent('package.json')); - expect(packageConfig.dependencies['@angular/cdk']).toBe('~17.2.0'); + expect(packageConfig.dependencies['@angular/cdk']).toBe('^17.0.0'); }); it('should update budgets if updateBudgets option is true', async () => { diff --git a/packages/devextreme-schematics/src/add-sample-views/index_spec.ts b/packages/devextreme-schematics/src/add-sample-views/index_spec.ts index cea2ce4eb..26370c427 100644 --- a/packages/devextreme-schematics/src/add-sample-views/index_spec.ts +++ b/packages/devextreme-schematics/src/add-sample-views/index_spec.ts @@ -49,7 +49,9 @@ describe('sample views', () => { const navigationContent = tree.readContent('/src/app/app-navigation.ts'); expect(navigationContent).toMatch(/text: 'Home'/); - expect(navigationContent).toContain(`export const navigation = [ + expect(navigationContent).toContain( + `type NavigationItem = { path?: string, text: string, icon?: string, items?: NavigationItem[] }; +export const navigation: NavigationItem[] = [ { text: 'Home', path: '/home', diff --git a/packages/devextreme-schematics/src/add-view/index_spec.ts b/packages/devextreme-schematics/src/add-view/index_spec.ts index d9f3a7877..8d057ae16 100644 --- a/packages/devextreme-schematics/src/add-view/index_spec.ts +++ b/packages/devextreme-schematics/src/add-view/index_spec.ts @@ -117,7 +117,9 @@ describe('view', () => { expect(moduleContent).toMatch(/text: 'Test'/); expect(moduleContent).toMatch(/icon: 'folder'/); - expect(moduleContent).toContain(`navigation = [ + expect(moduleContent).toContain( + `type NavigationItem = { path?: string, text: string, icon?: string, items?: NavigationItem[] }; +export const navigation: NavigationItem[] = [ { text: 'Test', path: '/pages/test', diff --git a/packages/devextreme-schematics/src/utility/change.ts b/packages/devextreme-schematics/src/utility/change.ts index 2145d24f6..09b4303b6 100644 --- a/packages/devextreme-schematics/src/utility/change.ts +++ b/packages/devextreme-schematics/src/utility/change.ts @@ -36,14 +36,19 @@ export function insertItemToArray( const nodeContent = node.getText(); const nodePosition = node.getStart(); - const leftBracketPosition = nodePosition + nodeContent.indexOf('['); + const leftBracketPosition = nodePosition + nodeContent.indexOf('[', nodeContent.lastIndexOf('=') || 0); const rightBracketPosition = nodePosition + nodeContent.lastIndexOf(']'); let itemPosition = leftBracketPosition + 1; let fileRecorder = host.beginUpdate(filePath); item = newLine + item; - const isNodeEmpty = !/\[[\s\S]*\S+[\s\S]*\]/m.test(nodeContent); + const isNodeEmpty = !( + nodeContent.includes('=') + ? /=\s*\[[\s\S]*\S+[\s\S]*\]/m + : /\[[\s\S]*\S+[\s\S]*\]/m + ).test(nodeContent); + if (isNodeEmpty) { const formattedArray = `[${newLine}]`; fileRecorder.remove(leftBracketPosition, rightBracketPosition - leftBracketPosition + 1);