quidproquo-web-admin 0.1.12 → 0.1.13

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 (65) hide show
  1. package/lib/commonjs/App/App.js +4 -1
  2. package/lib/commonjs/App/App.js.map +1 -1
  3. package/lib/commonjs/Auth/Auth.js +1 -2
  4. package/lib/commonjs/Auth/Auth.js.map +1 -1
  5. package/lib/commonjs/Auth/AuthChallengeMfaSetup/AuthChallengeMfaSetup.js +7 -2
  6. package/lib/commonjs/Auth/AuthChallengeMfaSetup/AuthChallengeMfaSetup.js.map +1 -1
  7. package/lib/commonjs/Auth/AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired.js +7 -2
  8. package/lib/commonjs/Auth/AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired.js.map +1 -1
  9. package/lib/commonjs/Auth/AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa.js +7 -2
  10. package/lib/commonjs/Auth/AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa.js.map +1 -1
  11. package/lib/commonjs/Auth/logic/authRuntime.d.ts +2 -1
  12. package/lib/commonjs/Auth/logic/authRuntime.js +8 -1
  13. package/lib/commonjs/Auth/logic/authRuntime.js.map +1 -1
  14. package/lib/commonjs/LogViewer/LogChat/LogChat.js +1 -2
  15. package/lib/commonjs/LogViewer/LogChat/LogChat.js.map +1 -1
  16. package/lib/commonjs/LogViewer/LogChat/eventDocAiLogChatRuntime.js +11 -3
  17. package/lib/commonjs/LogViewer/LogChat/eventDocAiLogChatRuntime.js.map +1 -1
  18. package/lib/commonjs/adminApp/actions/askApplySessionEventToLog.js +3 -1
  19. package/lib/commonjs/adminApp/actions/askApplySessionEventToLog.js.map +1 -1
  20. package/lib/commonjs/adminApp/adminAppRuntime.js +13 -1
  21. package/lib/commonjs/adminApp/adminAppRuntime.js.map +1 -1
  22. package/lib/commonjs/adminApp/components/AdminAppProvider/AdminAppProvider.js +5 -10
  23. package/lib/commonjs/adminApp/components/AdminAppProvider/AdminAppProvider.js.map +1 -1
  24. package/lib/commonjs/adminApp/hooks/useAdminApp.d.ts +1 -1
  25. package/lib/commonjs/adminApp/hooks/useAdminApp.js +3 -4
  26. package/lib/commonjs/adminApp/hooks/useAdminApp.js.map +1 -1
  27. package/lib/commonjs/adminApp/stateUpdaters/sessionLog/eventAppended.js +7 -8
  28. package/lib/commonjs/adminApp/stateUpdaters/sessionLog/eventAppended.js.map +1 -1
  29. package/lib/commonjs/adminApp/stateUpdaters/sessionLog/eventSaved.js +3 -2
  30. package/lib/commonjs/adminApp/stateUpdaters/sessionLog/eventSaved.js.map +1 -1
  31. package/lib/commonjs/adminApp/testHelpers/makeSessionEvent.js +2 -1
  32. package/lib/commonjs/adminApp/testHelpers/makeSessionEvent.js.map +1 -1
  33. package/lib/esm/App/App.js +5 -2
  34. package/lib/esm/App/App.js.map +1 -1
  35. package/lib/esm/Auth/Auth.js +1 -2
  36. package/lib/esm/Auth/Auth.js.map +1 -1
  37. package/lib/esm/Auth/AuthChallengeMfaSetup/AuthChallengeMfaSetup.js +7 -2
  38. package/lib/esm/Auth/AuthChallengeMfaSetup/AuthChallengeMfaSetup.js.map +1 -1
  39. package/lib/esm/Auth/AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired.js +7 -2
  40. package/lib/esm/Auth/AuthChallengeNewPasswordRequired/AuthChallengeNewPasswordRequired.js.map +1 -1
  41. package/lib/esm/Auth/AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa.js +7 -2
  42. package/lib/esm/Auth/AuthChallengeSoftwareTokenMfa/AuthChallengeSoftwareTokenMfa.js.map +1 -1
  43. package/lib/esm/Auth/logic/authRuntime.d.ts +2 -1
  44. package/lib/esm/Auth/logic/authRuntime.js +8 -1
  45. package/lib/esm/Auth/logic/authRuntime.js.map +1 -1
  46. package/lib/esm/LogViewer/LogChat/LogChat.js +1 -2
  47. package/lib/esm/LogViewer/LogChat/LogChat.js.map +1 -1
  48. package/lib/esm/LogViewer/LogChat/eventDocAiLogChatRuntime.js +11 -3
  49. package/lib/esm/LogViewer/LogChat/eventDocAiLogChatRuntime.js.map +1 -1
  50. package/lib/esm/adminApp/actions/askApplySessionEventToLog.js +4 -2
  51. package/lib/esm/adminApp/actions/askApplySessionEventToLog.js.map +1 -1
  52. package/lib/esm/adminApp/adminAppRuntime.js +13 -1
  53. package/lib/esm/adminApp/adminAppRuntime.js.map +1 -1
  54. package/lib/esm/adminApp/components/AdminAppProvider/AdminAppProvider.js +6 -11
  55. package/lib/esm/adminApp/components/AdminAppProvider/AdminAppProvider.js.map +1 -1
  56. package/lib/esm/adminApp/hooks/useAdminApp.d.ts +1 -1
  57. package/lib/esm/adminApp/hooks/useAdminApp.js +3 -4
  58. package/lib/esm/adminApp/hooks/useAdminApp.js.map +1 -1
  59. package/lib/esm/adminApp/stateUpdaters/sessionLog/eventAppended.js +6 -13
  60. package/lib/esm/adminApp/stateUpdaters/sessionLog/eventAppended.js.map +1 -1
  61. package/lib/esm/adminApp/stateUpdaters/sessionLog/eventSaved.js +3 -8
  62. package/lib/esm/adminApp/stateUpdaters/sessionLog/eventSaved.js.map +1 -1
  63. package/lib/esm/adminApp/testHelpers/makeSessionEvent.js +2 -1
  64. package/lib/esm/adminApp/testHelpers/makeSessionEvent.js.map +1 -1
  65. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"AdminAppProvider.js","sourceRoot":"","sources":["../../../../../src/adminApp/components/AdminAppProvider/AdminAppProvider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE/G,OAAO,EAAa,UAAU,EAAE,MAAM,OAAO,CAAC;AAE9C,OAAO,EAAE,mCAAmC,EAAE,MAAM,mDAAmD,CAAC;AACxG,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAoB,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACrF,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAM9D,8EAA8E;AAC9E,8EAA8E;AAC9E,uCAAuC;AACvC,MAAM,oBAAoB,GAAoC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC7E,aAAa,CAAC,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,mCAAmC,CAAC,CAAC;IAEhG,OAAO,KAAC,uBAAuB,IAAC,OAAO,EAAE,eAAe,YAAG,QAAQ,GAA2B,CAAC;AACjG,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IAChF,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAE1C,MAAM,SAAS,GAAqB;QAClC,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI,EAAE;KACpC,CAAC;IAEF,OAAO,CACL,KAAC,kBAAkB,IAAC,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,EAAE,SAAS,YACvE,KAAC,oBAAoB,cAAE,QAAQ,GAAwB,GACpC,CACtB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { authContext, QpqContextProvider, QpqRuntimeEffectCatcher, useQpqRuntime } from 'quidproquo-web-react';\n\nimport { ReactNode, useContext } from 'react';\n\nimport { getApplySessionEventActionProcessor } from '../../actions/getApplySessionEventActionProcessor';\nimport { adminAppRuntime } from '../../adminAppRuntime';\nimport { AdminUserContext, adminUserContext } from '../../contexts/adminUserContext';\nimport { askAdminAppMain } from '../../logic/askAdminAppMain';\n\ntype AdminAppProviderProps = {\n children?: ReactNode;\n};\n\n// Mounts only once authenticated (inside Auth), so mounting IS session start:\n// the boot story creates the session doc, seeds it from the URL, and runs the\n// flush loop for the life of the page.\nconst AdminAppRuntimeMount: React.FC<AdminAppProviderProps> = ({ children }) => {\n useQpqRuntime(adminAppRuntime, askAdminAppMain, undefined, getApplySessionEventActionProcessor);\n\n return <QpqRuntimeEffectCatcher runtime={adminAppRuntime}>{children}</QpqRuntimeEffectCatcher>;\n};\n\nexport const AdminAppProvider: React.FC<AdminAppProviderProps> = ({ children }) => {\n const authState = useContext(authContext);\n\n const adminUser: AdminUserContext = {\n username: authState?.username ?? '',\n };\n\n return (\n <QpqContextProvider contextIdentifier={adminUserContext} value={adminUser}>\n <AdminAppRuntimeMount>{children}</AdminAppRuntimeMount>\n </QpqContextProvider>\n );\n};\n"]}
1
+ {"version":3,"file":"AdminAppProvider.js","sourceRoot":"","sources":["../../../../../src/adminApp/components/AdminAppProvider/AdminAppProvider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAEhG,OAAO,EAAa,UAAU,EAAE,MAAM,OAAO,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAoB,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAMrF,yEAAyE;AACzE,8EAA8E;AAC9E,4EAA4E;AAC5E,wCAAwC;AACxC,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IAChF,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAE1C,MAAM,SAAS,GAAqB;QAClC,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI,EAAE;KACpC,CAAC;IAEF,OAAO,CACL,KAAC,kBAAkB,IAAC,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,EAAE,SAAS,YACvE,KAAC,uBAAuB,IAAC,OAAO,EAAE,eAAe,YAAG,QAAQ,GAA2B,GACpE,CACtB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { authContext, QpqContextProvider, QpqRuntimeEffectCatcher } from 'quidproquo-web-react';\n\nimport { ReactNode, useContext } from 'react';\n\nimport { adminAppRuntime } from '../../adminAppRuntime';\nimport { AdminUserContext, adminUserContext } from '../../contexts/adminUserContext';\n\ntype AdminAppProviderProps = {\n children?: ReactNode;\n};\n\n// Mounts only once authenticated (inside Auth), so the first bind of the\n// adminApp area IS session start: the definition's onInit creates the session\n// doc, seeds it from the URL, and runs the flush loop until logout unmounts\n// the subtree and the area is released.\nexport const AdminAppProvider: React.FC<AdminAppProviderProps> = ({ children }) => {\n const authState = useContext(authContext);\n\n const adminUser: AdminUserContext = {\n username: authState?.username ?? '',\n };\n\n return (\n <QpqContextProvider contextIdentifier={adminUserContext} value={adminUser}>\n <QpqRuntimeEffectCatcher runtime={adminAppRuntime}>{children}</QpqRuntimeEffectCatcher>\n </QpqContextProvider>\n );\n};\n"]}
@@ -14,4 +14,4 @@ export declare const useAdminApp: () => [import("quidproquo-web-react").QpqMappe
14
14
  askRunLogLogSearch: typeof import("..").askRunLogLogSearch;
15
15
  askRunLogSearch: typeof import("..").askRunLogSearch;
16
16
  askSendChatMessage: typeof import("..").askSendChatMessage;
17
- }>, import("..").AdminAppState, (action: any) => void];
17
+ }>, import("..").AdminAppState, (action: import("..").SessionLogEffects | import("..").VolatileEffects) => void];
@@ -1,7 +1,6 @@
1
1
  import { useQpqRuntime } from 'quidproquo-web-react';
2
- import { getApplySessionEventActionProcessor } from '../actions/getApplySessionEventActionProcessor';
3
2
  import { adminAppRuntime } from '../adminAppRuntime';
4
- // The admin runtime + its ApplyEvent processor. The boot story runs once in
5
- // AdminAppProvider; every other consumer mounts without a main story.
6
- export const useAdminApp = () => useQpqRuntime(adminAppRuntime, undefined, undefined, getApplySessionEventActionProcessor);
3
+ // The ApplyEvent processor and the boot story both live on the definition, so
4
+ // every consumer binds the same way; the first bind starts the session.
5
+ export const useAdminApp = () => useQpqRuntime(adminAppRuntime);
7
6
  //# sourceMappingURL=useAdminApp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAdminApp.js","sourceRoot":"","sources":["../../../../src/adminApp/hooks/useAdminApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,mCAAmC,EAAE,MAAM,gDAAgD,CAAC;AACrG,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,4EAA4E;AAC5E,sEAAsE;AACtE,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,mCAAmC,CAAC,CAAC","sourcesContent":["import { useQpqRuntime } from 'quidproquo-web-react';\n\nimport { getApplySessionEventActionProcessor } from '../actions/getApplySessionEventActionProcessor';\nimport { adminAppRuntime } from '../adminAppRuntime';\n\n// The admin runtime + its ApplyEvent processor. The boot story runs once in\n// AdminAppProvider; every other consumer mounts without a main story.\nexport const useAdminApp = () => useQpqRuntime(adminAppRuntime, undefined, undefined, getApplySessionEventActionProcessor);\n"]}
1
+ {"version":3,"file":"useAdminApp.js","sourceRoot":"","sources":["../../../../src/adminApp/hooks/useAdminApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,8EAA8E;AAC9E,wEAAwE;AACxE,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC","sourcesContent":["import { useQpqRuntime } from 'quidproquo-web-react';\n\nimport { adminAppRuntime } from '../adminAppRuntime';\n\n// The ApplyEvent processor and the boot story both live on the definition, so\n// every consumer binds the same way; the first bind starts the session.\nexport const useAdminApp = () => useQpqRuntime(adminAppRuntime);\n"]}
@@ -1,8 +1,4 @@
1
1
  import { coalesceEventTypes } from '../../constants/coalesceEventTypes';
2
- const nextLocalIndex = (state) => {
3
- const tail = state.pendingEvents[state.pendingEvents.length - 1] ?? state.events[state.events.length - 1];
4
- return tail ? tail.payload.metadata.index + 1 : 0;
5
- };
6
2
  // Optimistic append with coalescing: while the previous event of the same
7
3
  // coalescable type is still pending, the new one replaces it (latest value
8
4
  // wins). The head is never coalesced while the flush has it in flight — the
@@ -16,7 +12,9 @@ export const eventAppended = (state, event) => {
16
12
  ...event,
17
13
  payload: {
18
14
  ...event.payload,
19
- metadata: { ...event.payload.metadata, index: last.payload.metadata.index },
15
+ // Keeps the replaced event's id, so the coalesced event holds its place in the log
16
+ // rather than jumping to the end.
17
+ metadata: { ...event.payload.metadata, eventId: last.payload.metadata.eventId },
20
18
  },
21
19
  };
22
20
  return {
@@ -24,16 +22,11 @@ export const eventAppended = (state, event) => {
24
22
  pendingEvents: [...state.pendingEvents.slice(0, -1), coalesced],
25
23
  };
26
24
  }
27
- const appended = {
28
- ...event,
29
- payload: {
30
- ...event.payload,
31
- metadata: { ...event.payload.metadata, index: nextLocalIndex(state) },
32
- },
33
- };
25
+ // The event already carries the id minted when it was created, and sortable ids order
26
+ // themselves, so there is nothing to assign here.
34
27
  return {
35
28
  ...state,
36
- pendingEvents: [...state.pendingEvents, appended],
29
+ pendingEvents: [...state.pendingEvents, event],
37
30
  };
38
31
  };
39
32
  //# sourceMappingURL=eventAppended.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"eventAppended.js","sourceRoot":"","sources":["../../../../../src/adminApp/stateUpdaters/sessionLog/eventAppended.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAIxE,MAAM,cAAc,GAAG,CAAC,KAAsB,EAAU,EAAE;IACxD,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC1G,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,+DAA+D;AAC/D,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAsB,EAAE,KAAoB,EAAmB,EAAE;IAC7F,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEjE,MAAM,kBAAkB,GAAG,KAAK,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;IACpF,MAAM,cAAc,GAClB,CAAC,CAAC,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAA6B,CAAC,CAAC;IAEhI,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,SAAS,GAAkB;YAC/B,GAAG,KAAK;YACR,OAAO,EAAE;gBACP,GAAG,KAAK,CAAC,OAAO;gBAChB,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE;aAC5E;SACF,CAAC;QAEF,OAAO;YACL,GAAG,KAAK;YACR,aAAa,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;SAChE,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAkB;QAC9B,GAAG,KAAK;QACR,OAAO,EAAE;YACP,GAAG,KAAK,CAAC,OAAO;YAChB,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,EAAE;SACtE;KACF,CAAC;IAEF,OAAO;QACL,GAAG,KAAK;QACR,aAAa,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,EAAE,QAAQ,CAAC;KAClD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { EventDocEvent } from 'quidproquo-features';\n\nimport { coalesceEventTypes } from '../../constants/coalesceEventTypes';\nimport { AdminSessionEventType } from '../../effects/session/AdminSessionEventType';\nimport { SessionLogState } from '../../SessionLogState';\n\nconst nextLocalIndex = (state: SessionLogState): number => {\n const tail = state.pendingEvents[state.pendingEvents.length - 1] ?? state.events[state.events.length - 1];\n return tail ? tail.payload.metadata.index + 1 : 0;\n};\n\n// Optimistic append with coalescing: while the previous event of the same\n// coalescable type is still pending, the new one replaces it (latest value\n// wins). The head is never coalesced while the flush has it in flight — the\n// POSTed clientMessageId must stay matchable for the save ack.\nexport const eventAppended = (state: SessionLogState, event: EventDocEvent): SessionLogState => {\n const last = state.pendingEvents[state.pendingEvents.length - 1];\n\n const lastIsInFlightHead = state.pendingEvents.length === 1 && state.flush.inFlight;\n const shouldCoalesce =\n !!last && !lastIsInFlightHead && last.type === event.type && coalesceEventTypes.includes(event.type as AdminSessionEventType);\n\n if (shouldCoalesce) {\n const coalesced: EventDocEvent = {\n ...event,\n payload: {\n ...event.payload,\n metadata: { ...event.payload.metadata, index: last.payload.metadata.index },\n },\n };\n\n return {\n ...state,\n pendingEvents: [...state.pendingEvents.slice(0, -1), coalesced],\n };\n }\n\n const appended: EventDocEvent = {\n ...event,\n payload: {\n ...event.payload,\n metadata: { ...event.payload.metadata, index: nextLocalIndex(state) },\n },\n };\n\n return {\n ...state,\n pendingEvents: [...state.pendingEvents, appended],\n };\n};\n"]}
1
+ {"version":3,"file":"eventAppended.js","sourceRoot":"","sources":["../../../../../src/adminApp/stateUpdaters/sessionLog/eventAppended.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAIxE,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,+DAA+D;AAC/D,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAsB,EAAE,KAAoB,EAAmB,EAAE;IAC7F,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEjE,MAAM,kBAAkB,GAAG,KAAK,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;IACpF,MAAM,cAAc,GAClB,CAAC,CAAC,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAA6B,CAAC,CAAC;IAEhI,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,SAAS,GAAkB;YAC/B,GAAG,KAAK;YACR,OAAO,EAAE;gBACP,GAAG,KAAK,CAAC,OAAO;gBAChB,mFAAmF;gBACnF,kCAAkC;gBAClC,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE;aAChF;SACF,CAAC;QAEF,OAAO;YACL,GAAG,KAAK;YACR,aAAa,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;SAChE,CAAC;IACJ,CAAC;IAED,sFAAsF;IACtF,kDAAkD;IAClD,OAAO;QACL,GAAG,KAAK;QACR,aAAa,EAAE,CAAC,GAAG,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC;KAC/C,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { EventDocEvent } from 'quidproquo-features';\n\nimport { coalesceEventTypes } from '../../constants/coalesceEventTypes';\nimport { AdminSessionEventType } from '../../effects/session/AdminSessionEventType';\nimport { SessionLogState } from '../../SessionLogState';\n\n// Optimistic append with coalescing: while the previous event of the same\n// coalescable type is still pending, the new one replaces it (latest value\n// wins). The head is never coalesced while the flush has it in flight — the\n// POSTed clientMessageId must stay matchable for the save ack.\nexport const eventAppended = (state: SessionLogState, event: EventDocEvent): SessionLogState => {\n const last = state.pendingEvents[state.pendingEvents.length - 1];\n\n const lastIsInFlightHead = state.pendingEvents.length === 1 && state.flush.inFlight;\n const shouldCoalesce =\n !!last && !lastIsInFlightHead && last.type === event.type && coalesceEventTypes.includes(event.type as AdminSessionEventType);\n\n if (shouldCoalesce) {\n const coalesced: EventDocEvent = {\n ...event,\n payload: {\n ...event.payload,\n // Keeps the replaced event's id, so the coalesced event holds its place in the log\n // rather than jumping to the end.\n metadata: { ...event.payload.metadata, eventId: last.payload.metadata.eventId },\n },\n };\n\n return {\n ...state,\n pendingEvents: [...state.pendingEvents.slice(0, -1), coalesced],\n };\n }\n\n // The event already carries the id minted when it was created, and sortable ids order\n // themselves, so there is nothing to assign here.\n return {\n ...state,\n pendingEvents: [...state.pendingEvents, event],\n };\n};\n"]}
@@ -4,17 +4,12 @@
4
4
  export const eventSaved = (state, payload) => {
5
5
  const savedAt = state.pendingEvents.findIndex((event) => event.payload.metadata.clientMessageId === payload.clientMessageId);
6
6
  const remaining = savedAt === -1 ? state.pendingEvents : [...state.pendingEvents.slice(0, savedAt), ...state.pendingEvents.slice(savedAt + 1)];
7
- const renumbered = remaining.map((event, offset) => ({
8
- ...event,
9
- payload: {
10
- ...event.payload,
11
- metadata: { ...event.payload.metadata, index: payload.storedEvent.payload.metadata.index + 1 + offset },
12
- },
13
- }));
7
+ // No renumbering: each pending event minted its own sortable id, which already sorts after
8
+ // the saved log. Removing one from the middle leaves the rest correctly ordered.
14
9
  return {
15
10
  ...state,
16
11
  events: [...state.events, payload.storedEvent],
17
- pendingEvents: renumbered,
12
+ pendingEvents: remaining,
18
13
  flush: { inFlight: false, lastError: null, retryCount: 0 },
19
14
  };
20
15
  };
@@ -1 +1 @@
1
- {"version":3,"file":"eventSaved.js","sourceRoot":"","sources":["../../../../../src/adminApp/stateUpdaters/sessionLog/eventSaved.ts"],"names":[],"mappings":"AAKA,+EAA+E;AAC/E,+EAA+E;AAC/E,iFAAiF;AACjF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAsB,EAAE,OAAoC,EAAmB,EAAE;IAC1G,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAE7H,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IAE/I,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAiB,EAAE,CAAC,CAAC;QAClE,GAAG,KAAK;QACR,OAAO,EAAE;YACP,GAAG,KAAK,CAAC,OAAO;YAChB,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,GAAG,MAAM,EAAE;SACxG;KACF,CAAC,CAAC,CAAC;IAEJ,OAAO;QACL,GAAG,KAAK;QACR,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC;QAC9C,aAAa,EAAE,UAAU;QACzB,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE;KAC3D,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { EventDocEvent } from 'quidproquo-features';\n\nimport { SessionLogEventSavedPayload } from '../../effects/sessionLog/SessionLogEventSavedEffect';\nimport { SessionLogState } from '../../SessionLogState';\n\n// Server ack: the pending event moves to the acked log with its server-stamped\n// metadata, and the remaining pending events renumber onto consecutive indexes\n// after it (the server may have assigned a later index than our optimistic one).\nexport const eventSaved = (state: SessionLogState, payload: SessionLogEventSavedPayload): SessionLogState => {\n const savedAt = state.pendingEvents.findIndex((event) => event.payload.metadata.clientMessageId === payload.clientMessageId);\n\n const remaining = savedAt === -1 ? state.pendingEvents : [...state.pendingEvents.slice(0, savedAt), ...state.pendingEvents.slice(savedAt + 1)];\n\n const renumbered = remaining.map((event, offset): EventDocEvent => ({\n ...event,\n payload: {\n ...event.payload,\n metadata: { ...event.payload.metadata, index: payload.storedEvent.payload.metadata.index + 1 + offset },\n },\n }));\n\n return {\n ...state,\n events: [...state.events, payload.storedEvent],\n pendingEvents: renumbered,\n flush: { inFlight: false, lastError: null, retryCount: 0 },\n };\n};\n"]}
1
+ {"version":3,"file":"eventSaved.js","sourceRoot":"","sources":["../../../../../src/adminApp/stateUpdaters/sessionLog/eventSaved.ts"],"names":[],"mappings":"AAKA,+EAA+E;AAC/E,+EAA+E;AAC/E,iFAAiF;AACjF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAsB,EAAE,OAAoC,EAAmB,EAAE;IAC1G,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAE7H,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IAE/I,2FAA2F;IAC3F,iFAAiF;IACjF,OAAO;QACL,GAAG,KAAK;QACR,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC;QAC9C,aAAa,EAAE,SAAS;QACxB,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE;KAC3D,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { EventDocEvent } from 'quidproquo-features';\n\nimport { SessionLogEventSavedPayload } from '../../effects/sessionLog/SessionLogEventSavedEffect';\nimport { SessionLogState } from '../../SessionLogState';\n\n// Server ack: the pending event moves to the acked log with its server-stamped\n// metadata, and the remaining pending events renumber onto consecutive indexes\n// after it (the server may have assigned a later index than our optimistic one).\nexport const eventSaved = (state: SessionLogState, payload: SessionLogEventSavedPayload): SessionLogState => {\n const savedAt = state.pendingEvents.findIndex((event) => event.payload.metadata.clientMessageId === payload.clientMessageId);\n\n const remaining = savedAt === -1 ? state.pendingEvents : [...state.pendingEvents.slice(0, savedAt), ...state.pendingEvents.slice(savedAt + 1)];\n\n // No renumbering: each pending event minted its own sortable id, which already sorts after\n // the saved log. Removing one from the middle leaves the rest correctly ordered.\n return {\n ...state,\n events: [...state.events, payload.storedEvent],\n pendingEvents: remaining,\n flush: { inFlight: false, lastError: null, retryCount: 0 },\n };\n};\n"]}
@@ -10,7 +10,8 @@ export const makeSessionEvent = (type, data, index, overrides) => ({
10
10
  clientMessageId: overrides?.clientMessageId ?? `cmid-${index}`,
11
11
  createdBy: { userId: 'test-user', userDisplayName: 'Test User' },
12
12
  createdAt: overrides?.createdAt ?? `2026-07-07T00:00:0${Math.min(index, 9)}.000Z`,
13
- index,
13
+ // Padded so the stub ids sort in creation order, like real sortable ids.
14
+ eventId: String(index).padStart(4, '0'),
14
15
  },
15
16
  },
16
17
  });
@@ -1 +1 @@
1
- {"version":3,"file":"makeSessionEvent.js","sourceRoot":"","sources":["../../../../src/adminApp/testHelpers/makeSessionEvent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAiB,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAEnF,oEAAoE;AACpE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,IAAY,EACZ,IAAO,EACP,KAAa,EACb,SAAoE,EACrD,EAAE,CAAC,CAAC;IACnB,IAAI;IACJ,OAAO,EAAE;QACP,IAAI;QACJ,QAAQ,EAAE;YACR,OAAO,EAAE,yBAAyB;YAClC,eAAe,EAAE,SAAS,EAAE,eAAe,IAAI,QAAQ,KAAK,EAAE;YAC9D,SAAS,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE;YAChE,SAAS,EAAE,SAAS,EAAE,SAAS,IAAK,qBAAqB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,OAA0B;YACrG,KAAK;SACN;KACF;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAAU,EAAE,IAAY,EAAiB,EAAE,CAC5E,gBAAgB,CAAC,cAAc,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC","sourcesContent":["import { QpqIsoDateTime } from 'quidproquo-core';\nimport { EventDocEffect, EventDocEvent } from 'quidproquo-features';\n\nimport { adminSessionSchemaVersion } from '../constants/adminSessionSchemaVersion';\n\n// Builds a session event with sensible metadata defaults for tests.\nexport const makeSessionEvent = <T>(\n type: string,\n data: T,\n index: number,\n overrides?: { clientMessageId?: string; createdAt?: QpqIsoDateTime },\n): EventDocEvent => ({\n type,\n payload: {\n data,\n metadata: {\n version: adminSessionSchemaVersion,\n clientMessageId: overrides?.clientMessageId ?? `cmid-${index}`,\n createdBy: { userId: 'test-user', userDisplayName: 'Test User' },\n createdAt: overrides?.createdAt ?? (`2026-07-07T00:00:0${Math.min(index, 9)}.000Z` as QpqIsoDateTime),\n index,\n },\n },\n});\n\nexport const makeInitStateEvent = (id: string, name: string): EventDocEvent =>\n makeSessionEvent(EventDocEffect.InitState, { id, code: 'session-code', name }, 0);\n"]}
1
+ {"version":3,"file":"makeSessionEvent.js","sourceRoot":"","sources":["../../../../src/adminApp/testHelpers/makeSessionEvent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAiB,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAEnF,oEAAoE;AACpE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,IAAY,EACZ,IAAO,EACP,KAAa,EACb,SAAoE,EACrD,EAAE,CAAC,CAAC;IACnB,IAAI;IACJ,OAAO,EAAE;QACP,IAAI;QACJ,QAAQ,EAAE;YACR,OAAO,EAAE,yBAAyB;YAClC,eAAe,EAAE,SAAS,EAAE,eAAe,IAAI,QAAQ,KAAK,EAAE;YAC9D,SAAS,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE;YAChE,SAAS,EAAE,SAAS,EAAE,SAAS,IAAK,qBAAqB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,OAA0B;YACrG,yEAAyE;YACzE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;SACxC;KACF;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAAU,EAAE,IAAY,EAAiB,EAAE,CAC5E,gBAAgB,CAAC,cAAc,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC","sourcesContent":["import { QpqIsoDateTime } from 'quidproquo-core';\nimport { EventDocEffect, EventDocEvent } from 'quidproquo-features';\n\nimport { adminSessionSchemaVersion } from '../constants/adminSessionSchemaVersion';\n\n// Builds a session event with sensible metadata defaults for tests.\nexport const makeSessionEvent = <T>(\n type: string,\n data: T,\n index: number,\n overrides?: { clientMessageId?: string; createdAt?: QpqIsoDateTime },\n): EventDocEvent => ({\n type,\n payload: {\n data,\n metadata: {\n version: adminSessionSchemaVersion,\n clientMessageId: overrides?.clientMessageId ?? `cmid-${index}`,\n createdBy: { userId: 'test-user', userDisplayName: 'Test User' },\n createdAt: overrides?.createdAt ?? (`2026-07-07T00:00:0${Math.min(index, 9)}.000Z` as QpqIsoDateTime),\n // Padded so the stub ids sort in creation order, like real sortable ids.\n eventId: String(index).padStart(4, '0'),\n },\n },\n});\n\nexport const makeInitStateEvent = (id: string, name: string): EventDocEvent =>\n makeSessionEvent(EventDocEffect.InitState, { id, code: 'session-code', name }, 0);\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quidproquo-web-admin",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -44,12 +44,12 @@
44
44
  "date-fns": "^2.30.0",
45
45
  "dayjs": "^1.11.7",
46
46
  "javascript-time-ago": "^2.5.9",
47
- "quidproquo-core": "0.1.12",
48
- "quidproquo-features": "0.1.12",
49
- "quidproquo-tsconfig": "0.1.12",
50
- "quidproquo-web": "0.1.12",
51
- "quidproquo-web-react": "0.1.12",
52
- "quidproquo-webserver": "0.1.12",
47
+ "quidproquo-core": "0.1.13",
48
+ "quidproquo-features": "0.1.13",
49
+ "quidproquo-tsconfig": "0.1.13",
50
+ "quidproquo-web": "0.1.13",
51
+ "quidproquo-web-react": "0.1.13",
52
+ "quidproquo-webserver": "0.1.13",
53
53
  "react": ">=18.3.1",
54
54
  "react-d3-tree": "^3.6.6",
55
55
  "react-dom": "18.3.1",