Skip to content

Commit

Permalink
Merge pull request #491 from kaliber5/typescript
Browse files Browse the repository at this point in the history
Convert to TypeScript
  • Loading branch information
simonihmig authored May 16, 2022
2 parents 57cf2bc + e007b63 commit 0b86919
Show file tree
Hide file tree
Showing 9 changed files with 571 additions and 90 deletions.
20 changes: 18 additions & 2 deletions packages/ember-stargate/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

module.exports = {
root: true,
parser: 'babel-eslint',
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2018,
ecmaVersion: 2021,
sourceType: 'module',
ecmaFeatures: {
legacyDecorators: true,
Expand All @@ -21,6 +21,22 @@ module.exports = {
},
rules: {},
overrides: [
// ts files
{
files: ['**/*.ts'],
extends: [
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
'@typescript-eslint/explicit-module-boundary-types': 'error', // We want to be strict with types
'@typescript-eslint/explicit-function-return-type': 'error', // We want to be strict with types
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_' },
],
},
},
// node files
{
files: [
Expand Down
3 changes: 1 addition & 2 deletions packages/ember-stargate/babel.config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"presets": [["@babel/preset-typescript"]],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
"@babel/plugin-proposal-class-properties",
"@embroider/addon-dev/template-colocation-plugin"
]
}
16 changes: 9 additions & 7 deletions packages/ember-stargate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@
"dependencies": {
"@ember/render-modifiers": "^2.0.0",
"@embroider/addon-shim": "^1.0.0",
"@glimmer/component": "^1.0.4",
"ember-resources": "^4.4.0",
"@glimmer/component": "^1.1.2",
"ember-resources": "^4.6.4",
"tracked-maps-and-sets": "^3.0.1"
},
"devDependencies": {
"@babel/core": "7.17.10",
"@babel/plugin-proposal-class-properties": "7.16.7",
"@babel/plugin-proposal-decorators": "7.17.9",
"@babel/plugin-syntax-decorators": "7.17.0",
"@babel/preset-typescript": "^7.16.7",
"@embroider/addon-dev": "1.6.0",
"@rollup/plugin-babel": "5.3.1",
"@types/ember": "^4.0.0",
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"babel-eslint": "10.1.0",
"ember-template-lint": "4.8.0",
"eslint": "7.32.0",
Expand All @@ -51,7 +51,9 @@
"eslint-plugin-prettier": "4.0.0",
"eslint-plugin-qunit": "7.2.0",
"npm-run-all": "4.1.5",
"rollup": "2.73.0"
"rollup": "2.73.0",
"rollup-plugin-ts": "^2.0.7",
"typescript": "^4.6.4"
},
"engines": {
"node": "12.* || >= 14"
Expand Down
13 changes: 10 additions & 3 deletions packages/ember-stargate/rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import babel from '@rollup/plugin-babel';
import typescript from 'rollup-plugin-ts';
import { Addon } from '@embroider/addon-dev/rollup';

const addon = new Addon({
Expand All @@ -14,18 +14,25 @@ export default {
plugins: [
// These are the modules that users should be able to import from your
// addon. Anything not listed here may get optimized away.
addon.publicEntrypoints(['components/**/*.js', 'services/**/*.js']),
addon.publicEntrypoints(['components/**/*.ts', 'services/**/*.ts']),

// These are the modules that should get reexported into the traditional
// "app" tree. Things in here should also be in publicEntrypoints above, but
// not everything in publicEntrypoints necessarily needs to go here.
addon.appReexports(['components/**/*.js', 'services/**/*.js']),

// compile TypeScript
typescript({
transpiler: 'babel',
browserslist: false,
transpileOnly: false,
}),

// This babel config should *not* apply presets or compile away ES modules.
// It exists only to provide development niceties for you, like automatic
// template colocation.
// See `babel.config.json` for the actual Babel configuration!
babel({ babelHelpers: 'bundled' }),
// babel({ babelHelpers: 'bundled' }),

// Ensure that standalone .hbs files are properly integrated as Javascript.
addon.hbs(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,28 @@ import Component from '@glimmer/component';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import { assert } from '@ember/debug';
import type PortalService from '../services/-portal';

export default class PortalTargetComponent extends Component {
interface PortalTargetSignature {
Element: HTMLDivElement;
Args: {
name: string;
multiple?: boolean;
onChange?: (count: number) => void;
};
Blocks: { default: [number] };
}

export default class PortalTargetComponent extends Component<PortalTargetSignature> {
@service('-portal')
portalService;
portalService!: PortalService;

get count() {
get count(): number {
return this.portalService.getPortalCount(this.args.name);
}

@action
register(element) {
register(element: Element): void {
assert('PortalTargets needs a name', this.args.name);
const options = {
multiple: this.args.multiple,
Expand All @@ -22,7 +33,7 @@ export default class PortalTargetComponent extends Component {
}

@action
unregister() {
unregister(): void {
this.portalService.unregisterTarget(this.args.name);
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { next } from '@ember/runloop';
import { LifecycleResource, useResource } from 'ember-resources';
import { LifecycleResource, Positional, useResource } from 'ember-resources';
import type PortalService from '../services/-portal';
import type { Target } from '../services/-portal';

class PortalTrackerResource extends LifecycleResource {
class PortalTrackerResource extends LifecycleResource<Positional<[string]>> {
@service('-portal')
portalService;
portalService!: PortalService;

_target;
_target!: string;

get target() {
get target(): Target | undefined {
return this.portalService.getTarget(this._target);
}

setup() {
setup(): void {
this._target = this.args.positional[0];
next(() => this.portalService.registerPortal(this._target));
}

update() {
update(): void {
const previousTarget = this._target;
const newTarget = this.args.positional[0];
next(() => {
Expand All @@ -28,19 +30,30 @@ class PortalTrackerResource extends LifecycleResource {
this._target = newTarget;
}

teardown() {
teardown(): void {
this.portalService.unregisterPortal(this._target);
}
}

export default class PortalComponent extends Component {
interface PortalSignature {
Args: {
target: string;
renderInPlace?: boolean;
fallback?: 'inplace';
};
Blocks: { default: [] };
}

export default class PortalComponent extends Component<PortalSignature> {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore the types of ember-resources cause an error here
tracker = useResource(this, PortalTrackerResource, () => [this.args.target]);

get target() {
get target(): Target | undefined {
return this.tracker.target;
}

get renderInPlace() {
get renderInPlace(): boolean {
return (
this.args.renderInPlace === true ||
(!this.target && this.args.fallback === 'inplace')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,24 @@ import { assert } from '@ember/debug';
import { next } from '@ember/runloop';
import { TrackedMap } from 'tracked-maps-and-sets';

class TargetTracker {
name;
element;
multiple;
onChange;
interface TargetTrackerOptions {
multiple?: boolean;
onChange?: (count: number) => void;
}

export interface Target {
name: string;
element: Element;
multiple: boolean;
}

class TargetTracker implements Target {
name: string;
element: Element;
multiple: boolean;
onChange?: (count: number) => void;

constructor(name, element, options) {
constructor(name: string, element: Element, options: TargetTrackerOptions) {
this.name = name;
this.element = element;
this.multiple = options.multiple ?? false;
Expand All @@ -18,52 +29,62 @@ class TargetTracker {
}

export default class PortalService extends Service {
#targets = new TrackedMap();
#portalCount = new TrackedMap();
#targets = new TrackedMap<string, TargetTracker>();
#portalCount = new TrackedMap<string, number>();

getTarget(name) {
getTarget(name: string): Target | undefined {
return this.#targets.get(name);
}

getPortalCount(name) {
getPortalCount(name: string): number {
return this.#portalCount.get(name) ?? 0;
}

registerTarget(name, element, options) {
registerTarget(
name: string,
element: Element,
options: TargetTrackerOptions
): void {
next(this, () => {
assert(
`Portal target with name ${name} already exists`,
!this.#targets.has(name)
);

this.#targets.set(name, new TargetTracker(name, element, options));
});
}

unregisterTarget(name) {
unregisterTarget(name: string): void {
this.#targets.delete(name);
}

registerPortal(name) {
registerPortal(name: string): void {
const count = (this.#portalCount.get(name) ?? 0) + 1;
this.#portalCount.set(name, count);
const target = this.getTarget(name);
const target = this.#targets.get(name);
if (target && target.onChange) {
target.onChange(count);
}
}

unregisterPortal(name) {
unregisterPortal(name: string): void {
let count = this.#portalCount.get(name) ?? 0;
assert(
`Trying to unregister a portal "${name}" that hasn't been registered before`,
count > 0
);
count--;
this.#portalCount.set(name, count);
const target = this.getTarget(name);
const target = this.#targets.get(name);
if (target && target.onChange) {
target.onChange(count);
}
}
}

// DO NOT DELETE: this is how TypeScript knows how to look up your services.
declare module '@ember/service' {
interface Registry {
'-portal': PortalService;
}
}
15 changes: 15 additions & 0 deletions packages/ember-stargate/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "es2015",
"inlineSourceMap": true,
"inlineSources": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"strict": true,
"declaration": true
},
"include": [
"src/**/*",
]
}
Loading

0 comments on commit 0b86919

Please sign in to comment.