diff --git a/package-lock.json b/package-lock.json index 9e25be4310a5be..b23f5fbad982cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13881,7 +13881,6 @@ "is-promise": "^4.0.0", "lodash": "^4.17.21", "memize": "^1.1.0", - "redux": "^4.1.0", "turbo-combine-reducers": "^1.0.2", "use-memo-one": "^1.1.1" } @@ -14610,6 +14609,7 @@ "@babel/runtime": "^7.13.10", "is-promise": "^4.0.0", "lodash": "^4.17.21", + "redux": "^4.1.0", "rungen": "^0.3.2" } }, diff --git a/packages/data/package.json b/packages/data/package.json index f54851feaf6fd9..4799899d676666 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -38,10 +38,12 @@ "is-promise": "^4.0.0", "lodash": "^4.17.21", "memize": "^1.1.0", - "redux": "^4.1.0", "turbo-combine-reducers": "^1.0.2", "use-memo-one": "^1.1.1" }, + "peerDependencies": { + "redux": "^4.1.0" + }, "publishConfig": { "access": "public" } diff --git a/packages/data/tsconfig.json b/packages/data/tsconfig.json index 574fdc56223364..471410eceef0fe 100644 --- a/packages/data/tsconfig.json +++ b/packages/data/tsconfig.json @@ -11,8 +11,7 @@ { "path": "../element" }, { "path": "../is-shallow-equal" }, { "path": "../priority-queue" }, - // Needs to be added once it is typed - // { "path": "../redux-routine" } + { "path": "../redux-routine" } ], "include": [ "src/redux-store/metadata/actions.js" diff --git a/packages/redux-routine/CHANGELOG.md b/packages/redux-routine/CHANGELOG.md index bf149958f0a098..18f38c6079938e 100644 --- a/packages/redux-routine/CHANGELOG.md +++ b/packages/redux-routine/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Features + +- Added and published TypeScript annotations + ## 4.1.0 (2021-05-20) ## 4.0.0 (2021-05-14) diff --git a/packages/redux-routine/README.md b/packages/redux-routine/README.md index 067ae8fb331cb2..2a4f428461ae09 100644 --- a/packages/redux-routine/README.md +++ b/packages/redux-routine/README.md @@ -70,11 +70,11 @@ execution is not continued. _Parameters_ -- _controls_ `Object`: Object of control handlers. +- _controls_ `Record Promise | boolean>`: Object of control handlers. _Returns_ -- `Function`: Co-routine runtime +- `import('redux').Middleware`: Co-routine runtime diff --git a/packages/redux-routine/package.json b/packages/redux-routine/package.json index 6caa9ce2e5c9b4..7cc921fdc1d315 100644 --- a/packages/redux-routine/package.json +++ b/packages/redux-routine/package.json @@ -26,11 +26,13 @@ "main": "build/index.js", "module": "build-module/index.js", "react-native": "src/index", + "types": "build-types", "sideEffects": false, "dependencies": { "@babel/runtime": "^7.13.10", "is-promise": "^4.0.0", "lodash": "^4.17.21", + "redux": "^4.1.0", "rungen": "^0.3.2" }, "publishConfig": { diff --git a/packages/redux-routine/src/index.js b/packages/redux-routine/src/index.js index 99414dc56627bb..cd7101a61d99bf 100644 --- a/packages/redux-routine/src/index.js +++ b/packages/redux-routine/src/index.js @@ -12,9 +12,9 @@ import createRuntime from './runtime'; * value of the yield assignment. If the control handler returns undefined, the * execution is not continued. * - * @param {Object} controls Object of control handlers. + * @param {Record Promise | boolean>} controls Object of control handlers. * - * @return {Function} Co-routine runtime + * @return {import('redux').Middleware} Co-routine runtime */ export default function createMiddleware( controls = {} ) { return ( store ) => { diff --git a/packages/redux-routine/src/is-action.js b/packages/redux-routine/src/is-action.js index 152119d001fe29..f9a430b8b8f9a5 100644 --- a/packages/redux-routine/src/is-action.js +++ b/packages/redux-routine/src/is-action.js @@ -3,12 +3,13 @@ */ import { isPlainObject, isString } from 'lodash'; +/* eslint-disable jsdoc/valid-types */ /** * Returns true if the given object quacks like an action. * - * @param {*} object Object to test + * @param {any} object Object to test * - * @return {boolean} Whether object is an action. + * @return {object is import('redux').AnyAction} Whether object is an action. */ export function isAction( object ) { return isPlainObject( object ) && isString( object.type ); @@ -18,11 +19,12 @@ export function isAction( object ) { * Returns true if the given object quacks like an action and has a specific * action type * - * @param {*} object Object to test - * @param {string} expectedType The expected type for the action. + * @param {unknown} object Object to test + * @param {string} expectedType The expected type for the action. * - * @return {boolean} Whether object is an action and is of specific type. + * @return {object is import('redux').AnyAction} Whether object is an action and is of specific type. */ export function isActionOfType( object, expectedType ) { + /* eslint-enable jsdoc/valid-types */ return isAction( object ) && object.type === expectedType; } diff --git a/packages/redux-routine/src/is-generator.js b/packages/redux-routine/src/is-generator.js index 952d267ed4b061..414fc3f9dc17c3 100644 --- a/packages/redux-routine/src/is-generator.js +++ b/packages/redux-routine/src/is-generator.js @@ -1,13 +1,15 @@ +/* eslint-disable jsdoc/valid-types */ /** * Returns true if the given object is a generator, or false otherwise. * * @see https://www.ecma-international.org/ecma-262/6.0/#sec-generator-objects * - * @param {*} object Object to test. + * @param {any} object Object to test. * - * @return {boolean} Whether object is a generator. + * @return {object is Generator} Whether object is a generator. */ export default function isGenerator( object ) { + /* eslint-enable jsdoc/valid-types */ // Check that iterator (next) and iterable (Symbol.iterator) interfaces are satisfied. // These checks seem to be compatible with several generator helpers as well as the native implementation. return ( diff --git a/packages/redux-routine/src/rungen.d.ts b/packages/redux-routine/src/rungen.d.ts new file mode 100644 index 00000000000000..0d2c93ae3d6b5e --- /dev/null +++ b/packages/redux-routine/src/rungen.d.ts @@ -0,0 +1,17 @@ +declare module 'rungen' { + type Control = ( + value: any, + next: any, + iterate: any, + yieldNext: ( result: boolean ) => void, + yieldError: ( err: Error ) => void + ) => Promise< boolean > | boolean; + + function create( + ...args: any[] + ): ( + action: any, + successCallback: ( result: any ) => void, + errorCallaback: () => void + ) => void; +} diff --git a/packages/redux-routine/src/runtime.js b/packages/redux-routine/src/runtime.ts similarity index 67% rename from packages/redux-routine/src/runtime.js rename to packages/redux-routine/src/runtime.ts index 1148ea1af5ccdd..3f88a56c6a4f38 100644 --- a/packages/redux-routine/src/runtime.js +++ b/packages/redux-routine/src/runtime.ts @@ -1,9 +1,10 @@ /** * External dependencies */ -import { create } from 'rungen'; +import { create, Control } from 'rungen'; import { map } from 'lodash'; import isPromise from 'is-promise'; +import type { Dispatch, AnyAction } from 'redux'; /** * Internal dependencies @@ -13,15 +14,19 @@ import { isActionOfType, isAction } from './is-action'; /** * Create a co-routine runtime. * - * @param {Object} controls Object of control handlers. - * @param {Function} dispatch Unhandled action dispatch. - * - * @return {Function} co-routine runtime + * @param controls Object of control handlers. + * @param dispatch Unhandled action dispatch. */ -export default function createRuntime( controls = {}, dispatch ) { +export default function createRuntime( + controls: Record< + string, + ( value: any ) => Promise< boolean > | boolean + > = {}, + dispatch: Dispatch +) { const rungenControls = map( controls, - ( control, actionType ) => ( + ( control, actionType ): Control => ( value, next, iterate, @@ -42,7 +47,10 @@ export default function createRuntime( controls = {}, dispatch ) { } ); - const unhandledActionControl = ( value, next ) => { + const unhandledActionControl = ( + value: AnyAction | unknown, + next: () => void + ) => { if ( ! isAction( value ) ) { return false; } @@ -54,7 +62,7 @@ export default function createRuntime( controls = {}, dispatch ) { const rungenRuntime = create( rungenControls ); - return ( action ) => + return ( action: AnyAction | Generator ) => new Promise( ( resolve, reject ) => rungenRuntime( action, diff --git a/packages/redux-routine/tsconfig.json b/packages/redux-routine/tsconfig.json new file mode 100644 index 00000000000000..f108b30216124f --- /dev/null +++ b/packages/redux-routine/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "build-types", + "noUnusedParameters": false + }, + "include": [ "src/**/*" ] +}