@capture.dev/event-logger 0.0.1

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 (92) hide show
  1. package/LICENSE.txt +7 -0
  2. package/dist/event-logger.d.ts +25 -0
  3. package/dist/event-logger.d.ts.map +1 -0
  4. package/dist/event-logger.js +42 -0
  5. package/dist/event-sink.d.ts +11 -0
  6. package/dist/event-sink.d.ts.map +1 -0
  7. package/dist/event-sink.js +32 -0
  8. package/dist/global-state.d.ts +14 -0
  9. package/dist/global-state.d.ts.map +1 -0
  10. package/dist/global-state.js +28 -0
  11. package/dist/index-internal.d.ts +20 -0
  12. package/dist/index-internal.d.ts.map +1 -0
  13. package/dist/index-internal.js +18 -0
  14. package/dist/index.d.ts +5 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +4 -0
  17. package/dist/register-logger.d.ts +8 -0
  18. package/dist/register-logger.d.ts.map +1 -0
  19. package/dist/register-logger.js +24 -0
  20. package/dist/register-state-logger.d.ts +5 -0
  21. package/dist/register-state-logger.d.ts.map +1 -0
  22. package/dist/register-state-logger.js +5 -0
  23. package/dist/snapshot-event-to-operation.d.ts +5 -0
  24. package/dist/snapshot-event-to-operation.d.ts.map +1 -0
  25. package/dist/snapshot-event-to-operation.js +7 -0
  26. package/dist/state-logger.d.ts +37 -0
  27. package/dist/state-logger.d.ts.map +1 -0
  28. package/dist/state-logger.js +90 -0
  29. package/dist/to-json/__tests__/serialize-class.test.d.ts +2 -0
  30. package/dist/to-json/__tests__/serialize-class.test.d.ts.map +1 -0
  31. package/dist/to-json/__tests__/serialize-class.test.js +79 -0
  32. package/dist/to-json/__tests__/serialize-date.test.d.ts +2 -0
  33. package/dist/to-json/__tests__/serialize-date.test.d.ts.map +1 -0
  34. package/dist/to-json/__tests__/serialize-date.test.js +20 -0
  35. package/dist/to-json/__tests__/serialize-error.test.d.ts +2 -0
  36. package/dist/to-json/__tests__/serialize-error.test.d.ts.map +1 -0
  37. package/dist/to-json/__tests__/serialize-error.test.js +71 -0
  38. package/dist/to-json/__tests__/serialize-function.test.d.ts +2 -0
  39. package/dist/to-json/__tests__/serialize-function.test.d.ts.map +1 -0
  40. package/dist/to-json/__tests__/serialize-function.test.js +84 -0
  41. package/dist/to-json/__tests__/serialize-map.test.d.ts +2 -0
  42. package/dist/to-json/__tests__/serialize-map.test.d.ts.map +1 -0
  43. package/dist/to-json/__tests__/serialize-map.test.js +90 -0
  44. package/dist/to-json/__tests__/serialize-object.test.d.ts +2 -0
  45. package/dist/to-json/__tests__/serialize-object.test.d.ts.map +1 -0
  46. package/dist/to-json/__tests__/serialize-object.test.js +138 -0
  47. package/dist/to-json/__tests__/serialize-regex.test.d.ts +2 -0
  48. package/dist/to-json/__tests__/serialize-regex.test.d.ts.map +1 -0
  49. package/dist/to-json/__tests__/serialize-regex.test.js +64 -0
  50. package/dist/to-json/__tests__/serialize-set.test.d.ts +2 -0
  51. package/dist/to-json/__tests__/serialize-set.test.d.ts.map +1 -0
  52. package/dist/to-json/__tests__/serialize-set.test.js +74 -0
  53. package/dist/to-json/__tests__/to-json.test.d.ts +2 -0
  54. package/dist/to-json/__tests__/to-json.test.d.ts.map +1 -0
  55. package/dist/to-json/__tests__/to-json.test.js +356 -0
  56. package/dist/to-json/serialize-class.d.ts +4 -0
  57. package/dist/to-json/serialize-class.d.ts.map +1 -0
  58. package/dist/to-json/serialize-class.js +14 -0
  59. package/dist/to-json/serialize-date.d.ts +3 -0
  60. package/dist/to-json/serialize-date.d.ts.map +1 -0
  61. package/dist/to-json/serialize-date.js +8 -0
  62. package/dist/to-json/serialize-error.d.ts +3 -0
  63. package/dist/to-json/serialize-error.d.ts.map +1 -0
  64. package/dist/to-json/serialize-error.js +22 -0
  65. package/dist/to-json/serialize-function.d.ts +3 -0
  66. package/dist/to-json/serialize-function.d.ts.map +1 -0
  67. package/dist/to-json/serialize-function.js +7 -0
  68. package/dist/to-json/serialize-map.d.ts +4 -0
  69. package/dist/to-json/serialize-map.d.ts.map +1 -0
  70. package/dist/to-json/serialize-map.js +10 -0
  71. package/dist/to-json/serialize-object.d.ts +4 -0
  72. package/dist/to-json/serialize-object.d.ts.map +1 -0
  73. package/dist/to-json/serialize-object.js +17 -0
  74. package/dist/to-json/serialize-regex.d.ts +3 -0
  75. package/dist/to-json/serialize-regex.d.ts.map +1 -0
  76. package/dist/to-json/serialize-regex.js +6 -0
  77. package/dist/to-json/serialize-set.d.ts +4 -0
  78. package/dist/to-json/serialize-set.d.ts.map +1 -0
  79. package/dist/to-json/serialize-set.js +10 -0
  80. package/dist/to-json/serialized-markers.d.ts +23 -0
  81. package/dist/to-json/serialized-markers.d.ts.map +1 -0
  82. package/dist/to-json/serialized-markers.js +22 -0
  83. package/dist/to-json/serialized-types.d.ts +55 -0
  84. package/dist/to-json/serialized-types.d.ts.map +1 -0
  85. package/dist/to-json/serialized-types.js +39 -0
  86. package/dist/to-json/to-json.constants.d.ts +11 -0
  87. package/dist/to-json/to-json.constants.d.ts.map +1 -0
  88. package/dist/to-json/to-json.constants.js +10 -0
  89. package/dist/to-json/to-json.d.ts +14 -0
  90. package/dist/to-json/to-json.d.ts.map +1 -0
  91. package/dist/to-json/to-json.js +141 -0
  92. package/package.json +51 -0
package/LICENSE.txt ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2026 Capture.dev
2
+
3
+ All rights reserved.
4
+
5
+ This software is made available for use by Capture.dev customers.
6
+ Unauthorized copying, modification, distribution, or use of this software
7
+ is strictly prohibited.
@@ -0,0 +1,25 @@
1
+ import type { EventSink } from "./event-sink.js";
2
+ import type { SerializedValue } from "./to-json/serialized-types.js";
3
+ export type BaseEvent = {
4
+ time: number;
5
+ [key: string]: SerializedValue | undefined;
6
+ };
7
+ export type EventLoggerType = "state" | "events";
8
+ export type EventLoggerMeta = {
9
+ identifier: string;
10
+ name?: string;
11
+ version?: number;
12
+ };
13
+ export declare class EventLogger<EventType extends BaseEvent = BaseEvent> {
14
+ type: EventLoggerType;
15
+ private sinks;
16
+ private queue;
17
+ private errorQueue;
18
+ meta: EventLoggerMeta;
19
+ initialize(meta: EventLoggerMeta): void;
20
+ registerSink(sink: EventSink): void;
21
+ logEvent: (event: EventType) => void;
22
+ logInternalError: (error: unknown) => void;
23
+ start(): void;
24
+ }
25
+ //# sourceMappingURL=event-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-logger.d.ts","sourceRoot":"","sources":["../src/event-logger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEjD,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,qBAAa,WAAW,CAAC,SAAS,SAAS,SAAS,GAAG,SAAS;IAC9D,IAAI,EAAE,eAAe,CAAY;IAEjC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,UAAU,CAAiB;IAE5B,IAAI,EAAE,eAAe,CAE1B;IAEF,UAAU,CAAC,IAAI,EAAE,eAAe;IAOhC,YAAY,CAAC,IAAI,EAAE,SAAS;IAU5B,QAAQ,GAAI,OAAO,SAAS,UAM1B;IAEF,gBAAgB,GAAI,OAAO,OAAO,UAMhC;IAEF,KAAK;CAGN"}
@@ -0,0 +1,42 @@
1
+ import { getGlobalSinks } from "./global-state.js";
2
+ export class EventLogger {
3
+ type = "events";
4
+ sinks = [];
5
+ queue = [];
6
+ errorQueue = [];
7
+ meta = {
8
+ identifier: "events",
9
+ };
10
+ initialize(meta) {
11
+ this.meta = meta;
12
+ getGlobalSinks().forEach((sink) => {
13
+ this.registerSink(sink);
14
+ });
15
+ }
16
+ registerSink(sink) {
17
+ this.sinks.push(sink);
18
+ this.queue.forEach((item) => {
19
+ sink.log(this.type, this.meta, item);
20
+ });
21
+ this.errorQueue.forEach((error) => {
22
+ sink.logInternalError(this.type, this.meta, error);
23
+ });
24
+ }
25
+ logEvent = (event) => {
26
+ this.sinks.forEach((sink) => {
27
+ sink.log(this.type, this.meta, event);
28
+ });
29
+ this.queue.push(event);
30
+ this.queue = this.queue.slice(-250);
31
+ };
32
+ logInternalError = (error) => {
33
+ this.sinks.forEach((sink) => {
34
+ sink.logInternalError(this.type, this.meta, error);
35
+ });
36
+ this.errorQueue.push(error);
37
+ this.errorQueue = this.errorQueue.slice(-50);
38
+ };
39
+ start() {
40
+ // Override in subclasses
41
+ }
42
+ }
@@ -0,0 +1,11 @@
1
+ import type { BaseEvent, EventLoggerMeta, EventLoggerType } from "./event-logger.js";
2
+ /**
3
+ * Base EventSink class used to register loggers and forward events to storage.
4
+ * The base sink does not implement any storage itself.
5
+ */
6
+ export declare class EventSink {
7
+ constructor();
8
+ log(_loggerType: EventLoggerType, _loggerMeta: EventLoggerMeta, _event: BaseEvent): void;
9
+ logInternalError: (loggerType: EventLoggerType, loggerMeta: EventLoggerMeta, error: unknown) => void;
10
+ }
11
+ //# sourceMappingURL=event-sink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-sink.d.ts","sourceRoot":"","sources":["../src/event-sink.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,qBAAa,SAAS;;IAYpB,GAAG,CACD,WAAW,EAAE,eAAe,EAC5B,WAAW,EAAE,eAAe,EAC5B,MAAM,EAAE,SAAS;IAKnB,gBAAgB,GACd,YAAY,eAAe,EAC3B,YAAY,eAAe,EAC3B,OAAO,OAAO,UAed;CACH"}
@@ -0,0 +1,32 @@
1
+ import { getGlobalLoggers, getGlobalSinks } from "./global-state.js";
2
+ import { toJSON } from "./to-json/to-json.js";
3
+ /**
4
+ * Base EventSink class used to register loggers and forward events to storage.
5
+ * The base sink does not implement any storage itself.
6
+ */
7
+ export class EventSink {
8
+ constructor() {
9
+ // Registering a sink will cause the logger to call methods on this sink. Timeout is
10
+ // necessary to allow the constructor to complete so those methods are available.
11
+ setTimeout(() => {
12
+ getGlobalSinks().add(this);
13
+ getGlobalLoggers().forEach((logger) => {
14
+ logger.registerSink(this);
15
+ });
16
+ }, 0);
17
+ }
18
+ log(_loggerType, _loggerMeta, _event) {
19
+ throw new Error("Method not implemented.");
20
+ }
21
+ logInternalError = (loggerType, loggerMeta, error) => {
22
+ if (error instanceof Error) {
23
+ this.log("events", { identifier: "__internal__" }, {
24
+ time: Date.now(),
25
+ type: "internal-error",
26
+ loggerType,
27
+ loggerMeta,
28
+ error: toJSON(error),
29
+ });
30
+ }
31
+ };
32
+ }
@@ -0,0 +1,14 @@
1
+ import type { EventLogger } from "./event-logger.js";
2
+ import type { EventSink } from "./event-sink.js";
3
+ type LoggerMap = Map<string, EventLogger>;
4
+ type SinkSet = Set<EventSink>;
5
+ export interface CaptureGlobalState {
6
+ browserClientInitialized?: boolean;
7
+ loggers?: LoggerMap;
8
+ sinks?: SinkSet;
9
+ }
10
+ export declare const getGlobalState: () => CaptureGlobalState;
11
+ export declare const getGlobalLoggers: () => LoggerMap;
12
+ export declare const getGlobalSinks: () => SinkSet;
13
+ export {};
14
+ //# sourceMappingURL=global-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-state.d.ts","sourceRoot":"","sources":["../src/global-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,KAAK,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAC1C,KAAK,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,cAAc,QAAO,kBASjC,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,SAQnC,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,OAQjC,CAAC"}
@@ -0,0 +1,28 @@
1
+ export const getGlobalState = () => {
2
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3
+ let state = window.__capture;
4
+ if (!state) {
5
+ state = {};
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ window.__capture = state;
8
+ }
9
+ return state;
10
+ };
11
+ export const getGlobalLoggers = () => {
12
+ const state = getGlobalState();
13
+ let loggers = state.loggers;
14
+ if (!loggers) {
15
+ loggers = new Map();
16
+ state.loggers = loggers;
17
+ }
18
+ return loggers;
19
+ };
20
+ export const getGlobalSinks = () => {
21
+ const state = getGlobalState();
22
+ let sinks = state.sinks;
23
+ if (!sinks) {
24
+ sinks = new Set();
25
+ state.sinks = sinks;
26
+ }
27
+ return sinks;
28
+ };
@@ -0,0 +1,20 @@
1
+ export { internalRegisterEventLogger } from "./register-logger.js";
2
+ export { ACTIVITY_LOGGER_IDENTIFIER } from "./register-logger.js";
3
+ export { STATE_LOGGER_SNAPSHOT_INTERVAL, type StatePatchEvent, type StateSnapshotEvent, type StateEvent, } from "./state-logger.js";
4
+ export type { EventLoggerType } from "./event-logger.js";
5
+ export * from "./event-sink.js";
6
+ export * from "./global-state.js";
7
+ export * from "./to-json/to-json.constants.js";
8
+ export * from "./to-json/serialized-types.js";
9
+ export * from "./to-json/serialize-error.js";
10
+ export * from "./to-json/to-json.js";
11
+ export * from "./snapshot-event-to-operation.js";
12
+ export { serializeClass } from "./to-json/serialize-class.js";
13
+ export { serializeDate } from "./to-json/serialize-date.js";
14
+ export { serializeError } from "./to-json/serialize-error.js";
15
+ export { serializeFunction } from "./to-json/serialize-function.js";
16
+ export { serializeMap } from "./to-json/serialize-map.js";
17
+ export { serializeObject } from "./to-json/serialize-object.js";
18
+ export { serializeRegex } from "./to-json/serialize-regex.js";
19
+ export { serializeSet } from "./to-json/serialize-set.js";
20
+ //# sourceMappingURL=index-internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-internal.d.ts","sourceRoot":"","sources":["../src/index-internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EACL,8BAA8B,EAC9B,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,UAAU,GAChB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,kCAAkC,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,18 @@
1
+ export { internalRegisterEventLogger } from "./register-logger.js";
2
+ export { ACTIVITY_LOGGER_IDENTIFIER } from "./register-logger.js";
3
+ export { STATE_LOGGER_SNAPSHOT_INTERVAL, } from "./state-logger.js";
4
+ export * from "./event-sink.js";
5
+ export * from "./global-state.js";
6
+ export * from "./to-json/to-json.constants.js";
7
+ export * from "./to-json/serialized-types.js";
8
+ export * from "./to-json/serialize-error.js";
9
+ export * from "./to-json/to-json.js";
10
+ export * from "./snapshot-event-to-operation.js";
11
+ export { serializeClass } from "./to-json/serialize-class.js";
12
+ export { serializeDate } from "./to-json/serialize-date.js";
13
+ export { serializeError } from "./to-json/serialize-error.js";
14
+ export { serializeFunction } from "./to-json/serialize-function.js";
15
+ export { serializeMap } from "./to-json/serialize-map.js";
16
+ export { serializeObject } from "./to-json/serialize-object.js";
17
+ export { serializeRegex } from "./to-json/serialize-regex.js";
18
+ export { serializeSet } from "./to-json/serialize-set.js";
@@ -0,0 +1,5 @@
1
+ export { EventLogger, type EventLoggerMeta, type BaseEvent, } from "./event-logger.js";
2
+ export { StateLogger } from "./state-logger.js";
3
+ export { registerEventLogger } from "./register-logger.js";
4
+ export * from "./register-state-logger.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,KAAK,eAAe,EACpB,KAAK,SAAS,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,cAAc,4BAA4B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { EventLogger, } from "./event-logger.js";
2
+ export { StateLogger } from "./state-logger.js";
3
+ export { registerEventLogger } from "./register-logger.js";
4
+ export * from "./register-state-logger.js";
@@ -0,0 +1,8 @@
1
+ import { EventLogger } from "./event-logger.js";
2
+ import type { BaseEvent, EventLoggerMeta } from "./event-logger.js";
3
+ export declare function internalRegisterEventLogger<TEvent extends BaseEvent>(meta: EventLoggerMeta): EventLogger<TEvent>;
4
+ export declare function internalRegisterEventLogger<TLogger extends EventLogger<any>>(meta: EventLoggerMeta, create: () => TLogger): TLogger;
5
+ export declare const ACTIVITY_LOGGER_IDENTIFIER = "activity";
6
+ export declare function registerEventLogger<TEvent extends BaseEvent>(meta: EventLoggerMeta): EventLogger<TEvent>;
7
+ export declare function registerEventLogger<TLogger extends EventLogger<any>>(meta: EventLoggerMeta, create: () => TLogger): TLogger;
8
+ //# sourceMappingURL=register-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-logger.d.ts","sourceRoot":"","sources":["../src/register-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpE,wBAAgB,2BAA2B,CAAC,MAAM,SAAS,SAAS,EAClE,IAAI,EAAE,eAAe,GACpB,WAAW,CAAC,MAAM,CAAC,CAAC;AAEvB,wBAAgB,2BAA2B,CAAC,OAAO,SAAS,WAAW,CAAC,GAAG,CAAC,EAC1E,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,MAAM,OAAO,GACpB,OAAO,CAAC;AAqBX,eAAO,MAAM,0BAA0B,aAAa,CAAC;AAErD,wBAAgB,mBAAmB,CAAC,MAAM,SAAS,SAAS,EAC1D,IAAI,EAAE,eAAe,GACpB,WAAW,CAAC,MAAM,CAAC,CAAC;AAEvB,wBAAgB,mBAAmB,CAAC,OAAO,SAAS,WAAW,CAAC,GAAG,CAAC,EAClE,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,MAAM,OAAO,GACpB,OAAO,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { EventLogger } from "./event-logger.js";
2
+ import { getGlobalLoggers } from "./global-state.js";
3
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
+ export function internalRegisterEventLogger(meta, create) {
5
+ const loggers = getGlobalLoggers();
6
+ let logger = loggers.get(meta.identifier);
7
+ if (!logger) {
8
+ logger = create ? create() : new EventLogger();
9
+ logger.initialize(meta);
10
+ logger.start();
11
+ loggers.set(meta.identifier, logger);
12
+ return logger;
13
+ }
14
+ return logger;
15
+ }
16
+ export const ACTIVITY_LOGGER_IDENTIFIER = "activity";
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ export function registerEventLogger(meta, create) {
19
+ if (meta.identifier === ACTIVITY_LOGGER_IDENTIFIER) {
20
+ throw new Error(`${meta.identifier} is a reserved identifier. Please use an alternative for this logger.`);
21
+ }
22
+ //@ts-expect-error -- overloads ensure correct types
23
+ return internalRegisterEventLogger(meta, create);
24
+ }
@@ -0,0 +1,5 @@
1
+ import { StateLogger } from "./state-logger.js";
2
+ import type { StateLoggerMeta } from "./state-logger.js";
3
+ export declare function registerStateLogger(meta: StateLoggerMeta): StateLogger;
4
+ export declare function registerStateLogger<TLogger extends StateLogger>(meta: StateLoggerMeta, create: () => TLogger): TLogger;
5
+ //# sourceMappingURL=register-state-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-state-logger.d.ts","sourceRoot":"","sources":["../src/register-state-logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,WAAW,CAAC;AACxE,wBAAgB,mBAAmB,CAAC,OAAO,SAAS,WAAW,EAC7D,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,MAAM,OAAO,GACpB,OAAO,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { internalRegisterEventLogger } from "./register-logger.js";
2
+ import { StateLogger } from "./state-logger.js";
3
+ export function registerStateLogger(meta, create) {
4
+ return internalRegisterEventLogger(meta, create || (() => new StateLogger()));
5
+ }
@@ -0,0 +1,5 @@
1
+ import type { StateSnapshotEvent } from "./state-logger.js";
2
+ import type { SerializedValue } from "./to-json/serialized-types.js";
3
+ import type { Operation } from "@capture.dev/fast-json-patch";
4
+ export declare function snapshotEventToOperation(snapshotEvent: StateSnapshotEvent): Operation<SerializedValue>;
5
+ //# sourceMappingURL=snapshot-event-to-operation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-event-to-operation.d.ts","sourceRoot":"","sources":["../src/snapshot-event-to-operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE9D,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,kBAAkB,GAChC,SAAS,CAAC,eAAe,CAAC,CAM5B"}
@@ -0,0 +1,7 @@
1
+ export function snapshotEventToOperation(snapshotEvent) {
2
+ return {
3
+ op: "replace",
4
+ path: "",
5
+ value: snapshotEvent.value,
6
+ };
7
+ }
@@ -0,0 +1,37 @@
1
+ import { type Operation } from "@capture.dev/fast-json-patch";
2
+ import { EventLogger } from "./event-logger.js";
3
+ import type { BaseEvent, EventLoggerMeta, EventLoggerType } from "./event-logger.js";
4
+ import type { SerializedValue } from "./to-json/serialized-types.js";
5
+ export declare const STATE_LOGGER_SNAPSHOT_INTERVAL: number;
6
+ export interface StateLoggerMeta extends EventLoggerMeta {
7
+ contextLabel?: string;
8
+ }
9
+ export interface StatePatchEvent extends BaseEvent {
10
+ id: string;
11
+ type: "patch";
12
+ label?: string;
13
+ ops: Operation<SerializedValue>[];
14
+ context?: SerializedValue;
15
+ }
16
+ export interface StateSnapshotEvent extends BaseEvent {
17
+ type: "snapshot";
18
+ value: SerializedValue;
19
+ }
20
+ export type StateEvent = StatePatchEvent | StateSnapshotEvent;
21
+ interface StateLoggerOpts<State = unknown> {
22
+ initialState?: State;
23
+ }
24
+ export declare class StateLogger extends EventLogger<StateEvent> {
25
+ type: EventLoggerType;
26
+ private previousState;
27
+ private idCounter;
28
+ private snapshotInterval;
29
+ meta: StateLoggerMeta;
30
+ constructor({ initialState }?: StateLoggerOpts);
31
+ start(): void;
32
+ stop(): void;
33
+ logState(state: unknown, label?: string, context?: unknown): void;
34
+ private logSnapshot;
35
+ }
36
+ export {};
37
+ //# sourceMappingURL=state-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-logger.d.ts","sourceRoot":"","sources":["../src/state-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE,eAAO,MAAM,8BAA8B,QAAY,CAAC;AAExD,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;IAClC,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACnD,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAE9D,UAAU,eAAe,CAAC,KAAK,GAAG,OAAO;IACvC,YAAY,CAAC,EAAE,KAAK,CAAC;CACtB;AAED,qBAAa,WAAY,SAAQ,WAAW,CAAC,UAAU,CAAC;IACtD,IAAI,EAAE,eAAe,CAAW;IAEhC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,gBAAgB,CAAuB;IAExC,IAAI,EAAE,eAAe,CAG1B;gBAEU,EAAE,YAAY,EAAE,GAAE,eAAoB;IAelD,KAAK;IAQL,IAAI;IAOJ,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;IAqC1D,OAAO,CAAC,WAAW;CAgBpB"}
@@ -0,0 +1,90 @@
1
+ import { compare } from "@capture.dev/fast-json-patch";
2
+ import { EventLogger } from "./event-logger.js";
3
+ import { toJSON } from "./to-json/to-json.js";
4
+ export const STATE_LOGGER_SNAPSHOT_INTERVAL = 1000 * 60; // 1 minute
5
+ export class StateLogger extends EventLogger {
6
+ type = "state";
7
+ previousState;
8
+ idCounter = 0;
9
+ snapshotInterval = null;
10
+ meta = {
11
+ identifier: "state",
12
+ name: "State",
13
+ };
14
+ constructor({ initialState } = {}) {
15
+ super();
16
+ if (initialState === undefined || initialState === null) {
17
+ this.previousState = null;
18
+ }
19
+ else if (typeof initialState !== "object") {
20
+ console.warn(`StateLogger can only log state of type "object", received "${initialState === null ? "null" : typeof initialState}"`);
21
+ this.previousState = null;
22
+ }
23
+ else {
24
+ this.previousState = initialState;
25
+ this.logSnapshot(initialState);
26
+ }
27
+ }
28
+ start() {
29
+ this.snapshotInterval = window.setInterval(() => {
30
+ if (this.previousState !== null) {
31
+ this.logSnapshot(this.previousState);
32
+ }
33
+ }, STATE_LOGGER_SNAPSHOT_INTERVAL);
34
+ }
35
+ stop() {
36
+ if (this.snapshotInterval) {
37
+ clearInterval(this.snapshotInterval);
38
+ this.snapshotInterval = null;
39
+ }
40
+ }
41
+ logState(state, label, context) {
42
+ if (typeof state !== "object" || state === null) {
43
+ console.warn(`StateLogger can only log state of type "object", received "${state === null ? "null" : typeof state}"`);
44
+ return;
45
+ }
46
+ try {
47
+ let ops = [];
48
+ if (this.previousState === null) {
49
+ this.logSnapshot(state);
50
+ }
51
+ else {
52
+ ops = toJSON(compare(this.previousState, state), {
53
+ onError: this.logInternalError,
54
+ });
55
+ }
56
+ const serializedContext = context !== undefined
57
+ ? toJSON(context, {
58
+ onError: this.logInternalError,
59
+ maxDepth: 10,
60
+ })
61
+ : undefined;
62
+ this.logEvent({
63
+ id: `${this.idCounter++}`,
64
+ time: Date.now(),
65
+ type: "patch",
66
+ ops,
67
+ label,
68
+ context: serializedContext,
69
+ });
70
+ this.previousState = state;
71
+ }
72
+ catch (error) {
73
+ this.logInternalError(error);
74
+ }
75
+ }
76
+ logSnapshot(state) {
77
+ if (typeof state !== "object" || state === null) {
78
+ console.warn(`StateLogger can only log state of type "object", received "${state === null ? "null" : typeof state}"`);
79
+ return;
80
+ }
81
+ this.logEvent({
82
+ time: Date.now(),
83
+ type: "snapshot",
84
+ value: toJSON(state, {
85
+ onError: this.logInternalError,
86
+ }),
87
+ });
88
+ this.previousState = state;
89
+ }
90
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=serialize-class.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize-class.test.d.ts","sourceRoot":"","sources":["../../../src/to-json/__tests__/serialize-class.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,79 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { isClass, serializeClass } from "../serialize-class.js";
3
+ describe("isClass", () => {
4
+ it("returns true for a class", () => {
5
+ class MyClass {
6
+ }
7
+ expect(isClass(MyClass)).toBe(true);
8
+ });
9
+ it("returns false for a regular function", () => {
10
+ function myFunc() { }
11
+ expect(isClass(myFunc)).toBe(false);
12
+ });
13
+ it("returns false for an arrow function", () => {
14
+ const arrow = () => { };
15
+ expect(isClass(arrow)).toBe(false);
16
+ });
17
+ it("returns false for a method", () => {
18
+ const obj = { method() { } };
19
+ expect(isClass(obj.method)).toBe(false);
20
+ });
21
+ it("returns true for an anonymous class", () => {
22
+ const AnonymousClass = class {
23
+ };
24
+ expect(isClass(AnonymousClass)).toBe(true);
25
+ });
26
+ it("returns true for a class with extends", () => {
27
+ class Parent {
28
+ }
29
+ class Child extends Parent {
30
+ }
31
+ expect(isClass(Child)).toBe(true);
32
+ });
33
+ it("returns false for native functions", () => {
34
+ expect(isClass(Array.isArray)).toBe(false);
35
+ });
36
+ });
37
+ describe("serializeClass", () => {
38
+ it("serializes a named class", () => {
39
+ class MyClass {
40
+ }
41
+ const result = serializeClass(MyClass);
42
+ expect(result).toEqual({
43
+ __CAPTURE_TYPE__: "classConstructor",
44
+ name: "MyClass",
45
+ });
46
+ });
47
+ it("serializes an anonymous class as (anonymous)", () => {
48
+ const AnonymousClass = class {
49
+ };
50
+ Object.defineProperty(AnonymousClass, "name", { value: "" });
51
+ const result = serializeClass(AnonymousClass);
52
+ expect(result).toEqual({
53
+ __CAPTURE_TYPE__: "classConstructor",
54
+ name: "(anonymous)",
55
+ });
56
+ });
57
+ it("serializes a class with inheritance", () => {
58
+ class Animal {
59
+ }
60
+ class Dog extends Animal {
61
+ }
62
+ const result = serializeClass(Dog);
63
+ expect(result).toEqual({
64
+ __CAPTURE_TYPE__: "classConstructor",
65
+ name: "Dog",
66
+ });
67
+ });
68
+ it("serializes a class with properties", () => {
69
+ class User {
70
+ name = "test";
71
+ age = 25;
72
+ }
73
+ const result = serializeClass(User);
74
+ expect(result).toEqual({
75
+ __CAPTURE_TYPE__: "classConstructor",
76
+ name: "User",
77
+ });
78
+ });
79
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=serialize-date.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize-date.test.d.ts","sourceRoot":"","sources":["../../../src/to-json/__tests__/serialize-date.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { serializeDate } from "../serialize-date.js";
3
+ describe("serializeDate", () => {
4
+ it("serializes a valid date to a timestamp", () => {
5
+ const date = new Date("2024-01-15T12:00:00.000Z");
6
+ const result = serializeDate(date);
7
+ expect(result).toEqual({
8
+ __CAPTURE_TYPE__: "date",
9
+ value: 1705320000000,
10
+ });
11
+ });
12
+ it("serializes an invalid date to null", () => {
13
+ const date = new Date("invalid-date-string");
14
+ const result = serializeDate(date);
15
+ expect(result).toEqual({
16
+ __CAPTURE_TYPE__: "date",
17
+ value: null,
18
+ });
19
+ });
20
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=serialize-error.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize-error.test.d.ts","sourceRoot":"","sources":["../../../src/to-json/__tests__/serialize-error.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,71 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { serializeError } from "../serialize-error.js";
3
+ describe("serializeError", () => {
4
+ it("serializes a basic error with name and message", () => {
5
+ const error = new Error("Something went wrong");
6
+ const result = serializeError(error);
7
+ expect(result).toEqual({
8
+ __CAPTURE_TYPE__: "error",
9
+ error: {
10
+ name: "Error",
11
+ message: "Something went wrong",
12
+ stack: expect.any(String),
13
+ },
14
+ });
15
+ });
16
+ it("serializes a TypeError", () => {
17
+ const error = new TypeError("Cannot read property 'foo' of undefined");
18
+ const result = serializeError(error);
19
+ expect(result.__CAPTURE_TYPE__).toBe("error");
20
+ expect(result.error.name).toBe("TypeError");
21
+ expect(result.error.message).toBe("Cannot read property 'foo' of undefined");
22
+ });
23
+ it("serializes a custom error class", () => {
24
+ class CustomError extends Error {
25
+ constructor(message) {
26
+ super(message);
27
+ this.name = "CustomError";
28
+ }
29
+ }
30
+ const error = new CustomError("Custom error message");
31
+ const result = serializeError(error);
32
+ expect(result.error.name).toBe("CustomError");
33
+ expect(result.error.message).toBe("Custom error message");
34
+ });
35
+ it("includes stack trace when present", () => {
36
+ const error = new Error("With stack");
37
+ const result = serializeError(error);
38
+ expect(result.error.stack).toBeDefined();
39
+ expect(result.error.stack).toContain("Error: With stack");
40
+ });
41
+ it("handles error without stack trace", () => {
42
+ const error = new Error("No stack");
43
+ error.stack = undefined;
44
+ const result = serializeError(error);
45
+ expect(result.error.stack).toBeUndefined();
46
+ });
47
+ it("serializes error with Error cause", () => {
48
+ const cause = new Error("Root cause");
49
+ const error = new Error("Wrapper error", { cause });
50
+ const result = serializeError(error);
51
+ expect(result.error.cause).toEqual({
52
+ name: "Error",
53
+ message: "Root cause",
54
+ stack: expect.any(String),
55
+ });
56
+ });
57
+ it("serializes nested error causes", () => {
58
+ const rootCause = new Error("Root");
59
+ const middleCause = new Error("Middle", { cause: rootCause });
60
+ const error = new Error("Top", { cause: middleCause });
61
+ const result = serializeError(error);
62
+ expect(result.error.message).toBe("Top");
63
+ expect(result.error.cause?.message).toBe("Middle");
64
+ expect(result.error.cause?.cause?.message).toBe("Root");
65
+ });
66
+ it("handles non-Error cause by setting null", () => {
67
+ const error = new Error("With string cause", { cause: "string cause" });
68
+ const result = serializeError(error);
69
+ expect(result.error.cause).toBeNull();
70
+ });
71
+ });