🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@nx/devkit

Package Overview
Dependencies
Maintainers
5
Versions
1869
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
23.0.1
to
23.0.2
+9
dist/src/utils/catalog/manager-utils.d.ts
import { type Tree } from 'nx/src/devkit-exports';
import type { CatalogDefinitions } from './types';
export declare function readCatalogConfigFromFs(filename: string, fullPath: string): CatalogDefinitions | null;
export declare function readCatalogConfigFromTree(filename: string, tree: Tree): CatalogDefinitions | null;
export declare function updateCatalogVersionsInFile(filename: string, treeOrRoot: Tree | string, updates: Array<{
packageName: string;
version: string;
catalogName?: string;
}>): void;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.readCatalogConfigFromFs = readCatalogConfigFromFs;
exports.readCatalogConfigFromTree = readCatalogConfigFromTree;
exports.updateCatalogVersionsInFile = updateCatalogVersionsInFile;
// Keep in sync with packages/nx/src/utils/catalog/manager-utils.ts; the body below
// the imports is duplicated because @nx/devkit supports a range of nx majors and
// this logic isn't part of the nx surface it can import across that range.
const js_yaml_1 = require("@zkochan/js-yaml");
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const devkit_exports_1 = require("nx/src/devkit-exports");
const devkit_internals_1 = require("nx/src/devkit-internals");
const yaml_1 = require("yaml");
// Walks `path` resolving aliases at every step so structural checks can
// see through `key: *anchor` references. Neither `doc.getIn` nor
// `doc.hasIn` traverse aliases on their own. Returns the resolved node, or
// `undefined` if any ancestor isn't a map.
function resolveAt(doc, path) {
let node = doc.contents;
for (let i = 0; i < path.length; i++) {
if ((0, yaml_1.isAlias)(node))
node = node.resolve(doc);
if (!(0, yaml_1.isMap)(node))
return undefined;
node = node.get(path[i], true);
}
if ((0, yaml_1.isAlias)(node))
node = node.resolve(doc);
return node;
}
function isMapAt(doc, path) {
return (0, yaml_1.isMap)(resolveAt(doc, path));
}
function existsAt(doc, path) {
return resolveAt(doc, path) !== undefined;
}
// `doc.getIn` does not traverse aliases. For aliased paths it returns
// undefined even when the resolved node has a value. Use the alias-aware
// walk and unwrap scalar nodes to their JS value.
function getValueAt(doc, path) {
const node = resolveAt(doc, path);
return (0, yaml_1.isScalar)(node) ? node.value : node;
}
// Walks `targetPath` resolving aliases at every step and mutates the
// resolved map directly so anchors are preserved. When a step is missing
// or holds a null placeholder (`key:` with no value), creates a fresh map
// inside the current parent and carries over the placeholder's comments
// and anchor so they aren't dropped. A dropped anchor would leave any
// alias referencing it unresolved and make `String(doc)` throw. Falls back
// to `doc.setIn` when the current parent isn't a map: an empty-document
// root gets bootstrapped, while a non-map value where a catalog map was
// expected makes `setIn` throw, surfacing the malformed config.
function setThroughAliases(doc, targetPath, value) {
let parent = doc.contents;
if ((0, yaml_1.isAlias)(parent))
parent = parent.resolve(doc);
for (let i = 0; i < targetPath.length - 1; i++) {
if (!(0, yaml_1.isMap)(parent)) {
doc.setIn(targetPath, value);
return;
}
let next = parent.get(targetPath[i], true);
const nextWasAlias = (0, yaml_1.isAlias)(next);
if ((0, yaml_1.isAlias)(next))
next = next.resolve(doc);
const placeholder = (0, yaml_1.isScalar)(next) && next.value === null ? next : undefined;
if (next === undefined || placeholder) {
let cur = parent;
for (let j = i; j < targetPath.length - 1; j++) {
const fresh = new yaml_1.YAMLMap();
if (j === i && placeholder) {
if (placeholder.comment)
fresh.comment = placeholder.comment;
if (placeholder.commentBefore)
fresh.commentBefore = placeholder.commentBefore;
// Copy the anchor only for a directly-held placeholder. When it
// was reached through an alias, the anchor still lives on the
// definition node, so re-emitting it here would duplicate it.
if (!nextWasAlias && placeholder.anchor)
fresh.anchor = placeholder.anchor;
}
cur.set(targetPath[j], fresh);
cur = fresh;
}
cur.set(targetPath[targetPath.length - 1], value);
return;
}
parent = next;
}
if (!(0, yaml_1.isMap)(parent)) {
doc.setIn(targetPath, value);
return;
}
parent.set(targetPath[targetPath.length - 1], value);
}
function readCatalogConfigFromFs(filename, fullPath) {
try {
return (0, devkit_internals_1.readYamlFile)(fullPath);
}
catch (error) {
devkit_exports_1.output.warn({
title: `Unable to parse ${filename}`,
bodyLines: [error.toString()],
});
return null;
}
}
function readCatalogConfigFromTree(filename, tree) {
const content = tree.read(filename, 'utf-8');
try {
return (0, js_yaml_1.load)(content, { filename });
}
catch (error) {
devkit_exports_1.output.warn({
title: `Unable to parse ${filename}`,
bodyLines: [error.toString()],
});
return null;
}
}
function updateCatalogVersionsInFile(filename, treeOrRoot, updates) {
let checkExists;
let readYaml;
let writeYaml;
if (typeof treeOrRoot === 'string') {
const configPath = (0, node_path_1.join)(treeOrRoot, filename);
checkExists = () => (0, node_fs_1.existsSync)(configPath);
readYaml = () => (0, node_fs_1.readFileSync)(configPath, 'utf-8');
writeYaml = (content) => (0, node_fs_1.writeFileSync)(configPath, content, 'utf-8');
}
else {
checkExists = () => treeOrRoot.exists(filename);
readYaml = () => treeOrRoot.read(filename, 'utf-8');
writeYaml = (content) => treeOrRoot.write(filename, content);
}
if (!checkExists()) {
devkit_exports_1.output.warn({
title: `No ${filename} found`,
bodyLines: [
`Cannot update catalog versions without a ${filename} file.`,
`Create a ${filename} file to use catalogs.`,
],
});
return;
}
try {
// parseDocument keeps comments and anchors so a catalog bump doesn't
// rewrite the user's config file.
const lineCounter = new yaml_1.LineCounter();
const doc = (0, yaml_1.parseDocument)(readYaml(), { lineCounter });
// parseDocument collects syntax errors instead of throwing; surface them
// now, with their line/column detail, rather than failing later in
// `String(doc)` with a generic message or skipping a no-op write on a
// malformed file (the previous js-yaml `load()` threw here).
if (doc.errors.length > 0) {
throw new Error(doc.errors.map((e) => e.message).join('\n'));
}
// A dangling alias (`*ref` with no matching `&ref`) is not a syntax error,
// so parseDocument leaves it out of doc.errors. Surface it here with the
// same line/column detail the old js-yaml `load()` reported; otherwise a
// broken reference is silently overwritten or written back untouched.
const unresolvedAliases = [];
(0, yaml_1.visit)(doc, {
Alias(_key, node) {
if (node.resolve(doc) !== undefined)
return;
const pos = node.range ? lineCounter.linePos(node.range[0]) : undefined;
unresolvedAliases.push(pos
? `Unresolved alias "${node.source}" at line ${pos.line}, column ${pos.col}`
: `Unresolved alias "${node.source}"`);
},
});
if (unresolvedAliases.length > 0) {
throw new Error(unresolvedAliases.join('\n'));
}
let hasChanges = false;
for (const update of updates) {
const { packageName, version, catalogName } = update;
const normalizedCatalogName = catalogName === 'default' ? undefined : catalogName;
let targetPath;
if (!normalizedCatalogName) {
// An empty `catalog:` placeholder must not claim the default route
// when `catalogs.default` is populated; that would create a
// duplicate-default config rejected by pnpm.
if (isMapAt(doc, ['catalog'])) {
targetPath = ['catalog', packageName];
}
else if (existsAt(doc, ['catalogs', 'default'])) {
targetPath = ['catalogs', 'default', packageName];
}
else {
targetPath = ['catalog', packageName];
}
}
else {
targetPath = ['catalogs', normalizedCatalogName, packageName];
}
if (getValueAt(doc, targetPath) !== version) {
setThroughAliases(doc, targetPath, version);
hasChanges = true;
}
}
if (hasChanges) {
writeYaml(String(doc));
}
}
catch (error) {
devkit_exports_1.output.error({
title: 'Failed to update catalog versions',
bodyLines: [error instanceof Error ? error.message : String(error)],
});
throw error;
}
}
+1
-1

@@ -5,4 +5,4 @@ import type { ExecutorContext, Target } from 'nx/src/devkit-exports';

*
* Works as if you invoked the target yourself without passing any command lint overrides.
* Works as if you invoked the target yourself without passing any command line overrides.
*/
export declare function readTargetOptions<T = any>({ project, target, configuration }: Target, context: ExecutorContext): T;

@@ -9,3 +9,3 @@ "use strict";

*
* Works as if you invoked the target yourself without passing any command lint overrides.
* Works as if you invoked the target yourself without passing any command line overrides.
*/

@@ -12,0 +12,0 @@ function readTargetOptions({ project, target, configuration }, context) {

@@ -8,2 +8,14 @@ "use strict";

const path = tslib_1.__importStar(require("path"));
// Prettier v3 (ESM) exposes its API as named exports; v2 (CJS) exposes it under
// `.default` when loaded via `import()`. Return whichever carries the API, or
// null if prettier isn't installed.
async function importPrettier() {
try {
const imported = await import('prettier');
return (imported.resolveConfig ? imported : imported.default);
}
catch {
return null;
}
}
/**

@@ -36,3 +48,3 @@ * Formats all the created or updated files using Prettier

try {
prettier = await import('prettier');
prettier = await importPrettier();
/**

@@ -39,0 +51,0 @@ * Even after we discovered prettier in node_modules, we need to be sure that the user is intentionally using prettier

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PnpmCatalogManager = void 0;
const js_yaml_1 = require("@zkochan/js-yaml");
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const devkit_exports_1 = require("nx/src/devkit-exports");
const devkit_internals_1 = require("nx/src/devkit-internals");
const manager_1 = require("./manager");
const manager_utils_1 = require("./manager-utils");
const PNPM_WORKSPACE_FILENAME = 'pnpm-workspace.yaml';

@@ -43,3 +41,3 @@ /**

}
return readConfigFromFs(configPath);
return (0, manager_utils_1.readCatalogConfigFromFs)(PNPM_WORKSPACE_FILENAME, configPath);
}

@@ -50,3 +48,3 @@ else {

}
return readConfigFromTree(treeOrRoot, PNPM_WORKSPACE_FILENAME);
return (0, manager_utils_1.readCatalogConfigFromTree)(PNPM_WORKSPACE_FILENAME, treeOrRoot);
}

@@ -152,101 +150,5 @@ }

updateCatalogVersions(treeOrRoot, updates) {
let checkExists;
let readYaml;
let writeYaml;
if (typeof treeOrRoot === 'string') {
const configPath = (0, node_path_1.join)(treeOrRoot, PNPM_WORKSPACE_FILENAME);
checkExists = () => (0, node_fs_1.existsSync)(configPath);
readYaml = () => (0, node_fs_1.readFileSync)(configPath, 'utf-8');
writeYaml = (content) => (0, node_fs_1.writeFileSync)(configPath, content, 'utf-8');
}
else {
checkExists = () => treeOrRoot.exists(PNPM_WORKSPACE_FILENAME);
readYaml = () => treeOrRoot.read(PNPM_WORKSPACE_FILENAME, 'utf-8');
writeYaml = (content) => treeOrRoot.write(PNPM_WORKSPACE_FILENAME, content);
}
if (!checkExists()) {
devkit_exports_1.output.warn({
title: `No ${PNPM_WORKSPACE_FILENAME} found`,
bodyLines: [
`Cannot update catalog versions without a ${PNPM_WORKSPACE_FILENAME} file.`,
`Create a ${PNPM_WORKSPACE_FILENAME} file to use catalogs.`,
],
});
return;
}
try {
const configContent = readYaml();
const configData = (0, js_yaml_1.load)(configContent) || {};
let hasChanges = false;
for (const update of updates) {
const { packageName, version, catalogName } = update;
const normalizedCatalogName = catalogName === 'default' ? undefined : catalogName;
let targetCatalog;
if (!normalizedCatalogName) {
// Default catalog - update whichever exists, prefer catalog over catalogs.default
if (configData.catalog) {
targetCatalog = configData.catalog;
}
else if (configData.catalogs?.default) {
targetCatalog = configData.catalogs.default;
}
else {
// Neither exists, create catalog (shorthand syntax)
configData.catalog ??= {};
targetCatalog = configData.catalog;
}
}
else {
// Named catalog
configData.catalogs ??= {};
configData.catalogs[normalizedCatalogName] ??= {};
targetCatalog = configData.catalogs[normalizedCatalogName];
}
if (targetCatalog[packageName] !== version) {
targetCatalog[packageName] = version;
hasChanges = true;
}
}
if (hasChanges) {
writeYaml((0, js_yaml_1.dump)(configData, {
indent: 2,
quotingType: '"',
forceQuotes: true,
}));
}
}
catch (error) {
devkit_exports_1.output.error({
title: 'Failed to update catalog versions',
bodyLines: [error instanceof Error ? error.message : String(error)],
});
throw error;
}
(0, manager_utils_1.updateCatalogVersionsInFile)(PNPM_WORKSPACE_FILENAME, treeOrRoot, updates);
}
}
exports.PnpmCatalogManager = PnpmCatalogManager;
function readConfigFromFs(path) {
try {
return (0, devkit_internals_1.readYamlFile)(path);
}
catch (error) {
devkit_exports_1.output.warn({
title: `Unable to parse ${PNPM_WORKSPACE_FILENAME}`,
bodyLines: [error.toString()],
});
return null;
}
}
function readConfigFromTree(tree, path) {
const content = tree.read(path, 'utf-8');
try {
return (0, js_yaml_1.load)(content, { filename: path });
}
catch (error) {
devkit_exports_1.output.warn({
title: `Unable to parse ${PNPM_WORKSPACE_FILENAME}`,
bodyLines: [error.toString()],
});
return null;
}
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.YarnCatalogManager = void 0;
const js_yaml_1 = require("@zkochan/js-yaml");
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const devkit_exports_1 = require("nx/src/devkit-exports");
const devkit_internals_1 = require("nx/src/devkit-internals");
const manager_1 = require("./manager");
const manager_utils_1 = require("./manager-utils");
const YARNRC_FILENAME = '.yarnrc.yml';

@@ -43,3 +41,3 @@ /**

}
return readConfigFromFs(configPath);
return (0, manager_utils_1.readCatalogConfigFromFs)(YARNRC_FILENAME, configPath);
}

@@ -50,3 +48,3 @@ else {

}
return readConfigFromTree(treeOrRoot, YARNRC_FILENAME);
return (0, manager_utils_1.readCatalogConfigFromTree)(YARNRC_FILENAME, treeOrRoot);
}

@@ -152,101 +150,5 @@ }

updateCatalogVersions(treeOrRoot, updates) {
let checkExists;
let readYaml;
let writeYaml;
if (typeof treeOrRoot === 'string') {
const configPath = (0, node_path_1.join)(treeOrRoot, YARNRC_FILENAME);
checkExists = () => (0, node_fs_1.existsSync)(configPath);
readYaml = () => (0, node_fs_1.readFileSync)(configPath, 'utf-8');
writeYaml = (content) => (0, node_fs_1.writeFileSync)(configPath, content, 'utf-8');
}
else {
checkExists = () => treeOrRoot.exists(YARNRC_FILENAME);
readYaml = () => treeOrRoot.read(YARNRC_FILENAME, 'utf-8');
writeYaml = (content) => treeOrRoot.write(YARNRC_FILENAME, content);
}
if (!checkExists()) {
devkit_exports_1.output.warn({
title: `No ${YARNRC_FILENAME} found`,
bodyLines: [
`Cannot update catalog versions without a ${YARNRC_FILENAME} file.`,
`Create a ${YARNRC_FILENAME} file to use catalogs.`,
],
});
return;
}
try {
const configContent = readYaml();
const configData = (0, js_yaml_1.load)(configContent) || {};
let hasChanges = false;
for (const update of updates) {
const { packageName, version, catalogName } = update;
const normalizedCatalogName = catalogName === 'default' ? undefined : catalogName;
let targetCatalog;
if (!normalizedCatalogName) {
// Default catalog - update whichever exists, prefer catalog over catalogs.default
if (configData.catalog) {
targetCatalog = configData.catalog;
}
else if (configData.catalogs?.default) {
targetCatalog = configData.catalogs.default;
}
else {
// Neither exists, create catalog (shorthand syntax)
configData.catalog ??= {};
targetCatalog = configData.catalog;
}
}
else {
// Named catalog
configData.catalogs ??= {};
configData.catalogs[normalizedCatalogName] ??= {};
targetCatalog = configData.catalogs[normalizedCatalogName];
}
if (targetCatalog[packageName] !== version) {
targetCatalog[packageName] = version;
hasChanges = true;
}
}
if (hasChanges) {
writeYaml((0, js_yaml_1.dump)(configData, {
indent: 2,
quotingType: '"',
forceQuotes: true,
}));
}
}
catch (error) {
devkit_exports_1.output.error({
title: 'Failed to update catalog versions',
bodyLines: [error instanceof Error ? error.message : String(error)],
});
throw error;
}
(0, manager_utils_1.updateCatalogVersionsInFile)(YARNRC_FILENAME, treeOrRoot, updates);
}
}
exports.YarnCatalogManager = YarnCatalogManager;
function readConfigFromFs(path) {
try {
return (0, devkit_internals_1.readYamlFile)(path);
}
catch (error) {
devkit_exports_1.output.warn({
title: `Unable to parse ${YARNRC_FILENAME}`,
bodyLines: [error.toString()],
});
return null;
}
}
function readConfigFromTree(tree, path) {
const content = tree.read(path, 'utf-8');
try {
return (0, js_yaml_1.load)(content, { filename: path });
}
catch (error) {
devkit_exports_1.output.warn({
title: `Unable to parse ${YARNRC_FILENAME}`,
bodyLines: [error.toString()],
});
return null;
}
}
{
"name": "@nx/devkit",
"version": "23.0.1",
"version": "23.0.2",
"private": false,

@@ -59,7 +59,8 @@ "type": "commonjs",

"minimatch": "10.2.5",
"enquirer": "~2.3.6"
"enquirer": "~2.3.6",
"yaml": "^2.8.3"
},
"devDependencies": {
"jest": "30.3.0",
"nx": "23.0.1"
"nx": "23.0.2"
},

@@ -66,0 +67,0 @@ "peerDependencies": {