Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,6 @@ storybook-static
.cursor/rules/nx-rules.mdc
.github/instructions/nx.instructions.md
.nx/polygraph/

.nx/polygraph
.nx/self-healing
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ apps/intellij/*
!apps/intellij/project.json

/.nx/cache
/.nx/workspace-data
/.nx/workspace-data
.nx/self-healing
2 changes: 1 addition & 1 deletion apps/intellij/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ val nxlsRoot = "${rootDir}/dist/apps/nxls"
layout.buildDirectory = file("${rootDir}/dist/apps/intellij")

plugins {
id("dev.nx.gradle.project-graph") version ("0.1.12")
id("dev.nx.gradle.project-graph") version ("0.1.20")
id("java")
id("org.jetbrains.changelog") version "2.4.0"
id("org.jetbrains.intellij.platform") version "2.11.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
NxGeneratorOptionsRequest,
NxGeneratorOptionsRequestOptions,
} from '@nx-console/language-server-types';
import {
e2eCwd,
newWorkspace,
simpleReactWorkspaceOptions,
uniq,
} from '@nx-console/shared-e2e-utils';
import { Option } from '@nx-console/shared-schema';
import { readFileSync } from 'fs';
import { join } from 'path';
import { NxlsWrapper } from '../nxls-wrapper';

const nxVersion = '22.7.0-beta.17';
const workspaceName = uniq('workspace');
const workspacePath = join(e2eCwd, workspaceName);
const convertToSwcSchemaPath = join(
workspacePath,
'node_modules',
'@nx',
'js',
'src',
'generators',
'convert-to-swc',
'schema.json',
);

let nxlsWrapper: NxlsWrapper;

describe(`generator options - nx ${nxVersion}`, () => {
beforeAll(async () => {
newWorkspace({
name: workspaceName,
options: simpleReactWorkspaceOptions,
version: nxVersion,
});

nxlsWrapper = new NxlsWrapper();
await nxlsWrapper.startNxls(workspacePath);
});

afterAll(async () => {
return await nxlsWrapper.stopNxls(nxVersion);
});

it('should clear unsupported JSON schema items objects from normalized options', async () => {
const schema = JSON.parse(readFileSync(convertToSwcSchemaPath, 'utf-8'));
expect(Array.isArray(schema.properties.targets.items)).toBe(false);
expect(schema.properties.targets.items).toMatchObject({
type: 'string',
});

const generatorOptions = await nxlsWrapper.sendRequest({
...NxGeneratorOptionsRequest,
params: {
options: {
collection: '@nx/js',
name: 'convert-to-swc',
path: convertToSwcSchemaPath,
} satisfies NxGeneratorOptionsRequestOptions,
},
});
const options = generatorOptions.result as Option[];

const targetsOption = options.find((option) => option.name === 'targets');
expect(targetsOption).toBeDefined();
expect(targetsOption?.type).toEqual('array');
expect(targetsOption?.default).toEqual(['build']);
expect(targetsOption?.items).toBeUndefined();
});
});
2 changes: 1 addition & 1 deletion apps/nxls/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
WatcherStatus,
} from '@nx-console/shared-watcher';
import type { ProjectGraph } from 'nx/src/devkit-exports';
import type { ConfigurationSourceMaps } from 'nx/src/project-graph/utils/project-configuration-utils';
import type { ConfigurationSourceMaps } from 'nx/src/project-graph/utils/project-configuration/source-maps';
import { ClientCapabilities, TextDocument } from 'vscode-json-languageservice';
import {
CreateFilesParams,
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ group = "dev.nx.console"
layout.buildDirectory = File("dist")

plugins {
id("dev.nx.gradle.project-graph") version "0.1.12"
id("dev.nx.gradle.project-graph") version "0.1.20"
id("com.ncorti.ktfmt.gradle") version "0.24.0"

id("org.jetbrains.kotlin.jvm") version "2.2.0"
Expand Down
13 changes: 8 additions & 5 deletions libs/language-server/workspace/src/lib/get-pdv-data.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { directoryExists } from '@nx-console/shared-file-system';
import { workspaceDependencyPath } from '@nx-console/shared-npm';
import { findNxPackagePath } from '@nx-console/shared-npm';
import { gte } from '@nx-console/nx-version';
import { PDVData } from '@nx-console/shared-types';
import type {
ProjectConfiguration,
ProjectGraphProjectNode,
} from 'nx/src/devkit-exports';
import { join, relative } from 'path';
import { dirname, join, relative } from 'path';
import { getNxCloudStatus } from './get-nx-cloud-status';
import {
getNxVersion,
Expand Down Expand Up @@ -139,13 +139,16 @@ export async function getPDVData(
async function getGraphBasePath(
workspacePath: string,
): Promise<string | undefined> {
const nxWorkspaceDepPath = await workspaceDependencyPath(workspacePath, 'nx');
const graphIndexPath = await findNxPackagePath(
workspacePath,
join('src', 'core', 'graph', 'index.html'),
);

if (!nxWorkspaceDepPath) {
if (!graphIndexPath) {
return undefined;
}

const graphBasePath = join(nxWorkspaceDepPath, 'src', 'core', 'graph');
const graphBasePath = dirname(graphIndexPath);

if (await directoryExists(graphBasePath)) {
return graphBasePath;
Expand Down
27 changes: 20 additions & 7 deletions libs/shared/npm/src/lib/find-nx-package-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ export async function findNxPackagePath(
workspacePath: string,
filePath: string,
): Promise<string | undefined> {
const buildPath = (base: string) => join(base, filePath);
const nxPathVariants = getNxPathVariants(filePath);
const buildPaths = (base: string) =>
nxPathVariants.map((path) => join(base, path));

const nxWorkspaceDepPath = await workspaceDependencyPath(workspacePath, 'nx');
if (nxWorkspaceDepPath) {
const path = buildPath(nxWorkspaceDepPath);
if (await fileExists(path)) {
return path;
for (const path of buildPaths(nxWorkspaceDepPath)) {
if (await fileExists(path)) {
return path;
}
}
}

Expand All @@ -31,13 +34,23 @@ export async function findNxPackagePath(
'@nrwl/workspace',
);
if (nrwlWorkspaceDepPath) {
const path = buildPath(nrwlWorkspaceDepPath);
if (await fileExists(path)) {
return path;
for (const path of buildPaths(nrwlWorkspaceDepPath)) {
if (await fileExists(path)) {
return path;
}
}
}
}

function getNxPathVariants(filePath: string): string[] {
const srcPrefix = `src${platform() === 'win32' ? '\\' : '/'}`;
if (filePath === 'src' || filePath.startsWith(srcPrefix)) {
return [filePath, join('dist', filePath)];
}

return [filePath];
}

/**
* Finds the nx executable binary in the workspace.
*
Expand Down
22 changes: 12 additions & 10 deletions libs/shared/npm/src/lib/local-nx-utils/cache-dir.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { join } from 'path';
import {
importWorkspaceDependency,
workspaceDependencyPath,
} from '../workspace-dependencies';
import { findNxPackagePath } from '../find-nx-package-path';
import { importWorkspaceDependency } from '../workspace-dependencies';

export async function getCacheDir(workspacePath: string): Promise<string> {
const nxPath = await workspaceDependencyPath(workspacePath, 'nx');
if (!nxPath) {
const importPath = await findNxPackagePath(
workspacePath,
join('src', 'utils', 'cache-directory.js'),
);
if (!importPath) {
throw 'local nx dependency not found';
}
const importPath = join(nxPath, 'src/utils/cache-directory');
const { cacheDir } =
await importWorkspaceDependency<
typeof import('nx/src/utils/cache-directory')
Expand All @@ -20,11 +20,13 @@ export async function getCacheDir(workspacePath: string): Promise<string> {
export async function getWorkspaceDataDirectory(
workspacePath: string,
): Promise<string> {
const nxPath = await workspaceDependencyPath(workspacePath, 'nx');
if (!nxPath) {
const importPath = await findNxPackagePath(
workspacePath,
join('src', 'utils', 'cache-directory.js'),
);
if (!importPath) {
throw 'local nx dependency not found';
}
const importPath = join(nxPath, 'src/utils/cache-directory');
const { workspaceDataDirectory } =
await importWorkspaceDependency<
typeof import('nx/src/utils/cache-directory')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
ProjectGraph,
} from 'nx/src/devkit-exports';
import type { ProjectGraphError } from 'nx/src/project-graph/error-types';
import type { ConfigurationSourceMaps } from 'nx/src/project-graph/utils/project-configuration-utils';
import type { ConfigurationSourceMaps } from 'nx/src/project-graph/utils/project-configuration/source-maps';
import { performance } from 'perf_hooks';
import {
getNxOutput,
Expand Down
2 changes: 1 addition & 1 deletion libs/shared/nx-workspace-info/src/lib/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { getNxVersion } from './get-nx-version';
import { getNxWorkspaceConfig } from './get-nx-workspace-config';
import { getNxDaemonClient } from './get-nx-workspace-package';
import type { ProjectGraph } from 'nx/src/devkit-exports';
import type { ConfigurationSourceMaps } from 'nx/src/project-graph/utils/project-configuration-utils';
import type { ConfigurationSourceMaps } from 'nx/src/project-graph/utils/project-configuration/source-maps';
import { execSync } from 'child_process';

const enum Status {
Expand Down
39 changes: 37 additions & 2 deletions libs/shared/schema/src/normalize-schema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ describe('utils', () => {
};

it('should work with schema without any properties', async () => {
// @ts-expect-error absence of required property "properties" is needed to test failure resistance
const r = await normalizeSchema({});
const r = await normalizeSchema({} as Schema);
expect(r).toEqual([]);
});

Expand Down Expand Up @@ -71,6 +70,42 @@ describe('utils', () => {
expect(r[0].items).toEqual(['test']);
});

it('should set items when items contains an enum object', async () => {
const option = {
...mockOption,
items: {
type: OptionType.String,
enum: ['test'],
},
};
const r = await getSchema({ option });
expect(r[0].items).toEqual(['test']);
});

it('should ignore items objects without an enum', async () => {
const option = {
...mockOption,
items: {
type: OptionType.String,
},
};
const r = await getSchema({ option });
expect(r[0].items).toBeUndefined();
});

it('should ignore tuple-schema items arrays', async () => {
const option = {
...mockOption,
items: [
{
type: OptionType.String,
},
],
};
const r = await getSchema({ option });
expect(r[0].items).toBeUndefined();
});

describe('xPrompt', () => {
const xPromptItems = [
{ value: 'css', label: 'CSS' },
Expand Down
31 changes: 22 additions & 9 deletions libs/shared/schema/src/normalize-schema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
CliOption,
ItemsWithEnum,
ItemTooltips,
LongFormXPrompt,
Option,
Expand Down Expand Up @@ -162,14 +161,28 @@ function isFieldRequired(
return requiredFields.has(nxOption.name);
}

function getItems(option: CliOption): { items: string[] } | undefined {
return (
option.items && {
items:
(option.items as ItemsWithEnum).enum ||
((option.items as string[]).length && option.items),
}
);
function getItems(option: CliOption): { items?: string[] } | undefined {
if (!option.items) {
return undefined;
}
const items = normalizeOptionItems(option.items);
return { items };
}

function normalizeOptionItems(items: CliOption['items']): string[] | undefined {
if (!items) {
return undefined;
}

if (Array.isArray(items)) {
return items.every((item) => typeof item === 'string') ? items : undefined;
}

if ('enum' in items && Array.isArray(items.enum)) {
return items.enum.map((item) => String(item));
}

return undefined;
}

function isLongFormXPrompt(xPrompt: XPrompt): xPrompt is LongFormXPrompt {
Expand Down
10 changes: 8 additions & 2 deletions libs/shared/schema/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export enum OptionType {
}

export type OptionPropertyDescription = Schema['properties'][number];
export type CompatibleOptionItems =
| OptionPropertyDescription['items']
| string[]
| ItemsWithEnum;

export type CliOption = {
name: string;
Expand All @@ -18,9 +22,11 @@ export type CliOption = {
alias?: string;
hidden?: boolean;
deprecated?: boolean | string;
} & OptionPropertyDescription;
} & Omit<OptionPropertyDescription, 'items'> & {
items?: CompatibleOptionItems;
};

export interface Option extends CliOption {
export interface Option extends Omit<CliOption, 'items'> {
tooltip?: string;
itemTooltips?: ItemTooltips;
items?: string[] | ItemsWithEnum;
Expand Down
2 changes: 1 addition & 1 deletion libs/shared/types/src/lib/nx-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {
ProjectFileMap,
ProjectGraph,
} from 'nx/src/devkit-exports';
import type { ConfigurationSourceMaps } from 'nx/src/project-graph/utils/project-configuration-utils';
import type { ConfigurationSourceMaps } from 'nx/src/project-graph/utils/project-configuration/source-maps';

export type NxProjectConfiguration = ProjectConfiguration & {
files?: { file: string }[];
Expand Down
2 changes: 1 addition & 1 deletion libs/shared/watcher/src/lib/passive-daemon-watcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { Logger } from '@nx-console/shared-utils';
import { randomUUID } from 'crypto';
import type { ProjectGraph } from 'nx/src/config/project-graph';
import type { ConfigurationSourceMaps } from 'nx/src/project-graph/utils/project-configuration-utils';
import type { ConfigurationSourceMaps } from 'nx/src/project-graph/utils/project-configuration/source-maps';
import { AnyEventObject, createActor, fromPromise, setup } from 'xstate';

export type WatcherStatus = 'operational' | 'daemonDisabled' | 'notRunning';
Expand Down
Loading
Loading