Skip to content
Open
2 changes: 2 additions & 0 deletions .yarn/versions/92c64300.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
releases:
"@yarnpkg/sdks": minor
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ The `yarn dlx @yarnpkg/sdks` command will look at the content of your *root* `pa
| [vscode-eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) | [eslint](https://yarnpkg.com/package/eslint) |
| [prettier-vscode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) | [prettier](https://yarnpkg.com/package/prettier) |
| [relay](https://marketplace.visualstudio.com/items?itemName=meta.relay) | [relay](https://relay.dev/)
| [oxc](https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode) | [oxlint](https://yarnpkg.com/package/oxlint)
| [oxc](https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode) | [oxfmt](https://yarnpkg.com/package/oxfmt)

If you'd like to contribute more, [take a look here!](https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-sdks/sources/generateSdk.ts)

Expand Down
23 changes: 22 additions & 1 deletion packages/yarnpkg-sdks/sources/generateSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ const TEMPLATE = (relPnpApiPath: PortablePath, module: string, {setupEnv = false
`\n`,
` process.env.NODE_OPTIONS = process.env.NODE_OPTIONS || \`\`;\n`,
` process.env.NODE_OPTIONS += \` -r \${absPnpApiPath}\`;\n`,
` if (isPnpLoaderEnabled && register) {\n`,
` process.env.NODE_OPTIONS += \` --experimental-loader \${pathToFileURL(absPnpLoaderPath)}\`;\n`,
` }\n`,
` }\n`,
] : []),
...(usePnpify ? [
Expand Down Expand Up @@ -201,7 +204,10 @@ export type SupportedSdk =
| `typescript-language-server`
| `typescript`
| `svelte-language-server`
| `flow-bin`;
| `flow-bin`
| `oxfmt`
| `oxlint`
| `oxlint-tsgolint`;

export type BaseSdks = Array<[
SupportedSdk,
Expand Down Expand Up @@ -343,6 +349,21 @@ export class Wrapper {
return absWrapperPath;
}

async writeRaw(relPackagePath: PortablePath, content: string, options: {mode?: number} = {}) {
const topLevelInformation = this.pnpApi.getPackageInformation(this.pnpApi.topLevel)!;
const projectRoot = npath.toPortablePath(topLevelInformation.packageLocation);

const absPath = ppath.join(this.target, this.name, relPackagePath);
const relProjectPath = ppath.relative(projectRoot, absPath);

await xfs.mkdirPromise(ppath.dirname(absPath), {recursive: true});
await xfs.writeFilePromise(absPath, content, {mode: options.mode});

this.paths.set(relPackagePath, relProjectPath);

return absPath;
}

getProjectPathTo(relPackagePath: PortablePath) {
const relProjectPath = this.paths.get(relPackagePath);

Expand Down
54 changes: 54 additions & 0 deletions packages/yarnpkg-sdks/sources/sdks/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,57 @@ export const generateFlowBinBaseWrapper: GenerateBaseWrapper = async (pnpApi: Pn
return wrapper;
};

export const generateOxfmtBaseWrapper: GenerateBaseWrapper = async (pnpApi: PnpApi, target: PortablePath) => {
const wrapper = new Wrapper(`oxfmt` as PortablePath, {pnpApi, target});

await wrapper.writeDefaults();
await wrapper.writeBinary(`bin/oxfmt` as PortablePath, {setupEnv: true});

return wrapper;
};

export const generateOxlintBaseWrapper: GenerateBaseWrapper = async (pnpApi: PnpApi, target: PortablePath) => {
const wrapper = new Wrapper(`oxlint` as PortablePath, {pnpApi, target});
await wrapper.writeDefaults();

// There are two workarounds here:
// 1. Injecting into PATH to enable tsgolint's PATH resolution strategy in the following tsgolint wrapper.
// 2. Direct file import to work around the top-level await and exports restrictions in oxlint.
const oxlintMonkeyPatch = `
module => module;

process.env.PATH += \`;\${resolve(__dirname, \`../../oxlint-tsgolint/bin\`)}\`;
import(pathToFileURL(resolve(require(\`pnpapi\`).resolveToUnqualified(\`oxlint\`, absPnpApiPath), \`dist/cli.js\`)));
`;

// This intentionally produces a dummy export; the main logic is in the import above.
// Originally, the binary does not export anything.
await wrapper.writeBinary(`bin/oxlint` as PortablePath, {
requirePath: `` as PortablePath,
wrapModule: oxlintMonkeyPatch,
});

return wrapper;
};

export const generateOxlintTsgolintBaseWrapper: GenerateBaseWrapper = async (pnpApi: PnpApi, target: PortablePath) => {
const wrapper = new Wrapper(`oxlint-tsgolint` as PortablePath, {pnpApi, target});

// We are using the oxc_linter tsgolint resolution mechanism via the PATH environment variable
// since it's the only realistic approach to correctly resolve the tsgolint binary when using Yarn PnP.
// Ref: https://github.com/oxc-project/oxc/blob/d3dcf5bc9718ebb4839be27062b5d82da2118e2e/crates/oxc_linter/src/tsgolint.rs#L1164-L1225
// With this approach, we need to manually create both Unix and Windows executable shim for tsgolint.js.
const tsgolintCmd = `
@goto #_undefined_# 2>NUL || @title %COMSPEC% & @setlocal & @"node" "%~dp0tsgolint.js" %*
`.trim().replace(/^ {4}/gm, ``);

await wrapper.writeDefaults();
await wrapper.writeBinary(`bin/tsgolint` as PortablePath);
await wrapper.writeRaw(`bin/tsgolint.cmd` as PortablePath, tsgolintCmd, {mode: 0o755});

return wrapper;
};

export const BASE_SDKS: BaseSdks = [
[`@astrojs/language-server`, generateAstroLanguageServerBaseWrapper],
[`eslint`, generateEslintBaseWrapper],
Expand All @@ -294,4 +345,7 @@ export const BASE_SDKS: BaseSdks = [
[`typescript`, generateTypescriptBaseWrapper],
[`svelte-language-server`, generateSvelteLanguageServerBaseWrapper],
[`flow-bin`, generateFlowBinBaseWrapper],
[`oxfmt`, generateOxfmtBaseWrapper],
[`oxlint`, generateOxlintBaseWrapper],
[`oxlint-tsgolint`, generateOxlintTsgolintBaseWrapper],
];
22 changes: 22 additions & 0 deletions packages/yarnpkg-sdks/sources/sdks/cocvim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,29 @@ export const generateTypescriptWrapper: GenerateIntegrationWrapper = async (pnpA
});
};

export const generateOxfmtWrapper: GenerateIntegrationWrapper = async (pnpApi: PnpApi, target: PortablePath, wrapper: Wrapper) => {
await addCocVimWorkspaceConfiguration(pnpApi, CocVimConfiguration.settings, {
[`oxc.oxfmt.binPath`]: npath.fromPortablePath(
wrapper.getProjectPathTo(
ppath.normalize(wrapper.manifest.bin.oxfmt),
),
),
});
};

export const generateOxlintWrapper: GenerateIntegrationWrapper = async (pnpApi: PnpApi, target: PortablePath, wrapper: Wrapper) => {
await addCocVimWorkspaceConfiguration(pnpApi, CocVimConfiguration.settings, {
[`oxc.oxlint.binPath`]: npath.fromPortablePath(
wrapper.getProjectPathTo(
ppath.normalize(wrapper.manifest.bin.oxlint),
),
),
});
};

export const COC_VIM_SDKS: IntegrationSdks = [
[`eslint`, generateEslintWrapper],
[`typescript`, generateTypescriptWrapper],
[`oxfmt`, generateOxfmtWrapper],
[`oxlint`, generateOxlintWrapper],
];
38 changes: 38 additions & 0 deletions packages/yarnpkg-sdks/sources/sdks/vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,41 @@ export const generateFlowBinWrapper: GenerateIntegrationWrapper = async (pnpApi:
});
};

export const generateOxfmtWrapper: GenerateIntegrationWrapper = async (pnpApi: PnpApi, target: PortablePath, wrapper: Wrapper) => {
await addVSCodeWorkspaceConfiguration(pnpApi, VSCodeConfiguration.settings, {
[`oxc.path.oxfmt`]: npath.fromPortablePath(
wrapper.getProjectPathTo(
ppath.normalize(wrapper.manifest.bin.oxfmt),
),
),
});

await addVSCodeWorkspaceConfiguration(pnpApi, VSCodeConfiguration.extensions, {
[`recommendations`]: [
`oxc.oxc-vscode`,
],
});
};

export const generateOxlintWrapper: GenerateIntegrationWrapper = async (pnpApi: PnpApi, target: PortablePath, wrapper: Wrapper) => {
await addVSCodeWorkspaceConfiguration(pnpApi, VSCodeConfiguration.settings, {
[`oxc.path.oxlint`]: npath.fromPortablePath(
wrapper.getProjectPathTo(
ppath.normalize(wrapper.manifest.bin.oxlint),
),
),
});

await addVSCodeWorkspaceConfiguration(pnpApi, VSCodeConfiguration.extensions, {
[`recommendations`]: [
`oxc.oxc-vscode`,
],
});
};

export const generateOxlintTsgolintWrapper: GenerateIntegrationWrapper = async (pnpApi: PnpApi, target: PortablePath, wrapper: Wrapper) => {
};

export const VSCODE_SDKS: IntegrationSdks = [
[null, generateDefaultWrapper],
[`@astrojs/language-server`, generateAstroLanguageServerWrapper],
Expand All @@ -149,4 +184,7 @@ export const VSCODE_SDKS: IntegrationSdks = [
[`typescript`, generateTypescriptWrapper],
[`svelte-language-server`, generateSvelteLanguageServerWrapper],
[`flow-bin`, generateFlowBinWrapper],
[`oxfmt`, generateOxfmtWrapper],
[`oxlint`, generateOxlintWrapper],
[`oxlint-tsgolint`, generateOxlintTsgolintWrapper],
];
Loading