diff --git a/.glintrc.yml b/.glintrc.yml new file mode 100644 index 00000000..10ef9a52 --- /dev/null +++ b/.glintrc.yml @@ -0,0 +1,4 @@ +environment: ember-loose +include: + - 'addon/**' + - 'tests/**' diff --git a/README.md b/README.md index 19ce6424..c29295a4 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,14 @@ For action helpers, this will mean better currying semantics: ``` +## Glint types +To enable Glint template typechecking for the addon, add: +```js +import 'ember-composable-helpers/glint'; +``` +anywhere you put your app's global types into, e.g. `types/global.d.ts`. +See also [Glint documentation](https://typed-ember.gitbook.io/glint/using-glint/ember/using-addons) + ## Upgrade Guide For help upgrading between major versions, check out the [upgrading documentation](https://github.com/DockYard/ember-composable-helpers/blob/master/UPGRADING.md). diff --git a/glint.d.ts b/glint.d.ts new file mode 100644 index 00000000..53ecd46c --- /dev/null +++ b/glint.d.ts @@ -0,0 +1,201 @@ +import { HelperLike } from '@glint/template'; + +type AnyFunction = (...args: never[]) => unknown; +type AnyObject = Record; + +declare module '@glint/environment-ember-loose/registry' { + export default interface Registry { + // Action helpers + pipe: HelperLike<{ + Args: { Positional: [AnyFunction[]] }; + Return: AnyFunction; + }>; + 'pipe-action': HelperLike<{ + Args: { Positional: [AnyFunction[]] }; + Return: AnyFunction; + }>; + call: HelperLike<{ + Args: { Positional: [func: AnyFunction] }; + Return: void; + }>; + compute: HelperLike<{ + Args: { Positional: [func: AnyFunction, args: unknown[]] }; + Return: unknown; + }>; + toggle: HelperLike<{ + Args: { Positional: [fieldName: string, obj: AnyObject] }; + Return: void; + }>; + 'toggle-action': HelperLike<{ + Args: { Positional: [fieldName: string, obj: AnyObject] }; + Return: AnyFunction; + }>; + noop: HelperLike<{ + Args: { Positional: [] }; + Return: AnyFunction; + }>; + optional: HelperLike<{ + Args: { Positional: [func?: AnyFunction] }; + Return: AnyFunction; + }>; + queue: HelperLike<{ + Args: { Positional: [AnyFunction[]] }; + Return: AnyFunction; + }>; + // Array helpers + map: HelperLike<{ + Args: { Positional: [callback: AnyFunction, array: unknown[]] }; + Return: unknown; + }>; + 'map-by': HelperLike<{ + Args: { Positional: [byPath: string, array: unknown[]] }; + Return: unknown; + }>; + 'sort-by': HelperLike<{ + Args: { Positional: [sortParams: string[] | AnyFunction, array: unknown[]] }; + Return: unknown[]; + }>; + filter: HelperLike<{ + Args: { Positional: [func: AnyFunction, array: unknown[]] }; + Return: unknown[]; + }>; + 'filter-by': HelperLike<{ + Args: { Positional: [fieldName: string, fieldValue: unknown | AnyFunction, array?: unknown[]] }; + Return: unknown[]; + }>; + 'reject-by': HelperLike<{ + Args: { Positional: [fieldName: string, fieldValue: unknown | AnyFunction, array?: unknown[]] }; + Return: unknown[]; + }>; + 'find-by': HelperLike<{ + Args: { Positional: [fieldName: string, fieldValue: unknown, array: unknown[]] }; + Return: unknown | undefined; + }>; + intersect: HelperLike<{ + Args: { Positional: [array1: Array, array2: unknown[]] }; + Return: Array | undefined; + }>; + invoke: HelperLike<{ + Args: { Positional: [methodName: string, obj: AnyObject | AnyObject[]] }; + Return: AnyFunction; + }>; + union: HelperLike<{ + Args: { Positional: [arrays: Array>] }; + Return: Array; + }>; + take: HelperLike<{ + Args: { Positional: [takeAmount: number, array: Array] }; + Return: Array; + }>; + drop: HelperLike<{ + Args: { Positional: [dropAmount: number, array: Array] }; + Return: Array; + }>; + reduce: HelperLike<{ + Args: { Positional: [callback: AnyFunction, initialValue: unknown, array?: unknown[]] }; + Return: unknown | undefined; + }>; + repeat: HelperLike<{ + Args: { Positional: [length: number, value?: unknown] }; + Return: unknown[]; + }>; + reverse: HelperLike<{ + Args: { Positional: [array: Array] }; + Return: Array; + }>; + range: HelperLike<{ + Args: { Positional: [min: number, max: number, inclusive?: boolean] }; + Return: number[]; + }>; + join: HelperLike<{ + Args: { Positional: [separator: string, rawArray: unknown | Array] }; + Return: string; + }>; + compact: HelperLike<{ + Args: { Positional: [rawArray: Array] }; + Return: Array; + }>; + includes: HelperLike<{ + Args: { Positional: [needleOrNeedles: unknown | Array, haystack: Array] }; + Return: boolean; + }>; + append: HelperLike<{ + Args: { Positional: [arrays: Array] }; + Return: Array; + }>; + chunk: HelperLike<{ + Args: { Positional: [num: number, array: Array] }; + Return: Array; + }>; + without: HelperLike<{ + Args: { Positional: [needleOrNeedles: unknown | Array, haystack: Array] }; + Return: Array; + }>; + shuffle: HelperLike<{ + Args: { Positional: [randomizer: AnyFunction | Array, array?: Array] }; + Return: Array; + }>; + flatten: HelperLike<{ + Args: { Positional: [array: Array] }; + Return: Array; + }>; + 'object-at': HelperLike<{ + Args: { Positional: [index: number, array: Array] }; + Return: unknown; + }>; + slice: HelperLike<{ + Args: { Positional: [start: number | Array, end?: number, array?: Array] }; + Return: Array; + }>; + next: HelperLike<{ + Args: { Positional: [currentValue: unknown, useDeepEqual?: boolean | Array, array?: Array] }; + Return: unknown; + }>; + 'has-next': HelperLike<{ + Args: { Positional: [currentValue: unknown, useDeepEqual?: boolean | Array, array?: Array] }; + Return: boolean; + }>; + previous: HelperLike<{ + Args: { Positional: [currentValue: unknown, useDeepEqual?: boolean | Array, array?: Array] }; + Return: unknown; + }>; + 'has-previous': HelperLike<{ + Args: { Positional: [currentValue: unknown, useDeepEqual?: boolean | Array, array?: Array] }; + Return: boolean; + }>; + // Object helpers + entries: HelperLike<{ + Args: { Positional: [obj: { [s: string]: unknown } | ArrayLike] }; + Return: [string, unknown][]; + }>; + 'from-entries': HelperLike<{ + Args: { Positional: [entries: Iterable] }; + Return: { [k: string]: unknown }; + }>; + 'group-by': HelperLike<{ + Args: { Positional: [byPath: string, array: AnyObject[] | AnyObject | Map | Set] }; + Return: Record>; + }>; + keys: HelperLike<{ + Args: { Positional: [obj: AnyObject] }; + Return: Array; + }>; + pick: HelperLike<{ + Args: { Positional: [path: string, action?: AnyFunction] }; + Return: AnyFunction; + }>; + values: HelperLike<{ + Args: { Positional: [obj: AnyObject] }; + Return: Array; + }>; + // Math helpers + inc: HelperLike<{ + Args: { Positional: [stepOrVal: number, val?: number] }; + Return: number; + }>; + dec: HelperLike<{ + Args: { Positional: [stepOrVal: number, val?: number] }; + Return: number; + }>; + } +} diff --git a/package.json b/package.json index 0c6b866a..124293c3 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "Composable helpers for Ember", "scripts": { "build": "ember build", + "glint": "node node_modules/@glint/core/bin/glint.js", "lint:hbs": "ember-template-lint .", "lint:js": "eslint .", "start": "ember serve", @@ -25,6 +26,8 @@ "@ember/optional-features": "^2.0.0", "@ember/test-helpers": "^2.4.2", "@embroider/test-setup": "^0.43.5", + "@glint/core": "^0.9.7", + "@glint/environment-ember-loose": "^0.9.7", "babel-eslint": "^10.0.3", "broccoli-asset-rev": "^3.0.0", "chai": "^3.5.0", @@ -35,7 +38,6 @@ "ember-cli-inject-live-reload": "^1.8.2", "ember-cli-release": "^0.2.9", "ember-cli-sri": "^2.1.1", - "ember-template-lint": "^3.6.0", "ember-cli-terser": "^4.0.2", "ember-data": "^3.28.0", "ember-disable-prototype-extensions": "^1.1.3", @@ -48,6 +50,7 @@ "ember-sinon": "^3.0.0", "ember-source": "~3.28.0", "ember-source-channel-url": "^2.0.1", + "ember-template-lint": "^3.6.0", "ember-try": "^1.4.0", "eslint": "^5.16.0", "eslint-plugin-ember": "^7.1.0", @@ -56,6 +59,7 @@ "mocha": "^2.4.5", "qunit": "^2.16.0", "qunit-dom": "^1.6.0", + "typescript": "^4.8.4", "webpack": "^5.64.4" }, "keywords": [