Socket
Socket
Sign inDemoInstall

@nx/devkit

Package Overview
Dependencies
Maintainers
0
Versions
642
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nx/devkit - npm Package Compare versions

Comparing version 20.0.0-canary.20241001-8fa7065 to 20.0.0-canary.20241002-1d10a19

5

package.json
{
"name": "@nx/devkit",
"version": "20.0.0-canary.20241001-8fa7065",
"version": "20.0.0-canary.20241002-1d10a19",
"private": false,

@@ -37,3 +37,4 @@ "description": "The Nx Devkit is used to customize Nx for different technologies and use cases. It contains many utility functions for reading and writing files, updating configuration, working with Abstract Syntax Trees(ASTs), and more. Learn more about [extending Nx by leveraging the Nx Devkit](https://nx.dev/extending-nx/intro/getting-started) on our docs.",

"yargs-parser": "21.1.1",
"minimatch": "9.0.3"
"minimatch": "9.0.3",
"enquirer": "~2.3.6"
},

@@ -40,0 +41,0 @@ "peerDependencies": {

10

src/generators/artifact-name-and-directory-utils.d.ts
import { type Tree } from 'nx/src/devkit-exports';
export type NameAndDirectoryFormat = 'as-provided';
export type ArtifactGenerationOptions = {
name: string;
directory?: string;
path: string;
name?: string;
fileExtension?: 'js' | 'jsx' | 'ts' | 'tsx' | 'vue';
fileName?: string;
nameAndDirectoryFormat?: NameAndDirectoryFormat;
suffix?: string;

@@ -33,5 +31,3 @@ };

};
export declare function determineArtifactNameAndDirectoryOptions(tree: Tree, options: ArtifactGenerationOptions): Promise<NameAndDirectoryOptions & {
nameAndDirectoryFormat: NameAndDirectoryFormat;
}>;
export declare function determineArtifactNameAndDirectoryOptions(tree: Tree, options: ArtifactGenerationOptions): Promise<NameAndDirectoryOptions>;
export declare function getRelativeCwd(): string;

@@ -38,0 +34,0 @@ /**

@@ -10,64 +10,34 @@ "use strict";

async function determineArtifactNameAndDirectoryOptions(tree, options) {
const nameAndDirectoryOptions = getNameAndDirectoryOptions(tree, options);
validateResolvedProject(tree, nameAndDirectoryOptions.project, options, nameAndDirectoryOptions.directory);
return {
...nameAndDirectoryOptions,
nameAndDirectoryFormat: 'as-provided',
};
const normalizedOptions = getNameAndDirectoryOptions(tree, options);
validateResolvedProject(normalizedOptions.project, normalizedOptions.directory);
return normalizedOptions;
}
function getNameAndDirectoryOptions(tree, options) {
const directory = options.directory
? (0, devkit_exports_1.normalizePath)(options.directory.replace(/^\.?\//, ''))
const path = options.path
? (0, devkit_exports_1.normalizePath)(options.path.replace(/^\.?\//, ''))
: undefined;
const fileExtension = options.fileExtension ?? 'ts';
const { name: extractedName, directory: extractedDirectory } = extractNameAndDirectoryFromName(options.name);
if (extractedDirectory && directory) {
throw new Error(`You can't specify both a directory (${options.directory}) and a name with a directory path (${options.name}). ` +
`Please specify either a directory or a name with a directory path.`);
}
const asProvidedOptions = getAsProvidedOptions(tree, {
...options,
directory: directory ?? extractedDirectory,
fileExtension,
name: extractedName,
});
return asProvidedOptions;
}
function getAsProvidedOptions(tree, options) {
let { name: extractedName, directory } = extractNameAndDirectoryFromPath(path);
const relativeCwd = getRelativeCwd();
let asProvidedDirectory;
if (options.directory) {
// append the directory to the current working directory if it doesn't start with it
if (options.directory === relativeCwd ||
options.directory.startsWith(`${relativeCwd}/`)) {
asProvidedDirectory = options.directory;
}
else {
asProvidedDirectory = (0, devkit_exports_1.joinPathFragments)(relativeCwd, options.directory);
}
// append the directory to the current working directory if it doesn't start with it
if (directory !== relativeCwd && !directory.startsWith(`${relativeCwd}/`)) {
directory = (0, devkit_exports_1.joinPathFragments)(relativeCwd, directory);
}
else {
asProvidedDirectory = relativeCwd;
}
const asProvidedProject = findProjectFromPath(tree, asProvidedDirectory);
const asProvidedFileName = options.fileName ??
(options.suffix ? `${options.name}.${options.suffix}` : options.name);
const asProvidedFilePath = (0, devkit_exports_1.joinPathFragments)(asProvidedDirectory, `${asProvidedFileName}.${options.fileExtension}`);
const project = findProjectFromPath(tree, directory);
const name = options.fileName ??
(options.suffix ? `${extractedName}.${options.suffix}` : extractedName);
const filePath = (0, devkit_exports_1.joinPathFragments)(directory, `${name}.${fileExtension}`);
return {
artifactName: options.name,
directory: asProvidedDirectory,
fileName: asProvidedFileName,
filePath: asProvidedFilePath,
project: asProvidedProject,
artifactName: options.name ?? extractedName,
directory: directory,
fileName: name,
filePath: filePath,
project: project,
};
}
function validateResolvedProject(tree, project, options, normalizedDirectory) {
function validateResolvedProject(project, normalizedDirectory) {
if (project) {
return;
}
if (options.directory) {
throw new Error(`The provided directory resolved relative to the current working directory "${normalizedDirectory}" does not exist under any project root. ` +
`Please make sure to navigate to a location or provide a directory that exists under a project root.`);
}
throw new Error(`The current working directory "${getRelativeCwd() || '.'}" does not exist under any project root. ` +
throw new Error(`The provided directory resolved relative to the current working directory "${normalizedDirectory}" does not exist under any project root. ` +
`Please make sure to navigate to a location or provide a directory that exists under a project root.`);

@@ -98,7 +68,9 @@ }

}
function extractNameAndDirectoryFromName(rawName) {
const parsedName = (0, devkit_exports_1.normalizePath)(rawName).split('/');
const name = parsedName.pop();
const directory = parsedName.length ? parsedName.join('/') : undefined;
function extractNameAndDirectoryFromPath(path) {
// Remove trailing slash
path = path.replace(/\/$/, '');
const parsedPath = (0, devkit_exports_1.normalizePath)(path).split('/');
const name = parsedPath.pop();
const directory = parsedPath.join('/');
return { name, directory };
}
import { type ProjectType, type Tree } from 'nx/src/devkit-exports';
export type ProjectNameAndRootFormat = 'as-provided';
export type ProjectGenerationOptions = {
name: string;
directory: string;
name?: string;
projectType: ProjectType;
directory?: string;
importPath?: string;
rootProject?: boolean;
projectNameAndRootFormat?: ProjectNameAndRootFormat;
};

@@ -14,4 +12,3 @@ export type ProjectNameAndRootOptions = {

* Normalized full project name, including scope if name was provided with
* scope (e.g., `@scope/name`, only available when `projectNameAndRootFormat`
* is `as-provided`).
* scope (e.g., `@scope/name`)
*/

@@ -40,8 +37,3 @@ projectName: string;

};
export declare function determineProjectNameAndRootOptions(tree: Tree, options: ProjectGenerationOptions): Promise<ProjectNameAndRootOptions & {
projectNameAndRootFormat: ProjectNameAndRootFormat;
}>;
/**
* Function for setting cwd during testing
*/
export declare function setCwd(path: string): void;
export declare function determineProjectNameAndRootOptions(tree: Tree, options: ProjectGenerationOptions): Promise<ProjectNameAndRootOptions>;
export declare function ensureProjectName(tree: Tree, options: Omit<ProjectGenerationOptions, 'projectType'>, projectType: 'application' | 'library'): Promise<void>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.determineProjectNameAndRootOptions = determineProjectNameAndRootOptions;
exports.setCwd = setCwd;
exports.ensureProjectName = ensureProjectName;
const enquirer_1 = require("enquirer");
const devkit_exports_1 = require("nx/src/devkit-exports");
const path_1 = require("path");
async function determineProjectNameAndRootOptions(tree, options) {
validateName(options.name);
const projectNameAndRootOptions = getProjectNameAndRootOptions(tree, options);
return {
...projectNameAndRootOptions,
projectNameAndRootFormat: 'as-provided',
};
}
function validateName(name) {
/**
* Matches two types of project names:
*
* 1. Valid npm package names (e.g., '@scope/name' or 'name').
* 2. Names starting with a letter and can contain any character except whitespace and ':'.
*
* The second case is to support the legacy behavior (^[a-zA-Z].*$) with the difference
* that it doesn't allow the ":" character. It was wrong to allow it because it would
* conflict with the notation for tasks.
*/
const pattern = '(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$';
const validationRegex = new RegExp(pattern);
if (!validationRegex.test(name)) {
throw new Error(`The project name should match the pattern "${pattern}". The provided value "${name}" does not match.`);
}
}
function getProjectNameAndRootOptions(tree, options) {
const directory = options.directory
? (0, devkit_exports_1.normalizePath)(options.directory.replace(/^\.?\//, ''))
: undefined;
const { name: asProvidedParsedName, directory: asProvidedParsedDirectory } = parseNameForAsProvided(options.name);
if (asProvidedParsedDirectory && directory) {
throw new Error(`You can't specify both a directory (${options.directory}) and a name with a directory path (${options.name}). ` +
`Please specify either a directory or a name with a directory path.`);
}
const asProvidedOptions = getAsProvidedOptions(tree, {
...options,
directory: directory ?? asProvidedParsedDirectory,
name: asProvidedParsedName,
});
return asProvidedOptions;
}
function getAsProvidedOptions(tree, options) {
validateOptions(options);
const directory = (0, devkit_exports_1.normalizePath)(options.directory);
const name = options.name ??
directory.match(/(@[^@/]+(\/[^@/]+)+)/)?.[1] ??
directory.substring(directory.lastIndexOf('/') + 1);
let projectSimpleName;
let projectFileName;
if (options.name.startsWith('@')) {
const [_scope, ...rest] = options.name.split('/');
if (name.startsWith('@')) {
const [_scope, ...rest] = name.split('/');
projectFileName = rest.join('-');

@@ -57,15 +22,14 @@ projectSimpleName = rest.pop();

else {
projectSimpleName = options.name;
projectFileName = options.name;
projectSimpleName = name;
projectFileName = name;
}
let projectRoot;
const relativeCwd = getRelativeCwd();
if (options.directory) {
if (directory) {
// append the directory to the current working directory if it doesn't start with it
if (options.directory === relativeCwd ||
options.directory.startsWith(`${relativeCwd}/`)) {
projectRoot = options.directory;
if (directory === relativeCwd || directory.startsWith(`${relativeCwd}/`)) {
projectRoot = directory;
}
else {
projectRoot = (0, devkit_exports_1.joinPathFragments)(relativeCwd, options.directory);
projectRoot = (0, devkit_exports_1.joinPathFragments)(relativeCwd, directory);
}

@@ -79,4 +43,4 @@ }

// append the project name to the current working directory if it doesn't end with it
if (!relativeCwd.endsWith(options.name)) {
projectRoot = (0, devkit_exports_1.joinPathFragments)(relativeCwd, options.name);
if (!relativeCwd.endsWith(name)) {
projectRoot = (0, devkit_exports_1.joinPathFragments)(relativeCwd, name);
}

@@ -88,4 +52,4 @@ }

if (!importPath) {
if (options.name.startsWith('@')) {
importPath = options.name;
if (name.startsWith('@')) {
importPath = name;
}

@@ -97,4 +61,4 @@ else {

? (0, devkit_exports_1.readJson)(tree, 'package.json').name ??
getImportPath(npmScope, options.name)
: getImportPath(npmScope, options.name);
getImportPath(npmScope, name)
: getImportPath(npmScope, name);
}

@@ -104,3 +68,3 @@ }

return {
projectName: options.name,
projectName: name,
names: {

@@ -114,2 +78,48 @@ projectSimpleName,

}
async function ensureProjectName(tree, options, projectType) {
if (!options.name) {
if (options.directory === '.' && getRelativeCwd() === '') {
const result = await (0, enquirer_1.prompt)({
type: 'input',
name: 'name',
message: `What do you want to name the ${projectType}?`,
}).then(({ name }) => (options.name = name));
}
const { projectName } = await determineProjectNameAndRootOptions(tree, {
...options,
projectType,
});
options.name = projectName;
}
}
function validateOptions(options) {
if (options.directory === '.') {
/**
* Root projects must provide name option
*/
if (!options.name) {
throw new Error(`Root projects must also specify name option.`);
}
}
else {
/**
* Both directory and name (if present) must match one of two cases:
*
* 1. Valid npm package names (e.g., '@scope/name' or 'name').
* 2. Names starting with a letter and can contain any character except whitespace and ':'.
*
* The second case is to support the legacy behavior (^[a-zA-Z].*$) with the difference
* that it doesn't allow the ":" character. It was wrong to allow it because it would
* conflict with the notation for tasks.
*/
const pattern = '(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$';
const validationRegex = new RegExp(pattern);
if (options.name && !validationRegex.test(options.name)) {
throw new Error(`The name should match the pattern "${pattern}". The provided value "${options.name}" does not match.`);
}
if (!validationRegex.test(options.directory)) {
throw new Error(`The directory should match the pattern "${pattern}". The provided value "${options.directory}" does not match.`);
}
}
}
function getImportPath(npmScope, name) {

@@ -138,24 +148,1 @@ return npmScope ? `${npmScope === '@' ? '' : '@'}${npmScope}/${name}` : name;

}
/**
* Function for setting cwd during testing
*/
function setCwd(path) {
process.env.INIT_CWD = (0, path_1.join)(devkit_exports_1.workspaceRoot, path);
}
function parseNameForAsProvided(rawName) {
const directory = (0, devkit_exports_1.normalizePath)(rawName);
if (rawName.includes('@')) {
const index = directory.lastIndexOf('@');
if (index === 0) {
return { name: rawName, directory: undefined };
}
const name = directory.substring(index);
return { name, directory };
}
if (rawName.includes('/')) {
const index = directory.lastIndexOf('/');
const name = directory.substring(index + 1);
return { name, directory };
}
return { name: rawName, directory: undefined };
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc