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

Initial version of a ts-plugin #114

Merged
merged 1 commit into from
Jan 24, 2024
Merged
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
3 changes: 3 additions & 0 deletions grats-ts-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# grats-ts-plugin

Experimental TypeScript plugin for Grats. This plugin is not ready for production use.
11 changes: 11 additions & 0 deletions grats-ts-plugin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use strict";

// TypeScript is vary particular about how plugins are structured. They must be
// CommonJS and they must have a single value for `module.exports`. Additionally,
// the plugin must be a plain module name (no `/` characters allowed).
//
// However, the logic for the plugin is tightly coupled with Grats itself and
// should really live (and ship) alongside each version of Grats. While
// I continue to struggle with figuring out how to let Grats operate as its own
// TypeScript plugin, this package is just a shim.
module.exports = require("grats").initTsPlugin;
11 changes: 11 additions & 0 deletions grats-ts-plugin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "grats-ts-plugin",
"version": "0.0.2",
"license": "MIT",
"main": "./",
"module": "./index.js",
"peerDependencies": {
"grats": ">=0.0.19"
},
"prettier": {}
}
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
packages:
- 'website'
- 'examples/*'
- 'examples/*'
- 'grats-ts-plugin'
1 change: 1 addition & 0 deletions src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { applyDefaultNullability } from "./transforms/applyDefaultNullability";
import { mergeExtensions } from "./transforms/mergeExtensions";
import { sortSchemaAst } from "./transforms/sortSchemaAst";
import { validateSemanticNullability } from "./validations/validateSemanticNullability";
export { initTsPlugin } from "./tsPlugin/initTsPlugin";

export type SchemaAndDoc = {
schema: GraphQLSchema;
Expand Down
43 changes: 43 additions & 0 deletions src/tsPlugin/initTsPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type * as TS from "typescript/lib/tsserverlibrary";
import { extract } from "../Extractor";

// An experimental plugin for TypeScript that adds a new language service
// which reports diagnostics for the current file. Currently it only reports
// syntax errors because semantic errors are too expensive to compute on each
// keystroke.
export function initTsPlugin(modules: { typescript: typeof TS }) {
const ts = modules.typescript;

function create(info: TS.server.PluginCreateInfo): TS.LanguageService {
const projectRoot = info.project.getCurrentDirectory();
info.project.projectService.logger.info(
`Grats: Initializing Plugin with project root: ${projectRoot} and TypeScript version: ${ts.version}`,
);

// Set up decorator object
const proxy: TS.LanguageService = Object.create(null);
for (const k of Object.keys(info.languageService) as Array<
keyof TS.LanguageService
>) {
const x = info.languageService[k];
// @ts-expect-error
proxy[k] = (...args: Array<any>) => x.apply(info.languageService, args);
}

proxy.getSyntacticDiagnostics = (filename): TS.DiagnosticWithLocation[] => {
const prior = info.languageService.getSyntacticDiagnostics(filename);
const doc = info.languageService.getProgram()?.getSourceFile(filename);

if (doc == null) return prior;
const result = extract(doc);

if (result.kind === "OK") return prior;

return [...prior, ...result.err];
};

return proxy;
}

return { create };
}
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"src/tests/fixtures",
"docs",
"examples",
"website"
"website",
"grats-ts-plugin"
]
}