diff --git a/apps/vscode/src/main.ts b/apps/vscode/src/main.ts index ce6543bb79..8c1f076134 100644 --- a/apps/vscode/src/main.ts +++ b/apps/vscode/src/main.ts @@ -44,18 +44,12 @@ import { NxProjectTreeItem, NxProjectTreeProvider, } from '@nx-console/vscode/nx-project-view'; -import { - getNxConfig, - verifyWorkspace, - WorkspaceCodeLensProvider, -} from '@nx-console/vscode/nx-workspace'; import { environment } from './environments/environment'; import { WorkspaceJsonSchema, ProjectJsonSchema, } from '@nx-console/vscode/json-schema'; -import { GeneratorType } from '@nx-console/schema'; let runTargetTreeView: TreeView; let nxProjectTreeView: TreeView; @@ -68,7 +62,7 @@ let cliTaskProvider: CliTaskProvider; let context: ExtensionContext; let workspaceFileWatcher: FileSystemWatcher | undefined; -export function activate(c: ExtensionContext) { +export async function activate(c: ExtensionContext) { try { const startTime = Date.now(); context = c; @@ -131,6 +125,9 @@ export function activate(c: ExtensionContext) { ); // registers itself as a CodeLensProvider and watches config to dispose/re-register + const { WorkspaceCodeLensProvider } = await import( + '@nx-console/vscode/nx-workspace' + ); new WorkspaceCodeLensProvider(context); new WorkspaceJsonSchema(context); new ProjectJsonSchema(context); @@ -213,8 +210,9 @@ async function setWorkspace(workspaceJsonPath: string) { 'nxWorkspaceJsonPath', workspaceJsonPath ); + const { verifyWorkspace } = await import('@nx-console/vscode/nx-workspace'); - const { validWorkspaceJson } = verifyWorkspace(); + const { validWorkspaceJson } = await verifyWorkspace(); if (!validWorkspaceJson) { return; } @@ -277,7 +275,8 @@ async function setWorkspace(workspaceJsonPath: string) { } async function setApplicationAndLibraryContext(workspaceJsonPath: string) { - const nxConfig = getNxConfig(dirname(workspaceJsonPath)); + const { getNxConfig } = await import('@nx-console/vscode/nx-workspace'); + const nxConfig = await getNxConfig(dirname(workspaceJsonPath)); commands.executeCommand('setContext', 'nxAppsDir', [ join( diff --git a/apps/vscode/webpack.prod.config.js b/apps/vscode/webpack.prod.config.js new file mode 100644 index 0000000000..0d91435d20 --- /dev/null +++ b/apps/vscode/webpack.prod.config.js @@ -0,0 +1,14 @@ +module.exports = function transformWebpack(config) { + // the default node webpack config has minimize: false when optimization is set to true + config.output.filename = '[name].js'; + config.optimization = { + minimize: true, + concatenateModules: true, + sideEffects: false, + splitChunks: { + chunks: 'all', + }, + }; + + return config; +}; diff --git a/libs/server/src/lib/abstract-tree-provider.ts b/libs/server/src/lib/abstract-tree-provider.ts index a5f87bf931..9510401d53 100644 --- a/libs/server/src/lib/abstract-tree-provider.ts +++ b/libs/server/src/lib/abstract-tree-provider.ts @@ -7,12 +7,12 @@ import { } from 'vscode'; export abstract class AbstractTreeProvider - implements TreeDataProvider { - private readonly _onDidChangeTreeData: EventEmitter< - Item | undefined - > = new EventEmitter(); - readonly onDidChangeTreeData: Event = this - ._onDidChangeTreeData.event; + implements TreeDataProvider +{ + private readonly _onDidChangeTreeData: EventEmitter = + new EventEmitter(); + readonly onDidChangeTreeData: Event = + this._onDidChangeTreeData.event; refresh(): void { this._onDidChangeTreeData.fire(undefined); @@ -22,7 +22,6 @@ export abstract class AbstractTreeProvider return element; } - abstract getParent(element: Item): Item | null | undefined; - + abstract getParent(element: Item): ProviderResult; abstract getChildren(element?: Item): ProviderResult; } diff --git a/libs/vscode/nx-project-view/src/lib/nx-project-tree-provider.ts b/libs/vscode/nx-project-view/src/lib/nx-project-tree-provider.ts index 2530bb49c4..111147ab73 100644 --- a/libs/vscode/nx-project-view/src/lib/nx-project-tree-provider.ts +++ b/libs/vscode/nx-project-view/src/lib/nx-project-tree-provider.ts @@ -38,7 +38,9 @@ export class NxProjectTreeProvider extends AbstractTreeProvider { const { project, target } = element.nxProject; if (target) { @@ -55,7 +57,7 @@ export class NxProjectTreeProvider extends AbstractTreeProvider { + async getChildren( + parent?: NxProjectTreeItem + ): Promise { if (!parent) { - const projects = this.cliTaskProvider.getProjectEntries(); - return projects.map( - ([name, def]): NxProjectTreeItem => - this.createNxProjectTreeItem( - { project: name }, - name, - Boolean(def.targets) - ) + const projects = await this.cliTaskProvider.getProjectEntries(); + return Promise.all( + projects.map( + async ([name, def]): Promise => + this.createNxProjectTreeItem( + { project: name }, + name, + Boolean(def.targets) + ) + ) ); } const { nxProject } = parent; const { target, project } = nxProject; - const projectDef = this.cliTaskProvider.getProjects()[project]; + const projectDef = (await this.cliTaskProvider.getProjects())[project]; if (!projectDef) { return; @@ -106,13 +113,15 @@ export class NxProjectTreeProvider extends AbstractTreeProvider - this.createNxProjectTreeItem( - { target: { name }, project }, - name, - Boolean(projectDef.targets?.[name].configurations) - ) + return Promise.all( + Object.keys(projectDef.targets).map( + async (name): Promise => + this.createNxProjectTreeItem( + { target: { name }, project }, + name, + Boolean(projectDef.targets?.[name].configurations) + ) + ) ); } } else { @@ -129,14 +138,14 @@ export class NxProjectTreeProvider extends AbstractTreeProvider { - const item = this.createNxProjectTreeItem( - { target: { ...target, configuration: name }, project }, - name - ); - - return item; - }); + return Promise.all( + Object.keys(configurations).map(async (name) => + this.createNxProjectTreeItem( + { target: { ...target, configuration: name }, project }, + name + ) + ) + ); } } diff --git a/libs/vscode/nx-workspace/src/lib/get-nx-config.ts b/libs/vscode/nx-workspace/src/lib/get-nx-config.ts index c8a5cdbc9e..f603939220 100644 --- a/libs/vscode/nx-workspace/src/lib/get-nx-config.ts +++ b/libs/vscode/nx-workspace/src/lib/get-nx-config.ts @@ -3,12 +3,14 @@ import { NxJsonConfiguration } from '@nrwl/devkit'; import { join } from 'path'; import { getNxWorkspacePackageFileUtils } from './get-nx-workspace-package'; -export function getNxConfig(baseDir: string): NxJsonConfiguration { +export async function getNxConfig( + baseDir: string +): Promise { try { let cachedNxJson = cacheJson('nx.json', baseDir).json; if (!cachedNxJson) { - const nxJson = getNxWorkspacePackageFileUtils().readNxJson( + const nxJson = (await getNxWorkspacePackageFileUtils()).readNxJson( join(baseDir, 'nx.json') ); diff --git a/libs/vscode/nx-workspace/src/lib/get-nx-workspace-config.ts b/libs/vscode/nx-workspace/src/lib/get-nx-workspace-config.ts index 363ff43de0..2fb321ce61 100644 --- a/libs/vscode/nx-workspace/src/lib/get-nx-workspace-config.ts +++ b/libs/vscode/nx-workspace/src/lib/get-nx-workspace-config.ts @@ -2,18 +2,20 @@ import { readAndCacheJsonFile, cacheJson } from '@nx-console/server'; import { getNxWorkspacePackageFileUtils } from './get-nx-workspace-package'; import type { WorkspaceJsonConfiguration } from '@nrwl/devkit'; -export function getNxWorkspaceConfig( +export async function getNxWorkspaceConfig( basedir: string, workspaceJsonPath: string -): WorkspaceJsonConfiguration { +): Promise { // try and use the workspace version of nx try { let cachedWorkspaceJson = cacheJson(workspaceJsonPath).json; if (!cachedWorkspaceJson) { - const workspace = getNxWorkspacePackageFileUtils().readWorkspaceConfig({ + const workspace = ( + await getNxWorkspacePackageFileUtils() + ).readWorkspaceConfig({ format: 'nx', path: basedir, - } as any); + }); cachedWorkspaceJson = cacheJson(workspaceJsonPath, '', workspace).json; } return cachedWorkspaceJson; diff --git a/libs/vscode/nx-workspace/src/lib/get-nx-workspace-package.ts b/libs/vscode/nx-workspace/src/lib/get-nx-workspace-package.ts index 782073f62a..60020658a0 100644 --- a/libs/vscode/nx-workspace/src/lib/get-nx-workspace-package.ts +++ b/libs/vscode/nx-workspace/src/lib/get-nx-workspace-package.ts @@ -1,24 +1,35 @@ import { WorkspaceConfigurationStore } from '@nx-console/vscode/configuration'; import { dirname, join } from 'path'; -import type * as NxWorkspacePackage from '@nrwl/workspace'; +import * as NxWorkspaceFileUtils from '@nrwl/workspace/src/core/file-utils'; +import { getOutputChannel } from '@nx-console/server'; + /** * Get the local installed version of @nrwl/workspace */ -export function getNxWorkspacePackageFileUtils(): typeof NxWorkspacePackage { +export async function getNxWorkspacePackageFileUtils(): Promise< + typeof NxWorkspaceFileUtils +> { const workspacePath = dirname( WorkspaceConfigurationStore.instance.get('nxWorkspaceJsonPath', '') ); - // webpack hacks.. - return eval('require')( - join( - workspacePath, - 'node_modules', - '@nrwl', - 'workspace', - 'src', - 'core', - 'file-utils' - ) - ); + try { + return import( + /*webpackIgnore: true*/ + join( + workspacePath, + 'node_modules', + '@nrwl', + 'workspace', + 'src', + 'core', + 'file-utils' + ) + ); + } catch (err) { + getOutputChannel().appendLine( + `Error loading @nrwl/workspace from workspace. Falling back to extension dependency` + ); + return NxWorkspaceFileUtils; + } } diff --git a/libs/vscode/nx-workspace/src/lib/verify-workspace.ts b/libs/vscode/nx-workspace/src/lib/verify-workspace.ts index 248d6b7e07..abcb749e03 100644 --- a/libs/vscode/nx-workspace/src/lib/verify-workspace.ts +++ b/libs/vscode/nx-workspace/src/lib/verify-workspace.ts @@ -10,12 +10,12 @@ import { WorkspaceConfigurationStore } from '@nx-console/vscode/configuration'; import { WorkspaceJsonConfiguration } from '@nrwl/devkit'; import { getNxWorkspaceConfig } from './get-nx-workspace-config'; -export function verifyWorkspace(): { +export async function verifyWorkspace(): Promise<{ validWorkspaceJson: boolean; json: WorkspaceJsonConfiguration; workspaceType: 'ng' | 'nx'; configurationFilePath: string; -} { +}> { const workspacePath = dirname( WorkspaceConfigurationStore.instance.get('nxWorkspaceJsonPath', '') ); @@ -29,7 +29,7 @@ export function verifyWorkspace(): { validWorkspaceJson: true, // TODO(cammisuli): change all instances to use the new version - basically reverse this to the new format json: toWorkspaceFormat( - getNxWorkspaceConfig(workspacePath, workspaceJsonPath) + await getNxWorkspaceConfig(workspacePath, workspaceJsonPath) ), workspaceType: 'nx', configurationFilePath: workspaceJsonPath, @@ -38,7 +38,7 @@ export function verifyWorkspace(): { return { validWorkspaceJson: true, json: toWorkspaceFormat( - getNxWorkspaceConfig(workspacePath, angularJsonPath) + await getNxWorkspaceConfig(workspacePath, angularJsonPath) ), workspaceType: 'ng', configurationFilePath: angularJsonPath, diff --git a/libs/vscode/nx-workspace/src/lib/workspace-codelens-provider.ts b/libs/vscode/nx-workspace/src/lib/workspace-codelens-provider.ts index aac10961ea..ebb4d9f86c 100644 --- a/libs/vscode/nx-workspace/src/lib/workspace-codelens-provider.ts +++ b/libs/vscode/nx-workspace/src/lib/workspace-codelens-provider.ts @@ -47,7 +47,9 @@ export class WorkspaceCodeLensProvider implements CodeLensProvider { * @param document a document matched by the pattern passed to registerCodeLensProvider * @returns ProjectCodeLens Range locations and properties for the document */ - provideCodeLenses(document: TextDocument): CodeLens[] | undefined { + async provideCodeLenses( + document: TextDocument + ): Promise { const lens: CodeLens[] = []; let projectName = ''; @@ -71,7 +73,7 @@ export class WorkspaceCodeLensProvider implements CodeLensProvider { } const projectLocations = getProjectLocations(document, projectName); - const { validWorkspaceJson, workspaceType } = verifyWorkspace(); + const { validWorkspaceJson, workspaceType } = await verifyWorkspace(); if (!validWorkspaceJson) { return; } @@ -163,9 +165,10 @@ export class WorkspaceCodeLensProvider implements CodeLensProvider { GlobalConfigurationStore.configurationSection ); if (affectsNxConsoleConfig) { - const enableWorkspaceConfigCodeLens = GlobalConfigurationStore.instance.get( - 'enableWorkspaceConfigCodeLens' - ); + const enableWorkspaceConfigCodeLens = + GlobalConfigurationStore.instance.get( + 'enableWorkspaceConfigCodeLens' + ); if (enableWorkspaceConfigCodeLens && !this.codeLensProvider) { this.registerWorkspaceCodeLensProvider(this.context); } else if (!enableWorkspaceConfigCodeLens && this.codeLensProvider) { diff --git a/libs/vscode/tasks/src/lib/cli-task-commands.ts b/libs/vscode/tasks/src/lib/cli-task-commands.ts index 250c969038..ea1473eaca 100644 --- a/libs/vscode/tasks/src/lib/cli-task-commands.ts +++ b/libs/vscode/tasks/src/lib/cli-task-commands.ts @@ -61,8 +61,8 @@ export function registerCliTaskCommands( ); } ); - commands.registerCommand(`${cli}.run.fileexplorer`, (uri: Uri) => - selectCliCommandAndPromptForFlags('run', getCliProjectFromUri(uri)) + commands.registerCommand(`${cli}.run.fileexplorer`, async (uri: Uri) => + selectCliCommandAndPromptForFlags('run', await getCliProjectFromUri(uri)) ); commands.registerCommand(`${cli}.generate`, () => @@ -118,7 +118,7 @@ export function registerCliTaskCommands( }); } -function selectCliCommandAndShowUi( +async function selectCliCommandAndShowUi( command: string, extensionPath: string, uri?: Uri, @@ -131,7 +131,7 @@ function selectCliCommandAndShowUi( ); return; } - const { validWorkspaceJson, configurationFilePath } = verifyWorkspace(); + const { validWorkspaceJson, configurationFilePath } = await verifyWorkspace(); if (!validWorkspaceJson) { window.showErrorMessage('Invalid configuration file'); return; @@ -163,7 +163,7 @@ async function selectCliCommandAndPromptForFlags( // don't prompt for flags when project and target are already specified flags = []; } - const { validWorkspaceJson, json, workspaceType } = verifyWorkspace(); + const { validWorkspaceJson, json, workspaceType } = await verifyWorkspace(); if (!projectName) { const selection = validWorkspaceJson @@ -237,7 +237,7 @@ async function selectCliCommandAndPromptForFlags( async function selectGeneratorAndPromptForFlags() { const { validWorkspaceJson, workspaceType, configurationFilePath } = - verifyWorkspace(); + await verifyWorkspace(); if (!validWorkspaceJson) { return; @@ -263,17 +263,18 @@ async function selectGeneratorAndPromptForFlags() { } } -export function getCliProjectFromUri(uri: Uri): string | undefined { - const project = cliTaskProvider.projectForPath(uri.fsPath); +export async function getCliProjectFromUri( + uri: Uri +): Promise { + const project = await cliTaskProvider.projectForPath(uri.fsPath); return project?.name; } -export function selectCliProject( +export async function selectCliProject( command: string, json: WorkspaceJsonConfiguration ) { - const items = cliTaskProvider - .getProjectEntries(json) + const items = (await cliTaskProvider.getProjectEntries(json)) .filter(([, { targets }]) => Boolean(targets)) .flatMap(([project, { targets }]) => ({ project, targets })) .filter( diff --git a/libs/vscode/tasks/src/lib/cli-task-provider.ts b/libs/vscode/tasks/src/lib/cli-task-provider.ts index 116b25cb11..e554c806dd 100644 --- a/libs/vscode/tasks/src/lib/cli-task-provider.ts +++ b/libs/vscode/tasks/src/lib/cli-task-provider.ts @@ -115,11 +115,11 @@ export class CliTaskProvider implements TaskProvider { }); } - getProjects(json?: WorkspaceJsonConfiguration) { + async getProjects(json?: WorkspaceJsonConfiguration) { if (json) { return json.projects; } else { - const result = verifyWorkspace(); + const result = await verifyWorkspace(); if (!result.validWorkspaceJson || !result.json) { return {}; } else { @@ -128,18 +128,18 @@ export class CliTaskProvider implements TaskProvider { } } - getProjectNames(): string[] { - return Object.keys(this.getProjects() || {}); + async getProjectNames(): Promise { + return Object.keys((await this.getProjects()) || {}); } - getProjectEntries(json?: WorkspaceJsonConfiguration) { - return Object.entries(this.getProjects(json) || {}); + async getProjectEntries(json?: WorkspaceJsonConfiguration) { + return Object.entries((await this.getProjects(json)) || {}); } - projectForPath(selectedPath: string) { + async projectForPath(selectedPath: string) { if (!this.getWorkspaceJsonPath()) return null; - const entry = this.getProjectEntries().find(([, def]) => { + const entry = (await this.getProjectEntries()).find(([, def]) => { const fullProjectPath = join(this.getWorkspacePath(), def.root); if (fullProjectPath === selectedPath) { return true; diff --git a/libs/vscode/tasks/src/lib/nx-task-commands.ts b/libs/vscode/tasks/src/lib/nx-task-commands.ts index 315af73300..282ca59828 100644 --- a/libs/vscode/tasks/src/lib/nx-task-commands.ts +++ b/libs/vscode/tasks/src/lib/nx-task-commands.ts @@ -48,7 +48,7 @@ export function registerNxCommands( } async function promptForTarget(): Promise { - const { validWorkspaceJson, json } = verifyWorkspace(); + const { validWorkspaceJson, json } = await verifyWorkspace(); if (!validWorkspaceJson || !json) { return; @@ -259,7 +259,7 @@ async function promptForRunMany() { } let options = RUN_MANY_OPTIONS; - const projects = validProjectsForTarget(target); + const projects = await validProjectsForTarget(target); if (projects && projects.length) { options = [ { @@ -331,8 +331,10 @@ async function promptForMigrate() { tasks.executeTask(task); } -function validProjectsForTarget(target: string): string[] | undefined { - const { validWorkspaceJson, json } = verifyWorkspace(); +async function validProjectsForTarget( + target: string +): Promise { + const { validWorkspaceJson, json } = await verifyWorkspace(); if (!validWorkspaceJson || !json) { return; diff --git a/libs/vscode/webview/src/lib/get-task-execution-schema.ts b/libs/vscode/webview/src/lib/get-task-execution-schema.ts index ddc43668f0..25631f1348 100644 --- a/libs/vscode/webview/src/lib/get-task-execution-schema.ts +++ b/libs/vscode/webview/src/lib/get-task-execution-schema.ts @@ -25,7 +25,7 @@ export async function getTaskExecutionSchema( if (!cliTaskProvider.getWorkspacePath()) { return; } - const { validWorkspaceJson, json, workspaceType } = verifyWorkspace(); + const { validWorkspaceJson, json, workspaceType } = await verifyWorkspace(); if (!validWorkspaceJson) { return; @@ -64,8 +64,7 @@ export async function getTaskExecutionSchema( }; } case 'Run': { - const runnableItems = cliTaskProvider - .getProjectEntries() + const runnableItems = (await cliTaskProvider.getProjectEntries()) .filter(([, { targets }]) => Boolean(targets)) .flatMap(([project, { targets }]) => ({ project, targets })) .flatMap(({ project, targets }) => [ @@ -113,39 +112,39 @@ export async function getTaskExecutionSchema( }); } case 'Generate': { - return selectGenerator( + const generator = await selectGenerator( cliTaskProvider.getWorkspaceJsonPath(), generatorType - ).then((generator) => { - if (!generator) { - return; + ); + + if (!generator) { + return; + } + + for (const option of generator.options) { + // TODO: mixup between items and enum has been a source for recent bugs, + // util.ts normalizeSchema sets items from enum. + if (option.enum) { + continue; } - generator.options.forEach((option) => { - // TODO: mixup between items and enum has been a source for recent bugs, - // util.ts normalizeSchema sets items from enum. - if (option.enum) { - return; - } - - if (isProjectOption(option)) { - option.enum = option.items = cliTaskProvider - .getProjectEntries() - .map((entry) => entry[0]) - .sort(); - } - }); - - const contextValues = contextMenuUri - ? getConfigValuesFromContextMenuUri( - generator, - contextMenuUri, - cliTaskProvider - ) - : undefined; + if (isProjectOption(option)) { + const projects = await cliTaskProvider.getProjectEntries(); + option.enum = option.items = projects + .map((entry) => entry[0]) + .sort(); + } + } - return { ...generator, cliName: workspaceType, contextValues }; - }); + const contextValues = contextMenuUri + ? await getConfigValuesFromContextMenuUri( + generator, + contextMenuUri, + cliTaskProvider + ) + : undefined; + + return { ...generator, cliName: workspaceType, contextValues }; } } } catch (e) { @@ -167,20 +166,21 @@ export async function getTaskExecutionSchema( } // Get information about where the user clicked if invoked through right click in the explorer context menu -function getConfigValuesFromContextMenuUri( +async function getConfigValuesFromContextMenuUri( generator: TaskExecutionSchema, contextMenuUri: Uri | undefined, cliTaskProvider: CliTaskProvider -): +): Promise< | { path?: string; directory?: string; project?: string; projectName?: string; } - | undefined { + | undefined +> { if (contextMenuUri) { - const project = cliTaskProvider.projectForPath(contextMenuUri.fsPath); + const project = await cliTaskProvider.projectForPath(contextMenuUri.fsPath); const projectName = (project && project.name) || undefined; const workspacePath = cliTaskProvider.getWorkspacePath(); @@ -188,7 +188,7 @@ function getConfigValuesFromContextMenuUri( .replace(workspacePath, '') .replace(/\\/g, '/') .replace(/^\//, ''); - const nxConfig = getNxConfig(workspacePath); + const nxConfig = await getNxConfig(workspacePath); const appsDir = nxConfig.workspaceLayout?.appsDir ?? 'apps'; const libsDir = nxConfig.workspaceLayout?.libsDir ?? 'libs'; if ( diff --git a/package-scripts.js b/package-scripts.js index 1118d19008..e27b40bb84 100644 --- a/package-scripts.js +++ b/package-scripts.js @@ -28,7 +28,7 @@ module.exports = { }, vscode: { build: nps.series.nps('prepare.vscode.server', 'prepare.vscode.client'), - server: 'nx build vscode-app --prod --noSourceMap', + server: 'nx build vscode-app --prod', client: 'nx build vscode-ui --prod', }, ci: { diff --git a/package.json b/package.json index 6eb329a255..3765a5a78c 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "nx-console", "version": "17.10.0", "publisher": "nrwl", + "sideEffects": false, "author": { "name": "Narwhal Technologies Inc", "email": "hello@nrwl.io" diff --git a/workspace.json b/workspace.json index f206b44d00..8752c90cc7 100644 --- a/workspace.json +++ b/workspace.json @@ -129,7 +129,8 @@ "replace": "apps/vscode/src/environments/environment.ts", "with": "apps/vscode/src/environments/environment.prod.ts" } - ] + ], + "webpackConfig": "apps/vscode/webpack.prod.config.js" } }, "outputs": ["{options.outputPath}"]