@vived/host 5.5.0 → 5.6.0

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 (113) hide show
  1. package/dist/cjs/BoundaryLog/Adapters/boundaryLogAdapter.js +24 -0
  2. package/dist/cjs/BoundaryLog/Adapters/boundaryLogAdapter.js.map +1 -0
  3. package/dist/cjs/BoundaryLog/Adapters/index.js +18 -0
  4. package/dist/cjs/BoundaryLog/Adapters/index.js.map +1 -0
  5. package/dist/cjs/BoundaryLog/Controllers/clearBoundaryLog.js +15 -0
  6. package/dist/cjs/BoundaryLog/Controllers/clearBoundaryLog.js.map +1 -0
  7. package/dist/cjs/BoundaryLog/Controllers/index.js +18 -0
  8. package/dist/cjs/BoundaryLog/Controllers/index.js.map +1 -0
  9. package/dist/cjs/BoundaryLog/Entities/BoundaryLogEntity.js +45 -0
  10. package/dist/cjs/BoundaryLog/Entities/BoundaryLogEntity.js.map +1 -0
  11. package/dist/cjs/BoundaryLog/Entities/index.js +19 -0
  12. package/dist/cjs/BoundaryLog/Entities/index.js.map +1 -0
  13. package/dist/cjs/BoundaryLog/Entities/snapshotPayload.js +62 -0
  14. package/dist/cjs/BoundaryLog/Entities/snapshotPayload.js.map +1 -0
  15. package/dist/cjs/BoundaryLog/Factories/BoundaryLogFactory.js +62 -0
  16. package/dist/cjs/BoundaryLog/Factories/BoundaryLogFactory.js.map +1 -0
  17. package/dist/cjs/BoundaryLog/Factories/index.js +18 -0
  18. package/dist/cjs/BoundaryLog/Factories/index.js.map +1 -0
  19. package/dist/cjs/BoundaryLog/Mocks/BoundaryLogPMMock.js +16 -0
  20. package/dist/cjs/BoundaryLog/Mocks/BoundaryLogPMMock.js.map +1 -0
  21. package/dist/cjs/BoundaryLog/Mocks/index.js +18 -0
  22. package/dist/cjs/BoundaryLog/Mocks/index.js.map +1 -0
  23. package/dist/cjs/BoundaryLog/PMs/BoundaryLogPM.js +56 -0
  24. package/dist/cjs/BoundaryLog/PMs/BoundaryLogPM.js.map +1 -0
  25. package/dist/cjs/BoundaryLog/PMs/index.js +18 -0
  26. package/dist/cjs/BoundaryLog/PMs/index.js.map +1 -0
  27. package/dist/cjs/BoundaryLog/index.js +23 -0
  28. package/dist/cjs/BoundaryLog/index.js.map +1 -0
  29. package/dist/cjs/Dialog/Entities/DialogQueue.js +36 -21
  30. package/dist/cjs/Dialog/Entities/DialogQueue.js.map +1 -1
  31. package/dist/cjs/Dispatcher/Entities/HostDispatchEntity.js +17 -4
  32. package/dist/cjs/Dispatcher/Entities/HostDispatchEntity.js.map +1 -1
  33. package/dist/cjs/Dispatcher/Mocks/MockHostDispatcher.js +1 -0
  34. package/dist/cjs/Dispatcher/Mocks/MockHostDispatcher.js.map +1 -1
  35. package/dist/cjs/Handler/Entities/HostHandler.js +17 -0
  36. package/dist/cjs/Handler/Entities/HostHandler.js.map +1 -1
  37. package/dist/cjs/index.js +1 -0
  38. package/dist/cjs/index.js.map +1 -1
  39. package/dist/esm/BoundaryLog/Adapters/boundaryLogAdapter.js +21 -0
  40. package/dist/esm/BoundaryLog/Adapters/boundaryLogAdapter.js.map +1 -0
  41. package/dist/esm/BoundaryLog/Adapters/index.js +2 -0
  42. package/dist/esm/BoundaryLog/Adapters/index.js.map +1 -0
  43. package/dist/esm/BoundaryLog/Controllers/clearBoundaryLog.js +12 -0
  44. package/dist/esm/BoundaryLog/Controllers/clearBoundaryLog.js.map +1 -0
  45. package/dist/esm/BoundaryLog/Controllers/index.js +2 -0
  46. package/dist/esm/BoundaryLog/Controllers/index.js.map +1 -0
  47. package/dist/esm/BoundaryLog/Entities/BoundaryLogEntity.js +40 -0
  48. package/dist/esm/BoundaryLog/Entities/BoundaryLogEntity.js.map +1 -0
  49. package/dist/esm/BoundaryLog/Entities/index.js +3 -0
  50. package/dist/esm/BoundaryLog/Entities/index.js.map +1 -0
  51. package/dist/esm/BoundaryLog/Entities/snapshotPayload.js +59 -0
  52. package/dist/esm/BoundaryLog/Entities/snapshotPayload.js.map +1 -0
  53. package/dist/esm/BoundaryLog/Factories/BoundaryLogFactory.js +57 -0
  54. package/dist/esm/BoundaryLog/Factories/BoundaryLogFactory.js.map +1 -0
  55. package/dist/esm/BoundaryLog/Factories/index.js +2 -0
  56. package/dist/esm/BoundaryLog/Factories/index.js.map +1 -0
  57. package/dist/esm/BoundaryLog/Mocks/BoundaryLogPMMock.js +11 -0
  58. package/dist/esm/BoundaryLog/Mocks/BoundaryLogPMMock.js.map +1 -0
  59. package/dist/esm/BoundaryLog/Mocks/index.js +2 -0
  60. package/dist/esm/BoundaryLog/Mocks/index.js.map +1 -0
  61. package/dist/esm/BoundaryLog/PMs/BoundaryLogPM.js +51 -0
  62. package/dist/esm/BoundaryLog/PMs/BoundaryLogPM.js.map +1 -0
  63. package/dist/esm/BoundaryLog/PMs/index.js +2 -0
  64. package/dist/esm/BoundaryLog/PMs/index.js.map +1 -0
  65. package/dist/esm/BoundaryLog/index.js +7 -0
  66. package/dist/esm/BoundaryLog/index.js.map +1 -0
  67. package/dist/esm/Dialog/Entities/DialogQueue.js +36 -21
  68. package/dist/esm/Dialog/Entities/DialogQueue.js.map +1 -1
  69. package/dist/esm/Dispatcher/Entities/HostDispatchEntity.js +17 -4
  70. package/dist/esm/Dispatcher/Entities/HostDispatchEntity.js.map +1 -1
  71. package/dist/esm/Dispatcher/Mocks/MockHostDispatcher.js +1 -0
  72. package/dist/esm/Dispatcher/Mocks/MockHostDispatcher.js.map +1 -1
  73. package/dist/esm/Handler/Entities/HostHandler.js +17 -0
  74. package/dist/esm/Handler/Entities/HostHandler.js.map +1 -1
  75. package/dist/esm/index.js +1 -0
  76. package/dist/esm/index.js.map +1 -1
  77. package/dist/types/BoundaryLog/Adapters/boundaryLogAdapter.d.ts +4 -0
  78. package/dist/types/BoundaryLog/Adapters/boundaryLogAdapter.d.ts.map +1 -0
  79. package/dist/types/BoundaryLog/Adapters/index.d.ts +2 -0
  80. package/dist/types/BoundaryLog/Adapters/index.d.ts.map +1 -0
  81. package/dist/types/BoundaryLog/Controllers/clearBoundaryLog.d.ts +4 -0
  82. package/dist/types/BoundaryLog/Controllers/clearBoundaryLog.d.ts.map +1 -0
  83. package/dist/types/BoundaryLog/Controllers/index.d.ts +2 -0
  84. package/dist/types/BoundaryLog/Controllers/index.d.ts.map +1 -0
  85. package/dist/types/BoundaryLog/Entities/BoundaryLogEntity.d.ts +37 -0
  86. package/dist/types/BoundaryLog/Entities/BoundaryLogEntity.d.ts.map +1 -0
  87. package/dist/types/BoundaryLog/Entities/index.d.ts +3 -0
  88. package/dist/types/BoundaryLog/Entities/index.d.ts.map +1 -0
  89. package/dist/types/BoundaryLog/Entities/snapshotPayload.d.ts +16 -0
  90. package/dist/types/BoundaryLog/Entities/snapshotPayload.d.ts.map +1 -0
  91. package/dist/types/BoundaryLog/Factories/BoundaryLogFactory.d.ts +17 -0
  92. package/dist/types/BoundaryLog/Factories/BoundaryLogFactory.d.ts.map +1 -0
  93. package/dist/types/BoundaryLog/Factories/index.d.ts +2 -0
  94. package/dist/types/BoundaryLog/Factories/index.d.ts.map +1 -0
  95. package/dist/types/BoundaryLog/Mocks/BoundaryLogPMMock.d.ts +8 -0
  96. package/dist/types/BoundaryLog/Mocks/BoundaryLogPMMock.d.ts.map +1 -0
  97. package/dist/types/BoundaryLog/Mocks/index.d.ts +2 -0
  98. package/dist/types/BoundaryLog/Mocks/index.d.ts.map +1 -0
  99. package/dist/types/BoundaryLog/PMs/BoundaryLogPM.d.ts +18 -0
  100. package/dist/types/BoundaryLog/PMs/BoundaryLogPM.d.ts.map +1 -0
  101. package/dist/types/BoundaryLog/PMs/index.d.ts +2 -0
  102. package/dist/types/BoundaryLog/PMs/index.d.ts.map +1 -0
  103. package/dist/types/BoundaryLog/index.d.ts +7 -0
  104. package/dist/types/BoundaryLog/index.d.ts.map +1 -0
  105. package/dist/types/Dispatcher/Entities/HostDispatchEntity.d.ts +17 -0
  106. package/dist/types/Dispatcher/Entities/HostDispatchEntity.d.ts.map +1 -1
  107. package/dist/types/Dispatcher/Mocks/MockHostDispatcher.d.ts +1 -0
  108. package/dist/types/Dispatcher/Mocks/MockHostDispatcher.d.ts.map +1 -1
  109. package/dist/types/Handler/Entities/HostHandler.d.ts +18 -1
  110. package/dist/types/Handler/Entities/HostHandler.d.ts.map +1 -1
  111. package/dist/types/index.d.ts +1 -0
  112. package/dist/types/index.d.ts.map +1 -1
  113. package/package.json +1 -1
@@ -66,23 +66,36 @@ class HostDispatchEntityImp extends HostDispatchEntity {
66
66
  this.setupPayloadVersions = (payloadVersion) => {
67
67
  this.appPayloadVersions = payloadVersion;
68
68
  };
69
+ /**
70
+ * Notify the passive observer, if any. Wrapped so a throwing or slow observer
71
+ * can never alter, delay, or fail the Request's delivery (ADR-0002).
72
+ */
73
+ this.notifyObserver = (request, outcome) => {
74
+ if (!this.requestObserver)
75
+ return;
76
+ try {
77
+ this.requestObserver(request, outcome);
78
+ }
79
+ catch {
80
+ // Passive: an observer failure must never affect dispatch.
81
+ }
82
+ };
69
83
  this.dispatch = (request) => {
70
84
  if (!this.appHandler) {
71
85
  this.error("No app handler has been registered");
86
+ this.notifyObserver(request, "no-app-handler");
72
87
  return;
73
88
  }
74
89
  try {
75
90
  this.appHandler(request);
91
+ this.notifyObserver(request, "delivered");
76
92
  }
77
93
  catch (e) {
78
94
  this.warn(e.message);
95
+ this.notifyObserver(request, "threw");
79
96
  }
80
97
  };
81
98
  this.formRequestAndDispatch = (type, version, payload) => {
82
- if (!this.appHandler) {
83
- this.error("No app handler has been registered");
84
- return;
85
- }
86
99
  const request = {
87
100
  type,
88
101
  version,
@@ -1 +1 @@
1
- {"version":3,"file":"HostDispatchEntity.js","sourceRoot":"","sources":["../../../../src/Dispatcher/Entities/HostDispatchEntity.ts"],"names":[],"mappings":"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","sourcesContent":["import { AppObject, AppObjectEntity, AppObjectRepo } from \"@vived/core\";\nimport { Handler, Request } from \"@vived/core\";\n\nexport abstract class HostDispatchEntity extends AppObjectEntity {\n static readonly type = \"HostDispatchEntity\";\n\n abstract appHandlerVersion: number;\n abstract getRequestPayloadVersion(requestType: string): number | undefined;\n abstract registerAppHandler: (appHandler: Handler) => void;\n abstract clearAppHandler: () => void;\n abstract dispatch: (request: Request) => void;\n abstract formRequestAndDispatch: (\n type: string,\n version: number,\n payload?: object | undefined\n ) => void;\n\n static get(appObject: AppObject): HostDispatchEntity | undefined {\n const component = appObject.getComponent<HostDispatchEntity>(\n HostDispatchEntity.type\n );\n if (!component) {\n appObject.appObjectRepo.submitWarning(\n \"AssetEntity.get\",\n \"Unable to find HostDispatchEntity on app object \" + appObject.id\n );\n }\n return component;\n }\n\n static getByID(\n id: string,\n appObjects: AppObjectRepo\n ): HostDispatchEntity | undefined {\n const appObject = appObjects.get(id);\n if (!appObject) {\n appObjects.submitWarning(\n \"AssetEntity.getByID\",\n \"Unable to find app object \" + id\n );\n return;\n }\n return HostDispatchEntity.get(appObject);\n }\n}\n\nexport function makeHostDispatchEntity(\n appObject: AppObject\n): HostDispatchEntity {\n return new HostDispatchEntityImp(appObject);\n}\n\nclass HostDispatchEntityImp extends HostDispatchEntity {\n private appHandler?: Handler;\n\n private _appHandlerVersion = 0;\n public get appHandlerVersion() {\n return this._appHandlerVersion;\n }\n\n private appPayloadVersions = new Map<string, number>();\n\n registerAppHandler = (appHandler: Handler) => {\n this.appHandler = appHandler;\n this.getAppHandlerVersion();\n };\n\n clearAppHandler = () => {\n this.appHandler = undefined;\n };\n\n private getAppHandlerVersion() {\n const type = \"GET_APP_HANDLER_VERSION\";\n const payload = { callback: this.setupVersion };\n\n try {\n this.formRequestAndDispatch(type, 1, payload);\n } catch {\n // All good. this is probably an older app\n }\n }\n\n getRequestPayloadVersion = (requestType: string): number | undefined => {\n return this.appPayloadVersions.get(requestType);\n };\n\n private setupVersion = (version: number) => {\n // Apps before app package version 2.27 will not reach this\n this._appHandlerVersion = version;\n this.getPayloadVersions();\n };\n\n private getPayloadVersions = () => {\n const type = \"GET_APP_PAYLOAD_VERSION\";\n const payload = { callback: this.setupPayloadVersions };\n this.formRequestAndDispatch(type, 2, payload);\n };\n\n private setupPayloadVersions = (payloadVersion: Map<string, number>) => {\n this.appPayloadVersions = payloadVersion;\n };\n\n dispatch = (request: Request) => {\n if (!this.appHandler) {\n this.error(\"No app handler has been registered\");\n return;\n }\n\n try {\n this.appHandler(request);\n } catch (e) {\n this.warn((e as Error).message);\n }\n };\n\n formRequestAndDispatch = (\n type: string,\n version: number,\n payload?: object | undefined\n ) => {\n if (!this.appHandler) {\n this.error(\"No app handler has been registered\");\n return;\n }\n\n const request: Request = {\n type,\n version,\n payload\n };\n\n this.dispatch(request);\n };\n\n constructor(appObject: AppObject) {\n super(appObject, HostDispatchEntity.type);\n }\n}\n"]}
1
+ {"version":3,"file":"HostDispatchEntity.js","sourceRoot":"","sources":["../../../../src/Dispatcher/Entities/HostDispatchEntity.ts"],"names":[],"mappings":"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","sourcesContent":["import { AppObject, AppObjectEntity, AppObjectRepo } from \"@vived/core\";\r\nimport { Handler, Request } from \"@vived/core\";\r\n\r\n/**\r\n * The outcome of an outbound Dispatch, as seen at the dispatch chokepoint:\r\n * \"delivered\" (the app handler ran), \"no-app-handler\" (nothing registered to\r\n * receive it), or \"threw\" (the app handler raised).\r\n */\r\nexport type DispatchOutcome = \"delivered\" | \"no-app-handler\" | \"threw\";\r\n\r\n/**\r\n * Passive observer of outbound Dispatches. Notified after each Request is\r\n * dispatched, with the outcome. Purely observational — see the passivity\r\n * contract in ADR-0002: an observer must never alter, delay, or fail delivery.\r\n */\r\nexport type DispatchObserver = (\r\n request: Request,\r\n outcome: DispatchOutcome\r\n) => void;\r\n\r\nexport abstract class HostDispatchEntity extends AppObjectEntity {\r\n static readonly type = \"HostDispatchEntity\";\r\n\r\n abstract appHandlerVersion: number;\r\n abstract getRequestPayloadVersion(requestType: string): number | undefined;\r\n abstract registerAppHandler: (appHandler: Handler) => void;\r\n abstract clearAppHandler: () => void;\r\n abstract dispatch: (request: Request) => void;\r\n abstract formRequestAndDispatch: (\r\n type: string,\r\n version: number,\r\n payload?: object | undefined\r\n ) => void;\r\n\r\n /**\r\n * Optional passive observer of outbound Dispatches (ADR-0002). Unset by\r\n * default, so production hosts pay nothing and behave exactly as before.\r\n */\r\n abstract requestObserver?: DispatchObserver;\r\n\r\n static get(appObject: AppObject): HostDispatchEntity | undefined {\r\n const component = appObject.getComponent<HostDispatchEntity>(\r\n HostDispatchEntity.type\r\n );\r\n if (!component) {\r\n appObject.appObjectRepo.submitWarning(\r\n \"AssetEntity.get\",\r\n \"Unable to find HostDispatchEntity on app object \" + appObject.id\r\n );\r\n }\r\n return component;\r\n }\r\n\r\n static getByID(\r\n id: string,\r\n appObjects: AppObjectRepo\r\n ): HostDispatchEntity | undefined {\r\n const appObject = appObjects.get(id);\r\n if (!appObject) {\r\n appObjects.submitWarning(\r\n \"AssetEntity.getByID\",\r\n \"Unable to find app object \" + id\r\n );\r\n return;\r\n }\r\n return HostDispatchEntity.get(appObject);\r\n }\r\n}\r\n\r\nexport function makeHostDispatchEntity(\r\n appObject: AppObject\r\n): HostDispatchEntity {\r\n return new HostDispatchEntityImp(appObject);\r\n}\r\n\r\nclass HostDispatchEntityImp extends HostDispatchEntity {\r\n private appHandler?: Handler;\r\n\r\n private _appHandlerVersion = 0;\r\n public get appHandlerVersion() {\r\n return this._appHandlerVersion;\r\n }\r\n\r\n private appPayloadVersions = new Map<string, number>();\r\n\r\n registerAppHandler = (appHandler: Handler) => {\r\n this.appHandler = appHandler;\r\n this.getAppHandlerVersion();\r\n };\r\n\r\n clearAppHandler = () => {\r\n this.appHandler = undefined;\r\n };\r\n\r\n private getAppHandlerVersion() {\r\n const type = \"GET_APP_HANDLER_VERSION\";\r\n const payload = { callback: this.setupVersion };\r\n\r\n try {\r\n this.formRequestAndDispatch(type, 1, payload);\r\n } catch {\r\n // All good. this is probably an older app\r\n }\r\n }\r\n\r\n getRequestPayloadVersion = (requestType: string): number | undefined => {\r\n return this.appPayloadVersions.get(requestType);\r\n };\r\n\r\n private setupVersion = (version: number) => {\r\n // Apps before app package version 2.27 will not reach this\r\n this._appHandlerVersion = version;\r\n this.getPayloadVersions();\r\n };\r\n\r\n private getPayloadVersions = () => {\r\n const type = \"GET_APP_PAYLOAD_VERSION\";\r\n const payload = { callback: this.setupPayloadVersions };\r\n this.formRequestAndDispatch(type, 2, payload);\r\n };\r\n\r\n private setupPayloadVersions = (payloadVersion: Map<string, number>) => {\r\n this.appPayloadVersions = payloadVersion;\r\n };\r\n\r\n requestObserver?: DispatchObserver;\r\n\r\n /**\r\n * Notify the passive observer, if any. Wrapped so a throwing or slow observer\r\n * can never alter, delay, or fail the Request's delivery (ADR-0002).\r\n */\r\n private notifyObserver = (request: Request, outcome: DispatchOutcome) => {\r\n if (!this.requestObserver) return;\r\n try {\r\n this.requestObserver(request, outcome);\r\n } catch {\r\n // Passive: an observer failure must never affect dispatch.\r\n }\r\n };\r\n\r\n dispatch = (request: Request) => {\r\n if (!this.appHandler) {\r\n this.error(\"No app handler has been registered\");\r\n this.notifyObserver(request, \"no-app-handler\");\r\n return;\r\n }\r\n\r\n try {\r\n this.appHandler(request);\r\n this.notifyObserver(request, \"delivered\");\r\n } catch (e) {\r\n this.warn((e as Error).message);\r\n this.notifyObserver(request, \"threw\");\r\n }\r\n };\r\n\r\n formRequestAndDispatch = (\r\n type: string,\r\n version: number,\r\n payload?: object | undefined\r\n ) => {\r\n const request: Request = {\r\n type,\r\n version,\r\n payload\r\n };\r\n\r\n this.dispatch(request);\r\n };\r\n\r\n constructor(appObject: AppObject) {\r\n super(appObject, HostDispatchEntity.type);\r\n }\r\n}\r\n"]}
@@ -11,6 +11,7 @@ class MockHostDispatchEntity extends Entities_1.HostDispatchEntity {
11
11
  this.registerAppHandler = jest.fn();
12
12
  this.dispatch = jest.fn();
13
13
  this.formRequestAndDispatch = jest.fn();
14
+ this.requestObserver = undefined;
14
15
  }
15
16
  }
16
17
  exports.MockHostDispatchEntity = MockHostDispatchEntity;
@@ -1 +1 @@
1
- {"version":3,"file":"MockHostDispatcher.js","sourceRoot":"","sources":["../../../../src/Dispatcher/Mocks/MockHostDispatcher.ts"],"names":[],"mappings":";;;AACA,0CAAiD;AAEjD,MAAa,sBAAuB,SAAQ,6BAAkB;IAQ5D,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,6BAAkB,CAAC,IAAI,CAAC,CAAC;QAR5C,oBAAe,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC5B,sBAAiB,GAAG,CAAC,CAAC;QACtB,6BAAwB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACrC,uBAAkB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC/B,aAAQ,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACrB,2BAAsB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IAInC,CAAC;CACF;AAXD,wDAWC","sourcesContent":["import { AppObject } from \"@vived/core\";\nimport { HostDispatchEntity } from \"../Entities\";\n\nexport class MockHostDispatchEntity extends HostDispatchEntity {\n clearAppHandler = jest.fn();\n appHandlerVersion = 1;\n getRequestPayloadVersion = jest.fn();\n registerAppHandler = jest.fn();\n dispatch = jest.fn();\n formRequestAndDispatch = jest.fn();\n\n constructor(appObject: AppObject) {\n super(appObject, HostDispatchEntity.type);\n }\n}\n"]}
1
+ {"version":3,"file":"MockHostDispatcher.js","sourceRoot":"","sources":["../../../../src/Dispatcher/Mocks/MockHostDispatcher.ts"],"names":[],"mappings":";;;AACA,0CAAiD;AAEjD,MAAa,sBAAuB,SAAQ,6BAAkB;IAS5D,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,6BAAkB,CAAC,IAAI,CAAC,CAAC;QAT5C,oBAAe,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC5B,sBAAiB,GAAG,CAAC,CAAC;QACtB,6BAAwB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACrC,uBAAkB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC/B,aAAQ,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACrB,2BAAsB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACnC,oBAAe,GAAG,SAAS,CAAC;IAI5B,CAAC;CACF;AAZD,wDAYC","sourcesContent":["import { AppObject } from \"@vived/core\";\r\nimport { HostDispatchEntity } from \"../Entities\";\r\n\r\nexport class MockHostDispatchEntity extends HostDispatchEntity {\r\n clearAppHandler = jest.fn();\r\n appHandlerVersion = 1;\r\n getRequestPayloadVersion = jest.fn();\r\n registerAppHandler = jest.fn();\r\n dispatch = jest.fn();\r\n formRequestAndDispatch = jest.fn();\r\n requestObserver = undefined;\r\n\r\n constructor(appObject: AppObject) {\r\n super(appObject, HostDispatchEntity.type);\r\n }\r\n}\r\n"]}
@@ -17,17 +17,34 @@ class RequestHandlerImp extends HostHandlerEntity {
17
17
  constructor(appObj) {
18
18
  super(appObj, HostHandlerEntity.type);
19
19
  this.handlers = new Map();
20
+ /**
21
+ * Notify the passive observer, if any. Wrapped so a throwing or slow observer
22
+ * can never alter, delay, or fail the Request (ADR-0002).
23
+ */
24
+ this.notifyObserver = (request, outcome) => {
25
+ if (!this.requestObserver)
26
+ return;
27
+ try {
28
+ this.requestObserver(request, outcome);
29
+ }
30
+ catch {
31
+ // Passive: an observer failure must never affect handling.
32
+ }
33
+ };
20
34
  this.handler = (request) => {
21
35
  const handler = this.handlers.get(request.type);
22
36
  if (!handler) {
23
37
  this.warn(`Unsupported request type received: ${request.type}`);
38
+ this.notifyObserver(request, "unsupported");
24
39
  return;
25
40
  }
26
41
  try {
27
42
  handler.handleRequest(request.version, request.payload);
43
+ this.notifyObserver(request, "handled");
28
44
  }
29
45
  catch (e) {
30
46
  this.warn(`${e}`);
47
+ this.notifyObserver(request, "threw");
31
48
  }
32
49
  };
33
50
  this.registerRequestHandler = (handler) => {
@@ -1 +1 @@
1
- {"version":3,"file":"HostHandler.js","sourceRoot":"","sources":["../../../../src/Handler/Entities/HostHandler.ts"],"names":[],"mappings":";;;AAmBA,sDAEC;AArBD,sCAAyD;AAQzD,MAAsB,iBAAkB,SAAQ,sBAAe;IAG7D,MAAM,CAAC,GAAG,CAAC,SAAoB;QAC7B,OAAO,SAAS,CAAC,YAAY,CAAoB,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC3E,CAAC;;AALH,8CASC;AARQ,sBAAI,GAAG,mBAAmB,CAAC;AAUpC,SAAgB,qBAAqB,CAAC,SAAoB;IACxD,OAAO,IAAI,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,iBAAkB,SAAQ,iBAAiB;IA4B/C,YAAY,MAAiB;QAC3B,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;QA5BhC,aAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;QAErD,YAAO,GAAY,CAAC,OAAgB,EAAQ,EAAE;YAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAEhD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,IAAI,CAAC,IAAI,CAAC,sCAAsC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;gBAChE,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACpB,CAAC;QACH,CAAC,CAAC;QAEF,2BAAsB,GAAG,CAAC,OAAuB,EAAQ,EAAE;YACzD,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC,IAAI,CACP,iDAAiD,OAAO,CAAC,WAAW,yCAAyC,CAC9G,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAClD,CAAC,CAAC;IAIF,CAAC;CACF;AAED,MAAa,yBAA0B,SAAQ,KAAK;IAClD,YAAY,WAAmB,EAAE,OAAe;QAC9C,MAAM,GAAG,GAAG,WAAW,OAAO,oBAAoB,WAAW,mBAAmB,CAAC;QACjF,KAAK,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;CACF;AALD,8DAKC;AAED,MAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,WAAmB;QAC7B,MAAM,GAAG,GAAG,2BAA2B,WAAW,qBAAqB,CAAC;QACxE,KAAK,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;CACF;AALD,oDAKC;AAED,MAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,WAAmB,EAAE,OAAe,EAAE,OAAe;QAC/D,MAAM,GAAG,GAAG,sCAAsC,OAAO,oBAAoB,WAAW,KAAK,OAAO,EAAE,CAAC;QACvG,KAAK,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;CACF;AALD,oDAKC","sourcesContent":["import { AppObject, AppObjectEntity } from \"@vived/core\";\nimport { Handler, Request } from \"@vived/core\";\n\nexport interface RequestHandler {\n readonly requestType: string;\n handleRequest: (version: number, payload?: unknown) => void;\n}\n\nexport abstract class HostHandlerEntity extends AppObjectEntity {\n static type = \"HostHandlerEntity\";\n\n static get(appObject: AppObject) {\n return appObject.getComponent<HostHandlerEntity>(HostHandlerEntity.type);\n }\n\n abstract handler: Handler;\n abstract registerRequestHandler: (requestHandler: RequestHandler) => void;\n}\n\nexport function makeHostHandlerEntity(appObject: AppObject): HostHandlerEntity {\n return new RequestHandlerImp(appObject);\n}\n\nclass RequestHandlerImp extends HostHandlerEntity {\n private handlers = new Map<string, RequestHandler>();\n\n handler: Handler = (request: Request): void => {\n const handler = this.handlers.get(request.type);\n\n if (!handler) {\n this.warn(`Unsupported request type received: ${request.type}`);\n return;\n }\n\n try {\n handler.handleRequest(request.version, request.payload);\n } catch (e) {\n this.warn(`${e}`);\n }\n };\n\n registerRequestHandler = (handler: RequestHandler): void => {\n if (this.handlers.has(handler.requestType)) {\n this.warn(\n `More than one handler is being registered for ${handler.requestType}. Previous handler is being overwritten`\n );\n }\n\n this.handlers.set(handler.requestType, handler);\n };\n\n constructor(appObj: AppObject) {\n super(appObj, HostHandlerEntity.type);\n }\n}\n\nexport class UnsupportedRequestVersion extends Error {\n constructor(requestType: string, version: number) {\n const msg = `Version ${version} of request type ${requestType} is not supported`;\n super(msg);\n }\n}\n\nexport class ActionNotImplemented extends Error {\n constructor(requestType: string) {\n const msg = `Action for request type ${requestType} is not implemented`;\n super(msg);\n }\n}\n\nexport class UnableToParsePayload extends Error {\n constructor(requestType: string, version: number, payload: string) {\n const msg = `Unable to parse paylod for version ${version} of request type ${requestType}: ${payload}`;\n super(msg);\n }\n}\n"]}
1
+ {"version":3,"file":"HostHandler.js","sourceRoot":"","sources":["../../../../src/Handler/Entities/HostHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { AppObject, AppObjectEntity } from \"@vived/core\";\r\nimport { Handler, Request } from \"@vived/core\";\r\n\r\nexport interface RequestHandler {\r\n readonly requestType: string;\r\n handleRequest: (version: number, payload?: unknown) => void;\r\n}\r\n\r\n/**\r\n * The outcome of an inbound Request, as seen at the handler chokepoint:\r\n * \"handled\" (a registered handler ran), \"unsupported\" (no handler registered\r\n * for the type), or \"threw\" (the handler raised).\r\n */\r\nexport type HandlerOutcome = \"handled\" | \"unsupported\" | \"threw\";\r\n\r\n/**\r\n * Passive observer of inbound Requests. Notified after each Request is routed,\r\n * with the outcome. Purely observational — see the passivity contract in\r\n * ADR-0002: an observer must never alter, delay, or fail the Request.\r\n */\r\nexport type HandlerObserver = (\r\n request: Request,\r\n outcome: HandlerOutcome\r\n) => void;\r\n\r\nexport abstract class HostHandlerEntity extends AppObjectEntity {\r\n static type = \"HostHandlerEntity\";\r\n\r\n static get(appObject: AppObject) {\r\n return appObject.getComponent<HostHandlerEntity>(HostHandlerEntity.type);\r\n }\r\n\r\n abstract handler: Handler;\r\n abstract registerRequestHandler: (requestHandler: RequestHandler) => void;\r\n\r\n /**\r\n * Optional passive observer of inbound Requests (ADR-0002). Unset by default,\r\n * so production hosts pay nothing and behave exactly as before.\r\n */\r\n abstract requestObserver?: HandlerObserver;\r\n}\r\n\r\nexport function makeHostHandlerEntity(appObject: AppObject): HostHandlerEntity {\r\n return new RequestHandlerImp(appObject);\r\n}\r\n\r\nclass RequestHandlerImp extends HostHandlerEntity {\r\n private handlers = new Map<string, RequestHandler>();\r\n\r\n requestObserver?: HandlerObserver;\r\n\r\n /**\r\n * Notify the passive observer, if any. Wrapped so a throwing or slow observer\r\n * can never alter, delay, or fail the Request (ADR-0002).\r\n */\r\n private notifyObserver = (request: Request, outcome: HandlerOutcome) => {\r\n if (!this.requestObserver) return;\r\n try {\r\n this.requestObserver(request, outcome);\r\n } catch {\r\n // Passive: an observer failure must never affect handling.\r\n }\r\n };\r\n\r\n handler: Handler = (request: Request): void => {\r\n const handler = this.handlers.get(request.type);\r\n\r\n if (!handler) {\r\n this.warn(`Unsupported request type received: ${request.type}`);\r\n this.notifyObserver(request, \"unsupported\");\r\n return;\r\n }\r\n\r\n try {\r\n handler.handleRequest(request.version, request.payload);\r\n this.notifyObserver(request, \"handled\");\r\n } catch (e) {\r\n this.warn(`${e}`);\r\n this.notifyObserver(request, \"threw\");\r\n }\r\n };\r\n\r\n registerRequestHandler = (handler: RequestHandler): void => {\r\n if (this.handlers.has(handler.requestType)) {\r\n this.warn(\r\n `More than one handler is being registered for ${handler.requestType}. Previous handler is being overwritten`\r\n );\r\n }\r\n\r\n this.handlers.set(handler.requestType, handler);\r\n };\r\n\r\n constructor(appObj: AppObject) {\r\n super(appObj, HostHandlerEntity.type);\r\n }\r\n}\r\n\r\nexport class UnsupportedRequestVersion extends Error {\r\n constructor(requestType: string, version: number) {\r\n const msg = `Version ${version} of request type ${requestType} is not supported`;\r\n super(msg);\r\n }\r\n}\r\n\r\nexport class ActionNotImplemented extends Error {\r\n constructor(requestType: string) {\r\n const msg = `Action for request type ${requestType} is not implemented`;\r\n super(msg);\r\n }\r\n}\r\n\r\nexport class UnableToParsePayload extends Error {\r\n constructor(requestType: string, version: number, payload: string) {\r\n const msg = `Unable to parse paylod for version ${version} of request type ${requestType}: ${payload}`;\r\n super(msg);\r\n }\r\n}\r\n"]}
package/dist/cjs/index.js CHANGED
@@ -18,6 +18,7 @@ __exportStar(require("./Apps"), exports);
18
18
  __exportStar(require("./AppSandbox"), exports);
19
19
  __exportStar(require("./AssetPlugin"), exports);
20
20
  __exportStar(require("./Assets"), exports);
21
+ __exportStar(require("./BoundaryLog"), exports);
21
22
  __exportStar(require("./Cache"), exports);
22
23
  __exportStar(require("./ChallengeResults"), exports);
23
24
  __exportStar(require("./Dialog"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yCAAuB;AACvB,+CAA6B;AAC7B,gDAA8B;AAC9B,2CAAyB;AACzB,0CAAwB;AACxB,qDAAmC;AACnC,2CAAyB;AACzB,+CAA6B;AAC7B,2CAAyB;AACzB,4CAA0B;AAC1B,2CAAyB;AACzB,6CAA2B;AAC3B,iDAA+B;AAC/B,gDAA8B;AAC9B,6CAA2B;AAC3B,+CAA6B","sourcesContent":["export * from \"./Apps\";\nexport * from \"./AppSandbox\";\nexport * from \"./AssetPlugin\";\nexport * from \"./Assets\";\nexport * from \"./Cache\";\nexport * from \"./ChallengeResults\";\nexport * from \"./Dialog\";\nexport * from \"./Dispatcher\";\nexport * from \"./Events\";\nexport * from \"./Handler\";\nexport * from \"./Logger\";\nexport * from \"./Snackbar\";\nexport * from \"./StateMachine\";\nexport * from \"./ThemeColors\";\nexport * from \"./VivedAPI\";\nexport * from \"./ZSpaceHost\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yCAAuB;AACvB,+CAA6B;AAC7B,gDAA8B;AAC9B,2CAAyB;AACzB,gDAA8B;AAC9B,0CAAwB;AACxB,qDAAmC;AACnC,2CAAyB;AACzB,+CAA6B;AAC7B,2CAAyB;AACzB,4CAA0B;AAC1B,2CAAyB;AACzB,6CAA2B;AAC3B,iDAA+B;AAC/B,gDAA8B;AAC9B,6CAA2B;AAC3B,+CAA6B","sourcesContent":["export * from \"./Apps\";\r\nexport * from \"./AppSandbox\";\r\nexport * from \"./AssetPlugin\";\r\nexport * from \"./Assets\";\r\nexport * from \"./BoundaryLog\";\r\nexport * from \"./Cache\";\r\nexport * from \"./ChallengeResults\";\r\nexport * from \"./Dialog\";\r\nexport * from \"./Dispatcher\";\r\nexport * from \"./Events\";\r\nexport * from \"./Handler\";\r\nexport * from \"./Logger\";\r\nexport * from \"./Snackbar\";\r\nexport * from \"./StateMachine\";\r\nexport * from \"./ThemeColors\";\r\nexport * from \"./VivedAPI\";\r\nexport * from \"./ZSpaceHost\";\r\n"]}
@@ -0,0 +1,21 @@
1
+ import { BoundaryLogPM, defaultBoundaryLogVM } from "../PMs/BoundaryLogPM";
2
+ export const boundaryLogAdapter = {
3
+ defaultVM: defaultBoundaryLogVM,
4
+ subscribe: (appObjects, setVM) => {
5
+ const pm = BoundaryLogPM.get(appObjects);
6
+ if (!pm) {
7
+ appObjects.submitError("boundaryLogAdapter", "Unable to find BoundaryLogPM");
8
+ return;
9
+ }
10
+ pm.addView(setVM);
11
+ },
12
+ unsubscribe: (appObjects, setVM) => {
13
+ const pm = BoundaryLogPM.get(appObjects);
14
+ if (!pm) {
15
+ appObjects.submitError("boundaryLogAdapter", "Unable to find BoundaryLogPM");
16
+ return;
17
+ }
18
+ pm.removeView(setVM);
19
+ }
20
+ };
21
+ //# sourceMappingURL=boundaryLogAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundaryLogAdapter.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Adapters/boundaryLogAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EAEb,oBAAoB,EACrB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,CAAC,MAAM,kBAAkB,GAAsC;IACnE,SAAS,EAAE,oBAAoB;IAC/B,SAAS,EAAE,CACT,UAAyB,EACzB,KAAkC,EAClC,EAAE;QACF,MAAM,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,UAAU,CAAC,WAAW,CACpB,oBAAoB,EACpB,8BAA8B,CAC/B,CAAC;YACF,OAAO;QACT,CAAC;QACD,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,WAAW,EAAE,CACX,UAAyB,EACzB,KAAkC,EAClC,EAAE;QACF,MAAM,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,UAAU,CAAC,WAAW,CACpB,oBAAoB,EACpB,8BAA8B,CAC/B,CAAC;YACF,OAAO;QACT,CAAC;QACD,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;CACF,CAAC","sourcesContent":["import { AppObjectRepo, SingletonPmAdapter } from \"@vived/core\";\r\nimport {\r\n BoundaryLogPM,\r\n BoundaryLogVM,\r\n defaultBoundaryLogVM\r\n} from \"../PMs/BoundaryLogPM\";\r\n\r\nexport const boundaryLogAdapter: SingletonPmAdapter<BoundaryLogVM> = {\r\n defaultVM: defaultBoundaryLogVM,\r\n subscribe: (\r\n appObjects: AppObjectRepo,\r\n setVM: (vm: BoundaryLogVM) => void\r\n ) => {\r\n const pm = BoundaryLogPM.get(appObjects);\r\n if (!pm) {\r\n appObjects.submitError(\r\n \"boundaryLogAdapter\",\r\n \"Unable to find BoundaryLogPM\"\r\n );\r\n return;\r\n }\r\n pm.addView(setVM);\r\n },\r\n unsubscribe: (\r\n appObjects: AppObjectRepo,\r\n setVM: (vm: BoundaryLogVM) => void\r\n ) => {\r\n const pm = BoundaryLogPM.get(appObjects);\r\n if (!pm) {\r\n appObjects.submitError(\r\n \"boundaryLogAdapter\",\r\n \"Unable to find BoundaryLogPM\"\r\n );\r\n return;\r\n }\r\n pm.removeView(setVM);\r\n }\r\n};\r\n"]}
@@ -0,0 +1,2 @@
1
+ export * from "./boundaryLogAdapter";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC","sourcesContent":["export * from \"./boundaryLogAdapter\";\r\n"]}
@@ -0,0 +1,12 @@
1
+ import { BoundaryLogEntity } from "../Entities";
2
+ /** Clears the Boundary Log on demand (the tab's Clear action). */
3
+ export function clearBoundaryLog(appObjects) {
4
+ const entity = BoundaryLogEntity.get(appObjects);
5
+ if (entity) {
6
+ entity.clear();
7
+ }
8
+ else {
9
+ appObjects.submitError("clearBoundaryLog", "Unable to find BoundaryLogEntity");
10
+ }
11
+ }
12
+ //# sourceMappingURL=clearBoundaryLog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clearBoundaryLog.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Controllers/clearBoundaryLog.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,kEAAkE;AAClE,MAAM,UAAU,gBAAgB,CAAC,UAAyB;IACxD,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;SAAM,CAAC;QACN,UAAU,CAAC,WAAW,CACpB,kBAAkB,EAClB,kCAAkC,CACnC,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import { AppObjectRepo } from \"@vived/core\";\r\nimport { BoundaryLogEntity } from \"../Entities\";\r\n\r\n/** Clears the Boundary Log on demand (the tab's Clear action). */\r\nexport function clearBoundaryLog(appObjects: AppObjectRepo) {\r\n const entity = BoundaryLogEntity.get(appObjects);\r\n if (entity) {\r\n entity.clear();\r\n } else {\r\n appObjects.submitError(\r\n \"clearBoundaryLog\",\r\n \"Unable to find BoundaryLogEntity\"\r\n );\r\n }\r\n}\r\n"]}
@@ -0,0 +1,2 @@
1
+ export * from "./clearBoundaryLog";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Controllers/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC","sourcesContent":["export * from \"./clearBoundaryLog\";\r\n"]}
@@ -0,0 +1,40 @@
1
+ import { getSingletonComponent, AppObjectEntity } from "@vived/core";
2
+ import { snapshotPayload } from "./snapshotPayload";
3
+ /**
4
+ * The Boundary Log: a passive, chronological recording of every Request
5
+ * observed crossing the host↔App boundary. Accumulates unbounded within a
6
+ * session and is only reset by an explicit clear() — never by traffic itself.
7
+ */
8
+ export class BoundaryLogEntity extends AppObjectEntity {
9
+ static get(appObjects) {
10
+ return getSingletonComponent(BoundaryLogEntity.type, appObjects);
11
+ }
12
+ }
13
+ BoundaryLogEntity.type = "BoundaryLogEntity";
14
+ export function makeBoundaryLogEntity(appObject) {
15
+ return new BoundaryLogEntityImp(appObject);
16
+ }
17
+ class BoundaryLogEntityImp extends BoundaryLogEntity {
18
+ constructor(appObject) {
19
+ super(appObject, BoundaryLogEntity.type);
20
+ this.records = [];
21
+ this.recordTraffic = (direction, request, outcome) => {
22
+ const record = {
23
+ direction,
24
+ type: request.type,
25
+ version: request.version,
26
+ payload: snapshotPayload(request.payload),
27
+ timestamp: Date.now(),
28
+ outcome
29
+ };
30
+ this.records.push(record);
31
+ this.notifyOnChange();
32
+ };
33
+ this.clear = () => {
34
+ this.records = [];
35
+ this.notifyOnChange();
36
+ };
37
+ this.appObjects.registerSingleton(this);
38
+ }
39
+ }
40
+ //# sourceMappingURL=BoundaryLogEntity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BoundaryLogEntity.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Entities/BoundaryLogEntity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAErB,eAAe,EAGhB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAmB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA+BrE;;;;GAIG;AACH,MAAM,OAAgB,iBAAkB,SAAQ,eAAe;IAG7D,MAAM,CAAC,GAAG,CAAC,UAAyB;QAClC,OAAO,qBAAqB,CAC1B,iBAAiB,CAAC,IAAI,EACtB,UAAU,CACX,CAAC;IACJ,CAAC;;AAPM,sBAAI,GAAG,mBAAmB,CAAC;AAoBpC,MAAM,UAAU,qBAAqB,CAAC,SAAoB;IACxD,OAAO,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,oBAAqB,SAAQ,iBAAiB;IA0BlD,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;QA1B3C,YAAO,GAAoB,EAAE,CAAC;QAE9B,kBAAa,GAAG,CACd,SAA2B,EAC3B,OAAgB,EAChB,OAAuB,EACjB,EAAE;YACR,MAAM,MAAM,GAAkB;gBAC5B,SAAS;gBACT,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC;gBACzC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,OAAO;aACR,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC,CAAC;QAEF,UAAK,GAAG,GAAS,EAAE;YACjB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;YAClB,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC,CAAC;QAIA,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;CACF","sourcesContent":["import {\r\n getSingletonComponent,\r\n AppObject,\r\n AppObjectEntity,\r\n AppObjectRepo,\r\n Request\r\n} from \"@vived/core\";\r\nimport { PayloadSnapshot, snapshotPayload } from \"./snapshotPayload\";\r\n\r\n/** Which way a recorded Request crossed the host↔App boundary. */\r\nexport type RequestDirection = \"dispatch\" | \"handler\";\r\n\r\n/**\r\n * What happened to a recorded Request. Outbound (Dispatch) records use\r\n * \"delivered\" | \"no-app-handler\" | \"threw\"; inbound (Handler) records use\r\n * \"handled\" | \"unsupported\" | \"threw\".\r\n */\r\nexport type RequestOutcome =\r\n | \"delivered\"\r\n | \"no-app-handler\"\r\n | \"handled\"\r\n | \"unsupported\"\r\n | \"threw\";\r\n\r\n/**\r\n * One captured entry in the Boundary Log: the observed Request plus its\r\n * direction, a frozen payload snapshot, the time it was observed, and its\r\n * outcome. Distinct from the live wire Request it was captured from.\r\n */\r\nexport interface RequestRecord {\r\n direction: RequestDirection;\r\n type: string;\r\n version: number;\r\n payload: PayloadSnapshot;\r\n timestamp: number;\r\n outcome: RequestOutcome;\r\n}\r\n\r\n/**\r\n * The Boundary Log: a passive, chronological recording of every Request\r\n * observed crossing the host↔App boundary. Accumulates unbounded within a\r\n * session and is only reset by an explicit clear() — never by traffic itself.\r\n */\r\nexport abstract class BoundaryLogEntity extends AppObjectEntity {\r\n static type = \"BoundaryLogEntity\";\r\n\r\n static get(appObjects: AppObjectRepo) {\r\n return getSingletonComponent<BoundaryLogEntity>(\r\n BoundaryLogEntity.type,\r\n appObjects\r\n );\r\n }\r\n\r\n abstract records: RequestRecord[];\r\n\r\n abstract recordTraffic: (\r\n direction: RequestDirection,\r\n request: Request,\r\n outcome: RequestOutcome\r\n ) => void;\r\n\r\n abstract clear: () => void;\r\n}\r\n\r\nexport function makeBoundaryLogEntity(appObject: AppObject): BoundaryLogEntity {\r\n return new BoundaryLogEntityImp(appObject);\r\n}\r\n\r\nclass BoundaryLogEntityImp extends BoundaryLogEntity {\r\n records: RequestRecord[] = [];\r\n\r\n recordTraffic = (\r\n direction: RequestDirection,\r\n request: Request,\r\n outcome: RequestOutcome\r\n ): void => {\r\n const record: RequestRecord = {\r\n direction,\r\n type: request.type,\r\n version: request.version,\r\n payload: snapshotPayload(request.payload),\r\n timestamp: Date.now(),\r\n outcome\r\n };\r\n\r\n this.records.push(record);\r\n this.notifyOnChange();\r\n };\r\n\r\n clear = (): void => {\r\n this.records = [];\r\n this.notifyOnChange();\r\n };\r\n\r\n constructor(appObject: AppObject) {\r\n super(appObject, BoundaryLogEntity.type);\r\n this.appObjects.registerSingleton(this);\r\n }\r\n}\r\n"]}
@@ -0,0 +1,3 @@
1
+ export * from "./BoundaryLogEntity";
2
+ export * from "./snapshotPayload";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Entities/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC","sourcesContent":["export * from \"./BoundaryLogEntity\";\r\nexport * from \"./snapshotPayload\";\r\n"]}
@@ -0,0 +1,59 @@
1
+ const UNREADABLE = "⟨unreadable⟩";
2
+ /**
3
+ * Preview a single value one level deep. Objects and arrays are marked rather
4
+ * than expanded, so circular structures are inherently safe. Any access that
5
+ * throws (e.g. a getter) is caught and rendered as unreadable.
6
+ */
7
+ function previewValue(value) {
8
+ try {
9
+ if (value === null)
10
+ return "null";
11
+ if (value === undefined)
12
+ return "undefined";
13
+ const type = typeof value;
14
+ if (type === "function") {
15
+ const name = value.name;
16
+ return `ƒ ${name && name.length > 0 ? name : "anonymous"}`;
17
+ }
18
+ if (type === "string")
19
+ return JSON.stringify(value);
20
+ if (type === "number" || type === "boolean" || type === "bigint") {
21
+ return String(value);
22
+ }
23
+ if (type === "symbol")
24
+ return value.toString();
25
+ if (Array.isArray(value))
26
+ return `Array(${value.length})`;
27
+ if (type === "object")
28
+ return "{…}";
29
+ return String(value);
30
+ }
31
+ catch {
32
+ return UNREADABLE;
33
+ }
34
+ }
35
+ export function snapshotPayload(payload) {
36
+ const fields = {};
37
+ if (payload !== null && payload !== undefined && typeof payload === "object") {
38
+ let keys = [];
39
+ try {
40
+ keys = Object.keys(payload);
41
+ }
42
+ catch {
43
+ keys = [];
44
+ }
45
+ for (const key of keys) {
46
+ try {
47
+ fields[key] = previewValue(payload[key]);
48
+ }
49
+ catch {
50
+ fields[key] = UNREADABLE;
51
+ }
52
+ }
53
+ }
54
+ return {
55
+ isEmpty: Object.keys(fields).length === 0,
56
+ fields
57
+ };
58
+ }
59
+ //# sourceMappingURL=snapshotPayload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshotPayload.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Entities/snapshotPayload.ts"],"names":[],"mappings":"AAeA,MAAM,UAAU,GAAG,cAAc,CAAC;AAElC;;;;GAIG;AACH,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,CAAC;QACH,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC;QAClC,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,WAAW,CAAC;QAE5C,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC;QAE1B,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,MAAM,IAAI,GAAI,KAA2B,CAAC,IAAI,CAAC;YAC/C,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7D,CAAC;QACD,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACpD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACjE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAQ,KAAgB,CAAC,QAAQ,EAAE,CAAC;QAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,SAAS,KAAK,CAAC,MAAM,GAAG,CAAC;QAC1D,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAEpC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,UAAU,CAAC;IACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC7E,IAAI,IAAI,GAAa,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAkC,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,EAAE,CAAC;QACZ,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,CAAE,OAAmC,CAAC,GAAG,CAAC,CAAC,CAAC;YACxE,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;QACzC,MAAM;KACP,CAAC;AACJ,CAAC","sourcesContent":["/**\r\n * A best-effort, one-level-deep structural snapshot of a Request payload, taken\r\n * at the moment the Request crosses the host↔App boundary. It never throws:\r\n * callbacks, circular references, and throwing getters are all rendered as\r\n * previews rather than expanded or serialized. Nested objects/arrays are marked\r\n * (not recursed), so what a developer inspects is exactly what was sent —\r\n * frozen, safe to render, and cheap to build.\r\n */\r\nexport interface PayloadSnapshot {\r\n /** True when the payload was undefined/null or carried no own-enumerable keys. */\r\n isEmpty: boolean;\r\n /** Own-enumerable key → one-level preview string. */\r\n fields: Record<string, string>;\r\n}\r\n\r\nconst UNREADABLE = \"⟨unreadable⟩\";\r\n\r\n/**\r\n * Preview a single value one level deep. Objects and arrays are marked rather\r\n * than expanded, so circular structures are inherently safe. Any access that\r\n * throws (e.g. a getter) is caught and rendered as unreadable.\r\n */\r\nfunction previewValue(value: unknown): string {\r\n try {\r\n if (value === null) return \"null\";\r\n if (value === undefined) return \"undefined\";\r\n\r\n const type = typeof value;\r\n\r\n if (type === \"function\") {\r\n const name = (value as { name?: string }).name;\r\n return `ƒ ${name && name.length > 0 ? name : \"anonymous\"}`;\r\n }\r\n if (type === \"string\") return JSON.stringify(value);\r\n if (type === \"number\" || type === \"boolean\" || type === \"bigint\") {\r\n return String(value);\r\n }\r\n if (type === \"symbol\") return (value as symbol).toString();\r\n if (Array.isArray(value)) return `Array(${value.length})`;\r\n if (type === \"object\") return \"{…}\";\r\n\r\n return String(value);\r\n } catch {\r\n return UNREADABLE;\r\n }\r\n}\r\n\r\nexport function snapshotPayload(payload: unknown): PayloadSnapshot {\r\n const fields: Record<string, string> = {};\r\n\r\n if (payload !== null && payload !== undefined && typeof payload === \"object\") {\r\n let keys: string[] = [];\r\n try {\r\n keys = Object.keys(payload as Record<string, unknown>);\r\n } catch {\r\n keys = [];\r\n }\r\n\r\n for (const key of keys) {\r\n try {\r\n fields[key] = previewValue((payload as Record<string, unknown>)[key]);\r\n } catch {\r\n fields[key] = UNREADABLE;\r\n }\r\n }\r\n }\r\n\r\n return {\r\n isEmpty: Object.keys(fields).length === 0,\r\n fields\r\n };\r\n}\r\n"]}
@@ -0,0 +1,57 @@
1
+ import { DomainFactory } from "@vived/core";
2
+ import { AppSandboxEntity } from "../../AppSandbox/Entities/AppSandboxEntity";
3
+ import { HostDispatchEntity } from "../../Dispatcher/Entities/HostDispatchEntity";
4
+ import { HostHandlerEntity } from "../../Handler/Entities/HostHandler";
5
+ import { BoundaryLogEntity, makeBoundaryLogEntity } from "../Entities";
6
+ import { makeBoundaryLogPM } from "../PMs";
7
+ /**
8
+ * Sets up the Boundary Log and wires its passive observers into the per-App
9
+ * communication entities (ADR-0002). The observers are attached in finalSetup,
10
+ * after every entity exists but before the App mounts — so the host-internal
11
+ * version-negotiation dispatches fired at registration are captured too.
12
+ */
13
+ export class BoundaryLogFactory extends DomainFactory {
14
+ constructor(appObject) {
15
+ super(appObject);
16
+ this.factoryName = "BoundaryLogFactory";
17
+ }
18
+ setupEntities() {
19
+ makeBoundaryLogEntity(this.appObject);
20
+ }
21
+ setupUCs() {
22
+ // No use cases.
23
+ }
24
+ setupPMs() {
25
+ makeBoundaryLogPM(this.appObject);
26
+ }
27
+ finalSetup() {
28
+ const boundaryLog = BoundaryLogEntity.get(this.appObjects);
29
+ if (!boundaryLog) {
30
+ this.error("BoundaryLogEntity not found during final setup.");
31
+ return;
32
+ }
33
+ const sandbox = AppSandboxEntity.get(this.appObjects);
34
+ if (!sandbox) {
35
+ this.error("AppSandboxEntity not found during final setup.");
36
+ return;
37
+ }
38
+ const appObject = this.appObjects.get(sandbox.appID);
39
+ if (!appObject) {
40
+ this.error("App AppObject not found during final setup.");
41
+ return;
42
+ }
43
+ const dispatch = HostDispatchEntity.get(appObject);
44
+ if (dispatch) {
45
+ dispatch.requestObserver = (request, outcome) => boundaryLog.recordTraffic("dispatch", request, outcome);
46
+ }
47
+ const handler = HostHandlerEntity.get(appObject);
48
+ if (handler) {
49
+ handler.requestObserver = (request, outcome) => boundaryLog.recordTraffic("handler", request, outcome);
50
+ }
51
+ }
52
+ }
53
+ export function makeBoundaryLogFactory(appObjects) {
54
+ const ao = appObjects.getOrCreate("BoundaryLog");
55
+ return new BoundaryLogFactory(ao);
56
+ }
57
+ //# sourceMappingURL=BoundaryLogFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BoundaryLogFactory.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Factories/BoundaryLogFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,aAAa,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,OAAO,kBAAmB,SAAQ,aAAa;IAGnD,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,CAAC,CAAC;QAHV,gBAAW,GAAG,oBAAoB,CAAC;IAI5C,CAAC;IAED,aAAa;QACX,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;IAED,QAAQ;QACN,gBAAgB;IAClB,CAAC;IAED,QAAQ;QACN,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAED,UAAU;QACR,MAAM,WAAW,GAAG,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3D,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,IAAI,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;YAC9D,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;YAC1D,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAC9C,WAAW,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAC7C,WAAW,CAAC,aAAa,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB,CACpC,UAAyB;IAEzB,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IACjD,OAAO,IAAI,kBAAkB,CAAC,EAAE,CAAC,CAAC;AACpC,CAAC","sourcesContent":["import { AppObject, AppObjectRepo, DomainFactory } from \"@vived/core\";\r\nimport { AppSandboxEntity } from \"../../AppSandbox/Entities/AppSandboxEntity\";\r\nimport { HostDispatchEntity } from \"../../Dispatcher/Entities/HostDispatchEntity\";\r\nimport { HostHandlerEntity } from \"../../Handler/Entities/HostHandler\";\r\nimport { BoundaryLogEntity, makeBoundaryLogEntity } from \"../Entities\";\r\nimport { makeBoundaryLogPM } from \"../PMs\";\r\n\r\n/**\r\n * Sets up the Boundary Log and wires its passive observers into the per-App\r\n * communication entities (ADR-0002). The observers are attached in finalSetup,\r\n * after every entity exists but before the App mounts — so the host-internal\r\n * version-negotiation dispatches fired at registration are captured too.\r\n */\r\nexport class BoundaryLogFactory extends DomainFactory {\r\n readonly factoryName = \"BoundaryLogFactory\";\r\n\r\n constructor(appObject: AppObject) {\r\n super(appObject);\r\n }\r\n\r\n setupEntities(): void {\r\n makeBoundaryLogEntity(this.appObject);\r\n }\r\n\r\n setupUCs(): void {\r\n // No use cases.\r\n }\r\n\r\n setupPMs(): void {\r\n makeBoundaryLogPM(this.appObject);\r\n }\r\n\r\n finalSetup(): void {\r\n const boundaryLog = BoundaryLogEntity.get(this.appObjects);\r\n if (!boundaryLog) {\r\n this.error(\"BoundaryLogEntity not found during final setup.\");\r\n return;\r\n }\r\n\r\n const sandbox = AppSandboxEntity.get(this.appObjects);\r\n if (!sandbox) {\r\n this.error(\"AppSandboxEntity not found during final setup.\");\r\n return;\r\n }\r\n\r\n const appObject = this.appObjects.get(sandbox.appID);\r\n if (!appObject) {\r\n this.error(\"App AppObject not found during final setup.\");\r\n return;\r\n }\r\n\r\n const dispatch = HostDispatchEntity.get(appObject);\r\n if (dispatch) {\r\n dispatch.requestObserver = (request, outcome) =>\r\n boundaryLog.recordTraffic(\"dispatch\", request, outcome);\r\n }\r\n\r\n const handler = HostHandlerEntity.get(appObject);\r\n if (handler) {\r\n handler.requestObserver = (request, outcome) =>\r\n boundaryLog.recordTraffic(\"handler\", request, outcome);\r\n }\r\n }\r\n}\r\n\r\nexport function makeBoundaryLogFactory(\r\n appObjects: AppObjectRepo\r\n): BoundaryLogFactory {\r\n const ao = appObjects.getOrCreate(\"BoundaryLog\");\r\n return new BoundaryLogFactory(ao);\r\n}\r\n"]}
@@ -0,0 +1,2 @@
1
+ export * from "./BoundaryLogFactory";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Factories/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC","sourcesContent":["export * from \"./BoundaryLogFactory\";\r\n"]}
@@ -0,0 +1,11 @@
1
+ import { BoundaryLogPM } from "../PMs";
2
+ export class BoundaryLogPMMock extends BoundaryLogPM {
3
+ constructor(appObject) {
4
+ super(appObject, BoundaryLogPM.type);
5
+ this.vmsAreEqual = jest.fn();
6
+ }
7
+ }
8
+ export function makeBoundaryLogPMMock(appObjects) {
9
+ return new BoundaryLogPMMock(appObjects.getOrCreate("BoundaryLogPMMock"));
10
+ }
11
+ //# sourceMappingURL=BoundaryLogPMMock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BoundaryLogPMMock.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Mocks/BoundaryLogPMMock.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,OAAO,iBAAkB,SAAQ,aAAa;IAGlD,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;QAHvC,gBAAW,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IAIxB,CAAC;CACF;AAED,MAAM,UAAU,qBAAqB,CAAC,UAAyB;IAC7D,OAAO,IAAI,iBAAiB,CAAC,UAAU,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC,CAAC;AAC5E,CAAC","sourcesContent":["import { AppObject, AppObjectRepo } from \"@vived/core\";\r\nimport { BoundaryLogPM } from \"../PMs\";\r\n\r\nexport class BoundaryLogPMMock extends BoundaryLogPM {\r\n vmsAreEqual = jest.fn();\r\n\r\n constructor(appObject: AppObject) {\r\n super(appObject, BoundaryLogPM.type);\r\n }\r\n}\r\n\r\nexport function makeBoundaryLogPMMock(appObjects: AppObjectRepo) {\r\n return new BoundaryLogPMMock(appObjects.getOrCreate(\"BoundaryLogPMMock\"));\r\n}\r\n"]}
@@ -0,0 +1,2 @@
1
+ export * from "./BoundaryLogPMMock";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/Mocks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC","sourcesContent":["export * from \"./BoundaryLogPMMock\";\r\n"]}
@@ -0,0 +1,51 @@
1
+ import { getSingletonComponent, AppObjectPM } from "@vived/core";
2
+ import { BoundaryLogEntity } from "../Entities";
3
+ export const defaultBoundaryLogVM = {
4
+ records: [],
5
+ count: 0
6
+ };
7
+ export class BoundaryLogPM extends AppObjectPM {
8
+ static get(appObjects) {
9
+ return getSingletonComponent(BoundaryLogPM.type, appObjects);
10
+ }
11
+ }
12
+ BoundaryLogPM.type = "BoundaryLogPM";
13
+ export function makeBoundaryLogPM(appObject) {
14
+ return new BoundaryLogPMImp(appObject);
15
+ }
16
+ class BoundaryLogPMImp extends BoundaryLogPM {
17
+ get boundaryLog() {
18
+ return this.getCachedSingleton(BoundaryLogEntity.type);
19
+ }
20
+ vmsAreEqual(a, b) {
21
+ if (a.count !== b.count)
22
+ return false;
23
+ if (a.records.length !== b.records.length)
24
+ return false;
25
+ for (let i = 0; i < a.records.length; i++) {
26
+ if (a.records[i] !== b.records[i])
27
+ return false;
28
+ }
29
+ return true;
30
+ }
31
+ constructor(appObject) {
32
+ super(appObject, BoundaryLogPM.type);
33
+ this.onEntityChange = () => {
34
+ if (!this.boundaryLog)
35
+ return;
36
+ // Copy the array (new VM identity) but keep record references stable so
37
+ // vmsAreEqual can compare cheaply. Order is insertion order = the order the
38
+ // Requests were observed.
39
+ const records = [...this.boundaryLog.records];
40
+ const vm = {
41
+ records,
42
+ count: records.length
43
+ };
44
+ this.doUpdateView(vm);
45
+ };
46
+ this.onEntityChange();
47
+ this.boundaryLog?.addChangeObserver(this.onEntityChange);
48
+ this.appObjects.registerSingleton(this);
49
+ }
50
+ }
51
+ //# sourceMappingURL=BoundaryLogPM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BoundaryLogPM.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/PMs/BoundaryLogPM.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAErB,WAAW,EAEZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAiB,MAAM,aAAa,CAAC;AAY/D,MAAM,CAAC,MAAM,oBAAoB,GAAkB;IACjD,OAAO,EAAE,EAAE;IACX,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,MAAM,OAAgB,aAAc,SAAQ,WAA0B;IAGpE,MAAM,CAAC,GAAG,CAAC,UAAyB;QAClC,OAAO,qBAAqB,CAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC9E,CAAC;;AAJM,kBAAI,GAAG,eAAe,CAAC;AAOhC,MAAM,UAAU,iBAAiB,CAAC,SAAoB;IACpD,OAAO,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,gBAAiB,SAAQ,aAAa;IAC1C,IAAY,WAAW;QACrB,OAAO,IAAI,CAAC,kBAAkB,CAAoB,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC;IAED,WAAW,CAAC,CAAgB,EAAE,CAAgB;QAC5C,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACtC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC;QAClD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAiBD,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;QAhB/B,mBAAc,GAAG,GAAG,EAAE;YAC5B,IAAI,CAAC,IAAI,CAAC,WAAW;gBAAE,OAAO;YAE9B,wEAAwE;YACxE,4EAA4E;YAC5E,0BAA0B;YAC1B,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC9C,MAAM,EAAE,GAAkB;gBACxB,OAAO;gBACP,KAAK,EAAE,OAAO,CAAC,MAAM;aACtB,CAAC;YAEF,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC,CAAC;QAKA,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACzD,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;CACF","sourcesContent":["import {\r\n getSingletonComponent,\r\n AppObject,\r\n AppObjectPM,\r\n AppObjectRepo\r\n} from \"@vived/core\";\r\nimport { BoundaryLogEntity, RequestRecord } from \"../Entities\";\r\n\r\n/**\r\n * The view projection of the Boundary Log: the recorded Requests in observation\r\n * order (each row carries its direction so the view can side Dispatches and\r\n * Handlers independently) plus the total count.\r\n */\r\nexport interface BoundaryLogVM {\r\n records: RequestRecord[];\r\n count: number;\r\n}\r\n\r\nexport const defaultBoundaryLogVM: BoundaryLogVM = {\r\n records: [],\r\n count: 0\r\n};\r\n\r\nexport abstract class BoundaryLogPM extends AppObjectPM<BoundaryLogVM> {\r\n static type = \"BoundaryLogPM\";\r\n\r\n static get(appObjects: AppObjectRepo) {\r\n return getSingletonComponent<BoundaryLogPM>(BoundaryLogPM.type, appObjects);\r\n }\r\n}\r\n\r\nexport function makeBoundaryLogPM(appObject: AppObject): BoundaryLogPM {\r\n return new BoundaryLogPMImp(appObject);\r\n}\r\n\r\nclass BoundaryLogPMImp extends BoundaryLogPM {\r\n private get boundaryLog() {\r\n return this.getCachedSingleton<BoundaryLogEntity>(BoundaryLogEntity.type);\r\n }\r\n\r\n vmsAreEqual(a: BoundaryLogVM, b: BoundaryLogVM): boolean {\r\n if (a.count !== b.count) return false;\r\n if (a.records.length !== b.records.length) return false;\r\n for (let i = 0; i < a.records.length; i++) {\r\n if (a.records[i] !== b.records[i]) return false;\r\n }\r\n return true;\r\n }\r\n\r\n private onEntityChange = () => {\r\n if (!this.boundaryLog) return;\r\n\r\n // Copy the array (new VM identity) but keep record references stable so\r\n // vmsAreEqual can compare cheaply. Order is insertion order = the order the\r\n // Requests were observed.\r\n const records = [...this.boundaryLog.records];\r\n const vm: BoundaryLogVM = {\r\n records,\r\n count: records.length\r\n };\r\n\r\n this.doUpdateView(vm);\r\n };\r\n\r\n constructor(appObject: AppObject) {\r\n super(appObject, BoundaryLogPM.type);\r\n\r\n this.onEntityChange();\r\n this.boundaryLog?.addChangeObserver(this.onEntityChange);\r\n this.appObjects.registerSingleton(this);\r\n }\r\n}\r\n"]}
@@ -0,0 +1,2 @@
1
+ export * from "./BoundaryLogPM";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/BoundaryLog/PMs/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC","sourcesContent":["export * from \"./BoundaryLogPM\";\r\n"]}
@@ -0,0 +1,7 @@
1
+ export * from "./Adapters";
2
+ export * from "./Controllers";
3
+ export * from "./Entities";
4
+ export * from "./Factories";
5
+ export * from "./Mocks";
6
+ export * from "./PMs";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/BoundaryLog/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC","sourcesContent":["export * from \"./Adapters\";\r\nexport * from \"./Controllers\";\r\nexport * from \"./Entities\";\r\nexport * from \"./Factories\";\r\nexport * from \"./Mocks\";\r\nexport * from \"./PMs\";\r\n"]}