Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/fix-vscode-node-modules-resolution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/theme-check-node': patch
---

Fix VSCode extension failing to resolve custom check packages from node_modules (e.g. `extends: '@acme/theme-check-extension/recommended.yml'`). The extension server is webpack-bundled, so `require.resolve` was being handled by webpack instead of Node.js, returning a module ID rather than a file path. Now uses `createRequire` from `node:module` to get real Node.js resolution.
22 changes: 9 additions & 13 deletions packages/theme-check-node/src/config/resolve/read-yaml.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CheckSettings, Modes, Severity } from '@shopify/theme-check-common';
import { realpathSync } from 'node:fs';
import fs from 'node:fs/promises';
import { createRequire } from 'node:module';
import path from 'node:path';
import { parse } from 'yaml';
import { AbsolutePath } from '../../temp';
Expand Down Expand Up @@ -172,7 +173,14 @@ function resolvePath(
return path.resolve(root, pathLike);
}

return realpathSync(require.resolve(pathLike, { paths: getAncestorNodeModules(root)! }));
// Use createRequire to get the real Node.js require rather than webpack's
// substitute. When the VSCode extension server is bundled, `require.resolve`
// becomes webpack's version which doesn't support the `paths` option and
// returns a numeric module ID instead of a file path. createRequire creates
// a real Node.js require function that resolves from the given directory,
// traversing ancestor node_modules automatically.
const req = createRequire(path.join(root, '__placeholder'));
return realpathSync(req.resolve(pathLike));
}

/**
Expand Down Expand Up @@ -237,15 +245,3 @@ function isString(thing: unknown): thing is string {
function asArray<T>(thing: T | T[]): T[] {
return Array.isArray(thing) ? thing : [thing];
}

function getAncestorNodeModules(dir: string): string[] {
const root = path.parse(dir).root;
const nodeModulesPaths: string[] = [];

while (dir !== root) {
nodeModulesPaths.push(path.join(dir, 'node_modules'));
dir = path.dirname(dir);
}

return nodeModulesPaths;
}
Loading