Skip to content

Commit

Permalink
fix importAttributes is not avaliable in old node versions (#226)
Browse files Browse the repository at this point in the history
Co-authored-by: Lenz Weber-Tronic <[email protected]>
  • Loading branch information
yesmeck and phryneas authored Oct 15, 2024
1 parent e5b17b5 commit 57c51c8
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/smooth-dodos-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vscode-apollo": patch
---

Fixes config files being unable to load in old VSCode versions
77 changes: 70 additions & 7 deletions src/language-server/config/cache-busting-resolver.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,62 @@
// @ts-check
const { pathToFileURL } = require("node:url");

/** @import { ResolveContext, ResolutionResult, LoadResult, ImportContext } from "./cache-busting-resolver.types" */
/** @import { ResolveContext, ResolutionResult, LoadResult, ImportContext, ImportAttributes, ImportAssertions, LegacyResolveContext, LegacyImportContext, Format } from "./cache-busting-resolver.types" */

/**
* importAssertions was renamed to importAttributes after following versions of Node.js.
* Once we hit a minimum of v1.92 of VSCode, we can remove the legacy check and
* use `importAttributes` directly.
*
* - v21.0.0
* - v20.10.0
* - v18.19.0
*
* @see https://github.com/apollographql/vscode-graphql/issues/225
* @see https://nodejs.org/docs/latest/api/module.html#resolvespecifier-context-nextresolve
*
* @param {ResolveContext|ImportContext|LegacyResolveContext|LegacyImportContext} context
* @returns {context is ResolveContext|ImportContext}
*/
function isImportAttributesAvailable(context) {
return "importAttributes" in context;
}

/**
* @param {ResolveContext|ImportContext} context
* @returns {"importAttributes"|"importAssertions"}
*/
function resolveImportAttributesKeyName(context) {
if (isImportAttributesAvailable(context)) {
return "importAttributes";
}
return "importAssertions";
}

/**
* @param {ResolveContext|ImportContext|LegacyResolveContext|LegacyImportContext} context
* @returns {ImportAttributes|ImportAssertions}
*/
function resolveImportAttributes(context) {
if (isImportAttributesAvailable(context)) {
return context.importAttributes;
}
return context.importAssertions;
}

/**
* @param {ImportAttributes|ImportAssertions} importAttributes
* @returns {Format|null}
*/
function resolveConfigFormat(importAttributes) {
const [as, format] = importAttributes.as
? importAttributes.as.split(":")
: [];
if (as === "cachebust" && format) {
return /** @type {Format} */ (format);
}
return null;
}

/**
* @param {string} specifier
Expand All @@ -21,14 +76,16 @@ function bustFileName(specifier) {
* @returns {Promise<ResolutionResult>}
*/
async function resolve(specifier, context, nextResolve) {
if (context.importAttributes.as !== "cachebust") {
const importAttributes = resolveImportAttributes(context);
const format = resolveConfigFormat(importAttributes);
if (!format) {
return nextResolve(specifier, context);
}
// no need to resolve at all, we have all necessary information
return {
url: bustFileName(specifier),
format: context.importAttributes.format,
importAttributes: context.importAttributes,
format,
[resolveImportAttributesKeyName(context)]: importAttributes,
shortCircuit: true,
};
}
Expand All @@ -41,13 +98,19 @@ async function resolve(specifier, context, nextResolve) {
* @returns {Promise<LoadResult>}
*/
async function load(url, context, nextLoad) {
if (context.importAttributes.as !== "cachebust") {
const importAttributes = resolveImportAttributes(context);
const format = resolveConfigFormat(importAttributes);
if (!format) {
return nextLoad(url, context);
}
const contents =
"contents" in importAttributes
? importAttributes.contents
: Object.keys(importAttributes).find((key) => key != "as");
return {
format: context.format || "module",
format,
shortCircuit: true,
source: context.importAttributes.contents,
source: /** @type {string} */ (contents),
};
}

Expand Down
22 changes: 20 additions & 2 deletions src/language-server/config/cache-busting-resolver.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ import { pathToFileURL } from "node:url";

export type ImportAttributes =
| {
as: "cachebust";
as: `cachebust:${Format}`;
contents: string;
format: Format;
}
| { as?: undefined };

type Format =
export type ImportAssertions =
| {
as: `cachebust:${Format}`;
[key: string]: string;
}
| { as?: undefined };

export type Format =
| "builtin"
| "commonjs"
| "json"
Expand All @@ -17,12 +24,23 @@ type Format =
| null
| undefined;

export interface LegacyResolveContext {
conditions: string[];
importAssertions: ImportAssertions;
parentURL?: string;
}

export interface ResolveContext {
conditions: string[];
importAttributes: ImportAttributes;
parentURL?: string;
}

export interface LegacyImportContext {
conditions: string[];
importAssertions: ImportAssertions;
format: Format;
}
export interface ImportContext {
conditions: string[];
importAttributes: ImportAttributes;
Expand Down
16 changes: 12 additions & 4 deletions src/language-server/config/loadTsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ import { dirname, extname } from "node:path";
import typescript from "typescript";
import { pathToFileURL } from "node:url";
import { register } from "node:module";
import { ImportAttributes } from "./cache-busting-resolver.types";
import {
ImportAssertions,
ImportAttributes,
} from "./cache-busting-resolver.types";
// implementation based on https://github.com/cosmiconfig/cosmiconfig/blob/a5a842547c13392ebb89a485b9e56d9f37e3cbd3/src/loaders.ts
// Copyright (c) 2015 David Clark licensed MIT. Full license can be found here:
// https://github.com/cosmiconfig/cosmiconfig/blob/a5a842547c13392ebb89a485b9e56d9f37e3cbd3/LICENSE

if (process.env.JEST_WORKER_ID === undefined) {
try {
register(
pathToFileURL(require.resolve("./config/cache-busting-resolver.js")),
);
} else {
} catch {
register(pathToFileURL(require.resolve("./cache-busting-resolver.js")));
}

Expand Down Expand Up @@ -114,10 +117,15 @@ async function loadCachebustedJs(
// @ts-ignore
{
with: {
as: "cachebust",
as: `cachebust:${type}`,
contents,
format: type,
} satisfies ImportAttributes,
assert: {
as: `cachebust:${type}`,
contents,
format: type,
} satisfies ImportAssertions,
}
)
).default;
Expand Down

0 comments on commit 57c51c8

Please sign in to comment.