From cbc99c0782c2f8d94bfe19644f8cdeabc936aac7 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sun, 29 Aug 2021 13:10:20 -0400 Subject: [PATCH 1/7] feat(readme): document and test how would would compose useFunction --- README.md | 85 ++++++++++++++++ tests/unit/composition-test.ts | 177 +++++++++++++++++++++++++++++++++ 2 files changed, 262 insertions(+) create mode 100644 tests/unit/composition-test.ts diff --git a/README.md b/README.md index 79bc19880..72290fa41 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ An implementation of Resources in Ember.JS without decorators. - [LifecycleResource](#lifecycleresource) - [Functions](#function-resources) - [Thunks](#thunks) + - [Composition](#composition) - [Public Types](#public-types) - [Testing](#testing) - [Contributing](#contributing) @@ -424,6 +425,90 @@ when an object is passed containing either keys: `named` or `positional`: This is the same shape of args used throughout Ember's Helpers, Modifiers, etc +### Composition + +These patterns are primarily unexplored so if you run in to any issues, +please [open a bug report / issue](https://github.com/NullVoxPopuli/ember-resources/issues/new). + +Composing class-based resources is expected to "just work", as classes maintain their own state. + +#### useFunction + useFunction + +```js +import Component from '@glimmer/component'; +import { useFunction } from 'ember-resources'; + +class MyComponent extends Component { + rand = useFunction(this, () => { + return useFunction(this, () => Math.random()); + }); +} +``` +Accessing the result of `Math.random()` would be done via: +```hbs +{{this.rand.value.value}} +``` + +Something to note about composing resources is that if arguments passed to the +outer resource change, the inner resources are discarded entirely. + +For example, you'll need to manage the inner resource's cache invalidation yourself if you want +the inner resource's behavior to be reactive based on outer arguments: + +
Example data fetching composed functions + +```js +import Component from '@glimmer/component'; +import { useFunction } from 'ember-resources'; + +class MyComponent extends Component { + @tracked id = 1; + @tracked storeName = 'blogs'; + + records = useFunction(this, (state, storeName) => { + let result: Array = []; + + if (state?.previous?.storeName === storeName) { + return state.previous.innerFunction; + } + + let innerFunction = useFunction(this, (prev, id) => { + // pretend we fetched a record using the store service + let newValue = `record:${storeName}-${id}`; + + result = [...(prev || []), newValue]; + + return result; + }, + () => [this.id] + ); + + return new Proxy(innerFunction, { + get(target, key, receiver) { + if (key === 'previous') { + return { + innerFunction, + storeName, + }; + } + + return Reflect.get(target, key, receiver); + }, + }); + }, + () => [this.storeName] + ); +} +``` +```hbs +{{this.records.value.value}} -- an array of "records" +``` + + +
+ + + ## Public Types diff --git a/tests/unit/composition-test.ts b/tests/unit/composition-test.ts new file mode 100644 index 000000000..ab3ded229 --- /dev/null +++ b/tests/unit/composition-test.ts @@ -0,0 +1,177 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +/* eslint-disable ember/no-get */ +import { tracked } from '@glimmer/tracking'; +import { setOwner } from '@ember/application'; +import { get as consumeTag } from '@ember/object'; +import { settled } from '@ember/test-helpers'; +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +import { useFunction } from 'ember-resources'; + +module('composition of hooks', function () { + module('in js', function (hooks) { + setupTest(hooks); + + module('useFunction ∘ useFunction', function () { + test('basics work', async function (assert) { + class Test { + rand = useFunction(this, () => { + return useFunction(this, () => Math.random()); + }); + } + + let foo = new Test(); + + setOwner(foo, this.owner); + + // @ts-ignore + consumeTag(foo, 'rand.value.value'); + + assert.equal(foo.rand.value?.value, undefined); + await settled(); + + assert.notEqual(foo.rand.value?.value, undefined); + }); + + test('persistent state within inner function', async function (assert) { + class Test { + @tracked offset = 1; + + rand = useFunction(this, () => { + let result: Array = []; + + let innerFunction = useFunction( + this, + (prev, offset: number) => { + let newValue = Math.random() + offset; + + result = [...(prev || []), newValue]; + + return result; + }, + () => [this.offset] + ); + + return innerFunction; + }); + } + + let foo = new Test(); + + setOwner(foo, this.owner); + + // @ts-ignore + consumeTag(foo, 'rand.value.value'); + + assert.equal(foo.rand.value?.value, undefined); + await settled(); + + assert.equal(foo.rand.value.value.length, 1); + assert.notEqual(foo.rand.value.value[0], undefined); + + let originalFirst = foo.rand.value.value[0]; + + foo.offset = 2; + + await settled(); + + // @ts-ignore + consumeTag(foo, 'rand.value.value'); + await settled(); + + assert.equal(foo.rand.value.value.length, 2); + assert.notEqual(foo.rand.value.value[0], undefined); + assert.notEqual(foo.rand.value.value[1], undefined); + assert.equal(originalFirst, foo.rand.value.value[0]); + assert.true((foo.rand.value.value[1] ?? -1) > 2); + }); + + test('persistent state with outer and within inner function', async function (assert) { + interface Previous { + value: Array; + previous: { innerFunction: { value: Array }; storeName: string }; + } + class Test { + @tracked id = 1; + @tracked storeName = 'blogs'; + + records = useFunction( + this, + (state: Previous | undefined, storeName) => { + let result: Array = []; + + if (state?.previous?.storeName === storeName) { + return state.previous.innerFunction; + } + + let innerFunction = useFunction( + this, + (prev, id: number) => { + // pretend we fetched a record using the store service + let newValue = `record:${storeName}-${id}`; + + result = [...(prev || []), newValue]; + + return result; + }, + () => [this.id] + ); + + return new Proxy(innerFunction, { + get(target, key, receiver) { + if (key === 'previous') { + return { + innerFunction, + storeName, + }; + } + + return Reflect.get(target, key, receiver); + }, + }); + }, + () => [this.storeName] + ); + } + + let foo = new Test(); + + setOwner(foo, this.owner); + + // @ts-ignore + consumeTag(foo, 'records.value.value'); + + assert.equal(foo.records.value?.value, undefined); + await settled(); + + assert.equal(foo.records.value.value.length, 1); + assert.equal(foo.records.value.value[0], 'record:blogs-1'); + + foo.id = 2; + + await settled(); + + // @ts-ignore + consumeTag(foo, 'records.value.value'); + await settled(); + + assert.equal(foo.records.value.value.length, 2); + assert.equal(foo.records.value.value[0], 'record:blogs-1'); + assert.equal(foo.records.value.value[1], 'record:blogs-2'); + + foo.id = 4; + foo.storeName = 'posts'; + + await settled(); + + // @ts-ignore + consumeTag(foo, 'records.value.value'); + await settled(); + + assert.equal(foo.records.value.value.length, 1); + assert.equal(foo.records.value.value[0], 'record:posts-4'); + }); + }); + }); +}); From fe0acff308d1aa11c0e1933ba18e7bd538e19d2b Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sun, 29 Aug 2021 13:11:10 -0400 Subject: [PATCH 2/7] fix(useFunction, typescript): you may now specify a return type without specifying the args type --- addon/-private/use-function.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addon/-private/use-function.ts b/addon/-private/use-function.ts index 56fd83342..d59bb8756 100644 --- a/addon/-private/use-function.ts +++ b/addon/-private/use-function.ts @@ -44,7 +44,7 @@ type UseFunctionArgs = * @param {Object} destroyable context, e.g.: component instance aka "this" * @param {Function} theFunction the function to run with the return value available on .value */ -export function useFunction( +export function useFunction( ...passed: NonReactiveVanilla ): { value: Return }; /** @@ -55,7 +55,7 @@ export function useFunction( * @param {Function} theFunction the function to run with the return value available on .value * @param {Function} thunk to generate / bind tracked data to the function so that the function can re-run when the tracked data updates */ -export function useFunction( +export function useFunction( ...passed: VanillaArgs ): { value: Return }; /** @@ -67,7 +67,7 @@ export function useFunction( * @param {Function} theFunction the function to run with the return value available on .value * @param {Function} thunk to generate / bind tracked data to the function so that the function can re-run when the tracked data updates */ -export function useFunction( +export function useFunction( ...passed: WithInitialValueArgs ): { value: Return }; /** @@ -78,11 +78,11 @@ export function useFunction( * @param {Object} initialValue - a non-function that matches the shape of the eventual return value of theFunction * @param {Function} theFunction the function to run with the return value available on .value */ -export function useFunction( +export function useFunction( ...passed: NonReactiveWithInitialValue ): { value: Return }; -export function useFunction( +export function useFunction( ...passedArgs: UseFunctionArgs ): { value: Return } { let [context] = passedArgs; From b51f10fcc2fd9d0cd27ac8319325198ee3142a00 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sun, 29 Aug 2021 13:12:08 -0400 Subject: [PATCH 3/7] feat(useHelper): can now reactively invoke helpers from JS This is a light wrapper around the built-in `invokeHelper` API (which also is what powers the other resources). ```js import someHelper from 'app-name/helpers/my-helper'; import { useHelper } from 'ember-resources'; export default class MyComponent extends Component { @tracked count = 0; myHelper = useHelper(this, someHelper, () => [this.count]); } ``` ```hbs {{this.myHelper.value}} ``` --- addon/-private/use-helper.ts | 35 ++++++++++++++++++++++++++++++++++ addon/index.ts | 1 + tests/unit/use-helper-test.ts | 36 +++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 addon/-private/use-helper.ts create mode 100644 tests/unit/use-helper-test.ts diff --git a/addon/-private/use-helper.ts b/addon/-private/use-helper.ts new file mode 100644 index 000000000..a31cc52c6 --- /dev/null +++ b/addon/-private/use-helper.ts @@ -0,0 +1,35 @@ +/* eslint-disable @typescript-eslint/ban-types */ +// typed-ember has not publihsed types for this yet +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import { getValue } from '@glimmer/tracking/primitives/cache'; +// typed-ember has not publihsed types for this yet +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import { invokeHelper } from '@ember/helper'; + +import { DEFAULT_THUNK, normalizeThunk } from './utils'; + +import type { Cache, Thunk } from './types'; +import type { helper as emberFunctionHelper } from '@ember/component/helper'; +import type Helper from '@ember/component/helper'; + +export function useHelper( + context: object, + helper: Helper | ReturnType, + thunk: Thunk = DEFAULT_THUNK +) { + let resource: Cache; + + return { + get value(): unknown { + if (!resource) { + resource = invokeHelper(context, helper, () => { + return normalizeThunk(thunk); + }) as Cache; + } + + return getValue(resource)!; // eslint-disable-line + }, + }; +} diff --git a/addon/index.ts b/addon/index.ts index abb0b5f00..188fc5a52 100644 --- a/addon/index.ts +++ b/addon/index.ts @@ -6,6 +6,7 @@ export { Resource } from './-private/resources/simple'; export { useTask } from './-private/ember-concurrency'; export { useFunction } from './-private/use-function'; export { useResource } from './-private/use-resource'; +export { useHelper } from './-private/use-helper'; // Public Type Utilities export type { ArgsWrapper, Named, Positional } from './-private/types'; diff --git a/tests/unit/use-helper-test.ts b/tests/unit/use-helper-test.ts new file mode 100644 index 000000000..4e7c25491 --- /dev/null +++ b/tests/unit/use-helper-test.ts @@ -0,0 +1,36 @@ +import { tracked } from '@glimmer/tracking'; +import { setOwner } from '@ember/application'; +import { helper } from '@ember/component/helper'; +import { settled } from '@ember/test-helpers'; +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +import { useHelper } from 'ember-resources'; + +module('Helpers', function () { + // not testing in template, because that's the easy part + module('in js', function (hooks) { + setupTest(hooks); + + test('it works', async function (assert) { + class Test { + @tracked count = 1; + + _doubler = helper(([num]) => num * 2); + + doubler = useHelper(this, this._doubler, () => [this.count]); + } + + let foo = new Test(); + + setOwner(foo, this.owner); + + assert.equal(foo.doubler.value, 2); + + foo.count = 4; + await settled(); + + assert.equal(foo.doubler.value, 8); + }); + }); +}); From 0bcfb160c0ed036c38431f3518cce1816d88b790 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sun, 29 Aug 2021 13:16:00 -0400 Subject: [PATCH 4/7] chore(internal): minor cleanup --- package-lock.json | 5 ----- tests/helpers/.gitkeep | 0 2 files changed, 5 deletions(-) delete mode 100644 tests/helpers/.gitkeep diff --git a/package-lock.json b/package-lock.json index 1b15d926d..4196e253a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23789,11 +23789,6 @@ "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, "engines": { "node": ">=0.10.0" } diff --git a/tests/helpers/.gitkeep b/tests/helpers/.gitkeep deleted file mode 100644 index e69de29bb..000000000 From 09fa9a3e8279a07e3a0b85cb798eb5fa18f2b483 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sun, 29 Aug 2021 13:18:47 -0400 Subject: [PATCH 5/7] chore(internal): add ember-addon-automated-ci to devDeps --- package-lock.json | 16 ++++++++++++++++ package.json | 7 ++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4196e253a..28951a8c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,6 +52,7 @@ "@typescript-eslint/parser": "^4.29.3", "babel-eslint": "^10.1.0", "broccoli-asset-rev": "^3.0.0", + "ember-addon-automated-ci": "^2.1.0", "ember-auto-import": "^2.1.0", "ember-cli": "~3.28.0", "ember-cli-app-version": "^5.0.0", @@ -10714,6 +10715,15 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, + "node_modules/ember-addon-automated-ci": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ember-addon-automated-ci/-/ember-addon-automated-ci-2.1.0.tgz", + "integrity": "sha512-yAFbbJID4J+nzG0pzxzLm2nYEbTyLY+RLvEI9foa8vHFH/cDb9vRTQv7fgWKKRdzULnRLUGtTNyAZ76z4fgiwg==", + "dev": true, + "engines": { + "node": "12.* || >= 14" + } + }, "node_modules/ember-auto-import": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ember-auto-import/-/ember-auto-import-2.1.0.tgz", @@ -39682,6 +39692,12 @@ } } }, + "ember-addon-automated-ci": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ember-addon-automated-ci/-/ember-addon-automated-ci-2.1.0.tgz", + "integrity": "sha512-yAFbbJID4J+nzG0pzxzLm2nYEbTyLY+RLvEI9foa8vHFH/cDb9vRTQv7fgWKKRdzULnRLUGtTNyAZ76z4fgiwg==", + "dev": true + }, "ember-auto-import": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ember-auto-import/-/ember-auto-import-2.1.0.tgz", diff --git a/package.json b/package.json index 926096d75..29f92c4eb 100644 --- a/package.json +++ b/package.json @@ -44,9 +44,6 @@ "@nullvoxpopuli/eslint-configs": "^1.4.0", "@semantic-release/changelog": "^5.0.1", "@semantic-release/git": "^9.0.0", - "@types/ember-data": "^3.16.15", - "@types/ember-qunit": "^3.4.14", - "@types/ember-resolver": "^5.0.10", "@types/ember__application": "^3.16.3", "@types/ember__array": "^3.16.4", "@types/ember__component": "^3.16.6", @@ -64,6 +61,9 @@ "@types/ember__test": "^3.16.1", "@types/ember__test-helpers": "^2.0.1", "@types/ember__utils": "^3.16.2", + "@types/ember-data": "^3.16.15", + "@types/ember-qunit": "^3.4.14", + "@types/ember-resolver": "^5.0.10", "@types/htmlbars-inline-precompile": "^1.0.1", "@types/qunit": "^2.11.2", "@types/rsvp": "^4.0.4", @@ -71,6 +71,7 @@ "@typescript-eslint/parser": "^4.29.3", "babel-eslint": "^10.1.0", "broccoli-asset-rev": "^3.0.0", + "ember-addon-automated-ci": "^2.1.0", "ember-auto-import": "^2.1.0", "ember-cli": "~3.28.0", "ember-cli-app-version": "^5.0.0", From b65ccbc84491198cd632f139ec89591b15cc2a62 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sun, 29 Aug 2021 13:25:27 -0400 Subject: [PATCH 6/7] chore(internal): update ember-addon-automated-ci blueprint --- .github/renovate.json5 | 24 +++++++++++-- .github/workflows/ci.yml | 8 +++-- .github/workflows/lint.yml | 5 +-- .github/workflows/types.yml | 43 ++++++++++++++++-------- package.json | 6 ++-- tests/dummy/config/ember-cli-update.json | 12 +++++-- 6 files changed, 71 insertions(+), 27 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index da5f01931..fc2fc088a 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -7,7 +7,16 @@ ], "automerge": true, "masterIssue": true, - "rangeStrategy": "bump", + // bump for apps + // update-lockfile for addons/libraries + "rangeStrategy": "update-lockfile", + // From the docs: + // https://docs.renovatebot.com/configuration-options/#packagerules + // Important to know: Renovate will evaluate all packageRules and not stop once it gets a first match. + // Therefore, you should order your packageRules in order of importance so that later rules can override + // settings from earlier rules if necessary. + // + // (so if something is to be disabled, place that rule last) "packageRules": [ //////////////////////////////////////// // Grouping namespaced packages together @@ -17,7 +26,13 @@ { "groupName": "Type Definitions", "packagePatterns": ["^@types\/*"], - "schedule": ["after 9pm on sunday"], + "schedule": ["after 9pm on sunday"] + }, + // This library needs to be bumped, because otherwise we would not + // receive blueprint updates whenever a release occurs + { + "packageNames": ["ember-addon-automated-ci"], + "rangeStrategy": "bump" }, { "groupName": "Lint Dependencies", @@ -76,6 +91,11 @@ "qunit", "npm-run-all" ] + }, + { + // changing peerDependencies *at all* is a breaking change + "matchDepTypes": ["peerDependencies"], + "enabled": false } ] } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e9ea3ffc..0c0b473b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,7 +85,7 @@ jobs: run: node_modules/.bin/ember try:one ${{ matrix.ember-try-scenario }} --skip-cleanup ember-cli-update: - if: github.event_name == 'pull_request' && github.event.pusher.name == 'renovate-bot' + if: "github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && ( ! contains(toJSON(github.event.commits.*.message), '[skip ci]') )" runs-on: ubuntu-latest needs: [tests, try-scenarios] @@ -93,7 +93,7 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ github.head_ref }} - token: ${{ secrets.GitHubToken }} + token: ${{ secrets.ECU_TOKEN }} - uses: actions/setup-node@v2 - uses: kellyselden/ember-cli-update-action@v3 with: @@ -111,6 +111,10 @@ jobs: with: persist-credentials: false - uses: volta-cli/action@v1 + - uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }} - run: npm install - name: Release diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 953ba833f..b255c00cd 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,15 +1,12 @@ name: Lint -# based on: -# - https://github.com/NullVoxPopuli/eslint-plugin-decorator-position/blob/master/.github/workflows/lint.yml -# - https://github.com/NullVoxPopuli/ember-autostash-modifier/blob/master/.github/workflows/ci.yml -# - https://github.com/emberjs/ember-test-helpers/blob/master/.github/workflows/ci-build.yml on: pull_request: push: # filtering branches here prevents duplicate builds from pull_request and push branches: - main + - master env: CI: true diff --git a/.github/workflows/types.yml b/.github/workflows/types.yml index ef49e3fb1..d956f2871 100644 --- a/.github/workflows/types.yml +++ b/.github/workflows/types.yml @@ -1,31 +1,46 @@ -name: Types - -# based on: -# - https://github.com/NullVoxPopuli/eslint-plugin-decorator-position/blob/master/.github/workflows/lint.yml -# - https://github.com/NullVoxPopuli/ember-autostash-modifier/blob/master/.github/workflows/ci.yml -# - https://github.com/emberjs/ember-test-helpers/blob/master/.github/workflows/ci-build.yml +name: "Types" on: pull_request: push: # filtering branches here prevents duplicate builds from pull_request and push branches: - main + - master env: CI: true jobs: - types: + install_dependencies: if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')" - name: Type Checking + name: Install Dependencies runs-on: ubuntu-latest + timeout-minutes: 15 steps: - - uses: actions/checkout@v2 - - uses: volta-cli/action@v1 + - uses: actions/checkout@v2 + - uses: volta-cli/action@v1 + - uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }} + - run: npm install - - run: npm install + types: + if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')" + name: "Type Correctness" + runs-on: ubuntu-latest + timeout-minutes: 5 + needs: [install_dependencies] - - name: Type Checking - # run: yarn tsc --build - run: npm run prepack + steps: + - uses: actions/checkout@v2 + - uses: volta-cli/action@v1 + - uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }} + - run: npm run prepack + # - run: yarn tsc --build + # - run: npm run prepack + # - run: npm exec tsc --build diff --git a/package.json b/package.json index 29f92c4eb..76cd3951a 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,9 @@ "@nullvoxpopuli/eslint-configs": "^1.4.0", "@semantic-release/changelog": "^5.0.1", "@semantic-release/git": "^9.0.0", + "@types/ember-data": "^3.16.15", + "@types/ember-qunit": "^3.4.14", + "@types/ember-resolver": "^5.0.10", "@types/ember__application": "^3.16.3", "@types/ember__array": "^3.16.4", "@types/ember__component": "^3.16.6", @@ -61,9 +64,6 @@ "@types/ember__test": "^3.16.1", "@types/ember__test-helpers": "^2.0.1", "@types/ember__utils": "^3.16.2", - "@types/ember-data": "^3.16.15", - "@types/ember-qunit": "^3.4.14", - "@types/ember-resolver": "^5.0.10", "@types/htmlbars-inline-precompile": "^1.0.1", "@types/qunit": "^2.11.2", "@types/rsvp": "^4.0.4", diff --git a/tests/dummy/config/ember-cli-update.json b/tests/dummy/config/ember-cli-update.json index 8075f1b2b..cb1b46e6a 100644 --- a/tests/dummy/config/ember-cli-update.json +++ b/tests/dummy/config/ember-cli-update.json @@ -9,8 +9,16 @@ "name": "addon", "outputRepo": "https://github.com/ember-cli/ember-addon-output", "codemodsSource": "ember-addon-codemods-manifest@1", - "isBaseBlueprint": true, - "options": [] + "isBaseBlueprint": true + } + ] + }, + { + "name": "ember-addon-automated-ci", + "version": "2.1.0", + "blueprints": [ + { + "name": "ember-addon-automated-ci" } ] } From c5c8669b6504fcf2538ba6f701ec533618ea9628 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sun, 29 Aug 2021 13:25:49 -0400 Subject: [PATCH 7/7] chore(internal): lint --fix --- addon/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/index.ts b/addon/index.ts index 188fc5a52..b11c12140 100644 --- a/addon/index.ts +++ b/addon/index.ts @@ -5,8 +5,8 @@ export { Resource } from './-private/resources/simple'; // Public API -- for reducing consumed API surface export { useTask } from './-private/ember-concurrency'; export { useFunction } from './-private/use-function'; -export { useResource } from './-private/use-resource'; export { useHelper } from './-private/use-helper'; +export { useResource } from './-private/use-resource'; // Public Type Utilities export type { ArgsWrapper, Named, Positional } from './-private/types';