From fa8a2e7090757351327f7c01050fbb4587396b41 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:49:58 -0400 Subject: [PATCH 1/4] Add file for ensuring implicit .current --- test-app/app/components/implicit-current.gts | 21 ++++++++++++++++++++ test-app/tsconfig.json | 5 +++++ 2 files changed, 26 insertions(+) create mode 100644 test-app/app/components/implicit-current.gts diff --git a/test-app/app/components/implicit-current.gts b/test-app/app/components/implicit-current.gts new file mode 100644 index 000000000..4ba106311 --- /dev/null +++ b/test-app/app/components/implicit-current.gts @@ -0,0 +1,21 @@ +import { cell,resource } from 'ember-resources'; + +export const Now = resource(({ on }) => { + const now = cell(Date.now()); + + const timer = setInterval(() => { + now.set(Date.now()); + }); + + on.cleanup(() => { + clearInterval(timer); + }); + + return now; +}); + + + diff --git a/test-app/tsconfig.json b/test-app/tsconfig.json index 3afe8b29a..2a3bab3ec 100644 --- a/test-app/tsconfig.json +++ b/test-app/tsconfig.json @@ -6,6 +6,11 @@ "include": ["app/**/*", "tests/**/*", "type-tests/**/*", "types/**/*"], "compilerOptions": { "baseUrl": ".", + "skipLibCheck": true, + "noEmit": true, + "declaration": false, + "declarationMap": false, + "emitDeclarationOnly": false, "paths": { "test-app/tests/*": ["tests/*"], "test-app/*": ["app/*"], From 0420db7cf453a14fb8c5708738be4ce8649004a4 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:16:24 -0400 Subject: [PATCH 2/4] Make types more consistent --- test-app/app/components/implicit-current.gts | 1 + test-app/tests/core/implicit-current-test.gts | 38 +++++++++++++++++++ test-app/tests/type-tests/function-based.ts | 4 ++ 3 files changed, 43 insertions(+) create mode 100644 test-app/tests/core/implicit-current-test.gts diff --git a/test-app/app/components/implicit-current.gts b/test-app/app/components/implicit-current.gts index 4ba106311..933a6cfec 100644 --- a/test-app/app/components/implicit-current.gts +++ b/test-app/app/components/implicit-current.gts @@ -17,5 +17,6 @@ export const Now = resource(({ on }) => { diff --git a/test-app/tests/core/implicit-current-test.gts b/test-app/tests/core/implicit-current-test.gts new file mode 100644 index 000000000..5dcd0fbff --- /dev/null +++ b/test-app/tests/core/implicit-current-test.gts @@ -0,0 +1,38 @@ +import { on } from '@ember/modifier'; +import { click, render, settled } from '@ember/test-helpers'; +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; + +import { cell, resource, resourceFactory } from 'ember-resources'; + + +module('.current and implicit .current', function (hooks) { + setupRenderingTest(hooks); + + test('A resource has a current property', async function (assert) { + let change = () => 0; + const Now = resource(() => { + const now = cell(0); + + change = () => now.current++; + + return now; + }); + + await render( + + ); + + assert.dom('#implicit').hasText('0'); + assert.dom('explicit').hasText('0'); + + change(); + await settled(); + + assert.dom('#implicit').hasText('1'); + assert.dom('explicit').hasText('1'); + }); +}); diff --git a/test-app/tests/type-tests/function-based.ts b/test-app/tests/type-tests/function-based.ts index f96e01f92..d11cb3401 100644 --- a/test-app/tests/type-tests/function-based.ts +++ b/test-app/tests/type-tests/function-based.ts @@ -1,4 +1,5 @@ import { resource } from 'ember-resources'; +import { expectTypeOf } from 'expect-type'; import { expectType } from 'ts-expect'; /* @@ -13,3 +14,6 @@ import { expectType } from 'ts-expect'; */ expectType(resource(() => 'hi')); expectType(resource(() => () => 'hi')); + +expectTypeOf(resource(() => 'hi')).toMatchTypeOf(); +expectTypeOf(resource(() => 'hi')).toMatchTypeOf>(); From 25656df7840ab08775a05c430a296336b014fe57 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:47:24 -0400 Subject: [PATCH 3/4] wip --- ember-resources/package.json | 1 + ember-resources/src/index.ts | 2 +- ember-resources/src/resource.ts | 10 +++++----- ember-resources/src/types.ts | 2 ++ test-app/package.json | 1 + test-app/tests/type-tests/function-based.ts | 2 +- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/ember-resources/package.json b/ember-resources/package.json index 2c548e255..7a9e6c688 100644 --- a/ember-resources/package.json +++ b/ember-resources/package.json @@ -38,6 +38,7 @@ "start": "pnpm vite build --watch", "build": "pnpm vite build", "lint": "concurrently 'npm:lint:*(!fix)' --names 'lint:'", + "lint:types": "tsc --noEmit", "lint:fix": "concurrently 'npm:lint:*:fix' --names 'fix:'", "lint:js": "eslint . --cache", "lint:prettier": "prettier --check '**/*.{js,ts}'", diff --git a/ember-resources/src/index.ts b/ember-resources/src/index.ts index 88e04fe15..e1210f161 100644 --- a/ember-resources/src/index.ts +++ b/ember-resources/src/index.ts @@ -5,4 +5,4 @@ export { resource } from './resource.ts'; export { registerUsable, use } from './use.ts'; // Public Type Utilities -export type { Reactive, ResourceAPI } from './types.ts'; +export type { Reactive, Resource, ResourceAPI } from './types.ts'; diff --git a/ember-resources/src/resource.ts b/ember-resources/src/resource.ts index b26310ebd..ca5885015 100644 --- a/ember-resources/src/resource.ts +++ b/ember-resources/src/resource.ts @@ -7,7 +7,7 @@ import { INTERNAL } from './types.ts'; import { registerUsable } from './use.ts'; import { wrapForPlainUsage } from './utils.ts'; -import type { InternalFunctionResourceConfig, ResourceFn, ResourceFunction } from './types.ts'; +import type { InternalFunctionResourceConfig, Resource, ResourceFunction } from './types.ts'; const TYPE = 'function-based'; @@ -111,7 +111,7 @@ registerUsable(TYPE, (context: object, config: InternalFunctionResourceConfig) = * * ``` */ -export function resource(setup: ResourceFunction): Value; +export function resource(setup: ResourceFunction): Resource; /** * `resource` is an alternative API to the class-based `Resource`. @@ -167,14 +167,14 @@ export function resource(setup: ResourceFunction): Value; * } * ``` */ -export function resource(context: object, setup: ResourceFunction): Value; +export function resource(context: object, setup: ResourceFunction): Resource; /** */ export function resource( context: object | ResourceFunction, setup?: ResourceFunction, -): Value | InternalFunctionResourceConfig | ResourceFn { +): Value | InternalFunctionResourceConfig | Resource { if (!setup) { assert( `When using \`resource\` with @use, ` + @@ -205,7 +205,7 @@ export function resource( * using vanilla functions as resources without the resource wrapper * */ - return internalConfig as unknown as ResourceFn; + return internalConfig as unknown as Resource; } assert( diff --git a/ember-resources/src/types.ts b/ember-resources/src/types.ts index 3f38a7c66..cf35805b8 100644 --- a/ember-resources/src/types.ts +++ b/ember-resources/src/types.ts @@ -143,5 +143,7 @@ export type ResourceFunction = (hooks: ResourceAPI) => Value | */ export type ResourceFn = (hooks: ResourceAPI) => Value; +export type Resource = Value & Reactive; + export type Destructor = () => void; export type Cache = object; diff --git a/test-app/package.json b/test-app/package.json index 56968fab4..a2d26e8d5 100644 --- a/test-app/package.json +++ b/test-app/package.json @@ -12,6 +12,7 @@ }, "scripts": { "lint": "concurrently 'npm:lint:*(!fix)' --names 'lint:'", + "lint:types": "glint", "lint:fix": "concurrently 'npm:lint:*:fix' --names 'fix:'", "lint:hbs": "ember-template-lint . --no-error-on-unmatched-pattern", "lint:js": "eslint . --cache", diff --git a/test-app/tests/type-tests/function-based.ts b/test-app/tests/type-tests/function-based.ts index d11cb3401..b263972f6 100644 --- a/test-app/tests/type-tests/function-based.ts +++ b/test-app/tests/type-tests/function-based.ts @@ -1,4 +1,4 @@ -import { resource } from 'ember-resources'; +import { type Resource, resource } from 'ember-resources'; import { expectTypeOf } from 'expect-type'; import { expectType } from 'ts-expect'; From 9f616948f5b535c9863ad37e3aefdee0c92bb977 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:43:30 -0400 Subject: [PATCH 4/4] This might be blocked on accessor decorators --- ember-resources/src/type-tests/use.test.ts | 5 ++++- ember-resources/src/types.ts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ember-resources/src/type-tests/use.test.ts b/ember-resources/src/type-tests/use.test.ts index 023bff398..00584ea97 100644 --- a/ember-resources/src/type-tests/use.test.ts +++ b/ember-resources/src/type-tests/use.test.ts @@ -1,6 +1,8 @@ import { expectTypeOf } from 'expect-type'; -import { cell, type Reactive, resource, resourceFactory, use } from '../index.ts'; +import { cell, resource, resourceFactory, use } from '../index.ts'; + +import type { Reactive } from '../index.ts'; const StuckClock = resource(() => 2); @@ -36,6 +38,7 @@ class DemoA { let demoA = new DemoA(); expectTypeOf().toMatchTypeOf(); +expectTypeOf(demoA.clock).toMatchTypeOf>(); expectTypeOf().toMatchTypeOf>(); expectTypeOf().toMatchTypeOf(); expectTypeOf().toMatchTypeOf(); diff --git a/ember-resources/src/types.ts b/ember-resources/src/types.ts index cf35805b8..3f1389e8d 100644 --- a/ember-resources/src/types.ts +++ b/ember-resources/src/types.ts @@ -143,7 +143,7 @@ export type ResourceFunction = (hooks: ResourceAPI) => Value | */ export type ResourceFn = (hooks: ResourceAPI) => Value; -export type Resource = Value & Reactive; +export type Resource = Value | Reactive; export type Destructor = () => void; export type Cache = object;