From e56eac10754b6ab25669c917fab4679bd769f041 Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 17 Dec 2025 20:13:19 +0000 Subject: [PATCH 1/3] Remove NODE_ENV branching --- packages/api/src/hooks/useActivities.ts | 64 +++++++++++++------------ 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/packages/api/src/hooks/useActivities.ts b/packages/api/src/hooks/useActivities.ts index ea61e4fd21..bd41d7995e 100644 --- a/packages/api/src/hooks/useActivities.ts +++ b/packages/api/src/hooks/useActivities.ts @@ -10,53 +10,57 @@ declare const process: { }; }; -export default function useActivities(): readonly [readonly WebChatActivity[]] { - const activitiesFromGraphState = useOrderedActivities(); +function useActivitiesForProduction(): readonly [readonly WebChatActivity[]] { + return useOrderedActivities(); +} + +function useActivitiesForDevelopment(): readonly [readonly WebChatActivity[]] { + const activitiesFromGraphState = useActivitiesForProduction(); // Checks if store changed. const store = useStore(); const prevStore = usePrevious(store); - // ASSERTION: Before we fully migrate to graph, make sure graph and Redux are the same. - if (process.env.NODE_ENV !== 'production') { - const [activitiesFromGraph] = activitiesFromGraphState; + const [activitiesFromGraph] = activitiesFromGraphState; + + const activitiesFromRedux = useSelector(({ activities }) => activities); - // Assert based on NODE_ENV. - // eslint-disable-next-line react-hooks/rules-of-hooks - const activitiesFromRedux = useSelector(({ activities }) => activities); + // If store changed, skip one assertion turn. + // This is because is using `useState()` for propagating changes. + // It is always one render behind if `store` changed. + if (prevStore === store) { + if (activitiesFromGraph.length !== activitiesFromRedux.length) { + throw new Error( + `botframework-webchat-internal: Activities from graph and Redux are of different size (graph has ${activitiesFromGraph.length} activities, Redux has ${activitiesFromRedux.length} activities)`, + { + cause: { + activitiesFromGraph, + activitiesFromRedux + } + } + ); + } - // If store changed, skip one assertion turn. - // This is because is using `useState()` for propagating changes. - // It is always one render behind if `store` changed. - if (prevStore === store) { - if (activitiesFromGraph.length !== activitiesFromRedux.length) { + for (let index = 0; index < activitiesFromGraph.length; index++) { + if (!Object.is(activitiesFromGraph.at(index), activitiesFromRedux.at(index))) { throw new Error( - `botframework-webchat-internal: Activities from graph and Redux are of different size (graph has ${activitiesFromGraph.length} activities, Redux has ${activitiesFromRedux.length} activities)`, + `botframework-webchat-internal: Activities from graph and Redux are of different at index ${index}`, { cause: { activitiesFromGraph, - activitiesFromRedux + activitiesFromRedux, + index } } ); } - - for (let index = 0; index < activitiesFromGraph.length; index++) { - if (!Object.is(activitiesFromGraph.at(index), activitiesFromRedux.at(index))) { - throw new Error( - `botframework-webchat-internal: Activities from graph and Redux are of different at index ${index}`, - { - cause: { - activitiesFromGraph, - activitiesFromRedux, - index - } - } - ); - } - } } } return activitiesFromGraphState; } + +const useActivities: () => readonly [readonly WebChatActivity[]] = + process.env.NODE_ENV === 'production' ? useActivitiesForProduction : useActivitiesForDevelopment; + +export default useActivities; From f17e2c3f0c995d32f610228fe1a0647d719a092e Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 17 Dec 2025 20:19:27 +0000 Subject: [PATCH 2/3] Rename from Graph2 to Graph --- packages/core-graph/src/index.ts | 2 +- .../src/private/{Graph2.act.spec.ts => Graph.act.spec.ts} | 2 +- .../{Graph2.getState.spec.ts => Graph.getState.spec.ts} | 2 +- .../{Graph2.middleware.spec.ts => Graph.middleware.spec.ts} | 2 +- .../{Graph2.subscribe.spec.ts => Graph.subscribe.spec.ts} | 2 +- packages/core-graph/src/private/{Graph2.ts => Graph.ts} | 6 +++--- .../private/{Graph2.upsert.spec.ts => Graph.upsert.spec.ts} | 2 +- .../src/private/SlantGraph/SlantGraph.autoInversion.spec.ts | 2 +- packages/core-graph/src/private/SlantGraph/SlantGraph.ts | 2 +- .../src/private/SlantGraph/private/assertSlantNode.ts | 2 +- .../src/private/SlantGraph/private/autoInversion.ts | 2 +- packages/core-graph/src/private/SlantGraph/private/color.ts | 2 +- .../core-graph/src/private/SlantGraph/private/terminator.ts | 2 +- 13 files changed, 15 insertions(+), 15 deletions(-) rename packages/core-graph/src/private/{Graph2.act.spec.ts => Graph.act.spec.ts} (98%) rename packages/core-graph/src/private/{Graph2.getState.spec.ts => Graph.getState.spec.ts} (94%) rename packages/core-graph/src/private/{Graph2.middleware.spec.ts => Graph.middleware.spec.ts} (99%) rename packages/core-graph/src/private/{Graph2.subscribe.spec.ts => Graph.subscribe.spec.ts} (98%) rename packages/core-graph/src/private/{Graph2.ts => Graph.ts} (94%) rename packages/core-graph/src/private/{Graph2.upsert.spec.ts => Graph.upsert.spec.ts} (98%) diff --git a/packages/core-graph/src/index.ts b/packages/core-graph/src/index.ts index 8ab3dcca17..604969d229 100644 --- a/packages/core-graph/src/index.ts +++ b/packages/core-graph/src/index.ts @@ -6,7 +6,7 @@ export { type GraphSubscriberRecord, type ReadableGraph, type WritableGraph -} from './private/Graph2'; +} from './private/Graph'; export { SlantNodeSchema, type SlantNode } from './private/schemas/colorNode'; export { DirectLineActivityNodeSchema, diff --git a/packages/core-graph/src/private/Graph2.act.spec.ts b/packages/core-graph/src/private/Graph.act.spec.ts similarity index 98% rename from packages/core-graph/src/private/Graph2.act.spec.ts rename to packages/core-graph/src/private/Graph.act.spec.ts index 4f74fb4a87..0c58e6e9ff 100644 --- a/packages/core-graph/src/private/Graph2.act.spec.ts +++ b/packages/core-graph/src/private/Graph.act.spec.ts @@ -1,7 +1,7 @@ import { expect } from '@jest/globals'; import { scenario } from '@testduet/given-when-then'; import { assert, object } from 'valibot'; -import Graph from './Graph2'; +import Graph from './Graph'; import './schemas/private/expectExtendValibot'; import './schemas/private/expectIsFrozen'; diff --git a/packages/core-graph/src/private/Graph2.getState.spec.ts b/packages/core-graph/src/private/Graph.getState.spec.ts similarity index 94% rename from packages/core-graph/src/private/Graph2.getState.spec.ts rename to packages/core-graph/src/private/Graph.getState.spec.ts index 451809c15c..736dbbe50d 100644 --- a/packages/core-graph/src/private/Graph2.getState.spec.ts +++ b/packages/core-graph/src/private/Graph.getState.spec.ts @@ -1,6 +1,6 @@ import { expect } from '@jest/globals'; import { scenario } from '@testduet/given-when-then'; -import Graph from './Graph2'; +import Graph from './Graph'; import './schemas/private/expectExtendValibot'; import './schemas/private/expectIsFrozen'; diff --git a/packages/core-graph/src/private/Graph2.middleware.spec.ts b/packages/core-graph/src/private/Graph.middleware.spec.ts similarity index 99% rename from packages/core-graph/src/private/Graph2.middleware.spec.ts rename to packages/core-graph/src/private/Graph.middleware.spec.ts index 959d2166ec..e565c0bd0b 100644 --- a/packages/core-graph/src/private/Graph2.middleware.spec.ts +++ b/packages/core-graph/src/private/Graph.middleware.spec.ts @@ -2,7 +2,7 @@ import { expect } from '@jest/globals'; import { scenario } from '@testduet/given-when-then'; import { iteratorFilter, iteratorMap } from 'iter-fest'; import { fn } from 'jest-mock'; -import Graph from './Graph2'; +import Graph from './Graph'; import type { Identifier } from './schemas/Identifier'; import './schemas/private/expectExtendValibot'; import './schemas/private/expectIsFrozen'; diff --git a/packages/core-graph/src/private/Graph2.subscribe.spec.ts b/packages/core-graph/src/private/Graph.subscribe.spec.ts similarity index 98% rename from packages/core-graph/src/private/Graph2.subscribe.spec.ts rename to packages/core-graph/src/private/Graph.subscribe.spec.ts index 1dd867b760..5a23d89da3 100644 --- a/packages/core-graph/src/private/Graph2.subscribe.spec.ts +++ b/packages/core-graph/src/private/Graph.subscribe.spec.ts @@ -2,7 +2,7 @@ import { expect } from '@jest/globals'; import { scenario } from '@testduet/given-when-then'; import { fn } from 'jest-mock'; import { assert, map, string, unknown } from 'valibot'; -import Graph, { type GraphState } from './Graph2'; +import Graph, { type GraphState } from './Graph'; import './schemas/private/expectExtendValibot'; import './schemas/private/expectIsFrozen'; diff --git a/packages/core-graph/src/private/Graph2.ts b/packages/core-graph/src/private/Graph.ts similarity index 94% rename from packages/core-graph/src/private/Graph2.ts rename to packages/core-graph/src/private/Graph.ts index 055e3b9182..1660bd12ca 100644 --- a/packages/core-graph/src/private/Graph2.ts +++ b/packages/core-graph/src/private/Graph.ts @@ -33,7 +33,7 @@ type WritableGraph = { const requestSchema = pipe( map(IdentifierSchema, object({ '@id': IdentifierSchema })), check( - // TODO: Iterator.every is since iOS 18.4, we still need to use ponyfill for now. + // TODO: [P4] Iterator.every is since iOS 18.4, we still need to use ponyfill until we drop support of iOS 18.4. value => iteratorEvery(value.entries(), ([key, node]) => key === node['@id']), 'Key returned in Map must match `@id` in value' ) @@ -49,7 +49,7 @@ const middlewareValidator: GraphMiddleware = () => next => request => return Object.freeze(result); }; -class Graph2 implements ReadableGraph { +class Graph implements ReadableGraph { #busy = false; #middleware: GraphMiddleware; #state: GraphState = Object.freeze(new Map()); @@ -139,7 +139,7 @@ class Graph2 imple } } -export default Graph2; +export default Graph; export { type GraphMiddleware, type GraphNode, diff --git a/packages/core-graph/src/private/Graph2.upsert.spec.ts b/packages/core-graph/src/private/Graph.upsert.spec.ts similarity index 98% rename from packages/core-graph/src/private/Graph2.upsert.spec.ts rename to packages/core-graph/src/private/Graph.upsert.spec.ts index a5731f953f..c6614c7910 100644 --- a/packages/core-graph/src/private/Graph2.upsert.spec.ts +++ b/packages/core-graph/src/private/Graph.upsert.spec.ts @@ -1,6 +1,6 @@ import { expect } from '@jest/globals'; import { scenario } from '@testduet/given-when-then'; -import Graph from './Graph2'; +import Graph from './Graph'; import './schemas/private/expectExtendValibot'; import './schemas/private/expectIsFrozen'; import type { Identifier } from './schemas/Identifier'; diff --git a/packages/core-graph/src/private/SlantGraph/SlantGraph.autoInversion.spec.ts b/packages/core-graph/src/private/SlantGraph/SlantGraph.autoInversion.spec.ts index 715b23777f..7b7f9f5e19 100644 --- a/packages/core-graph/src/private/SlantGraph/SlantGraph.autoInversion.spec.ts +++ b/packages/core-graph/src/private/SlantGraph/SlantGraph.autoInversion.spec.ts @@ -1,7 +1,7 @@ import { expect } from '@jest/globals'; import { scenario } from '@testduet/given-when-then'; import { fn } from 'jest-mock'; -import { GraphSubscriber } from '../Graph2'; +import { GraphSubscriber } from '../Graph'; import SlantGraph from './SlantGraph'; scenario('SlantGraph auto-inversion', bdd => { diff --git a/packages/core-graph/src/private/SlantGraph/SlantGraph.ts b/packages/core-graph/src/private/SlantGraph/SlantGraph.ts index 381d127b72..a2997835b1 100644 --- a/packages/core-graph/src/private/SlantGraph/SlantGraph.ts +++ b/packages/core-graph/src/private/SlantGraph/SlantGraph.ts @@ -1,4 +1,4 @@ -import Graph from '../Graph2'; +import Graph from '../Graph'; import { type SlantNode } from '../schemas/colorNode'; import type { Identifier } from '../schemas/Identifier'; import assertSlantNode from './private/assertSlantNode'; diff --git a/packages/core-graph/src/private/SlantGraph/private/assertSlantNode.ts b/packages/core-graph/src/private/SlantGraph/private/assertSlantNode.ts index af0af7fde4..83b856a2b3 100644 --- a/packages/core-graph/src/private/SlantGraph/private/assertSlantNode.ts +++ b/packages/core-graph/src/private/SlantGraph/private/assertSlantNode.ts @@ -1,5 +1,5 @@ import { assert, type BaseSchema } from 'valibot'; -import { type GraphMiddleware } from '../../Graph2'; +import { type GraphMiddleware } from '../../Graph'; import { SlantNodeSchema, type SlantNode } from '../../schemas/colorNode'; import { DirectLineActivityNodeSchema } from '../../schemas/DirectLineActivityNode'; import isOfType from '../../schemas/isOfType'; diff --git a/packages/core-graph/src/private/SlantGraph/private/autoInversion.ts b/packages/core-graph/src/private/SlantGraph/private/autoInversion.ts index 1b65392f3e..d35dd1b5bd 100644 --- a/packages/core-graph/src/private/SlantGraph/private/autoInversion.ts +++ b/packages/core-graph/src/private/SlantGraph/private/autoInversion.ts @@ -1,6 +1,6 @@ // @ts-expect-error No @types/core-js-pure. import difference from 'core-js-pure/features/set/difference'; -import { type GraphMiddleware } from '../../Graph2'; +import { type GraphMiddleware } from '../../Graph'; import { type SlantNode } from '../../schemas/colorNode'; import type { Identifier } from '../../schemas/Identifier'; import { type NodeReference } from '../../schemas/NodeReference'; diff --git a/packages/core-graph/src/private/SlantGraph/private/color.ts b/packages/core-graph/src/private/SlantGraph/private/color.ts index 58e36938be..6334fb7cac 100644 --- a/packages/core-graph/src/private/SlantGraph/private/color.ts +++ b/packages/core-graph/src/private/SlantGraph/private/color.ts @@ -1,4 +1,4 @@ -import { type GraphMiddleware } from '../../Graph2'; +import { type GraphMiddleware } from '../../Graph'; import colorNode, { type SlantNode } from '../../schemas/colorNode'; import flattenNodeObject from '../../schemas/flattenNodeObject'; import type { Identifier } from '../../schemas/Identifier'; diff --git a/packages/core-graph/src/private/SlantGraph/private/terminator.ts b/packages/core-graph/src/private/SlantGraph/private/terminator.ts index 9047a3a0fc..b20394147e 100644 --- a/packages/core-graph/src/private/SlantGraph/private/terminator.ts +++ b/packages/core-graph/src/private/SlantGraph/private/terminator.ts @@ -1,4 +1,4 @@ -import { type GraphMiddleware } from '../../Graph2'; +import { type GraphMiddleware } from '../../Graph'; import { type SlantNode } from '../../schemas/colorNode'; import type { Identifier } from '../../schemas/Identifier'; import type { AnyNode } from '../SlantGraph'; From c43cd4ed6b2be48a9cd7d71910895a217dea729d Mon Sep 17 00:00:00 2001 From: William Wong Date: Wed, 17 Dec 2025 12:59:12 -0800 Subject: [PATCH 3/3] Update packages/api/src/hooks/useActivities.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/api/src/hooks/useActivities.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api/src/hooks/useActivities.ts b/packages/api/src/hooks/useActivities.ts index bd41d7995e..21ffa83806 100644 --- a/packages/api/src/hooks/useActivities.ts +++ b/packages/api/src/hooks/useActivities.ts @@ -44,7 +44,7 @@ function useActivitiesForDevelopment(): readonly [readonly WebChatActivity[]] { for (let index = 0; index < activitiesFromGraph.length; index++) { if (!Object.is(activitiesFromGraph.at(index), activitiesFromRedux.at(index))) { throw new Error( - `botframework-webchat-internal: Activities from graph and Redux are of different at index ${index}`, + `botframework-webchat-internal: Activities from graph and Redux are different at index ${index}`, { cause: { activitiesFromGraph,