Skip to content

Commit c5104dd

Browse files
committed
Install TypeScript
1 parent abe304b commit c5104dd

12 files changed

+15742
-11727
lines changed

.eslintrc.js

+12-7
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@
22

33
module.exports = {
44
root: true,
5-
parser: 'babel-eslint',
5+
parser: '@typescript-eslint/parser',
66
parserOptions: {
7-
ecmaVersion: 2018,
8-
sourceType: 'module',
9-
ecmaFeatures: {
10-
legacyDecorators: true,
11-
},
7+
ecmaVersion: 'latest',
128
},
13-
plugins: ['ember'],
9+
plugins: ['ember', '@typescript-eslint'],
1410
extends: [
1511
'eslint:recommended',
1612
'plugin:prettier/recommended',
@@ -21,6 +17,15 @@ module.exports = {
2117
},
2218
rules: {},
2319
overrides: [
20+
// ts files
21+
{
22+
files: ['**/*.ts'],
23+
extends: [
24+
'plugin:@typescript-eslint/eslint-recommended',
25+
'plugin:@typescript-eslint/recommended',
26+
],
27+
rules: {},
28+
},
2429
// node files
2530
{
2631
files: [

addon/index.js addon/index.ts

+17-12
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const managedKeys = new Set();
44
const localStorageCache = new TrackedMap();
55

66
// like JSON.parse() but all returned objects are frozen
7-
function jsonParseAndFreeze(json) {
7+
function jsonParseAndFreeze(json: string) {
88
return JSON.parse(json, (key, value) =>
99
typeof value === 'object' ? Object.freeze(value) : value
1010
);
@@ -22,19 +22,23 @@ window.addEventListener('storage', function ({ key, newValue }) {
2222
return;
2323
}
2424

25-
localStorageCache.set(key, jsonParseAndFreeze(newValue));
25+
localStorageCache.set(key, jsonParseAndFreeze(newValue as string));
2626
});
2727

28-
export default function localStorageDecoratorFactory(...args) {
28+
export default function localStorageDecoratorFactory(...args: unknown[]) {
2929
const isDirectDecoratorInvocation = isElementDescriptor(...args);
3030
const customLocalStorageKey = isDirectDecoratorInvocation
3131
? undefined
3232
: args[0];
3333

34-
function localStorageDecorator(target, key, descriptor) {
34+
function localStorageDecorator(
35+
target: unknown,
36+
key: PropertyKey,
37+
descriptor: PropertyDecorator & { initializer: () => void }
38+
) {
3539
const localStorageKey = customLocalStorageKey ?? key;
3640

37-
initalizeLocalStorageKey(localStorageKey);
41+
initalizeLocalStorageKey(localStorageKey as string);
3842

3943
// register getter and setter
4044
return {
@@ -46,21 +50,22 @@ export default function localStorageDecoratorFactory(...args) {
4650
: undefined)
4751
);
4852
},
49-
set(value) {
53+
set(value: unknown) {
5054
const json = JSON.stringify(value);
5155

5256
// Update local storage cache. It must include a froozen copy the
5357
// the value to prevent leaking state between different consumers.
5458
localStorageCache.set(localStorageKey, jsonParseAndFreeze(json));
5559

5660
// Update local storage.
57-
window.localStorage.setItem(localStorageKey, json);
61+
window.localStorage.setItem(localStorageKey as string, json);
5862
},
5963
};
6064
}
6165

6266
return isDirectDecoratorInvocation
63-
? localStorageDecorator(...args)
67+
? // @ts-expect-error A spread argument must either have a tuple type or be passed to a rest parameter.
68+
localStorageDecorator(...args)
6469
: localStorageDecorator;
6570
}
6671

@@ -69,7 +74,7 @@ export function clearLocalStorageCache() {
6974
localStorageCache.clear();
7075
}
7176

72-
export function initalizeLocalStorageKey(key) {
77+
export function initalizeLocalStorageKey(key: string) {
7378
// Check if key is already managed. If it is not managed yet, initialize it
7479
// in localStorageCache with the current value in local storage.
7580
// Need to use a separate, not tracked data store to do this check
@@ -79,7 +84,7 @@ export function initalizeLocalStorageKey(key) {
7984
managedKeys.add(key);
8085
localStorageCache.set(
8186
key,
82-
jsonParseAndFreeze(window.localStorage.getItem(key))
87+
jsonParseAndFreeze(window.localStorage.getItem(key) as string)
8388
);
8489
}
8590
}
@@ -88,8 +93,8 @@ export function initalizeLocalStorageKey(key) {
8893
//
8994
// Borrowed from the Ember Data source code:
9095
// https://github.com/emberjs/data/blob/22a8f20e2f11ed82c85160944e976073dc530d8b/packages/model/addon/-private/util.ts#L5
91-
function isElementDescriptor(...args) {
92-
let [maybeTarget, maybeKey, maybeDescriptor] = args;
96+
function isElementDescriptor(...args: unknown[]) {
97+
const [maybeTarget, maybeKey, maybeDescriptor] = args;
9398

9499
return (
95100
// Ensure we have the right number of args

ember-cli-build.js

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
44

55
module.exports = function (defaults) {
66
let app = new EmberAddon(defaults, {
7+
'ember-cli-babel': { enableTypeScriptTransform: true },
8+
79
// Add options here
810
});
911

index.js

+4
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@
22

33
module.exports = {
44
name: require('./package').name,
5+
6+
options: {
7+
'ember-cli-babel': { enableTypeScriptTransform: true },
8+
},
59
};

package.json

+12-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
"lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",
1818
"lint:hbs": "ember-template-lint .",
1919
"lint:js": "eslint .",
20+
"lint:types": "tsc --noEmit",
21+
"prepack": "tsc --project tsconfig.declarations.json",
22+
"postpack": "rimraf declarations",
2023
"start": "ember serve",
2124
"test": "npm-run-all lint:* test:*",
2225
"test:ember": "ember test",
@@ -32,7 +35,13 @@
3235
"@ember/test-helpers": "^2.4.2",
3336
"@glimmer/component": "^1.0.2",
3437
"@glimmer/tracking": "^1.0.2",
35-
"babel-eslint": "^10.1.0",
38+
"@glint/environment-ember-loose": "^1.4.0",
39+
"@glint/template": "^1.4.0",
40+
"@tsconfig/ember": "^3.0.8",
41+
"@types/qunit": "^2.19.10",
42+
"@types/rsvp": "^4.0.9",
43+
"@typescript-eslint/eslint-plugin": "^6.21.0",
44+
"@typescript-eslint/parser": "^6.21.0",
3645
"broccoli-asset-rev": "^3.0.0",
3746
"ember-auto-import": "^2.0.0",
3847
"ember-cli": "~4.11.0",
@@ -63,6 +72,8 @@
6372
"qunit-dom": "^2.0.0",
6473
"release-it": "^15.0.0",
6574
"release-it-lerna-changelog": "^5.0.0",
75+
"rimraf": "^5.0.1",
76+
"typescript": "^5.4.5",
6677
"webpack": "^5.60.0"
6778
},
6879
"engines": {
File renamed without changes.
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Type declarations for
3+
* import config from 'dummy/config/environment'
4+
*/
5+
declare const config: {
6+
environment: string;
7+
modulePrefix: string;
8+
podModulePrefix: string;
9+
locationType: 'history' | 'hash' | 'none';
10+
rootURL: string;
11+
APP: Record<string, unknown>;
12+
};
13+
14+
export default config;
File renamed without changes.

tsconfig.declarations.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"declarationDir": "declarations",
5+
"emitDeclarationOnly": true,
6+
"noEmit": false,
7+
"rootDir": "."
8+
},
9+
"include": ["addon", "addon-test-support"]
10+
}

tsconfig.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"extends": "@tsconfig/ember/tsconfig.json",
3+
"compilerOptions": {
4+
// The combination of `baseUrl` with `paths` allows Ember's classic package
5+
// layout, which is not resolvable with the Node resolution algorithm, to
6+
// work with TypeScript.
7+
"baseUrl": ".",
8+
"paths": {
9+
"dummy/tests/*": ["tests/*"],
10+
"dummy/*": ["tests/dummy/app/*", "app/*"],
11+
"ember-local-storage-decorator": ["addon"],
12+
"ember-local-storage-decorator/*": ["addon/*"],
13+
"ember-local-storage-decorator/test-support": ["addon-test-support"],
14+
"ember-local-storage-decorator/test-support/*": ["addon-test-support/*"],
15+
"*": ["types/*"]
16+
}
17+
}
18+
}

types/global.d.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import '@glint/environment-ember-loose';
2+
3+
import 'ember-source/types';
4+
import 'ember-source/types/preview';

0 commit comments

Comments
 (0)