From 43e2fcd4413d2bcd1dbddd08de34885fdcf4fa85 Mon Sep 17 00:00:00 2001 From: Layton Whiteley Date: Tue, 9 Jan 2024 14:01:55 +0100 Subject: [PATCH] refactor: use `options` as second parameter (#5) * refactor: use options as second parameter * refactor: create shouldSaveHistory utility * build: generate docs before release * chore: continue support for boolean second param * chore: remove process.env reference * chore: move warning to main file --- .github/workflows/ci.yml | 1 + .release-it.json | 2 +- packages/history-utility/README.md | 1 + packages/history-utility/docs/modules.md | 34 ++++++--- packages/history-utility/project.json | 2 +- .../history-utility/src/history-utility.ts | 69 +++++++++++++++---- packages/history-utility/tsconfig.json | 2 +- packages/history-utility/tsconfig.lib.json | 2 +- packages/history-utility/tsconfig.spec.json | 1 + tsconfig.base.json | 2 +- 10 files changed, 90 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d56ed0..aeed23f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,3 +38,4 @@ jobs: - run: pnpm nx format:check - run: pnpm nx affected -t lint,test --parallel=3 + - run: pnpm nx run-many -t build --parallel=3 --projects=tag:publish diff --git a/.release-it.json b/.release-it.json index 56ae11e..52d14fc 100644 --- a/.release-it.json +++ b/.release-it.json @@ -13,7 +13,7 @@ "versionArgs": ["--workspaces false"] }, "hooks": { - "after:bump": "pnpx auto-changelog -p" + "after:bump": ["pnpx auto-changelog -p", "pnpm nx run-many -t docs"] }, "plugins": { "@release-it/bumper": { diff --git a/packages/history-utility/README.md b/packages/history-utility/README.md index cec9a85..7692124 100644 --- a/packages/history-utility/README.md +++ b/packages/history-utility/README.md @@ -52,3 +52,4 @@ export default function App() { - the `history` object has changes - `history.snapshots` is renamed to `history.nodes` - a `HistoryNode` has the structure `{ snapshot: Snapshot; createdAt: Date; updatedAt?: Date; }` +- The second parameter of `proxyWithHistory` is now an object instead of a `boolean`. `{ skipSubscribe?: boolean }` diff --git a/packages/history-utility/docs/modules.md b/packages/history-utility/docs/modules.md index e521edc..73a272e 100644 --- a/packages/history-utility/docs/modules.md +++ b/packages/history-utility/docs/modules.md @@ -8,6 +8,7 @@ - [History](modules.md#history) - [HistoryNode](modules.md#historynode) +- [HistoryOptions](modules.md#historyoptions) ### Functions @@ -35,7 +36,7 @@ #### Defined in -[packages/history-utility/src/history-utility.ts:26](https://github.com/valtiojs/valtio-history/blob/86c1430/packages/history-utility/src/history-utility.ts#L26) +[packages/history-utility/src/history-utility.ts:27](https://github.com/valtiojs/valtio-history/blob/7853d84/packages/history-utility/src/history-utility.ts#L27) --- @@ -59,13 +60,29 @@ #### Defined in -[packages/history-utility/src/history-utility.ts:10](https://github.com/valtiojs/valtio-history/blob/86c1430/packages/history-utility/src/history-utility.ts#L10) +[packages/history-utility/src/history-utility.ts:11](https://github.com/valtiojs/valtio-history/blob/7853d84/packages/history-utility/src/history-utility.ts#L11) + +--- + +### HistoryOptions + +Ƭ **HistoryOptions**: `Object` + +#### Type declaration + +| Name | Type | Description | +| :--------------- | :-------- | :---------------------------------------------------------------- | +| `skipSubscribe?` | `boolean` | determines if the internal subscribe behaviour should be skipped. | + +#### Defined in + +[packages/history-utility/src/history-utility.ts:44](https://github.com/valtiojs/valtio-history/blob/7853d84/packages/history-utility/src/history-utility.ts#L44) ## Functions ### proxyWithHistory -▸ **proxyWithHistory**\<`V`\>(`initialValue`, `skipSubscribe?`): `Object` +▸ **proxyWithHistory**\<`V`\>(`initialValue`, `options?`): `Object` This creates a new proxy with history support (ProxyHistoryObject). It includes following main properties:
@@ -97,10 +114,10 @@ Notes:
#### Parameters -| Name | Type | Default value | Description | -| :-------------- | :-------- | :------------ | :---------------------------------------------------------------- | -| `initialValue` | `V` | `undefined` | any object to track | -| `skipSubscribe` | `boolean` | `false` | determines if the internal subscribe behaviour should be skipped. | +| Name | Type | Description | +| :------------- | :--------------------------------------------------------- | :--------------------------------------------- | +| `initialValue` | `V` | any value to be tracked | +| `options?` | `boolean` \| [`HistoryOptions`](modules.md#historyoptions) | use to configure the proxyWithHistory utility. | #### Returns @@ -121,6 +138,7 @@ proxyObject | `remove` | (`index`: `number`) => `undefined` \| [`HistoryNode`](modules.md#historynode)\<`V`\> | The remove method is only invoked when there are more than one nodes and when a valid index is provided. If the current index is removed, An index greater than the current index will be preferred as the next value. | | `replace` | (`index`: `number`, `value`: `INTERNAL_Snapshot`\<`V`\>) => `void` | utility to replace a value in history. The history changes will not be affected, only the value to be replaced. If a base value is needed to operate on, the `getNode` utility can be used to retrieve a cloned historyNode.

Notes:
- No operations are done on the value provided to this utility.
- This is an advanced method, please ensure the value provided is a snapshot of the same type of the value being tracked.
| | `saveHistory` | () => `void` | a function to execute saving history when changes are made to `value` | +| `shouldSaveHistory` | (`ops`: `Op`[]) => `boolean` | a function that returns true when the history should be updated | | `subscribe` | () => () => `void` | a function to subscribe to changes made to `value` | | `undo` | () => `void` | a function to go back in history | | `value` | `V` | any value to be tracked (does not have to be an object) | @@ -136,4 +154,4 @@ const state = proxyWithHistory({ #### Defined in -[packages/history-utility/src/history-utility.ts:94](https://github.com/valtiojs/valtio-history/blob/86c1430/packages/history-utility/src/history-utility.ts#L94) +[packages/history-utility/src/history-utility.ts:128](https://github.com/valtiojs/valtio-history/blob/7853d84/packages/history-utility/src/history-utility.ts#L128) diff --git a/packages/history-utility/project.json b/packages/history-utility/project.json index fa50b49..c1f2e6b 100644 --- a/packages/history-utility/project.json +++ b/packages/history-utility/project.json @@ -37,7 +37,7 @@ "options": { "commands": [ "cd packages/history-utility && pnpm typedoc --plugin typedoc-plugin-markdown src/index.ts && rm docs/README.md", - "sleep 3s && pnpm nx format:write" + "sleep 5s && pnpm nx format:write" ] } } diff --git a/packages/history-utility/src/history-utility.ts b/packages/history-utility/src/history-utility.ts index 9288ba5..a4e59e7 100644 --- a/packages/history-utility/src/history-utility.ts +++ b/packages/history-utility/src/history-utility.ts @@ -38,6 +38,15 @@ export type History = { index: number; }; +type SubscribeOps = Parameters[1]>[0]; + +export type HistoryOptions = { + /** + * determines if the internal subscribe behaviour should be skipped. + */ + skipSubscribe?: boolean; +}; + const isObject = (value: unknown): value is object => !!value && typeof value === 'object'; @@ -59,6 +68,32 @@ const deepClone = (value: T): T => { return baseObject; }; +const normalizeOptions = ( + options?: HistoryOptions | boolean +): HistoryOptions => { + if (typeof options === 'boolean') { + if (import.meta.env?.MODE !== 'production') { + console.warn(`The second parameter of 'proxyWithHistory' as boolean is deprecated and support for boolean will be removed + in the next major version. Please use the object syntax instead: + + { skipSubscribe: boolean } + `); + } + return { skipSubscribe: options }; + } + + const defaultOptions = { + skipSubscribe: false, + }; + + if (!options) return defaultOptions; + + return { + ...defaultOptions, + ...options, + }; +}; + /** * This creates a new proxy with history support (ProxyHistoryObject). * It includes following main properties:
@@ -81,8 +116,8 @@ const deepClone = (value: T): T => { * Notes:
* - Suspense/promise is not supported.
* - * @param initialValue - any object to track - * @param skipSubscribe - determines if the internal subscribe behaviour should be skipped. + * @param initialValue - any value to be tracked + * @param options - use to configure the proxyWithHistory utility. * @returns proxyObject * * @example @@ -91,7 +126,11 @@ const deepClone = (value: T): T => { * count: 1, * }) */ -export function proxyWithHistory(initialValue: V, skipSubscribe = false) { +export function proxyWithHistory( + initialValue: V, + options?: HistoryOptions | boolean +) { + const utilOptions = normalizeOptions(options); const proxyObject = proxy({ /** * any value to be tracked (does not have to be an object) @@ -191,20 +230,24 @@ export function proxyWithHistory(initialValue: V, skipSubscribe = false) { }); ++proxyObject.history.index; }, + /** + * a function that returns true when the history should be updated + * + * @param ops - subscribeOps from subscribe callback + * @returns boolean + */ + shouldSaveHistory: (ops: SubscribeOps) => + ops.every( + (op) => + op[1][0] === 'value' && + (op[0] !== 'set' || op[2] !== proxyObject.history.wip) + ), /** * a function to subscribe to changes made to `value` */ subscribe: () => subscribe(proxyObject, (ops) => { - if ( - ops.every( - (op) => - op[1][0] === 'value' && - (op[0] !== 'set' || op[2] !== proxyObject.history.wip) - ) - ) { - proxyObject.saveHistory(); - } + if (proxyObject.shouldSaveHistory(ops)) proxyObject.saveHistory(); }), // history rewrite utilities @@ -283,7 +326,7 @@ export function proxyWithHistory(initialValue: V, skipSubscribe = false) { proxyObject.saveHistory(); - if (!skipSubscribe) { + if (!utilOptions.skipSubscribe) { proxyObject.subscribe(); } diff --git a/packages/history-utility/tsconfig.json b/packages/history-utility/tsconfig.json index 3748580..dd04b77 100644 --- a/packages/history-utility/tsconfig.json +++ b/packages/history-utility/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "module": "commonjs", + "module": "ES2020", "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, diff --git a/packages/history-utility/tsconfig.lib.json b/packages/history-utility/tsconfig.lib.json index 142cd8a..9077b43 100644 --- a/packages/history-utility/tsconfig.lib.json +++ b/packages/history-utility/tsconfig.lib.json @@ -3,7 +3,7 @@ "compilerOptions": { "outDir": "../../dist/out-tsc", "declaration": true, - "types": ["node"] + "types": ["node", "vite/client"] }, "include": ["src/**/*.ts", "src/**/*.tsx"], "exclude": [ diff --git a/packages/history-utility/tsconfig.spec.json b/packages/history-utility/tsconfig.spec.json index 3c002c2..543310b 100644 --- a/packages/history-utility/tsconfig.spec.json +++ b/packages/history-utility/tsconfig.spec.json @@ -2,6 +2,7 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "../../dist/out-tsc", + "jsx": "react-jsx", "types": [ "vitest/globals", "vitest/importMeta", diff --git a/tsconfig.base.json b/tsconfig.base.json index 7ce7251..0486726 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -8,7 +8,7 @@ "emitDecoratorMetadata": true, "experimentalDecorators": true, "importHelpers": true, - "target": "es2015", + "target": "es2020", "module": "esnext", "lib": ["es2020", "dom"], "skipLibCheck": true,