diff --git a/.changeset/config.json b/.changeset/config.json index 4a65feeb44..0054b03de4 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -6,7 +6,6 @@ "access": "public", "baseBranch": "origin/main", "ignore": [ - "@rnx-kit/ignore", "@rnx-kit/template", "@rnx-kit/test-app", "@rnx-kit/test-app-macos", diff --git a/.yarnrc.yml b/.yarnrc.yml index 5e94c9aa49..5c20d02890 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -63,6 +63,7 @@ plugins: spec: "@yarnpkg/plugin-compat" - path: incubator/yarn-plugin-dynamic-extensions/index.js - path: incubator/yarn-plugin-external-workspaces/dist/external-workspaces.cjs + - path: incubator/yarn-plugin-ignore/dist/yarn-plugin-ignore.cjs - path: incubator/yarn-plugin-install-to/dist/yarn-plugin-install-to.cjs tsEnableAutoTypes: false diff --git a/docsite/package.json b/docsite/package.json index e453ef4bf8..74229b336d 100644 --- a/docsite/package.json +++ b/docsite/package.json @@ -33,12 +33,12 @@ "typescript": "catalog:" }, "resolutions": { - "@algolia/autocomplete-core": "link:../incubator/ignore", - "@docsearch/react": "link:../incubator/ignore", + "@algolia/autocomplete-core": "ignore:", + "@docsearch/react": "ignore:", "@pnpm/network.ca-file/graceful-fs": "^4.2.10", - "algoliasearch": "link:../incubator/ignore", - "algoliasearch-helper": "link:../incubator/ignore", - "node-gyp": "link:../incubator/ignore" + "algoliasearch": "ignore:", + "algoliasearch-helper": "ignore:", + "node-gyp": "ignore:" }, "browserslist": { "production": [ diff --git a/docsite/yarn.lock b/docsite/yarn.lock index 8046998452..c54f6808eb 100644 --- a/docsite/yarn.lock +++ b/docsite/yarn.lock @@ -5,9 +5,9 @@ __metadata: version: 8 cacheKey: 10c0 -"@algolia/autocomplete-core@link:../incubator/ignore::locator=%40rnx-kit%2Fdocsite%40workspace%3A.": +"@algolia/autocomplete-core@ignore:": version: 0.0.0-use.local - resolution: "@algolia/autocomplete-core@link:../incubator/ignore::locator=%40rnx-kit%2Fdocsite%40workspace%3A." + resolution: "@algolia/autocomplete-core@ignore:" languageName: node linkType: soft @@ -1800,9 +1800,9 @@ __metadata: languageName: node linkType: hard -"@docsearch/react@link:../incubator/ignore::locator=%40rnx-kit%2Fdocsite%40workspace%3A.": +"@docsearch/react@ignore:": version: 0.0.0-use.local - resolution: "@docsearch/react@link:../incubator/ignore::locator=%40rnx-kit%2Fdocsite%40workspace%3A." + resolution: "@docsearch/react@ignore:" languageName: node linkType: soft @@ -4381,15 +4381,15 @@ __metadata: languageName: node linkType: hard -"algoliasearch-helper@link:../incubator/ignore::locator=%40rnx-kit%2Fdocsite%40workspace%3A.": +"algoliasearch-helper@ignore:": version: 0.0.0-use.local - resolution: "algoliasearch-helper@link:../incubator/ignore::locator=%40rnx-kit%2Fdocsite%40workspace%3A." + resolution: "algoliasearch-helper@ignore:" languageName: node linkType: soft -"algoliasearch@link:../incubator/ignore::locator=%40rnx-kit%2Fdocsite%40workspace%3A.": +"algoliasearch@ignore:": version: 0.0.0-use.local - resolution: "algoliasearch@link:../incubator/ignore::locator=%40rnx-kit%2Fdocsite%40workspace%3A." + resolution: "algoliasearch@ignore:" languageName: node linkType: soft @@ -9344,9 +9344,9 @@ __metadata: languageName: node linkType: hard -"node-gyp@link:../incubator/ignore::locator=%40rnx-kit%2Fdocsite%40workspace%3A.": +"node-gyp@ignore:": version: 0.0.0-use.local - resolution: "node-gyp@link:../incubator/ignore::locator=%40rnx-kit%2Fdocsite%40workspace%3A." + resolution: "node-gyp@ignore:" languageName: node linkType: soft diff --git a/incubator/ignore/index.js b/incubator/ignore/index.js deleted file mode 100644 index f053ebf797..0000000000 --- a/incubator/ignore/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = {}; diff --git a/incubator/ignore/package.json b/incubator/ignore/package.json deleted file mode 100644 index 39e60c4455..0000000000 --- a/incubator/ignore/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@rnx-kit/ignore", - "version": "1.0.0", - "private": true, - "description": "Meta package for preventing packages from being installed", - "homepage": "https://github.com/microsoft/rnx-kit/tree/main/incubator/ignore#readme", - "license": "MIT", - "author": { - "name": "Microsoft Open Source", - "email": "microsoftopensource@users.noreply.github.com" - }, - "repository": { - "type": "git", - "url": "https://github.com/microsoft/rnx-kit", - "directory": "incubator/ignore" - }, - "files": [ - "index.js" - ], - "main": "index.js", - "engines": { - "node": ">=16.17" - }, - "experimental": true -} diff --git a/incubator/yarn-plugin-ignore/.gitignore b/incubator/yarn-plugin-ignore/.gitignore new file mode 100644 index 0000000000..6480e496f5 --- /dev/null +++ b/incubator/yarn-plugin-ignore/.gitignore @@ -0,0 +1,2 @@ +!dist/ +dist/*.map diff --git a/incubator/yarn-plugin-ignore/README.md b/incubator/yarn-plugin-ignore/README.md new file mode 100644 index 0000000000..26ed21ef4a --- /dev/null +++ b/incubator/yarn-plugin-ignore/README.md @@ -0,0 +1,29 @@ +# @rnx-kit/yarn-plugin-ignore + +[![Build](https://github.com/microsoft/rnx-kit/actions/workflows/build.yml/badge.svg)](https://github.com/microsoft/rnx-kit/actions/workflows/build.yml) +[![npm version](https://img.shields.io/npm/v/@rnx-kit/yarn-plugin-ignore)](https://www.npmjs.com/package/@rnx-kit/yarn-plugin-ignore) + +🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧 + +### THIS TOOL IS EXPERIMENTAL — USE WITH CAUTION + +🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧 + +A Yarn plugin for excluding packages from being installed. + +## Installation + +```sh +yarn plugin import https://raw.githubusercontent.com/microsoft/rnx-kit/main/incubator/yarn-plugin-ignore/dist/yarn-plugin-ignore.cjs +``` + +## Usage + +In the root `package.json`, add a `resolutions` section and use the `ignore:` +protocol to exclude packages. For example, to exclude `node-gyp`: + +```diff ++ "resolutions": { ++ "node-gyp": "ignore:" ++ }, +``` diff --git a/incubator/yarn-plugin-ignore/dist/yarn-plugin-ignore.cjs b/incubator/yarn-plugin-ignore/dist/yarn-plugin-ignore.cjs new file mode 100644 index 0000000000..0c752c44ed --- /dev/null +++ b/incubator/yarn-plugin-ignore/dist/yarn-plugin-ignore.cjs @@ -0,0 +1,153 @@ +/* eslint-disable */ +//prettier-ignore +module.exports = { +name: "@rnx-kit/yarn-plugin-ignore", +factory: function (require) { +"use strict"; +var plugin = (() => { + var __create = Object.create; + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __getProtoOf = Object.getPrototypeOf; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { + get: (a, b) => (typeof require !== "undefined" ? require : a)[b] + }) : x)(function(x) { + if (typeof require !== "undefined") return require.apply(this, arguments); + throw Error('Dynamic require of "' + x + '" is not supported'); + }); + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod + )); + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + + // src/index.ts + var index_exports = {}; + __export(index_exports, { + IgnoreFetcher: () => IgnoreFetcher, + IgnoreResolver: () => IgnoreResolver, + default: () => index_default + }); + + // src/IgnoreFetcher.ts + var import_fslib = __require("@yarnpkg/fslib"); + var fs = __toESM(__require("fs"), 1); + + // src/constants.ts + var IGNORE_PROTOCOL = "ignore:"; + var STUB_MODULE = `module.exports = {}; +`; + var STUB_PACKAGE = `{ + "name": "@rnx-kit/yarn-plugin-ignore/stub", + "version": "0.0.0", + "description": "Stub package for '@rnx-kit/yarn-plugin-ignore'", + "main": "index.js" +} +`; + + // src/IgnoreFetcher.ts + var IgnoreFetcher = class { + supports(locator) { + return locator.reference.startsWith(IGNORE_PROTOCOL); + } + getLocalPath() { + return null; + } + async fetch(_locator, opts) { + const base = opts.project.cwd; + const sourceFs = new import_fslib.CwdFS(base); + const localPath = import_fslib.ppath.resolve( + base, + "node_modules", + ".generated", + "@rnx-kit", + "yarn-plugin-ignore-stub" + ); + const nativePath = import_fslib.npath.fromPortablePath(localPath); + if (!fs.existsSync(nativePath)) { + fs.mkdirSync(nativePath, { recursive: true, mode: 493 }); + fs.writeFileSync(import_fslib.npath.join(nativePath, "package.json"), STUB_PACKAGE); + fs.writeFileSync(import_fslib.npath.join(nativePath, "index.js"), STUB_MODULE); + } + return { + packageFs: new import_fslib.CwdFS(localPath, { baseFs: sourceFs }), + prefixPath: import_fslib.PortablePath.dot, + discardFromLookup: true, + localPath + }; + } + }; + + // src/IgnoreResolver.ts + var import_core = __require("@yarnpkg/core"); + var import_node_assert = __require("assert"); + var IgnoreResolver = class { + supportsDescriptor(descriptor) { + return descriptor.range.startsWith(IGNORE_PROTOCOL); + } + supportsLocator(locator) { + return locator.reference.startsWith(IGNORE_PROTOCOL); + } + shouldPersistResolution() { + return false; + } + bindDescriptor(descriptor, _fromLocator) { + return descriptor; + } + getResolutionDependencies() { + return {}; + } + async getCandidates(descriptor, _dependencies, _opts) { + return [import_core.structUtils.makeLocator(descriptor, IGNORE_PROTOCOL)]; + } + async getSatisfying(_descriptor, _dependencies, locators, _opts) { + (0, import_node_assert.equal)(locators.length, 1, "Expected a single locator candidate"); + return { locators, sorted: true }; + } + async resolve(locator, opts) { + const manifest = new import_core.Manifest(); + return { + ...locator, + version: "0.0.0", + languageName: opts.project.configuration.get("defaultLanguageName"), + linkType: import_core.LinkType.SOFT, + conditions: null, + dependencies: manifest.dependencies, + peerDependencies: manifest.peerDependencies, + dependenciesMeta: manifest.dependenciesMeta, + peerDependenciesMeta: manifest.peerDependenciesMeta, + bin: manifest.bin + }; + } + }; + + // src/index.ts + var plugin = { + fetchers: [IgnoreFetcher], + resolvers: [IgnoreResolver] + }; + var index_default = plugin; + return __toCommonJS(index_exports); +})(); +return plugin; +} +}; +//# sourceMappingURL=yarn-plugin-ignore.cjs.map diff --git a/incubator/yarn-plugin-ignore/package.json b/incubator/yarn-plugin-ignore/package.json new file mode 100644 index 0000000000..1c57f64208 --- /dev/null +++ b/incubator/yarn-plugin-ignore/package.json @@ -0,0 +1,40 @@ +{ + "name": "@rnx-kit/yarn-plugin-ignore", + "version": "0.0.1", + "private": true, + "description": "EXPERIMENTAL - USE WITH CAUTION - yarn-plugin-ignore", + "homepage": "https://github.com/microsoft/rnx-kit/tree/main/incubator/yarn-plugin-ignore#readme", + "license": "MIT", + "author": { + "name": "Microsoft Open Source", + "email": "microsoftopensource@users.noreply.github.com" + }, + "repository": { + "type": "git", + "url": "https://github.com/microsoft/rnx-kit", + "directory": "incubator/yarn-plugin-ignore" + }, + "files": [ + "dist/yarn-plugin-ignore.cjs" + ], + "type": "module", + "main": "dist/yarn-plugin-ignore.cjs", + "scripts": { + "build": "rnx-kit-scripts build", + "bundle": "rnx-kit-scripts bundle --platform yarn --sourceMap", + "format": "rnx-kit-scripts format", + "lint": "rnx-kit-scripts lint", + "test": "rnx-kit-scripts test" + }, + "devDependencies": { + "@rnx-kit/scripts": "*", + "@rnx-kit/tsconfig": "*", + "@yarnpkg/core": "^4.2.0", + "@yarnpkg/fslib": "^3.1.1" + }, + "engines": { + "node": ">=18.12", + "yarn": ">=4.0" + }, + "experimental": true +} diff --git a/incubator/yarn-plugin-ignore/src/IgnoreFetcher.ts b/incubator/yarn-plugin-ignore/src/IgnoreFetcher.ts new file mode 100644 index 0000000000..8f46711c77 --- /dev/null +++ b/incubator/yarn-plugin-ignore/src/IgnoreFetcher.ts @@ -0,0 +1,45 @@ +import type { + Fetcher, + FetchOptions, + FetchResult, + Locator, +} from "@yarnpkg/core"; +import { CwdFS, npath, PortablePath, ppath } from "@yarnpkg/fslib"; +import * as fs from "node:fs"; +import { IGNORE_PROTOCOL, STUB_MODULE, STUB_PACKAGE } from "./constants.ts"; + +export class IgnoreFetcher implements Fetcher { + supports(locator: Locator): boolean { + return locator.reference.startsWith(IGNORE_PROTOCOL); + } + + getLocalPath(): PortablePath | null { + return null; + } + + async fetch(_locator: Locator, opts: FetchOptions): Promise { + const base = opts.project.cwd; + const sourceFs = new CwdFS(base); + const localPath = ppath.resolve( + base, + "node_modules", + ".generated", + "@rnx-kit", + "yarn-plugin-ignore-stub" + ); + + const nativePath = npath.fromPortablePath(localPath); + if (!fs.existsSync(nativePath)) { + fs.mkdirSync(nativePath, { recursive: true, mode: 0o755 }); + fs.writeFileSync(npath.join(nativePath, "package.json"), STUB_PACKAGE); + fs.writeFileSync(npath.join(nativePath, "index.js"), STUB_MODULE); + } + + return { + packageFs: new CwdFS(localPath, { baseFs: sourceFs }), + prefixPath: PortablePath.dot, + discardFromLookup: true, + localPath, + }; + } +} diff --git a/incubator/yarn-plugin-ignore/src/IgnoreResolver.ts b/incubator/yarn-plugin-ignore/src/IgnoreResolver.ts new file mode 100644 index 0000000000..b410929643 --- /dev/null +++ b/incubator/yarn-plugin-ignore/src/IgnoreResolver.ts @@ -0,0 +1,72 @@ +import type { + Descriptor, + Locator, + Package, + Resolver, + ResolveOptions, +} from "@yarnpkg/core"; +import { LinkType, Manifest, structUtils } from "@yarnpkg/core"; +import { equal } from "node:assert"; +import { IGNORE_PROTOCOL } from "./constants.ts"; + +export class IgnoreResolver implements Resolver { + supportsDescriptor(descriptor: Descriptor): boolean { + return descriptor.range.startsWith(IGNORE_PROTOCOL); + } + + supportsLocator(locator: Locator): boolean { + return locator.reference.startsWith(IGNORE_PROTOCOL); + } + + shouldPersistResolution(): boolean { + return false; + } + + bindDescriptor(descriptor: Descriptor, _fromLocator: Locator): Descriptor { + return descriptor; + } + + getResolutionDependencies(): Record { + return {}; + } + + async getCandidates( + descriptor: Descriptor, + _dependencies: Record, + _opts: ResolveOptions + ): Promise { + return [structUtils.makeLocator(descriptor, IGNORE_PROTOCOL)]; + } + + async getSatisfying( + _descriptor: Descriptor, + _dependencies: Record, + locators: Locator[], + _opts: ResolveOptions + ): Promise<{ locators: Locator[]; sorted: boolean }> { + equal(locators.length, 1, "Expected a single locator candidate"); + return { locators, sorted: true }; + } + + async resolve(locator: Locator, opts: ResolveOptions): Promise { + const manifest = new Manifest(); + return { + ...locator, + + version: "0.0.0", + + languageName: opts.project.configuration.get("defaultLanguageName"), + linkType: LinkType.SOFT, + + conditions: null, + + dependencies: manifest.dependencies, + peerDependencies: manifest.peerDependencies, + + dependenciesMeta: manifest.dependenciesMeta, + peerDependenciesMeta: manifest.peerDependenciesMeta, + + bin: manifest.bin, + }; + } +} diff --git a/incubator/yarn-plugin-ignore/src/constants.ts b/incubator/yarn-plugin-ignore/src/constants.ts new file mode 100644 index 0000000000..7e7d1589c6 --- /dev/null +++ b/incubator/yarn-plugin-ignore/src/constants.ts @@ -0,0 +1,11 @@ +export const IGNORE_PROTOCOL = "ignore:"; + +export const STUB_MODULE = `module.exports = {};\n`; + +export const STUB_PACKAGE = `{ + "name": "@rnx-kit/yarn-plugin-ignore/stub", + "version": "0.0.0", + "description": "Stub package for '@rnx-kit/yarn-plugin-ignore'", + "main": "index.js" +} +`; diff --git a/incubator/yarn-plugin-ignore/src/index.ts b/incubator/yarn-plugin-ignore/src/index.ts new file mode 100644 index 0000000000..140c2b283c --- /dev/null +++ b/incubator/yarn-plugin-ignore/src/index.ts @@ -0,0 +1,14 @@ +import type { Plugin } from "@yarnpkg/core"; +import { IgnoreFetcher } from "./IgnoreFetcher.ts"; +import { IgnoreResolver } from "./IgnoreResolver.ts"; + +export { IgnoreFetcher }; +export { IgnoreResolver }; + +const plugin: Plugin = { + fetchers: [IgnoreFetcher], + resolvers: [IgnoreResolver], +}; + +// oxlint-disable-next-line no-default-export +export default plugin; diff --git a/incubator/yarn-plugin-ignore/test/IgnoreFetcher.test.ts b/incubator/yarn-plugin-ignore/test/IgnoreFetcher.test.ts new file mode 100644 index 0000000000..f0756b288f --- /dev/null +++ b/incubator/yarn-plugin-ignore/test/IgnoreFetcher.test.ts @@ -0,0 +1,18 @@ +import { equal, ok } from "node:assert/strict"; +import { describe, it } from "node:test"; +import { IgnoreFetcher } from "../src/IgnoreFetcher.ts"; +import { makePackageInfo } from "./helper.ts"; + +describe("IgnoreFetcher", () => { + const fetcher = new IgnoreFetcher(); + + it("supports `ignore:` protocol", () => { + const { locator } = makePackageInfo(); + + ok(fetcher.supports(locator)); + }); + + it("returns `null` local path", () => { + equal(fetcher.getLocalPath(), null); + }); +}); diff --git a/incubator/yarn-plugin-ignore/test/IgnoreResolver.test.ts b/incubator/yarn-plugin-ignore/test/IgnoreResolver.test.ts new file mode 100644 index 0000000000..29e09dccbc --- /dev/null +++ b/incubator/yarn-plugin-ignore/test/IgnoreResolver.test.ts @@ -0,0 +1,94 @@ +import { LinkType } from "@yarnpkg/core"; +import { deepEqual, equal, ok } from "node:assert/strict"; +import { describe, it } from "node:test"; +import { IGNORE_PROTOCOL } from "../src/constants.ts"; +import { IgnoreResolver } from "../src/IgnoreResolver.ts"; +import { makePackageInfo, makeResolveOptions } from "./helper.ts"; + +describe("IgnoreResolver", () => { + const resolver = new IgnoreResolver(); + + it("supports `ignore:` protocol", () => { + const { descriptor, locator } = makePackageInfo(); + + ok(resolver.supportsDescriptor(descriptor)); + ok(resolver.supportsLocator(locator)); + }); + + it("does not persist resolution", () => { + ok(!resolver.shouldPersistResolution()); + }); + + it("binds descriptor", () => { + const { descriptor, locator } = makePackageInfo(); + const { name, range, scope } = resolver.bindDescriptor(descriptor, locator); + + equal(scope, locator.scope); + equal(name, locator.name); + equal(range, IGNORE_PROTOCOL); + }); + + it("returns no dependencies", () => { + deepEqual(resolver.getResolutionDependencies(), {}); + }); + + it("returns one candidate", async () => { + const { descriptor, locator } = makePackageInfo(); + const opts = makeResolveOptions(); + const candidates = await resolver.getCandidates(descriptor, {}, opts); + + equal(candidates.length, 1); + + const { name, reference, scope } = candidates[0]; + + equal(scope, locator.scope); + equal(name, locator.name); + equal(reference, IGNORE_PROTOCOL); + }); + + it("returns the one candidate as satisfying", async () => { + const { descriptor, locator } = makePackageInfo(); + const opts = makeResolveOptions(); + const res = await resolver.getSatisfying(descriptor, {}, [locator], opts); + + equal(res.locators.length, 1); + + const { name, reference, scope } = res.locators[0]; + + equal(scope, locator.scope); + equal(name, locator.name); + equal(reference, IGNORE_PROTOCOL); + }); + + it("resolves the stub", async () => { + const { locator } = makePackageInfo(); + const opts = makeResolveOptions(); + + const { + bin, + dependencies, + dependenciesMeta, + peerDependencies, + peerDependenciesMeta, + ...pkg + } = await resolver.resolve(locator, opts); + + deepEqual(pkg, { + ...locator, + + version: "0.0.0", + languageName: "node", + linkType: LinkType.SOFT, + + conditions: null, + }); + + equal(dependencies.size, 0); + equal(peerDependencies.size, 0); + + equal(dependenciesMeta.size, 0); + equal(peerDependenciesMeta.size, 0); + + equal(bin.size, 0); + }); +}); diff --git a/incubator/yarn-plugin-ignore/test/constants.test.ts b/incubator/yarn-plugin-ignore/test/constants.test.ts new file mode 100644 index 0000000000..7113b70f55 --- /dev/null +++ b/incubator/yarn-plugin-ignore/test/constants.test.ts @@ -0,0 +1,22 @@ +import { deepEqual, equal } from "node:assert/strict"; +import { spawnSync } from "node:child_process"; +import { describe, it } from "node:test"; +import { STUB_MODULE, STUB_PACKAGE } from "../src/constants.ts"; + +describe("stub package", () => { + it("contains a valid manifest", () => { + deepEqual(JSON.parse(STUB_PACKAGE), { + name: "@rnx-kit/yarn-plugin-ignore/stub", + version: "0.0.0", + description: "Stub package for '@rnx-kit/yarn-plugin-ignore'", + main: "index.js", + }); + }); + + it("contains a valid main file", () => { + const input = { input: STUB_MODULE }; + const { status } = spawnSync(process.argv0, ["--check", "-"], input); + + equal(status, 0); + }); +}); diff --git a/incubator/yarn-plugin-ignore/test/helper.ts b/incubator/yarn-plugin-ignore/test/helper.ts new file mode 100644 index 0000000000..b234e13249 --- /dev/null +++ b/incubator/yarn-plugin-ignore/test/helper.ts @@ -0,0 +1,28 @@ +import type { Descriptor, Locator, ResolveOptions } from "@yarnpkg/core"; +import { structUtils } from "@yarnpkg/core"; +import { IGNORE_PROTOCOL } from "../src/constants.ts"; + +export type PackageInfo = { + descriptor: Descriptor; + locator: Locator; +}; + +export function makePackageInfo(): PackageInfo { + const ident = structUtils.makeIdent("rnx-kit", "yarn-plugin-ignore"); + return { + descriptor: structUtils.makeDescriptor(ident, IGNORE_PROTOCOL), + locator: structUtils.makeLocator(ident, IGNORE_PROTOCOL), + }; +} + +export function makeResolveOptions(): ResolveOptions { + return { + project: { + configuration: { + get() { + return "node"; + }, + }, + }, + } as unknown as ResolveOptions; +} diff --git a/incubator/yarn-plugin-ignore/tsconfig.json b/incubator/yarn-plugin-ignore/tsconfig.json new file mode 100644 index 0000000000..02a01b0081 --- /dev/null +++ b/incubator/yarn-plugin-ignore/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@rnx-kit/tsconfig/tsconfig.node.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["src"] +} diff --git a/package.json b/package.json index 49c1525f1e..019d24f96b 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,7 @@ "@microsoft/eslint-plugin-sdl/eslint-plugin-react": "^7.37.3", "@microsoft/eslint-plugin-sdl/eslint-plugin-security": "^1.4.0", "@rnx-kit/react-native-host": "workspace:*", - "@vue/compiler-sfc": "link:./incubator/ignore", - "node-gyp": "link:./incubator/ignore", + "node-gyp": "ignore:", "nx/minimatch": "^10.2.4", "react-native-macos/@react-native/assets-registry": "^0.78.0", "react-native-macos/@react-native/codegen": "^0.78.0", diff --git a/scripts/src/commands/test.js b/scripts/src/commands/test.js index 4845fb7abf..67c9c97265 100644 --- a/scripts/src/commands/test.js +++ b/scripts/src/commands/test.js @@ -53,6 +53,13 @@ export class TestCommand extends Command { return await runScript("jest", "--passWithNoTests", ...this.args); } + const coverage = this.args.indexOf("--coverage"); + if (coverage >= 0) { + // TODO: Code coverage is still experimental as of Node v25.9.0 + // https://nodejs.org/api/cli.html#experimental-test-coverage + this.args[coverage] = "--experimental-test-coverage"; + } + const tests = this.args.length > 0 ? this.args : fs.globSync("test/**/*.test.ts"); return useTsx(manifest) diff --git a/yarn.lock b/yarn.lock index bbdad7db47..6028424125 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5507,12 +5507,6 @@ __metadata: languageName: unknown linkType: soft -"@rnx-kit/ignore@workspace:incubator/ignore": - version: 0.0.0-use.local - resolution: "@rnx-kit/ignore@workspace:incubator/ignore" - languageName: unknown - linkType: soft - "@rnx-kit/jest-preset@npm:*, @rnx-kit/jest-preset@workspace:*, @rnx-kit/jest-preset@workspace:packages/jest-preset": version: 0.0.0-use.local resolution: "@rnx-kit/jest-preset@workspace:packages/jest-preset" @@ -6350,6 +6344,17 @@ __metadata: languageName: unknown linkType: soft +"@rnx-kit/yarn-plugin-ignore@workspace:incubator/yarn-plugin-ignore": + version: 0.0.0-use.local + resolution: "@rnx-kit/yarn-plugin-ignore@workspace:incubator/yarn-plugin-ignore" + dependencies: + "@rnx-kit/scripts": "npm:*" + "@rnx-kit/tsconfig": "npm:*" + "@yarnpkg/core": "npm:^4.2.0" + "@yarnpkg/fslib": "npm:^3.1.1" + languageName: unknown + linkType: soft + "@rnx-kit/yarn-plugin-install-to@workspace:incubator/yarn-plugin-install-to": version: 0.0.0-use.local resolution: "@rnx-kit/yarn-plugin-install-to@workspace:incubator/yarn-plugin-install-to" @@ -14286,9 +14291,9 @@ __metadata: languageName: node linkType: hard -"node-gyp@link:./incubator/ignore::locator=rnx-kit%40workspace%3A.": +"node-gyp@ignore:": version: 0.0.0-use.local - resolution: "node-gyp@link:./incubator/ignore::locator=rnx-kit%40workspace%3A." + resolution: "node-gyp@ignore:" languageName: node linkType: soft