UNPKG

ducks

Version:

🦆🦆🦆 Ducks is a Reducer Bundles Manager that Implementing the Redux Ducks Modular Proposal with Great Convenience.

184 lines 6.62 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateDuck = void 0; /** * Ducks - https://github.com/huan/ducks * * @copyright 2020 Huan LI (李卓桓) <https://github.com/huan> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ const assert_1 = __importDefault(require("assert")); const getLogger = (debug) => (msg) => { if (debug) { console.info(msg); } }; let log; /** * Huan(202005) TODO: * Testing static types in TypeScript * https://2ality.com/2019/07/testing-static-types.html * * use tsd? tsdlint? * * To be added in the future: * 1. check selectors take a state as argument and returns a function * 2. check operations take a store as argument and returns a function * 3. Conditional Type Checks - https://github.com/dsherret/conditional-type-checks */ function validateDuck(duck, debug = false) { log = getLogger(debug); validateActions(duck.actions); validateOperations(duck.operations); validateReducer(duck.default); validateSelectors(duck.selectors); validateTypes(duck.types); /** * Middlewares */ validateMiddlewares(duck.middlewares); validateEpics(duck.epics); validateSagas(duck.sagas); validateSetDucks(duck.setDucks); } exports.validateDuck = validateDuck; /** * * Sub Validating Functions * */ function validateReducer(reducer) { assert_1.default.strictEqual(typeof reducer, 'function', 'default export should be function'); // const func = (a = 42, b) => a + b // func.length === 0 // assert.strictEqual(reducer.length, 2, 'reducer should has two arguments. reducer name: ' + reducer.name + ' arguments length: ' + reducer.length + ' reducer function: ' + reducer.toString()) } function validateActions(actions) { assert_1.default.ok(actions, 'should exported actions'); for (const [key, val] of Object.entries(actions)) { log('validateActions: validating: ' + key + ', ' + val); validateString(key); validateActionType(val); } } function validateOperations(operations) { if (!operations) { return; } assert_1.default.ok(operations, 'should exported operations'); Object.keys(operations).forEach(validateString); Object.values(operations).forEach(validateOperationType); } function validateSelectors(selectors) { if (!selectors) { return; } assert_1.default.ok(selectors, 'should exported selectors'); Object.keys(selectors).forEach(validateString); Object.values(selectors).forEach(validateSelectorType); } function validateTypes(types) { if (!types) { return; } assert_1.default.ok(types, 'should exported types'); Object.keys(types).forEach(validateString); Object.values(types).forEach(validateString); } function validateMiddlewares(middlewares) { if (!middlewares) { return; } Object.keys(middlewares).forEach(validateString); Object.values(middlewares).forEach(validateMiddlewareType); } function validateSagas(sagas) { if (!sagas) { return; } Object.keys(sagas).forEach(validateString); Object.values(sagas).forEach(validateSagaType); } function validateEpics(epics) { if (!epics) { return; } Object.keys(epics).forEach(validateString); Object.values(epics).forEach(validateEpicType); } function validateSetDucks(setDucks) { if (setDucks) { assert_1.default.strictEqual(typeof setDucks, 'function', 'setDucks should be a function'); assert_1.default.strictEqual(setDucks.length, 1, 'setDucks() should take 1 argument for the Ducks instance'); } } /** * * Helper Functions * */ function validateString(value) { assert_1.default.strictEqual(typeof value, 'string', 'should be string type: ' + value); } function validateActionType(actionCreator) { if (typeof actionCreator === 'object') { for (const [key, val] of Object.entries(actionCreator)) { // .cancel will be undefined when not defined. if (key === 'cancel' && !val) { continue; } assertAsyncKey(key); assertFunction(val); } } else { assertFunction(actionCreator); } function assertFunction(creator) { assert_1.default.strictEqual(typeof creator, 'function', 'actionCreator is expected to be a function, but we got: ' + typeof creator + ', ' + String(creator)); } function assertAsyncKey(key) { const ASYNC_KEY_LIST = [ 'request', 'success', 'failure', 'cancel', ]; (0, assert_1.default)(ASYNC_KEY_LIST.includes(key), 'async action creator should with object keys: request/success/failure/cancel. we got: ' + key); } } function validateSelectorType(selector) { assert_1.default.strictEqual(typeof selector, 'function', 'selector should be a function'); } function validateOperationType(operation) { assert_1.default.strictEqual(typeof operation, 'function', 'operation should be a function'); } function validateMiddlewareType(middleware) { assert_1.default.strictEqual(typeof middleware, 'function', 'middleware should be a function'); assert_1.default.strictEqual(middleware.length, 1, 'middleware should has 1 arguments'); assert_1.default.match(middleware.name, /Middleware$/, 'middleware should be named as xxxMiddleware (ends with `Middleware`)'); } function validateSagaType(saga) { assert_1.default.strictEqual(typeof saga, 'function', 'saga should be a function'); assert_1.default.match(saga.name, /Saga$/, 'saga should be named as xxxSaga (ends with `Saga`)'); } function validateEpicType(epic) { assert_1.default.strictEqual(typeof epic, 'function', 'epic should be a function'); assert_1.default.match(epic.name, /Epic$/, 'epic should be named as xxxEpic (ends with `Epic`)'); } //# sourceMappingURL=validate-duck.js.map