quidproquo-web-react 0.0.261 → 0.0.263

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/lib/commonjs/actionProcessor/ActionProcessorContext.d.ts +2 -0
  2. package/lib/commonjs/actionProcessor/ActionProcessorContext.js +14 -0
  3. package/lib/commonjs/actionProcessor/ActionProcessorProvider.d.ts +6 -0
  4. package/lib/commonjs/actionProcessor/ActionProcessorProvider.js +24 -0
  5. package/lib/commonjs/actionProcessor/index.d.ts +3 -0
  6. package/lib/commonjs/actionProcessor/index.js +19 -0
  7. package/lib/commonjs/actionProcessor/useActionProcessors.d.ts +1 -0
  8. package/lib/commonjs/actionProcessor/useActionProcessors.js +7 -0
  9. package/lib/commonjs/hooks/asmj/index.d.ts +1 -0
  10. package/lib/commonjs/hooks/asmj/index.js +1 -0
  11. package/lib/commonjs/hooks/asmj/useBubbleReducer.d.ts +2 -0
  12. package/lib/commonjs/hooks/asmj/useBubbleReducer.js +22 -0
  13. package/lib/commonjs/hooks/asmj/useQpqRuntime.d.ts +4 -2
  14. package/lib/commonjs/hooks/asmj/useQpqRuntime.js +14 -2
  15. package/lib/commonjs/hooks/useQpq.js +3 -1
  16. package/lib/commonjs/index.d.ts +1 -0
  17. package/lib/commonjs/index.js +1 -0
  18. package/lib/commonjs/webSocketQueue/hooks/actionProcessor/getServiceRequestActionProcessor.d.ts +4 -0
  19. package/lib/commonjs/webSocketQueue/hooks/actionProcessor/getServiceRequestActionProcessor.js +25 -0
  20. package/lib/commonjs/webSocketQueue/hooks/index.d.ts +2 -0
  21. package/lib/commonjs/webSocketQueue/hooks/index.js +2 -0
  22. package/lib/commonjs/webSocketQueue/hooks/useQpqWebsocketQueueRuntime.d.ts +11 -0
  23. package/lib/commonjs/webSocketQueue/hooks/useQpqWebsocketQueueRuntime.js +35 -0
  24. package/lib/commonjs/webSocketQueue/hooks/useWebsocketQueueSendEvent.d.ts +1 -1
  25. package/lib/commonjs/webSocketQueue/hooks/useWebsocketQueueSendEvent.js +53 -3
  26. package/lib/esm/actionProcessor/ActionProcessorContext.d.ts +2 -0
  27. package/lib/esm/actionProcessor/ActionProcessorContext.js +2 -0
  28. package/lib/esm/actionProcessor/ActionProcessorProvider.d.ts +6 -0
  29. package/lib/esm/actionProcessor/ActionProcessorProvider.js +12 -0
  30. package/lib/esm/actionProcessor/index.d.ts +3 -0
  31. package/lib/esm/actionProcessor/index.js +3 -0
  32. package/lib/esm/actionProcessor/useActionProcessors.d.ts +1 -0
  33. package/lib/esm/actionProcessor/useActionProcessors.js +3 -0
  34. package/lib/esm/hooks/asmj/index.d.ts +1 -0
  35. package/lib/esm/hooks/asmj/index.js +1 -0
  36. package/lib/esm/hooks/asmj/useBubbleReducer.d.ts +2 -0
  37. package/lib/esm/hooks/asmj/useBubbleReducer.js +18 -0
  38. package/lib/esm/hooks/asmj/useQpqRuntime.d.ts +4 -2
  39. package/lib/esm/hooks/asmj/useQpqRuntime.js +6 -2
  40. package/lib/esm/hooks/useQpq.js +3 -0
  41. package/lib/esm/index.d.ts +1 -0
  42. package/lib/esm/index.js +1 -0
  43. package/lib/esm/webSocketQueue/hooks/actionProcessor/getServiceRequestActionProcessor.d.ts +4 -0
  44. package/lib/esm/webSocketQueue/hooks/actionProcessor/getServiceRequestActionProcessor.js +11 -0
  45. package/lib/esm/webSocketQueue/hooks/index.d.ts +2 -0
  46. package/lib/esm/webSocketQueue/hooks/index.js +2 -0
  47. package/lib/esm/webSocketQueue/hooks/useQpqWebsocketQueueRuntime.d.ts +11 -0
  48. package/lib/esm/webSocketQueue/hooks/useQpqWebsocketQueueRuntime.js +24 -0
  49. package/lib/esm/webSocketQueue/hooks/useWebsocketQueueSendEvent.d.ts +1 -1
  50. package/lib/esm/webSocketQueue/hooks/useWebsocketQueueSendEvent.js +54 -4
  51. package/package.json +7 -7
@@ -0,0 +1,2 @@
1
+ import { ActionProcessorListResolver } from 'quidproquo-core';
2
+ export declare const ActionProcessorContext: import("react").Context<ActionProcessorListResolver>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ActionProcessorContext = void 0;
13
+ const react_1 = require("react");
14
+ exports.ActionProcessorContext = (0, react_1.createContext)(() => __awaiter(void 0, void 0, void 0, function* () { return ({}); }));
@@ -0,0 +1,6 @@
1
+ import { ActionProcessorListResolver } from 'quidproquo-core';
2
+ export type ActionProcessorProviderProps = {
3
+ children: React.ReactNode;
4
+ getActionProcessors: ActionProcessorListResolver;
5
+ };
6
+ export declare const ActionProcessorProvider: React.FC<ActionProcessorProviderProps>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ActionProcessorProvider = void 0;
13
+ const jsx_runtime_1 = require("react/jsx-runtime");
14
+ const react_1 = require("react");
15
+ const ActionProcessorContext_1 = require("./ActionProcessorContext");
16
+ const ActionProcessorProvider = ({ children, getActionProcessors }) => {
17
+ const parentGetActionProcessors = (0, react_1.useContext)(ActionProcessorContext_1.ActionProcessorContext);
18
+ // Merge: parent processors first, then this provider's (so child overrides parent)
19
+ const mergedGetActionProcessors = (qpqConfig, dynamicModuleLoader) => __awaiter(void 0, void 0, void 0, function* () {
20
+ return (Object.assign(Object.assign({}, (yield parentGetActionProcessors(qpqConfig, dynamicModuleLoader))), (yield getActionProcessors(qpqConfig, dynamicModuleLoader))));
21
+ });
22
+ return (0, jsx_runtime_1.jsx)(ActionProcessorContext_1.ActionProcessorContext.Provider, { value: mergedGetActionProcessors, children: children });
23
+ };
24
+ exports.ActionProcessorProvider = ActionProcessorProvider;
@@ -0,0 +1,3 @@
1
+ export * from './ActionProcessorContext';
2
+ export * from './ActionProcessorProvider';
3
+ export * from './useActionProcessors';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./ActionProcessorContext"), exports);
18
+ __exportStar(require("./ActionProcessorProvider"), exports);
19
+ __exportStar(require("./useActionProcessors"), exports);
@@ -0,0 +1 @@
1
+ export declare const useActionProcessors: () => import("quidproquo-core").ActionProcessorListResolver;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useActionProcessors = void 0;
4
+ const react_1 = require("react");
5
+ const ActionProcessorContext_1 = require("./ActionProcessorContext");
6
+ const useActionProcessors = () => (0, react_1.useContext)(ActionProcessorContext_1.ActionProcessorContext);
7
+ exports.useActionProcessors = useActionProcessors;
@@ -4,4 +4,5 @@ export * from './createQpqRuntimeDefinition';
4
4
  export * from './QpqContextProvider';
5
5
  export * from './QpqMappedApi';
6
6
  export * from './QpqRuntimeEffectCatcher';
7
+ export * from './useBubbleReducer';
7
8
  export * from './useQpqRuntime';
@@ -20,4 +20,5 @@ __exportStar(require("./createQpqRuntimeDefinition"), exports);
20
20
  __exportStar(require("./QpqContextProvider"), exports);
21
21
  __exportStar(require("./QpqMappedApi"), exports);
22
22
  __exportStar(require("./QpqRuntimeEffectCatcher"), exports);
23
+ __exportStar(require("./useBubbleReducer"), exports);
23
24
  __exportStar(require("./useQpqRuntime"), exports);
@@ -0,0 +1,2 @@
1
+ import { QpqBubbleReducer } from './bubbleReducer';
2
+ export declare const useBubbleReducer: <TState>(reducer: QpqBubbleReducer<TState, any>, initialState: TState | (() => TState)) => [TState, (action: unknown) => void];
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useBubbleReducer = void 0;
4
+ const react_1 = require("react");
5
+ const bubbleReducer_1 = require("./bubbleReducer");
6
+ const useBubbleReducer = (reducer, initialState) => {
7
+ const parentDispatch = (0, react_1.useContext)(bubbleReducer_1.BubbleReducerDispatchContext);
8
+ const [state, setState] = (0, react_1.useState)(initialState);
9
+ const stateRef = (0, react_1.useRef)(state);
10
+ stateRef.current = state;
11
+ const dispatch = (0, react_1.useCallback)((action) => {
12
+ const [newState, preventBubble] = reducer(stateRef.current, action);
13
+ if (preventBubble) {
14
+ setState(newState);
15
+ }
16
+ else {
17
+ parentDispatch(action);
18
+ }
19
+ }, [parentDispatch, reducer]);
20
+ return [state, dispatch];
21
+ };
22
+ exports.useBubbleReducer = useBubbleReducer;
@@ -1,4 +1,6 @@
1
- import { Story } from 'quidproquo-core';
1
+ import { ActionProcessorListResolver, Story } from 'quidproquo-core';
2
+ import { Dispatch } from 'react';
2
3
  import { QpqRuntimeDefinition } from './createQpqRuntimeDefinition';
3
4
  import { QpqApi, QpqMappedApi } from './QpqMappedApi';
4
- export declare function useQpqRuntime<TState, TAction, TApi extends QpqApi>(atom: QpqRuntimeDefinition<TState, TAction, TApi>, mainStory?: Story<any, any>, name?: string): [QpqMappedApi<TApi>, TState, (action: any) => void];
5
+ export type ActionProcessorListResolverFactory<TState = any> = (dispatch: Dispatch<any>, getCurrentState: () => TState) => ActionProcessorListResolver;
6
+ export declare function useQpqRuntime<TState, TAction, TApi extends QpqApi>(atom: QpqRuntimeDefinition<TState, TAction, TApi>, mainStory?: Story<any, any>, name?: string, getActionProcessors?: ActionProcessorListResolverFactory<TState>): [QpqMappedApi<TApi>, TState, (action: any) => void];
@@ -1,16 +1,28 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.useQpqRuntime = useQpqRuntime;
4
13
  const react_1 = require("react");
5
14
  const useQpq_1 = require("../useQpq");
6
15
  const actionProcessor_1 = require("./actionProcessor");
7
16
  const bubbleReducer_1 = require("./bubbleReducer");
8
- function useQpqRuntime(atom, mainStory, name) {
17
+ function useQpqRuntime(atom, mainStory, name, getActionProcessors = () => () => __awaiter(this, void 0, void 0, function* () { return ({}); })) {
9
18
  const atomInfo = (0, react_1.useMemo)(() => atom(name), [atom, name]);
10
19
  const [state, dispatch, getCurrentState] = (0, bubbleReducer_1.useQpqRuntimeBubblingReducer)(atom, name);
11
20
  // Api generators are memoized to prevent unnecessary re-renders.
12
21
  const [memoedApiGenerators] = (0, react_1.useState)(() => atomInfo.api);
13
- const resolver = (0, useQpq_1.useQpq)((0, actionProcessor_1.getStateActionProcessor)(dispatch, getCurrentState));
22
+ const mergedProcessors = (qpqConfig, dynamicModuleLoader) => __awaiter(this, void 0, void 0, function* () {
23
+ return (Object.assign(Object.assign({}, (yield (0, actionProcessor_1.getStateActionProcessor)(dispatch, getCurrentState)(qpqConfig, dynamicModuleLoader))), (yield getActionProcessors(dispatch, getCurrentState)(qpqConfig, dynamicModuleLoader))));
24
+ });
25
+ const resolver = (0, useQpq_1.useQpq)(mergedProcessors);
14
26
  // Wrap and remap each API generator using the resolver.
15
27
  const api = (0, react_1.useMemo)(() => {
16
28
  const wrapped = {};
@@ -13,6 +13,7 @@ exports.useQpq = useQpq;
13
13
  const quidproquo_actionprocessor_web_1 = require("quidproquo-actionprocessor-web");
14
14
  const quidproquo_core_1 = require("quidproquo-core");
15
15
  const react_1 = require("react");
16
+ const actionProcessor_1 = require("../actionProcessor");
16
17
  const QpqContextProvider_1 = require("./asmj/QpqContextProvider");
17
18
  function* withVersionCheck(story, versionRef, capturedVersion) {
18
19
  let nextValue = undefined;
@@ -37,6 +38,7 @@ const logger = {
37
38
  };
38
39
  function useQpq(getActionProcessors = () => __awaiter(this, void 0, void 0, function* () { return ({}); })) {
39
40
  const qpqContextValues = (0, QpqContextProvider_1.useQpqContextValues)();
41
+ const contextGetActionProcessors = (0, actionProcessor_1.useActionProcessors)();
40
42
  const versionRef = (0, react_1.useRef)(0);
41
43
  (0, react_1.useEffect)(() => {
42
44
  return () => {
@@ -47,7 +49,7 @@ function useQpq(getActionProcessors = () => __awaiter(this, void 0, void 0, func
47
49
  depth: 0,
48
50
  context: qpqContextValues,
49
51
  }, (qpqConfig, dynamicModuleLoader) => __awaiter(this, void 0, void 0, function* () {
50
- return (Object.assign(Object.assign({}, (yield (0, quidproquo_actionprocessor_web_1.getWebActionProcessors)(qpqConfig, dynamicModuleLoader))), (yield getActionProcessors(qpqConfig, dynamicModuleLoader))));
52
+ return (Object.assign(Object.assign(Object.assign({}, (yield (0, quidproquo_actionprocessor_web_1.getWebActionProcessors)(qpqConfig, dynamicModuleLoader))), (yield contextGetActionProcessors(qpqConfig, dynamicModuleLoader))), (yield getActionProcessors(qpqConfig, dynamicModuleLoader))));
51
53
  }), () => new Date().toISOString(), logger, `frontend::${'uuid'}`, quidproquo_core_1.QpqRuntimeType.UI, (_runtime) => __awaiter(this, void 0, void 0, function* () {
52
54
  // noop
53
55
  })), [qpqContextValues]);
@@ -1,4 +1,5 @@
1
1
  import 'symbol-observable';
2
+ export * from './actionProcessor';
2
3
  export * from './api';
3
4
  export * from './auth';
4
5
  export * from './baseUrl';
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  require("symbol-observable");
18
+ __exportStar(require("./actionProcessor"), exports);
18
19
  __exportStar(require("./api"), exports);
19
20
  __exportStar(require("./auth"), exports);
20
21
  __exportStar(require("./baseUrl"), exports);
@@ -0,0 +1,4 @@
1
+ import { ActionProcessorList } from 'quidproquo-core';
2
+ import { AnyWebSocketQueueEventMessageWithCorrelation } from 'quidproquo-webserver';
3
+ import { RefObject } from 'react';
4
+ export declare const getServiceRequestActionProcessor: (sendEventRef: RefObject<((event: Omit<AnyWebSocketQueueEventMessageWithCorrelation, "correlationId">) => Promise<any>) | null>) => ActionProcessorList;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getServiceRequestActionProcessor = void 0;
13
+ const quidproquo_core_1 = require("quidproquo-core");
14
+ const quidproquo_webserver_1 = require("quidproquo-webserver");
15
+ const getServiceRequestActionProcessor = (sendEventRef) => ({
16
+ [quidproquo_webserver_1.ServiceActionType.Request]: (_a) => __awaiter(void 0, [_a], void 0, function* ({ serviceName, method, payload, }) {
17
+ var _b;
18
+ const response = yield ((_b = sendEventRef.current) === null || _b === void 0 ? void 0 : _b.call(sendEventRef, { type: `qpq/serviceRequest/${serviceName}/${method}`, payload }));
19
+ if (response && !response.success) {
20
+ return (0, quidproquo_core_1.actionResultError)(response.error.errorType, response.error.errorText, response.error.errorStack);
21
+ }
22
+ return (0, quidproquo_core_1.actionResult)(response === null || response === void 0 ? void 0 : response.result);
23
+ }),
24
+ });
25
+ exports.getServiceRequestActionProcessor = getServiceRequestActionProcessor;
@@ -1,2 +1,4 @@
1
+ export * from './actionProcessor/getServiceRequestActionProcessor';
2
+ export * from './useQpqWebsocketQueueRuntime';
1
3
  export * from './useSubscribeToWebSocketQueueEvent';
2
4
  export * from './useWebsocketQueueSendEvent';
@@ -14,5 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./actionProcessor/getServiceRequestActionProcessor"), exports);
18
+ __exportStar(require("./useQpqWebsocketQueueRuntime"), exports);
17
19
  __exportStar(require("./useSubscribeToWebSocketQueueEvent"), exports);
18
20
  __exportStar(require("./useWebsocketQueueSendEvent"), exports);
@@ -0,0 +1,11 @@
1
+ import { Story } from 'quidproquo-core';
2
+ import { AnyWebSocketQueueEventMessageWithCorrelation } from 'quidproquo-webserver';
3
+ import { QpqRuntimeDefinition } from '../../hooks/asmj/createQpqRuntimeDefinition';
4
+ import { QpqApi, QpqMappedApi } from '../../hooks/asmj/QpqMappedApi';
5
+ import { ActionProcessorListResolverFactory } from '../../hooks/asmj/useQpqRuntime';
6
+ export declare function useQpqWebsocketQueueRuntime<TState, TAction, TApi extends QpqApi>(atom: QpqRuntimeDefinition<TState, TAction, TApi>, mainStory?: Story<any, any>, name?: string, getActionProcessors?: ActionProcessorListResolverFactory<TState>): [
7
+ QpqMappedApi<TApi>,
8
+ TState,
9
+ (action: any) => void,
10
+ (event: Omit<AnyWebSocketQueueEventMessageWithCorrelation, 'correlationId'>) => Promise<any>
11
+ ];
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.useQpqWebsocketQueueRuntime = useQpqWebsocketQueueRuntime;
13
+ const quidproquo_webserver_1 = require("quidproquo-webserver");
14
+ const react_1 = require("react");
15
+ const useQpqRuntime_1 = require("../../hooks/asmj/useQpqRuntime");
16
+ const getServiceRequestActionProcessor_1 = require("./actionProcessor/getServiceRequestActionProcessor");
17
+ const useWebsocketQueueSendEvent_1 = require("./useWebsocketQueueSendEvent");
18
+ function useQpqWebsocketQueueRuntime(atom, mainStory, name, getActionProcessors) {
19
+ const sendEventRef = (0, react_1.useRef)(null);
20
+ const mergedFactory = (dispatch, getCurrentState) => {
21
+ const serviceResolver = () => __awaiter(this, void 0, void 0, function* () { return (0, getServiceRequestActionProcessor_1.getServiceRequestActionProcessor)(sendEventRef); });
22
+ const callerResolver = getActionProcessors === null || getActionProcessors === void 0 ? void 0 : getActionProcessors(dispatch, getCurrentState);
23
+ return (qpqConfig, dynamicModuleLoader) => __awaiter(this, void 0, void 0, function* () {
24
+ return (Object.assign(Object.assign({}, (yield serviceResolver())), (callerResolver ? yield callerResolver(qpqConfig, dynamicModuleLoader) : {})));
25
+ });
26
+ };
27
+ const [api, state, dispatch] = (0, useQpqRuntime_1.useQpqRuntime)(atom, mainStory, name, mergedFactory);
28
+ const sendEvent = (0, useWebsocketQueueSendEvent_1.useWebsocketQueueSendEvent)((event) => {
29
+ if (event.type === quidproquo_webserver_1.WebSocketQueueServerMessageEventType.StateDispatch) {
30
+ dispatch(event.payload);
31
+ }
32
+ });
33
+ sendEventRef.current = sendEvent;
34
+ return [api, state, dispatch, sendEvent];
35
+ }
@@ -1,2 +1,2 @@
1
1
  import { AnyWebSocketQueueEventMessageWithCorrelation } from 'quidproquo-webserver';
2
- export declare const useWebsocketQueueSendEvent: <E extends AnyWebSocketQueueEventMessageWithCorrelation>() => (event: E) => void;
2
+ export declare const useWebsocketQueueSendEvent: <TSend extends AnyWebSocketQueueEventMessageWithCorrelation>(onCorrelatedMessage?: (event: AnyWebSocketQueueEventMessageWithCorrelation) => void) => (event: Omit<TSend, "correlationId">) => Promise<any>;
@@ -1,9 +1,59 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useWebsocketQueueSendEvent = void 0;
4
+ const quidproquo_web_1 = require("quidproquo-web");
5
+ const quidproquo_webserver_1 = require("quidproquo-webserver");
6
+ const react_1 = require("react");
7
+ const hooks_1 = require("../../hooks");
4
8
  const websocket_1 = require("../../websocket");
5
- const useWebsocketQueueSendEvent = () => {
6
- const sendMessage = (0, websocket_1.useWebsocketSendEvent)();
7
- return sendMessage;
9
+ const useWebsocketQueueSendEvent = (onCorrelatedMessage) => {
10
+ const websocketApi = (0, websocket_1.useWebsocketApi)();
11
+ const activeCorrelationsRef = (0, react_1.useRef)(new Set());
12
+ const pendingResolversRef = (0, react_1.useRef)(new Map());
13
+ // Subscribe to ALL messages, filter by active correlationIds
14
+ const handleMessage = (0, hooks_1.useFastCallback)((_ws, rawEvent) => {
15
+ if (!rawEvent)
16
+ return;
17
+ try {
18
+ const parsed = JSON.parse(rawEvent.data);
19
+ if (!parsed.correlationId || !activeCorrelationsRef.current.has(parsed.correlationId)) {
20
+ return;
21
+ }
22
+ if (parsed.type === quidproquo_webserver_1.WebSocketQueueServerMessageEventType.ServiceRequestResponse) {
23
+ const resolve = pendingResolversRef.current.get(parsed.correlationId);
24
+ if (resolve) {
25
+ resolve(parsed.payload);
26
+ pendingResolversRef.current.delete(parsed.correlationId);
27
+ activeCorrelationsRef.current.delete(parsed.correlationId);
28
+ }
29
+ }
30
+ else {
31
+ onCorrelatedMessage === null || onCorrelatedMessage === void 0 ? void 0 : onCorrelatedMessage(parsed);
32
+ }
33
+ }
34
+ catch (_a) {
35
+ // Not JSON or not a queue message — ignore
36
+ }
37
+ });
38
+ (0, websocket_1.useSubscribeToWebsocket)(quidproquo_web_1.WebsocketServiceEvent.MESSAGE, handleMessage);
39
+ // Send with auto-generated correlationId, register it as active
40
+ const sendEvent = (0, hooks_1.useFastCallback)((event) => {
41
+ if (!websocketApi) {
42
+ return Promise.resolve(undefined);
43
+ }
44
+ const correlationId = crypto.randomUUID();
45
+ activeCorrelationsRef.current.add(correlationId);
46
+ const isServiceRequest = event.type.startsWith('qpq/serviceRequest/');
47
+ if (isServiceRequest) {
48
+ const promise = new Promise((resolve) => {
49
+ pendingResolversRef.current.set(correlationId, resolve);
50
+ });
51
+ websocketApi.sendEvent(Object.assign(Object.assign({}, event), { correlationId }));
52
+ return promise;
53
+ }
54
+ websocketApi.sendEvent(Object.assign(Object.assign({}, event), { correlationId }));
55
+ return Promise.resolve(undefined);
56
+ });
57
+ return sendEvent;
8
58
  };
9
59
  exports.useWebsocketQueueSendEvent = useWebsocketQueueSendEvent;
@@ -0,0 +1,2 @@
1
+ import { ActionProcessorListResolver } from 'quidproquo-core';
2
+ export declare const ActionProcessorContext: import("react").Context<ActionProcessorListResolver>;
@@ -0,0 +1,2 @@
1
+ import { createContext } from 'react';
2
+ export const ActionProcessorContext = createContext(async () => ({}));
@@ -0,0 +1,6 @@
1
+ import { ActionProcessorListResolver } from 'quidproquo-core';
2
+ export type ActionProcessorProviderProps = {
3
+ children: React.ReactNode;
4
+ getActionProcessors: ActionProcessorListResolver;
5
+ };
6
+ export declare const ActionProcessorProvider: React.FC<ActionProcessorProviderProps>;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useContext } from 'react';
3
+ import { ActionProcessorContext } from './ActionProcessorContext';
4
+ export const ActionProcessorProvider = ({ children, getActionProcessors }) => {
5
+ const parentGetActionProcessors = useContext(ActionProcessorContext);
6
+ // Merge: parent processors first, then this provider's (so child overrides parent)
7
+ const mergedGetActionProcessors = async (qpqConfig, dynamicModuleLoader) => ({
8
+ ...(await parentGetActionProcessors(qpqConfig, dynamicModuleLoader)),
9
+ ...(await getActionProcessors(qpqConfig, dynamicModuleLoader)),
10
+ });
11
+ return _jsx(ActionProcessorContext.Provider, { value: mergedGetActionProcessors, children: children });
12
+ };
@@ -0,0 +1,3 @@
1
+ export * from './ActionProcessorContext';
2
+ export * from './ActionProcessorProvider';
3
+ export * from './useActionProcessors';
@@ -0,0 +1,3 @@
1
+ export * from './ActionProcessorContext';
2
+ export * from './ActionProcessorProvider';
3
+ export * from './useActionProcessors';
@@ -0,0 +1 @@
1
+ export declare const useActionProcessors: () => import("quidproquo-core").ActionProcessorListResolver;
@@ -0,0 +1,3 @@
1
+ import { useContext } from 'react';
2
+ import { ActionProcessorContext } from './ActionProcessorContext';
3
+ export const useActionProcessors = () => useContext(ActionProcessorContext);
@@ -4,4 +4,5 @@ export * from './createQpqRuntimeDefinition';
4
4
  export * from './QpqContextProvider';
5
5
  export * from './QpqMappedApi';
6
6
  export * from './QpqRuntimeEffectCatcher';
7
+ export * from './useBubbleReducer';
7
8
  export * from './useQpqRuntime';
@@ -4,4 +4,5 @@ export * from './createQpqRuntimeDefinition';
4
4
  export * from './QpqContextProvider';
5
5
  export * from './QpqMappedApi';
6
6
  export * from './QpqRuntimeEffectCatcher';
7
+ export * from './useBubbleReducer';
7
8
  export * from './useQpqRuntime';
@@ -0,0 +1,2 @@
1
+ import { QpqBubbleReducer } from './bubbleReducer';
2
+ export declare const useBubbleReducer: <TState>(reducer: QpqBubbleReducer<TState, any>, initialState: TState | (() => TState)) => [TState, (action: unknown) => void];
@@ -0,0 +1,18 @@
1
+ import { useCallback, useContext, useRef, useState } from 'react';
2
+ import { BubbleReducerDispatchContext } from './bubbleReducer';
3
+ export const useBubbleReducer = (reducer, initialState) => {
4
+ const parentDispatch = useContext(BubbleReducerDispatchContext);
5
+ const [state, setState] = useState(initialState);
6
+ const stateRef = useRef(state);
7
+ stateRef.current = state;
8
+ const dispatch = useCallback((action) => {
9
+ const [newState, preventBubble] = reducer(stateRef.current, action);
10
+ if (preventBubble) {
11
+ setState(newState);
12
+ }
13
+ else {
14
+ parentDispatch(action);
15
+ }
16
+ }, [parentDispatch, reducer]);
17
+ return [state, dispatch];
18
+ };
@@ -1,4 +1,6 @@
1
- import { Story } from 'quidproquo-core';
1
+ import { ActionProcessorListResolver, Story } from 'quidproquo-core';
2
+ import { Dispatch } from 'react';
2
3
  import { QpqRuntimeDefinition } from './createQpqRuntimeDefinition';
3
4
  import { QpqApi, QpqMappedApi } from './QpqMappedApi';
4
- export declare function useQpqRuntime<TState, TAction, TApi extends QpqApi>(atom: QpqRuntimeDefinition<TState, TAction, TApi>, mainStory?: Story<any, any>, name?: string): [QpqMappedApi<TApi>, TState, (action: any) => void];
5
+ export type ActionProcessorListResolverFactory<TState = any> = (dispatch: Dispatch<any>, getCurrentState: () => TState) => ActionProcessorListResolver;
6
+ export declare function useQpqRuntime<TState, TAction, TApi extends QpqApi>(atom: QpqRuntimeDefinition<TState, TAction, TApi>, mainStory?: Story<any, any>, name?: string, getActionProcessors?: ActionProcessorListResolverFactory<TState>): [QpqMappedApi<TApi>, TState, (action: any) => void];
@@ -2,12 +2,16 @@ import { useEffect, useMemo, useState } from 'react';
2
2
  import { useQpq } from '../useQpq';
3
3
  import { getStateActionProcessor } from './actionProcessor';
4
4
  import { useQpqRuntimeBubblingReducer } from './bubbleReducer';
5
- export function useQpqRuntime(atom, mainStory, name) {
5
+ export function useQpqRuntime(atom, mainStory, name, getActionProcessors = () => async () => ({})) {
6
6
  const atomInfo = useMemo(() => atom(name), [atom, name]);
7
7
  const [state, dispatch, getCurrentState] = useQpqRuntimeBubblingReducer(atom, name);
8
8
  // Api generators are memoized to prevent unnecessary re-renders.
9
9
  const [memoedApiGenerators] = useState(() => atomInfo.api);
10
- const resolver = useQpq(getStateActionProcessor(dispatch, getCurrentState));
10
+ const mergedProcessors = async (qpqConfig, dynamicModuleLoader) => ({
11
+ ...(await getStateActionProcessor(dispatch, getCurrentState)(qpqConfig, dynamicModuleLoader)),
12
+ ...(await getActionProcessors(dispatch, getCurrentState)(qpqConfig, dynamicModuleLoader)),
13
+ });
14
+ const resolver = useQpq(mergedProcessors);
11
15
  // Wrap and remap each API generator using the resolver.
12
16
  const api = useMemo(() => {
13
17
  const wrapped = {};
@@ -1,6 +1,7 @@
1
1
  import { getWebActionProcessors } from 'quidproquo-actionprocessor-web';
2
2
  import { createRuntime, defineModule, QpqRuntimeType, } from 'quidproquo-core';
3
3
  import { useCallback, useEffect, useMemo, useRef } from 'react';
4
+ import { useActionProcessors } from '../actionProcessor';
4
5
  import { useQpqContextValues } from './asmj/QpqContextProvider';
5
6
  function* withVersionCheck(story, versionRef, capturedVersion) {
6
7
  let nextValue = undefined;
@@ -25,6 +26,7 @@ const logger = {
25
26
  };
26
27
  export function useQpq(getActionProcessors = async () => ({})) {
27
28
  const qpqContextValues = useQpqContextValues();
29
+ const contextGetActionProcessors = useActionProcessors();
28
30
  const versionRef = useRef(0);
29
31
  useEffect(() => {
30
32
  return () => {
@@ -36,6 +38,7 @@ export function useQpq(getActionProcessors = async () => ({})) {
36
38
  context: qpqContextValues,
37
39
  }, async (qpqConfig, dynamicModuleLoader) => ({
38
40
  ...(await getWebActionProcessors(qpqConfig, dynamicModuleLoader)),
41
+ ...(await contextGetActionProcessors(qpqConfig, dynamicModuleLoader)),
39
42
  ...(await getActionProcessors(qpqConfig, dynamicModuleLoader)),
40
43
  }), () => new Date().toISOString(), logger, `frontend::${'uuid'}`, QpqRuntimeType.UI, async (_runtime) => {
41
44
  // noop
@@ -1,4 +1,5 @@
1
1
  import 'symbol-observable';
2
+ export * from './actionProcessor';
2
3
  export * from './api';
3
4
  export * from './auth';
4
5
  export * from './baseUrl';
package/lib/esm/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import 'symbol-observable';
2
+ export * from './actionProcessor';
2
3
  export * from './api';
3
4
  export * from './auth';
4
5
  export * from './baseUrl';
@@ -0,0 +1,4 @@
1
+ import { ActionProcessorList } from 'quidproquo-core';
2
+ import { AnyWebSocketQueueEventMessageWithCorrelation } from 'quidproquo-webserver';
3
+ import { RefObject } from 'react';
4
+ export declare const getServiceRequestActionProcessor: (sendEventRef: RefObject<((event: Omit<AnyWebSocketQueueEventMessageWithCorrelation, "correlationId">) => Promise<any>) | null>) => ActionProcessorList;
@@ -0,0 +1,11 @@
1
+ import { actionResult, actionResultError } from 'quidproquo-core';
2
+ import { ServiceActionType } from 'quidproquo-webserver';
3
+ export const getServiceRequestActionProcessor = (sendEventRef) => ({
4
+ [ServiceActionType.Request]: async ({ serviceName, method, payload, }) => {
5
+ const response = await sendEventRef.current?.({ type: `qpq/serviceRequest/${serviceName}/${method}`, payload });
6
+ if (response && !response.success) {
7
+ return actionResultError(response.error.errorType, response.error.errorText, response.error.errorStack);
8
+ }
9
+ return actionResult(response?.result);
10
+ },
11
+ });
@@ -1,2 +1,4 @@
1
+ export * from './actionProcessor/getServiceRequestActionProcessor';
2
+ export * from './useQpqWebsocketQueueRuntime';
1
3
  export * from './useSubscribeToWebSocketQueueEvent';
2
4
  export * from './useWebsocketQueueSendEvent';
@@ -1,2 +1,4 @@
1
+ export * from './actionProcessor/getServiceRequestActionProcessor';
2
+ export * from './useQpqWebsocketQueueRuntime';
1
3
  export * from './useSubscribeToWebSocketQueueEvent';
2
4
  export * from './useWebsocketQueueSendEvent';
@@ -0,0 +1,11 @@
1
+ import { Story } from 'quidproquo-core';
2
+ import { AnyWebSocketQueueEventMessageWithCorrelation } from 'quidproquo-webserver';
3
+ import { QpqRuntimeDefinition } from '../../hooks/asmj/createQpqRuntimeDefinition';
4
+ import { QpqApi, QpqMappedApi } from '../../hooks/asmj/QpqMappedApi';
5
+ import { ActionProcessorListResolverFactory } from '../../hooks/asmj/useQpqRuntime';
6
+ export declare function useQpqWebsocketQueueRuntime<TState, TAction, TApi extends QpqApi>(atom: QpqRuntimeDefinition<TState, TAction, TApi>, mainStory?: Story<any, any>, name?: string, getActionProcessors?: ActionProcessorListResolverFactory<TState>): [
7
+ QpqMappedApi<TApi>,
8
+ TState,
9
+ (action: any) => void,
10
+ (event: Omit<AnyWebSocketQueueEventMessageWithCorrelation, 'correlationId'>) => Promise<any>
11
+ ];
@@ -0,0 +1,24 @@
1
+ import { WebSocketQueueServerMessageEventType } from 'quidproquo-webserver';
2
+ import { useRef } from 'react';
3
+ import { useQpqRuntime } from '../../hooks/asmj/useQpqRuntime';
4
+ import { getServiceRequestActionProcessor } from './actionProcessor/getServiceRequestActionProcessor';
5
+ import { useWebsocketQueueSendEvent } from './useWebsocketQueueSendEvent';
6
+ export function useQpqWebsocketQueueRuntime(atom, mainStory, name, getActionProcessors) {
7
+ const sendEventRef = useRef(null);
8
+ const mergedFactory = (dispatch, getCurrentState) => {
9
+ const serviceResolver = async () => getServiceRequestActionProcessor(sendEventRef);
10
+ const callerResolver = getActionProcessors?.(dispatch, getCurrentState);
11
+ return async (qpqConfig, dynamicModuleLoader) => ({
12
+ ...(await serviceResolver()),
13
+ ...(callerResolver ? await callerResolver(qpqConfig, dynamicModuleLoader) : {}),
14
+ });
15
+ };
16
+ const [api, state, dispatch] = useQpqRuntime(atom, mainStory, name, mergedFactory);
17
+ const sendEvent = useWebsocketQueueSendEvent((event) => {
18
+ if (event.type === WebSocketQueueServerMessageEventType.StateDispatch) {
19
+ dispatch(event.payload);
20
+ }
21
+ });
22
+ sendEventRef.current = sendEvent;
23
+ return [api, state, dispatch, sendEvent];
24
+ }
@@ -1,2 +1,2 @@
1
1
  import { AnyWebSocketQueueEventMessageWithCorrelation } from 'quidproquo-webserver';
2
- export declare const useWebsocketQueueSendEvent: <E extends AnyWebSocketQueueEventMessageWithCorrelation>() => (event: E) => void;
2
+ export declare const useWebsocketQueueSendEvent: <TSend extends AnyWebSocketQueueEventMessageWithCorrelation>(onCorrelatedMessage?: (event: AnyWebSocketQueueEventMessageWithCorrelation) => void) => (event: Omit<TSend, "correlationId">) => Promise<any>;
@@ -1,5 +1,55 @@
1
- import { useWebsocketSendEvent } from '../../websocket';
2
- export const useWebsocketQueueSendEvent = () => {
3
- const sendMessage = useWebsocketSendEvent();
4
- return sendMessage;
1
+ import { WebsocketServiceEvent } from 'quidproquo-web';
2
+ import { WebSocketQueueServerMessageEventType } from 'quidproquo-webserver';
3
+ import { useRef } from 'react';
4
+ import { useFastCallback } from '../../hooks';
5
+ import { useSubscribeToWebsocket, useWebsocketApi } from '../../websocket';
6
+ export const useWebsocketQueueSendEvent = (onCorrelatedMessage) => {
7
+ const websocketApi = useWebsocketApi();
8
+ const activeCorrelationsRef = useRef(new Set());
9
+ const pendingResolversRef = useRef(new Map());
10
+ // Subscribe to ALL messages, filter by active correlationIds
11
+ const handleMessage = useFastCallback((_ws, rawEvent) => {
12
+ if (!rawEvent)
13
+ return;
14
+ try {
15
+ const parsed = JSON.parse(rawEvent.data);
16
+ if (!parsed.correlationId || !activeCorrelationsRef.current.has(parsed.correlationId)) {
17
+ return;
18
+ }
19
+ if (parsed.type === WebSocketQueueServerMessageEventType.ServiceRequestResponse) {
20
+ const resolve = pendingResolversRef.current.get(parsed.correlationId);
21
+ if (resolve) {
22
+ resolve(parsed.payload);
23
+ pendingResolversRef.current.delete(parsed.correlationId);
24
+ activeCorrelationsRef.current.delete(parsed.correlationId);
25
+ }
26
+ }
27
+ else {
28
+ onCorrelatedMessage?.(parsed);
29
+ }
30
+ }
31
+ catch {
32
+ // Not JSON or not a queue message — ignore
33
+ }
34
+ });
35
+ useSubscribeToWebsocket(WebsocketServiceEvent.MESSAGE, handleMessage);
36
+ // Send with auto-generated correlationId, register it as active
37
+ const sendEvent = useFastCallback((event) => {
38
+ if (!websocketApi) {
39
+ return Promise.resolve(undefined);
40
+ }
41
+ const correlationId = crypto.randomUUID();
42
+ activeCorrelationsRef.current.add(correlationId);
43
+ const isServiceRequest = event.type.startsWith('qpq/serviceRequest/');
44
+ if (isServiceRequest) {
45
+ const promise = new Promise((resolve) => {
46
+ pendingResolversRef.current.set(correlationId, resolve);
47
+ });
48
+ websocketApi.sendEvent({ ...event, correlationId });
49
+ return promise;
50
+ }
51
+ websocketApi.sendEvent({ ...event, correlationId });
52
+ return Promise.resolve(undefined);
53
+ });
54
+ return sendEvent;
5
55
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quidproquo-web-react",
3
- "version": "0.0.261",
3
+ "version": "0.0.263",
4
4
  "description": "",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -32,8 +32,8 @@
32
32
  },
33
33
  "homepage": "https://github.com/joe-coady/quidproquo#readme",
34
34
  "devDependencies": {
35
- "quidproquo-core": "0.0.261",
36
- "quidproquo-tsconfig": "0.0.261",
35
+ "quidproquo-core": "0.0.263",
36
+ "quidproquo-tsconfig": "0.0.263",
37
37
  "typescript": "^5.8.2"
38
38
  },
39
39
  "peerDependencies": {
@@ -42,9 +42,9 @@
42
42
  "dependencies": {
43
43
  "jotai": "^2.12.1",
44
44
  "symbol-observable": "^4.0.0",
45
- "quidproquo-web": "0.0.261",
46
- "quidproquo-webserver": "0.0.261",
47
- "quidproquo-actionprocessor-node": "0.0.261",
48
- "quidproquo-actionprocessor-web": "0.0.261"
45
+ "quidproquo-web": "0.0.263",
46
+ "quidproquo-webserver": "0.0.263",
47
+ "quidproquo-actionprocessor-node": "0.0.263",
48
+ "quidproquo-actionprocessor-web": "0.0.263"
49
49
  }
50
50
  }