Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cli-utils, internal): Fix retrieval of tsconfig.json extends and standard TS libs #251

Merged
merged 7 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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/nervous-rats-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@gql.tada/cli-utils": patch
---

Fix resolution of default lib path when libs aren't in standard location
5 changes: 5 additions & 0 deletions .changeset/violet-tools-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@gql.tada/internal": patch
---

Fix resolving `tsconfig.json`' `extends` option
2 changes: 1 addition & 1 deletion packages/cli-utils/src/ts/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { SourcePosition } from './utils';
import { spanToFilePosition } from './utils';

function maybeBind<T extends Function>(that: object, fn: T | undefined): T {
return fn ? fn.bind(that, fn) : fn;
return fn ? fn.bind(that) : fn;
}

export interface PluginCreateInfo<Config extends {} = GraphQLSPConfig>
Expand Down
8 changes: 3 additions & 5 deletions packages/cli-utils/src/ts/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,17 @@ export const programFactory = (params: ProgramFactoryParams): ProgramFactory =>
const virtualMap: VirtualMap = new Map();

const projectRoot = path.dirname(params.configPath);
const tslibPath = path.join(projectRoot, 'node_modules/typescript/lib/');
const system = createFSBackedSystem(vfsMap, projectRoot, ts, tslibPath);
const system = createFSBackedSystem(vfsMap, projectRoot, ts);
const config = resolveConfig(params, system);

for (const { filename, contents } of resolveLibs(params)) {
if (contents) system.writeFile(path.join(tslibPath, filename), contents);
if (contents) system.writeFile('/' + filename, contents);
kitten marked this conversation as resolved.
Show resolved Hide resolved
}

const rootNames = new Set(config.fileNames);
const options = {
getDefaultLibFilePath: ts.getDefaultLibFilePath(config.options),
kitten marked this conversation as resolved.
Show resolved Hide resolved
...defaultCompilerOptions,
...config.options,
getDefaultLibFilePath: tslibPath,
};
const host = createVirtualCompilerHost(system, options, ts);

Expand Down
14 changes: 9 additions & 5 deletions packages/internal/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ export interface GraphQLSPConfig {
}

export const parseConfig = (
input: Record<string, unknown>,
input: unknown,
/** Defines the path of the "main" `tsconfig.json` file.
* @remarks
* This should be the `rootPath` output from `loadConfig`,
* which is the path of the user's `tsconfig.json` before
* resolving `extends` options.
*/
rootPath: string = process.cwd()
) => {
): GraphQLSPConfig => {
const resolveConfigDir = (input: string | undefined) => {
if (!input) return input;
return path.normalize(
Expand All @@ -36,7 +36,11 @@ export const parseConfig = (
);
};

if (input.schema && typeof input.schema === 'object') {
if (input == null || typeof input !== 'object') {
throw new TadaError(`Configuration was not loaded properly (Received: ${input})`);
}

if ('schema' in input && input.schema && typeof input.schema === 'object') {
const { schema } = input;
if (!('url' in schema)) {
throw new TadaError('Configuration contains a `schema` object, but no `url` property');
Expand All @@ -55,7 +59,7 @@ export const parseConfig = (
"Configuration contains a `schema.headers` property, but it's not an object"
);
}
} else if (typeof input.schema !== 'string') {
} else if (!('schema' in input) || typeof input.schema !== 'string') {
throw new TadaError('Configuration is missing a `schema` property');
} else if (
'tadaOutputLocation' in input &&
Expand Down Expand Up @@ -98,5 +102,5 @@ export const parseConfig = (
tadaOutputLocation: resolveConfigDir(output.tadaOutputLocation),
tadaTurboLocation: resolveConfigDir(output.tadaTurboLocation),
tadaPersistedLocation: resolveConfigDir(output.tadaPersistedLocation),
} satisfies GraphQLSPConfig;
};
};
64 changes: 29 additions & 35 deletions packages/internal/src/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,46 +81,40 @@ export const loadConfig = async (targetPath?: string): Promise<LoadConfigResult>
: 'No tsconfig.json found at or above current working directory'
);
}
const tsconfig = await readTSConfigFile(rootTsconfigPath);
const pluginConfig = getPluginConfig(tsconfig);
if (pluginConfig) {
return {
pluginConfig,
configPath: rootTsconfigPath,
rootPath: path.dirname(rootTsconfigPath),
};
}

if (Array.isArray(tsconfig.extends)) {
for (let extend of tsconfig.extends) {
if (path.extname(extend) !== '.json') extend += '.json';
const load = async (targetPath: string): Promise<LoadConfigResult> => {
const tsconfig = await readTSConfigFile(targetPath);
const pluginConfig = getPluginConfig(tsconfig);

if (pluginConfig) {
return {
pluginConfig,
configPath: targetPath,
rootPath: path.dirname(rootTsconfigPath),
};
}

if (Array.isArray(tsconfig.extends)) {
for (let extend of tsconfig.extends) {
if (path.extname(extend) !== '.json') extend += '.json';
try {
const tsconfigPath = await resolveExtend(extend, path.dirname(rootTsconfigPath));
if (tsconfigPath) return load(tsconfigPath);
} catch (_error) {}
}
} else if (tsconfig.extends) {
try {
const tsconfigPath = await resolveExtend(extend, path.dirname(rootTsconfigPath));
if (tsconfigPath) {
const config = loadConfig(targetPath);
return {
...config,
rootPath: path.dirname(rootTsconfigPath),
};
}
const tsconfigPath = await resolveExtend(tsconfig.extends, path.dirname(rootTsconfigPath));
if (tsconfigPath) return load(tsconfigPath);
} catch (_error) {}
}
} else if (tsconfig.extends) {
try {
const tsconfigPath = await resolveExtend(tsconfig.extends, path.dirname(rootTsconfigPath));
if (tsconfigPath) {
const config = loadConfig(targetPath);
return {
...config,
rootPath: path.dirname(rootTsconfigPath),
};
}
} catch (_error) {}
}

throw new TadaError(
`Could not find a valid GraphQLSP plugin entry in: ${maybeRelative(rootTsconfigPath)}`
);
throw new TadaError(
`Could not find a valid GraphQLSP plugin entry in: ${maybeRelative(rootTsconfigPath)}`
);
};

return await load(rootTsconfigPath);
};

/** @deprecated Use {@link loadConfig} instead */
Expand Down
Loading