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

Feature Request: Accessing CLI-initialized Service #1147

Closed
harrysolovay opened this issue Nov 8, 2020 · 12 comments
Closed

Feature Request: Accessing CLI-initialized Service #1147

harrysolovay opened this issue Nov 8, 2020 · 12 comments

Comments

@harrysolovay
Copy link

Desired Behavior

I'm building a library, which is intended to be used within a ts-node process. I'd like to be able to access the register so that I can utilize its getTypeInfo method.

Is this request related to a problem?

As of right now, it is not possible to access the register when you initialize the process via the CLI.

Alternatives you've considered

Monkey-patching, re-initialization, creating an entirely new compiler instance & getting a fresh type-checker.

@cspotcode
Copy link
Collaborator

I think we already expose the ts-node service on process[require('ts-node').REGISTER_INSTANCE]

https://github.com/TypeStrong/ts-node/blob/master/src/index.ts#L29-L43

Will that work for you?

@harrysolovay
Copy link
Author

Ahhh, yes you do! Apologies for filing this already-solved issue 👍 THANK YOU!

@cspotcode
Copy link
Collaborator

All good, I am always happy to have an easy answer for you!

@harrysolovay
Copy link
Author

getTypeInfo isn't getting me 100% of the way. How would you feel about exposing the service itself? I'd be more than happy to file a PR.

@harrysolovay harrysolovay reopened this Nov 8, 2020
@harrysolovay harrysolovay changed the title Feature Request: Accessing CLI-initialized Register Feature Request: Accessing CLI-initialized Service Nov 8, 2020
@cspotcode
Copy link
Collaborator

Technically we don't always use the language service. We use a different API in --compiler-host mode. It's not certain that we use the language service even today, and it's possible that future changes might move away from the language service entirely. That's my only reservation.

@harrysolovay
Copy link
Author

Makes sense. I'm wondering if there'd be a well-fitting approach to enable some greater introspection via the type-checker (assuming it's enabled). My hope is that I can use a call site to find a particular location in the compiled code, and then use that location to get the source location, to then get type info from the existing type-checker instance. This could open doors to some great experiences.

To reiterate, I'd like to do the following within the ts-node process:

  • look up a source location by its corresponding compiled location
  • access the builder program

Is there any approach with which you'd feel comfortable exposing this functionality?

@cspotcode
Copy link
Collaborator

For what it's worth, we already install source map support, so call sites should already be mapped to proper .ts locations.

I think exposing a getProgram() method is feasible, but it would return a Program, not a BuilderProgram. We might want to keep the API flagged as experimental, so it would be named experimentalGetProgram() and might change in the near future if it turns out to have issues.

I'm not sure if this would work correctly for composite projects, since I think they have multiple programs.

@harrysolovay
Copy link
Author

harrysolovay commented Nov 10, 2020

Unfortunately, it does not seem that the source-mapping extends to call sites :/

const _prepareStackTrace = Error.prepareStackTrace;
Error.prepareStackTrace = (_, stack) => stack;
const frames = new Error().stack?.slice(1) as any as NodeJS.CallSite[];
Error.prepareStackTrace = _prepareStackTrace;
console.log({
  column: frames[0].getColumnNumber(), // <-- returns incorrect column number
  line: frames[0].getLineNumber(), // <-- returns incorrect line number
});

How would you recommend I get the source location from the compiled source location? And would this require changes to ts-node?

As for accessing the program instance, register.getProgram() would be great!

How should we proceed?

@cspotcode
Copy link
Collaborator

To add getProgram():
All the methods of our service are created and returned within create() in index.ts
https://github.com/TypeStrong/ts-node/blob/master/src/index.ts#L975

Callsite mapping
Here is where we install source-map-support: https://github.com/TypeStrong/ts-node/blob/master/src/index.ts#L476-L492
It's a third-party library and we don't alter the way it does callsite mapping. We provide it with sourcemaps and let it do the rest.

@harrysolovay
Copy link
Author

Gotcha. Looking through and I'm uncertain of the place(s) from which to inject the program into the Register.

What's going on here... is this the right place from which to derive the program instance?

@cspotcode
Copy link
Collaborator

The create() function is a factory which creates each of the methods of Register. It uses if-else blocks to conditionally create a different implementation depending on 2x options: transpileOnly and compilerHost.

  • the transpileOnly implementation uses TypeScript's transpileModule function and does not support typechecking.
  • the compilerHost implementation uses TypeScript's CompilerHost API
  • the non-transpileOnly, non-compilerHost implementation uses TypeScript's LanguageService API

You're looking at the third implementation, but any changes to our Register API will need to be implemented for all 3. The transpileOnly implementation's getTypeInfo method throws an error because it cannot do typechecking. https://github.com/TypeStrong/ts-node/blob/master/src/index.ts#L948-L950

@harrysolovay
Copy link
Author

Hmm... not all of those implementations offer a program instance. I suppose it could be an optional field on the Register, but it feels inconsistent.

For the sake of this tool's longevity, this feature might be out-of-scope :/ I enjoy ts-node quite a lot and wouldn't want it bogged down by non-essential features. Thank you for considering this feature request nonetheless!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants