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

[WIP] TypeScript #175

Closed

Conversation

buschtoens
Copy link
Contributor

Closes #140.

I had some spare time and wanted to start converting this addon over to TypeScript.
Unfortunately it doesn't fully work yet. But I'd like to gather some feedback already. 😊

apiURL: alias('options.apiURL'),
requestCredentials: alias('options.requestCredentials'),
export default class ApolloService extends Service {
client!: ApolloClient<any>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like using any here, but I'm not smart enough to know a more appropriate solution.

this.set('activeSubscriptions', A([]));
},
export default class QueryManager extends EmberObject {
@service apollo!: ApolloService;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the QueryManager guaranteed to only be instantiated through ApolloService#create QueryManager? In that case we should remove the @service injection here and make apollo a constructor parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can likely also drop the extends EmberObject bit.

export function getObservable(queryResult: {
[apolloObservableKey]: ObservableQuery;
}): ObservableQuery {
return queryResult[apolloObservableKey];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reckon that this is actually what was intended here.

In the original index.js this was done:

https://github.com/bgentry/ember-apollo-client/blob/98c5880830358d0506f5cc95ac23469ff69be7f7/addon/index.js#L5-L9

@josemarluedke
Copy link
Member

@buschtoens Thanks for starting the work on this. I'm very exited to have this addon in TS.

@bgentry I think it would be nice to start a new branch where we can merge the TS work into. That would allow us to move piece by piece, and so, once we are happy with the initial TS refactor, we could cut a beta release.

@buschtoens
Copy link
Contributor Author

ember-cli-typescript is available as an alpha for doing the transpilation with Babel. I can upgrade this PR to do that, however I'll then need to replace ember-auto-import with a custom setup, because of the aforementioned incompatibility.

@dfreeman
Copy link
Contributor

dfreeman commented Nov 6, 2018

It might be worthwhile to look at adding Babel 7 support to ember-auto-import rather than building custom import stuff here.

@ef4 said here that he'd ultimately like to have auto-import use a Babel plugin for discovering imports, which would avoid having to double-parse everything. That makes a ton of sense as a goal, but will also require some careful caching work to get right.

Maybe separating the Babel 7 support from that work and doing a first pass that continues with the status quo but can work with either the Babel 6 or 7 parser would be a good first step?

@josemarluedke
Copy link
Member

josemarluedke commented Nov 26, 2018

🎉 ember-auto-import v1.2.16 has now support for Babel 7. We should be unblocked now to move this PR further.

@buschtoens
Copy link
Contributor Author

Awesome! Maybe I can chip in some further work this evening. :)

@buschtoens buschtoens force-pushed the refactor/140-typescript branch from 11ab836 to c6d757c Compare December 5, 2018 19:12
@bgentry
Copy link
Member

bgentry commented Dec 5, 2018

@buschtoens Thank you for updating this! Is this ready for a review now that it's using the typescript-capable ember-auto-import?

This would actually be my first real experience with TypeScript. Is there anybody with more experience around it that can give this PR a review?

@buschtoens
Copy link
Contributor Author

buschtoens commented Dec 5, 2018

From the technical setup POV this is ready for a review. Only thing missing is failing the build for type errors, just because there are so many of them right now.

For all of this to make sense as a whole we also need #139, which can already be shipped before this PR.

The actual source code itself also needs some further TLC. Before merging this, I would like to remove all type errors. But until then we can already start reviewing this! :)

@buschtoens
Copy link
Contributor Author

buschtoens commented Dec 6, 2018

I've fixed all type errors. The remaining three errors are caused by missing *.d.ts for the test fixture *.gaphql:

tests/unit/services/apollo-test.ts:6:26 - error TS2307: Cannot find module '../build/test-mutation'.

6 import testMutation from '../build/test-mutation';
                           ~~~~~~~~~~~~~~~~~~~~~~~~

tests/unit/services/apollo-test.ts:5:23 - error TS2307: Cannot find module '../build/test-query'.

5 import testQuery from '../build/test-query';
                        ~~~~~~~~~~~~~~~~~~~~~

tests/unit/services/apollo-test.ts:6:26 - error TS2307: Cannot find module '../build/test-mutation'.

6 import testMutation from '../build/test-mutation';
                           ~~~~~~~~~~~~~~~~~~~~~~~~

In order to be able to enforce type checking and being able to merge this, we could codegen them statically for now.

I have no hands-on experience with GraphQL / Apollo (or this addon even 😂) yet, so I don't know what the preferred way for doing codegen is. Are these *.d.ts checked into the repo? Do we as ember-apollo-client need to provide automatic codegen to the consumer or is this something an IDE does?

What's the workflow here?

@buschtoens
Copy link
Contributor Author

Dang, Ember 2.12 is failing. Considering that the LTS schedule for 2.12 has expired, can we just remove it, if fixing this is non-trivial?

@josemarluedke
Copy link
Member

@buschtoens For the graphql files, we have a few options to proceed:

  1. Add @ts-ignore to these lines
  2. Add type definitions for these
  3. Allow importing files with .graphql extension (issue in broccoli-graphql-filter)

Here is what a fine definition would look like for the .graphql files

declare module '*.graphql' {
  import { DocumentNode } from 'graphql';
  const defaultDocument: DocumentNode;

  export default defaultDocument;
}

For codegen, I have been using https://graphql-code-generator.com/ for that and works great.

@bgentry
Copy link
Member

bgentry commented Dec 6, 2018

Dang, Ember 2.12 is failing. Considering that the LTS schedule for 2.12 has expired, can we just remove it, if fixing this is non-trivial?

Yes, I am absolutely down with removing old releases that are outside of LTS. I haven't done an ember-cli-update in awhile but that would probably include such a change.

@dfreeman
Copy link
Contributor

dfreeman commented Dec 6, 2018

I probably won't get to it in the next day or two, but I'm happy to give this a review next week if it's helpful.

@bgentry
Copy link
Member

bgentry commented Dec 17, 2018

This needs a rebase now that the Ember upgrade has been merged (thanks for that @buschtoens!).

@dfreeman have you or anybody else w/ TypeScript experience gotten to review this?

@buschtoens buschtoens force-pushed the refactor/140-typescript branch from 47a8132 to ca88c0c Compare December 17, 2018 19:53
@josemarluedke
Copy link
Member

I'm seeing the same problem with the duplicated graphql error. I have tried to add graphql as a peer dep, and it doesn't seem to solve it. @buschtoens If you could also take a look on that, it would be awesome. I will keep researching it.

@josemarluedke
Copy link
Member

I have submitted a PR to rebase this branch with latest changes on master:

buschtoens#8

@buschtoens
Copy link
Contributor Author

I'll have a look (latest) tomorrow, maybe already this evening. Thanks already!

@buschtoens buschtoens force-pushed the refactor/140-typescript branch from 12f8a02 to c0f1a0e Compare January 12, 2019 17:59
@buschtoens
Copy link
Contributor Author

My analysis in #175 (comment) of the graphql duplication bug was not 💯correct, but was thoroughly explained in embroider-build/ember-auto-import#170. In there Ed has explained that graphql needs to be defined as a peerDependency of ember-apollo-client and then as an actual dependency of the host app, similar to how it is done in graphql-tools. @josemarluedke has applied the fix in c0f1a0e.

However, Ed still uncovered a bug that is preventing our tests from going green: embroider-build/ember-auto-import#175

@@ -97,27 +112,30 @@ export default Service.extend({
* @return {!Object}
* @public
*/
clientOptions: computed(function() {
@computed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a need to make this a computed even if they are not dependent of any properties? Or should we add link,cache here?

Suggested change
@computed
@computed('link', 'cache')

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is computed to be cached.


cache: computed(function() {
@computed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This computed probably can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

let uri = this.get('apiURL');
let requestCredentials = this.get('requestCredentials');
const linkOptions = { uri, fetch };
@computed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, should we add dependent keys here?

Suggested change
@computed
@computed('requestCredentials', 'apiURL')

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand the original intention correctly, these three fields are computed without dependent keys, so that they are only computed once and are immutable afterwards, which makes sense because you cannot change these options, after the Apollo client has been instantiated.

See #186.

@@ -29,7 +29,7 @@ module.exports = {
toTree(tree) {
const GraphQLFilter = require('broccoli-graphql-filter');

return new GraphQLFilter(tree);
return new GraphQLFilter(tree, { keepExtension: true });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep backward compatibility, we need to add this as a configuration.

export default ApolloService.extend({
cache: computed(function() {
export default class extends ApolloService {
@computed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably doesn't need to be a computed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. It's a computed to make it cache / lazily instantiated. Using an assignment would have the same effect, but is eagerly evaluated. Just removing the @computed and making this a regular getter would return a new InMemoryChache instance every time.

// Override the clientOptions.
@computed
get clientOptions() {
const { get } = getSuperComputed(this, 'clientOptions');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is interesting. I wonder if this needs to be a computed property at all, if it doesn't then we could use use super.clientOptions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that these acrobatics are not really ideal. But I understand why it was implemented this way (see above comments). Maybe we can still find an alternative to computed.

@buschtoens
Copy link
Contributor Author

buschtoens commented Jan 26, 2019

Regarding the type generation for .gql, we might want to wait for typed-ember/ember-cli-typescript#192 instead?

Edit: lol, the RFC even mentions ember-apollo-client. Should have kept reading first. 😆

@bgentry
Copy link
Member

bgentry commented Mar 9, 2019

@buschtoens @josemarluedke are either of you able to summarize the current status of this PR? I'd really like to get it merged, but not actually sure what the remaining issues are. We're still on the 2.x beta series so it would be a good time to get any required breaking changes merged in.

I also merged subscription support so there might be slightly more surface area to convert.

@josemarluedke
Copy link
Member

@bgentry I'm really looking forward to move this forward, but we are blocked by this issue in ember-auto-import.

I'm wondering how can we keep moving the codebase for better TS support, a few things come to mind:

  • Move away from mixins
  • Convert to native classes
  • Decorators

I will start working on some of the above. I'm also looking forward to use this addon in Glimmer components (within ember).

@bgentry
Copy link
Member

bgentry commented Mar 9, 2019

If you think that ember-auto-import issue will be fixed soon, definitely ok to wait for that. Otherwise I like the approach you outlined. Don’t need to keep blocking on another issue if we can make obvious incremental improvements sooner.

@josemarluedke
Copy link
Member

As this PR stands at the moment, it would be very hard to land as it is. I will close this for now and we will use this as a reference for the TypeScript implementation. We still want to move to TS and with the recent refactorings, this will be easier now.

Thanks @buschtoens for your hard work here.

@buschtoens
Copy link
Contributor Author

Awesome 🚀

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

Successfully merging this pull request may close these issues.

Migrate to TypeScript
4 participants