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

[VEL-1590] Road to Glint support: Stage 2 — Kickoff Glint support #351

Open
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

phndiaye
Copy link
Member

@phndiaye phndiaye commented Dec 26, 2023

Background

Although we have pretty good Typescript support across the component library, it unfortunately can't see what's happening in templates, meaning we miss out on any typechecking and other helpful annotations it can provide.

Glint enables TypeScript to understand your templates as well, meaning you get end-to-end type safety for your entire application. You also get editor support for things like documentation and type info on hover, jumping to definitions, and automated codefixes and refactorings.

Interesting take on this too:

What does this PR do?

Built on top of the core dependencies updates, this PR introduces Glint setup and:

  • Updates components' signatures to the new format supported by Glint (via ember-codemod-args-to-signature codemod)
  • marks most components as type unsafe for the moment so we can gradually update
  • Make 2 helpers (fa-icon-style & fa-icon-value) type safe to serve as examples
  • Get helper typings for ember-intl's t helper and ember-truth-helpers common helpers (via https://github.com/Gavant/glint-template-types) as well as modifier typings for ember-render-modifiers (did-insert, will-destroy, etc.)

For the moment, only a couple component are considered "type-safe" and everything else is marked as type-unsafe. To enable full support, the best way (i believe) would be to first port components that depends on nothing (just HTML, no helpers, not using other components) then go up the chain with "composite" components (molecules?) and finish w/ the most complex ones.

To enable editor support for Glint, one needs to install the dedicated Glint Template Server extension:

What will affect us?

You'll notice that there are glint-nocheck comments in both the templates and the tests. This is what allows us to mark the components as type-unsafe so we can incrementally migrate them later.

While it doesn't make the templates way uglier, it does for tests files until we make them typesafe. Eventually, most of those comments will disappear as we increase the typesafety coverage.

However, It also forces us to pass the TestContext when rendering a component w/ a this usage in the args. This is something that's a good practice anyway but we were not doing it until now and it can affect the DX a bit. IMO, this can motivate us to always define a global renderComponent function in the tests so we don't have to put that render<TestContext>(...args) everytime.

Unfortunately (or fortunately 🤷‍♂️ ), Glint covers the same file covered by the tsconfig so we cannot opt-out of it on tests directory.

Final note: this PR only sets kicks off Glint support inside this package. Other ones in apps will follow to see the types are used.

Good PR checklist

  • Title makes sense
  • Is against the correct branch
  • Only addresses one issue
  • Properly assigned
  • Added/updated tests
  • Added/updated documentation
  • Migrated touched components to Glimmer Components
  • Properly labeled

types/glint.d.ts Outdated
Comment on lines 1 to 26
import '@glint/environment-ember-loose';
import '@gavant/glint-template-types/types/ember-intl/helpers/t';
import '@gavant/glint-template-types/types/ember-truth-helpers/and';
import '@gavant/glint-template-types/types/ember-truth-helpers/eq';
import '@gavant/glint-template-types/types/ember-truth-helpers/not';
import '@gavant/glint-template-types/types/ember-truth-helpers/or';

import type RenderModifiersRegistry from '@ember/render-modifiers/template-registry';
import TranslationHelper from 'ember-intl/helpers/t';
import And from 'ember-truth-helpers/helpers/and';
import Eq from 'ember-truth-helpers/helpers/eq';
import Not from 'ember-truth-helpers/helpers/not';
import Or from 'ember-truth-helpers/helpers/or';

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry extends RenderModifiersRegistry {
t: typeof TranslationHelper;
and: typeof And;
eq: typeof Eq;
not: typeof Not;
or: typeof Or;
}
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Types setup for render-modifiers, ember-intl, and ember-truth-helpers

Copy link
Member Author

Choose a reason for hiding this comment

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

This component is totally typesafe now, and when setup, the Glint language server should give you annotation on the arguments it needs along w/ their types :)

style?: IconStyle;
interface OSSIconSignature {
Args: {
icon: keyof typeof IconNames | string; // TODO: See https://github.com/FortAwesome/Font-Awesome/blob/6.x/js-packages/%40fortawesome/fontawesome-common-types/index.d.ts.
Copy link
Member Author

Choose a reason for hiding this comment

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

Turns out some icons we use are not listed, which is weird because they are in the right version 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

This is just to put a signature on a template-only component. Alternatively, we could create an empty component class and have the args defined just like other components you can see migrated in this PR.

await click('div');
assert.ok(this.redirectStub.calledOnceWithExactly(this.url, '_self'));
sinon.restore();
});

test('it redirects to the url on the provided target', async function (assert) {
this.redirectStub = sinon.stub(window, 'open');
await render(hbs`<div {{on "click" (redirect-to url=this.url target="_blank")}}>link</div>`);
await render<TestContext>(
Copy link
Member Author

Choose a reason for hiding this comment

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

TestContext usage example.

@phndiaye phndiaye changed the title Road to Glint support: Stage 2 — Kickoff Glint support [VEL-1590] Road to Glint support: Stage 2 — Kickoff Glint support Dec 28, 2023
Copy link

linear bot commented Dec 28, 2023

Base automatically changed from pn/chore/core-deps-update to master January 26, 2024 13:48
Copy link

sonarcloud bot commented Jan 31, 2024

Quality Gate Passed Quality Gate passed

The SonarCloud Quality Gate passed, but some issues were introduced.

116 New issues
0 Security Hotspots
No data about Coverage
2.4% Duplication on New Code

See analysis details on SonarCloud

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.

None yet

2 participants