diff --git a/package.json b/package.json index 4a11e4c..b8a73af 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,9 @@ "test": "jest", "single-test": "jest action-queue.evanescent-action.test.ts", "build": "tsc", - "pack": "npm run build && npm pack --pack-destination ~", "doc": "typedoc src/index-for-documentation.ts", - "prepublishOnly": "npm run build" + "make-tarball": "npm run build && npm run pack-locally", + "pack-locally": "npm pack --pack-destination ~/libs" }, "files": [ "dist", diff --git a/src/auxiliary/clone-object.ts b/src/auxiliary/clone-object.ts index 4f8da5c..2554673 100644 --- a/src/auxiliary/clone-object.ts +++ b/src/auxiliary/clone-object.ts @@ -1,5 +1,8 @@ export const cloneObject = (obj: any) => { + // it is causing errors in some of the stacks (e.g. older Create React App) + // @ts-ignore if (typeof structuredClone === "function") { + // @ts-ignore return structuredClone(obj); } /* istanbul ignore next */ diff --git a/src/auxiliary/get-unique-id.ts b/src/auxiliary/get-unique-id.ts index 32599ae..824a265 100644 --- a/src/auxiliary/get-unique-id.ts +++ b/src/auxiliary/get-unique-id.ts @@ -22,48 +22,15 @@ * SOFTWARE. */ -/* istanbul ignore next */ -const getCryptoRandomValues = (): number[] => { - const length = 16; - /** - * browser supports crypto API - */ - if (typeof window !== "undefined" && window.crypto?.getRandomValues) { - const array = new Uint32Array(length); - window.crypto.getRandomValues(array); - return Array.from(array); - } - /** - * Make this work for node.js - */ - if (typeof require === "function") { - const crypto = require("crypto"); - const array = crypto.randomBytes(length); - return Array.from(array); - } - return []; -}; +const randomized = () => Math.random().toString(16).slice(2); /** - * Generates an unique id. - * Useful for creating listener (callback) ids. - * Might be useful in other libraries like `key-value-state-container-react`. - * - * Example values returned: - * ``` - * "b18abf172490cb5bcd7ff108cc3b9c26" - * "bc4e0e4e0089fc7688c91f3256904a43" - * "78d6a7adb302fa91ea4561a2379969cf" - * "64e9d57be7b86406cd00f82b52c63ac9" - * "5a640299add47fb719f439ff9134fa58" - * "7690a143ce2ea74dab2c66f151186e43" - * ``` + * The previous implementation used crypto.getRandomValues() + * to generate unique random ids. + * + * However, problems to have this code compiled with Webpack 5 + * (and thus with the latest CRA) made the pure Math.random() + * more reasonable choice for job of auto-generating some random ids. + * See also https://github.com/facebook/create-react-app/issues/12865 */ -export const getUniqueId = () => { - const array = getCryptoRandomValues(); - let id = ""; - for (let i = 0; i < array.length; i++) { - id += array[i].toString(16).padStart(2, "0"); - } - return id; -}; +export const getUniqueId = () => `${randomized()}-${randomized()}`; diff --git a/src/register-state-changed-callback-logging.ts b/src/register-state-changed-callback-logging.ts index 0833eb6..30e74a0 100644 --- a/src/register-state-changed-callback-logging.ts +++ b/src/register-state-changed-callback-logging.ts @@ -1,18 +1,18 @@ /** * The MIT License (MIT) - * - * Copyright Tomasz Szatkowski and WealthArc https://www.wealtharc.com (c) 2023 - * + * + * Copyright Tomasz Szatkowski and WealthArc https://www.wealtharc.com (c) 2023 + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,12 +23,8 @@ */ import { ContainerInMemory } from "./types/container-in-memory"; -import { getActionPath } from "./auxiliary/get-action-path"; import { containers } from "./containers"; -import { - Action, - RegisterActionDispatchedCallbackArgs, -} from "./types/contracts"; +import { Action } from "./types/contracts"; interface Args { containerId: string; @@ -47,12 +43,10 @@ export const registerStateChangedCallbackLogging = ({ }: Args) => { switch (log) { case "container-not-found": { - if (container.config?.debug?.warnings) { - console.trace( - `Registration problem: container ${containerId} not found`, - containers - ); - } + console.trace( + `Registration problem: container ${containerId} not found`, + { containers } + ); break; } case "registered-listener-for-path": { diff --git a/src/tests/get-unique-id.test.ts b/src/tests/get-unique-id.test.ts index bdd9a9e..4330126 100644 --- a/src/tests/get-unique-id.test.ts +++ b/src/tests/get-unique-id.test.ts @@ -26,6 +26,6 @@ import _ from "lodash"; import { getUniqueId } from "../auxiliary/get-unique-id"; test("getUniqueId test", async () => { - const randomArray = Array.from({ length: 100000 }).map(() => getUniqueId()); + const randomArray = Array.from({ length: 1000000 }).map(() => getUniqueId()); expect(_.uniq(randomArray).length).toEqual(randomArray.length); }); diff --git a/src/types/contracts/dispatch-action.ts b/src/types/contracts/dispatch-action.ts index abe5020..b3642a7 100644 --- a/src/types/contracts/dispatch-action.ts +++ b/src/types/contracts/dispatch-action.ts @@ -1,18 +1,18 @@ /** * The MIT License (MIT) - * - * Copyright Tomasz Szatkowski and WealthArc https://www.wealtharc.com (c) 2023 - * + * + * Copyright Tomasz Szatkowski and WealthArc https://www.wealtharc.com (c) 2023 + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,37 +24,42 @@ import { Action } from "./action"; +export type DispatchActionArgs< + TState extends Object, + TAction extends Action, +> = { + /** + * The action object + */ + action: TAction; + /** + * The id of the container to which the action should be dispatched. + * If the container is not registered, the function will print a message, + * but will not throw an error. + */ + containerId: string; + /** + * Implements advanced scenario, in most cases you can ignore this. + * + * Sets some selected attributes to state "immediately" + * before waiting for `action` to get completely executed. + * + * The `immediateState` is a kind of "promise" the + * state (whole or particular attributes) will look like declared + * AFTER the action gets executed (`await reducer()` call gets done). + * + * Where it can be useful: in some of the React "asynchronous" aspects, + * where `getContainer()` calls might return inappropriate state. + */ + immediateState?: Partial; +}; + /** * @ignore * Contract for the `dispatchAction` function. */ export interface DispatchAction { ( - args: { - /** - * The action object - */ - action: TAction; - /** - * The id of the container to which the action should be dispatched. - * If the container is not registered, the function will print a message, - * but will not throw an error. - */ - containerId: string; - /** - * Implements advanced scenario, in most cases you can ignore this. - * - * Sets some selected attributes to state "immediately" - * before waiting for `action` to get completely executed. - * - * The `immediateState` is a kind of "promise" the - * state (whole or particular attributes) will look like declared - * AFTER the action gets executed (`await reducer()` call gets done). - * - * Where it can be useful: in some of the React "asynchronous" aspects, - * where `getContainer()` calls might return inappropriate state. - */ - immediateState?: Partial; - } + args: DispatchActionArgs, ): void; } diff --git a/src/types/contracts/register-state-container.ts b/src/types/contracts/register-state-container.ts index 2904a12..b8bb01d 100644 --- a/src/types/contracts/register-state-container.ts +++ b/src/types/contracts/register-state-container.ts @@ -40,6 +40,9 @@ export interface RegisterStateContainerArgs< /** * Please read the `AutoState` interface for more details. + * TODO: auto state should get invoked automatically after + * the initial state gets created (with all the keys initialized + * as the "changedPaths") */ autoState?: AutoState; diff --git a/src/types/contracts/unregister-action-dispatched-callback.ts b/src/types/contracts/unregister-action-dispatched-callback.ts index 32f2004..878cb1a 100644 --- a/src/types/contracts/unregister-action-dispatched-callback.ts +++ b/src/types/contracts/unregister-action-dispatched-callback.ts @@ -1,18 +1,18 @@ /** * The MIT License (MIT) - * - * Copyright Tomasz Szatkowski and WealthArc https://www.wealtharc.com (c) 2023 - * + * + * Copyright Tomasz Szatkowski and WealthArc https://www.wealtharc.com (c) 2023 + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,10 +24,16 @@ import { Action } from "./action"; +export interface UnregisterActionDispatchedCallbackArgs< + TAction extends Action +> { + action: Pick; + containerId: string; + listenerId: string; +} + export interface UnregisterActionDispatchedCallback { - (args: { - action: Pick; - containerId: string; - listenerId: string; - }): void; + ( + args: UnregisterActionDispatchedCallbackArgs + ): void; } diff --git a/src/types/contracts/unregister-state-changed-callback.ts b/src/types/contracts/unregister-state-changed-callback.ts index c6fa189..baece64 100644 --- a/src/types/contracts/unregister-state-changed-callback.ts +++ b/src/types/contracts/unregister-state-changed-callback.ts @@ -1,18 +1,18 @@ /** * The MIT License (MIT) - * - * Copyright Tomasz Szatkowski and WealthArc https://www.wealtharc.com (c) 2023 - * + * + * Copyright Tomasz Szatkowski and WealthArc https://www.wealtharc.com (c) 2023 + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,11 +24,15 @@ import { TKnownStatePath } from "./known-state-path"; +export interface UnregisterStateChangedCallbackArgs { + containerId: string; + lateInvoke?: boolean; + listenerId: string; + statePath: TKnownStatePath; +} + export interface UnregisterStateChangedCallback { - (args: { - containerId: string; - lateInvoke?: boolean; - listenerId: string; - statePath: TKnownStatePath - }): void -} \ No newline at end of file + ( + args: UnregisterStateChangedCallbackArgs + ): void; +}