node-avo-inspector 1.2.0-alpha.1 → 2.0.0-beta.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 (105) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +268 -4
  3. package/package.json +17 -1
  4. package/.claude/scheduled_tasks.lock +0 -1
  5. package/.claude/settings.local.json +0 -11
  6. package/.claude/worktrees/release-1.1.1/LICENSE +0 -21
  7. package/.claude/worktrees/release-1.1.1/README.md +0 -69
  8. package/.claude/worktrees/release-1.1.1/examples/node-inspector-js/index.js +0 -30
  9. package/.claude/worktrees/release-1.1.1/examples/node-inspector-js/package.json +0 -15
  10. package/.claude/worktrees/release-1.1.1/examples/node-inspector-js/yarn.lock +0 -6
  11. package/.claude/worktrees/release-1.1.1/examples/node-inspector-ts/dist/index.js +0 -34
  12. package/.claude/worktrees/release-1.1.1/examples/node-inspector-ts/index.ts +0 -30
  13. package/.claude/worktrees/release-1.1.1/examples/node-inspector-ts/package.json +0 -18
  14. package/.claude/worktrees/release-1.1.1/examples/node-inspector-ts/tsconfig.json +0 -15
  15. package/.claude/worktrees/release-1.1.1/examples/node-inspector-ts/yarn.lock +0 -11
  16. package/.claude/worktrees/release-1.1.1/package-lock.json +0 -4039
  17. package/.claude/worktrees/release-1.1.1/package.json +0 -48
  18. package/.claude/worktrees/release-1.1.1/reason/AvoInspector.rei +0 -11
  19. package/.claude/worktrees/release-1.1.1/reason/NodeAvoInspector.re +0 -27
  20. package/.claude/worktrees/release-1.1.1/src/AvoDeduplicator.ts +0 -146
  21. package/.claude/worktrees/release-1.1.1/src/AvoEncryption.ts +0 -90
  22. package/.claude/worktrees/release-1.1.1/src/AvoGuid.ts +0 -9
  23. package/.claude/worktrees/release-1.1.1/src/AvoInspector.ts +0 -383
  24. package/.claude/worktrees/release-1.1.1/src/AvoInspectorEnv.ts +0 -8
  25. package/.claude/worktrees/release-1.1.1/src/AvoNetworkCallsHandler.ts +0 -267
  26. package/.claude/worktrees/release-1.1.1/src/AvoSchemaParser.ts +0 -115
  27. package/.claude/worktrees/release-1.1.1/src/AvoStreamId.ts +0 -16
  28. package/.claude/worktrees/release-1.1.1/src/__tests__/TestAvoEncryption.ts +0 -515
  29. package/.claude/worktrees/release-1.1.1/src/__tests__/TestAvoEventSpecCache.ts +0 -242
  30. package/.claude/worktrees/release-1.1.1/src/__tests__/TestAvoEventSpecFetcher.ts +0 -241
  31. package/.claude/worktrees/release-1.1.1/src/__tests__/TestAvoInspector.ts +0 -360
  32. package/.claude/worktrees/release-1.1.1/src/__tests__/TestAvoStreamId.ts +0 -72
  33. package/.claude/worktrees/release-1.1.1/src/__tests__/TestDeduplicator.ts +0 -191
  34. package/.claude/worktrees/release-1.1.1/src/__tests__/TestEventValidator.ts +0 -231
  35. package/.claude/worktrees/release-1.1.1/src/__tests__/TestNetworkCallsHandler.ts +0 -179
  36. package/.claude/worktrees/release-1.1.1/src/__tests__/TestNetworkCallsHandlerPublic.ts +0 -208
  37. package/.claude/worktrees/release-1.1.1/src/__tests__/TestParsing.ts +0 -153
  38. package/.claude/worktrees/release-1.1.1/src/__tests__/constants.ts +0 -63
  39. package/.claude/worktrees/release-1.1.1/src/eventSpec/AvoEventSpecCache.ts +0 -109
  40. package/.claude/worktrees/release-1.1.1/src/eventSpec/AvoEventSpecFetchTypes.ts +0 -47
  41. package/.claude/worktrees/release-1.1.1/src/eventSpec/AvoEventSpecFetcher.ts +0 -106
  42. package/.claude/worktrees/release-1.1.1/src/eventSpec/EventValidator.ts +0 -74
  43. package/.claude/worktrees/release-1.1.1/src/index.ts +0 -2
  44. package/.claude/worktrees/release-1.1.1/src/utils.ts +0 -49
  45. package/.claude/worktrees/release-1.1.1/tsconfig.json +0 -13
  46. package/.claude/worktrees/release-1.1.1/yarn.lock +0 -2310
  47. package/.github/workflows/claude.yml +0 -55
  48. package/dist/__tests__/TestAvoEncryption.d.ts +0 -1
  49. package/dist/__tests__/TestAvoEncryption.js +0 -288
  50. package/dist/__tests__/TestAvoEventSpecCache.d.ts +0 -1
  51. package/dist/__tests__/TestAvoEventSpecCache.js +0 -194
  52. package/dist/__tests__/TestAvoEventSpecFetcher.d.ts +0 -1
  53. package/dist/__tests__/TestAvoEventSpecFetcher.js +0 -219
  54. package/dist/__tests__/TestAvoInspector.d.ts +0 -1
  55. package/dist/__tests__/TestAvoInspector.js +0 -291
  56. package/dist/__tests__/TestAvoStreamId.d.ts +0 -1
  57. package/dist/__tests__/TestAvoStreamId.js +0 -55
  58. package/dist/__tests__/TestDeduplicator.d.ts +0 -1
  59. package/dist/__tests__/TestDeduplicator.js +0 -102
  60. package/dist/__tests__/TestEventValidator.d.ts +0 -1
  61. package/dist/__tests__/TestEventValidator.js +0 -196
  62. package/dist/__tests__/TestNetworkCallsHandler.d.ts +0 -1
  63. package/dist/__tests__/TestNetworkCallsHandler.js +0 -86
  64. package/dist/__tests__/TestNetworkCallsHandlerPublic.d.ts +0 -1
  65. package/dist/__tests__/TestNetworkCallsHandlerPublic.js +0 -160
  66. package/dist/__tests__/TestParsing.d.ts +0 -1
  67. package/dist/__tests__/TestParsing.js +0 -128
  68. package/dist/__tests__/constants.d.ts +0 -42
  69. package/dist/__tests__/constants.js +0 -53
  70. package/examples/node-inspector-js/index.js +0 -30
  71. package/examples/node-inspector-js/package.json +0 -15
  72. package/examples/node-inspector-js/yarn.lock +0 -6
  73. package/examples/node-inspector-ts/dist/index.js +0 -34
  74. package/examples/node-inspector-ts/index.ts +0 -30
  75. package/examples/node-inspector-ts/package.json +0 -18
  76. package/examples/node-inspector-ts/tsconfig.json +0 -15
  77. package/examples/node-inspector-ts/yarn.lock +0 -11
  78. package/reason/AvoInspector.rei +0 -11
  79. package/reason/NodeAvoInspector.re +0 -27
  80. package/src/AvoDeduplicator.ts +0 -150
  81. package/src/AvoEncryption.ts +0 -90
  82. package/src/AvoGuid.ts +0 -9
  83. package/src/AvoInspector.ts +0 -498
  84. package/src/AvoInspectorEnv.ts +0 -8
  85. package/src/AvoNetworkCallsHandler.ts +0 -340
  86. package/src/AvoSchemaParser.ts +0 -115
  87. package/src/AvoStreamId.ts +0 -16
  88. package/src/__tests__/TestAvoEncryption.ts +0 -515
  89. package/src/__tests__/TestAvoEventSpecCache.ts +0 -242
  90. package/src/__tests__/TestAvoEventSpecFetcher.ts +0 -279
  91. package/src/__tests__/TestAvoInspector.ts +0 -376
  92. package/src/__tests__/TestAvoStreamId.ts +0 -72
  93. package/src/__tests__/TestDeduplicator.ts +0 -191
  94. package/src/__tests__/TestEventValidator.ts +0 -231
  95. package/src/__tests__/TestNetworkCallsHandler.ts +0 -181
  96. package/src/__tests__/TestNetworkCallsHandlerPublic.ts +0 -208
  97. package/src/__tests__/TestParsing.ts +0 -153
  98. package/src/__tests__/constants.ts +0 -63
  99. package/src/eventSpec/AvoEventSpecCache.ts +0 -119
  100. package/src/eventSpec/AvoEventSpecFetchTypes.ts +0 -47
  101. package/src/eventSpec/AvoEventSpecFetcher.ts +0 -186
  102. package/src/eventSpec/EventValidator.ts +0 -74
  103. package/src/index.ts +0 -2
  104. package/src/utils.ts +0 -49
  105. package/tsconfig.json +0 -13
@@ -1,219 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const AvoEventSpecFetcher_1 = require("../eventSpec/AvoEventSpecFetcher");
4
- const https = require("https");
5
- const events_1 = require("events");
6
- jest.mock("https");
7
- const mockedHttps = https;
8
- class MockIncomingMessage extends events_1.EventEmitter {
9
- constructor(statusCode) {
10
- super();
11
- this.statusCode = statusCode;
12
- }
13
- }
14
- class MockClientRequest extends events_1.EventEmitter {
15
- constructor() {
16
- super(...arguments);
17
- this.end = jest.fn();
18
- this.destroy = jest.fn();
19
- this.setTimeout = jest.fn();
20
- }
21
- }
22
- /** Build a wire-format response body matching the /trackingPlan/eventSpec API */
23
- function wireResponse(eventName, properties, metadata) {
24
- const p = {};
25
- for (const [name, constraint] of Object.entries(properties)) {
26
- p[name] = { t: constraint.t, r: true };
27
- }
28
- return {
29
- events: [{ b: metadata.branchId, id: "evt1", vids: [], p }],
30
- metadata,
31
- };
32
- }
33
- function setupMockRequest(responseStatusCode, responseBody) {
34
- const mockReq = new MockClientRequest();
35
- const mockRes = new MockIncomingMessage(responseStatusCode);
36
- mockedHttps.request.mockImplementation((_options, callback) => {
37
- callback(mockRes);
38
- const data = JSON.stringify(responseBody);
39
- mockRes.emit("data", Buffer.from(data));
40
- mockRes.emit("end");
41
- return mockReq;
42
- });
43
- return mockReq;
44
- }
45
- function setupMockRequestError() {
46
- const mockReq = new MockClientRequest();
47
- mockedHttps.request.mockImplementation((_options, _callback) => {
48
- process.nextTick(() => mockReq.emit("error", new Error("network failure")));
49
- return mockReq;
50
- });
51
- return mockReq;
52
- }
53
- describe("AvoEventSpecFetcher", () => {
54
- let fetcher;
55
- beforeEach(() => {
56
- jest.clearAllMocks();
57
- fetcher = new AvoEventSpecFetcher_1.AvoEventSpecFetcher("test-api-key");
58
- });
59
- afterEach(() => {
60
- fetcher.destroy();
61
- });
62
- test("fetches event spec via HTTPS GET", (done) => {
63
- const metadata = { schemaId: "s1", branchId: "b1", latestActionId: "a1", sourceId: "src1" };
64
- const wire = wireResponse("click", { target: { t: "string" } }, metadata);
65
- const expectedParsed = {
66
- eventSpec: {
67
- eventName: "click",
68
- properties: [{ propertyName: "target", propertyType: "string" }],
69
- },
70
- metadata,
71
- };
72
- setupMockRequest(200, wire);
73
- fetcher.fetch("click", "stream1", (result) => {
74
- expect(result).toEqual(expectedParsed);
75
- expect(mockedHttps.request).toHaveBeenCalledTimes(1);
76
- const callArgs = mockedHttps.request.mock.calls[0][0];
77
- expect(callArgs.method).toBe("GET");
78
- expect(callArgs.hostname).toBe("api.avo.app");
79
- done();
80
- });
81
- });
82
- test("in-flight dedup: exactly ONE https.request for concurrent same-key events", (done) => {
83
- const metadata = { schemaId: "s1", branchId: "b1", latestActionId: "a1", sourceId: "src1" };
84
- const wire = wireResponse("purchase", {}, metadata);
85
- const expectedParsed = {
86
- eventSpec: { eventName: "purchase", properties: [] },
87
- metadata,
88
- };
89
- // Delay the response so both calls are in-flight
90
- const mockReq = new MockClientRequest();
91
- const mockRes = new MockIncomingMessage(200);
92
- mockedHttps.request.mockImplementation((_options, callback) => {
93
- // Defer the response
94
- setTimeout(() => {
95
- callback(mockRes);
96
- const data = JSON.stringify(wire);
97
- mockRes.emit("data", Buffer.from(data));
98
- mockRes.emit("end");
99
- }, 10);
100
- return mockReq;
101
- });
102
- let callCount = 0;
103
- const checkDone = (result) => {
104
- callCount++;
105
- expect(result).toEqual(expectedParsed);
106
- if (callCount === 2) {
107
- // Only ONE actual https.request
108
- expect(mockedHttps.request).toHaveBeenCalledTimes(1);
109
- done();
110
- }
111
- };
112
- fetcher.fetch("purchase", "stream1", checkDone);
113
- fetcher.fetch("purchase", "stream1", checkDone);
114
- });
115
- test("in-flight failure: all queued callbacks resolved with null", (done) => {
116
- setupMockRequestError();
117
- let callCount = 0;
118
- const checkDone = (result) => {
119
- callCount++;
120
- expect(result).toBeNull();
121
- if (callCount === 2) {
122
- expect(mockedHttps.request).toHaveBeenCalledTimes(1);
123
- done();
124
- }
125
- };
126
- fetcher.fetch("fail-event", "stream1", checkDone);
127
- fetcher.fetch("fail-event", "stream1", checkDone);
128
- });
129
- test("non-200 status code resolves callback with null", (done) => {
130
- setupMockRequest(500, { error: "Internal Server Error" });
131
- fetcher.fetch("click", "stream1", (result) => {
132
- expect(result).toBeNull();
133
- expect(mockedHttps.request).toHaveBeenCalledTimes(1);
134
- done();
135
- });
136
- });
137
- test("malformed JSON body resolves callback with null", (done) => {
138
- const mockReq = new MockClientRequest();
139
- const mockRes = new MockIncomingMessage(200);
140
- mockedHttps.request.mockImplementation((_options, callback) => {
141
- callback(mockRes);
142
- mockRes.emit("data", Buffer.from("not valid json {{{"));
143
- mockRes.emit("end");
144
- return mockReq;
145
- });
146
- fetcher.fetch("click", "stream1", (result) => {
147
- expect(result).toBeNull();
148
- expect(mockedHttps.request).toHaveBeenCalledTimes(1);
149
- done();
150
- });
151
- });
152
- test("timeout resolves callback with null", (done) => {
153
- const mockReq = new MockClientRequest();
154
- mockedHttps.request.mockImplementation((_options, _callback) => {
155
- // Simulate timeout: never call the response callback,
156
- // instead emit "timeout" on next tick
157
- process.nextTick(() => mockReq.emit("timeout"));
158
- return mockReq;
159
- });
160
- fetcher.fetch("click", "stream1", (result) => {
161
- expect(result).toBeNull();
162
- expect(mockReq.destroy).toHaveBeenCalled();
163
- expect(mockedHttps.request).toHaveBeenCalledTimes(1);
164
- done();
165
- });
166
- });
167
- test("separate keys make separate requests", (done) => {
168
- const metadata = { schemaId: "s1", branchId: "b1", latestActionId: "a1", sourceId: "src1" };
169
- const wire = wireResponse("click", {}, metadata);
170
- const expectedParsed = {
171
- eventSpec: { eventName: "click", properties: [] },
172
- metadata,
173
- };
174
- setupMockRequest(200, wire);
175
- let callCount = 0;
176
- const checkDone = () => {
177
- callCount++;
178
- if (callCount === 2) {
179
- expect(mockedHttps.request).toHaveBeenCalledTimes(2);
180
- done();
181
- }
182
- };
183
- fetcher.fetch("click", "stream1", (result) => {
184
- expect(result).toEqual(expectedParsed);
185
- checkDone();
186
- });
187
- fetcher.fetch("purchase", "stream1", (result) => {
188
- // Both resolve with the same mock but that's fine for this test
189
- checkDone();
190
- });
191
- });
192
- test("parseWireResponse transforms wire format correctly", () => {
193
- const wire = {
194
- events: [{
195
- b: "main",
196
- id: "evt1",
197
- vids: [],
198
- p: {
199
- "Cli Action": { t: "string", r: true, v: { '["Status","Pull"]': ["evt1"] } },
200
- "Client": { t: "string", r: true },
201
- },
202
- }],
203
- metadata: { schemaId: "s1", branchId: "main", latestActionId: "a1", sourceId: "src1" },
204
- };
205
- const result = AvoEventSpecFetcher_1.AvoEventSpecFetcher.parseWireResponse(wire, "Cli Invoked");
206
- expect(result.metadata).toEqual({ schemaId: "s1", branchId: "main", latestActionId: "a1", sourceId: "src1" });
207
- expect(result.eventSpec).not.toBeNull();
208
- expect(result.eventSpec.eventName).toBe("Cli Invoked");
209
- expect(result.eventSpec.properties).toEqual([
210
- { propertyName: "Cli Action", propertyType: "string" },
211
- { propertyName: "Client", propertyType: "string" },
212
- ]);
213
- });
214
- test("parseWireResponse returns null eventSpec for empty events array", () => {
215
- const wire = { events: [], metadata: { schemaId: "s1", branchId: "b1", latestActionId: "a1", sourceId: "src1" } };
216
- const result = AvoEventSpecFetcher_1.AvoEventSpecFetcher.parseWireResponse(wire, "test");
217
- expect(result.eventSpec).toBeNull();
218
- });
219
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,291 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const AvoInspector_1 = require("../AvoInspector");
4
- const AvoInspectorEnv_1 = require("../AvoInspectorEnv");
5
- const constants_1 = require("./constants");
6
- const AvoNetworkCallsHandler_1 = require("../AvoNetworkCallsHandler");
7
- jest.mock("../AvoNetworkCallsHandler");
8
- describe("Initialization", () => {
9
- test("Network Handler is initialized on Inspector init", () => {
10
- const inspectorVersion = process.env.npm_package_version || "";
11
- const { apiKey, env, version, appName } = constants_1.defaultOptions;
12
- let inspector = new AvoInspector_1.AvoInspector(constants_1.defaultOptions);
13
- inspector.enableLogging(true);
14
- expect(AvoNetworkCallsHandler_1.AvoNetworkCallsHandler).toHaveBeenCalledTimes(1);
15
- expect(AvoNetworkCallsHandler_1.AvoNetworkCallsHandler).toHaveBeenCalledWith(apiKey, env, "my-test-app", version, inspectorVersion, undefined);
16
- });
17
- test("Api Key is set", () => {
18
- // Given
19
- const apiKey = "api-key-xxx";
20
- // When
21
- let inspector = new AvoInspector_1.AvoInspector({
22
- env: AvoInspectorEnv_1.AvoInspectorEnv.Prod,
23
- version: "0",
24
- apiKey,
25
- });
26
- // Then
27
- expect(inspector.apiKey).toBe(apiKey);
28
- });
29
- test("Error is thrown when Api Key is not set", () => {
30
- // Given
31
- // @ts-ignore
32
- let apiKey;
33
- // Then
34
- expect(() => {
35
- new AvoInspector_1.AvoInspector({
36
- env: AvoInspectorEnv_1.AvoInspectorEnv.Prod,
37
- version: "0",
38
- // @ts-ignore
39
- apiKey,
40
- });
41
- }).toThrow(constants_1.error.API_KEY);
42
- });
43
- test("Error is thrown when whitespace Api Key is used", () => {
44
- // Given
45
- const apiKey = " ";
46
- // Then
47
- expect(() => {
48
- new AvoInspector_1.AvoInspector({
49
- env: AvoInspectorEnv_1.AvoInspectorEnv.Prod,
50
- version: "0",
51
- apiKey,
52
- });
53
- }).toThrow(constants_1.error.API_KEY);
54
- });
55
- test("Error is thrown when empty string Api Key is used", () => {
56
- expect(() => {
57
- new AvoInspector_1.AvoInspector({
58
- env: AvoInspectorEnv_1.AvoInspectorEnv.Prod,
59
- version: "0",
60
- apiKey: "",
61
- });
62
- }).toThrow(constants_1.error.API_KEY);
63
- });
64
- test("Error is thrown when Api Key is set to null", () => {
65
- // Given
66
- const apiKey = null;
67
- // Then
68
- expect(() => {
69
- new AvoInspector_1.AvoInspector({
70
- env: AvoInspectorEnv_1.AvoInspectorEnv.Prod,
71
- version: "0",
72
- // @ts-ignore
73
- apiKey,
74
- });
75
- }).toThrow(constants_1.error.API_KEY);
76
- });
77
- test("Dev environment is used when env is not provided", () => {
78
- // Given
79
- // @ts-ignore
80
- let env;
81
- // When
82
- let inspector = new AvoInspector_1.AvoInspector({
83
- apiKey: "api-key-xxx",
84
- version: "0",
85
- // @ts-ignore
86
- env,
87
- });
88
- // Then
89
- expect(inspector.environment).toBe(AvoInspectorEnv_1.AvoInspectorEnv.Dev);
90
- });
91
- test("Dev environment is used when empty string is used", () => {
92
- // Given
93
- const env = "";
94
- // When
95
- let inspector = new AvoInspector_1.AvoInspector({
96
- apiKey: "api-key-xxx",
97
- version: "0",
98
- // @ts-ignore
99
- env,
100
- });
101
- // Then
102
- expect(inspector.environment).toBe(AvoInspectorEnv_1.AvoInspectorEnv.Dev);
103
- });
104
- test("Dev env is set using AvoInspectorEnv", () => {
105
- // When
106
- let inspector = new AvoInspector_1.AvoInspector({
107
- apiKey: "api-key-xxx",
108
- env: AvoInspectorEnv_1.AvoInspectorEnv.Dev,
109
- version: "0",
110
- });
111
- // Then
112
- expect(inspector.environment).toBe(AvoInspectorEnv_1.AvoInspectorEnv.Dev);
113
- });
114
- test("Dev environment is set using string", () => {
115
- // When
116
- let inspector = new AvoInspector_1.AvoInspector({
117
- apiKey: "api-key-xxx",
118
- env: "dev",
119
- version: "0",
120
- });
121
- // Then
122
- expect(inspector.environment).toBe(AvoInspectorEnv_1.AvoInspectorEnv.Dev);
123
- });
124
- test("Staging env is set using AvoInspectorEnv", () => {
125
- // When
126
- let inspector = new AvoInspector_1.AvoInspector({
127
- apiKey: "api-key-xxx",
128
- env: AvoInspectorEnv_1.AvoInspectorEnv.Staging,
129
- version: "0",
130
- });
131
- // Then
132
- expect(inspector.environment).toBe(AvoInspectorEnv_1.AvoInspectorEnv.Staging);
133
- });
134
- test("Staging environment is set using string", () => {
135
- // When
136
- let inspector = new AvoInspector_1.AvoInspector({
137
- apiKey: "api-key-xxx",
138
- env: "staging",
139
- version: "0",
140
- });
141
- // Then
142
- expect(inspector.environment).toBe(AvoInspectorEnv_1.AvoInspectorEnv.Staging);
143
- });
144
- test("Prod env is set using AvoInspectorEnv", () => {
145
- // When
146
- let inspector = new AvoInspector_1.AvoInspector({
147
- apiKey: "api-key-xxx",
148
- env: AvoInspectorEnv_1.AvoInspectorEnv.Prod,
149
- version: "0",
150
- });
151
- // Then
152
- expect(inspector.environment).toBe(AvoInspectorEnv_1.AvoInspectorEnv.Prod);
153
- });
154
- test("Prod environment is set using string", () => {
155
- // When
156
- let inspector = new AvoInspector_1.AvoInspector({
157
- apiKey: "api-key-xxx",
158
- env: "prod",
159
- version: "0",
160
- });
161
- // Then
162
- expect(inspector.environment).toBe(AvoInspectorEnv_1.AvoInspectorEnv.Prod);
163
- });
164
- test("Environment other than Dev, Staging, Prod falls back to Dev", () => {
165
- // When
166
- const env = "test";
167
- let inspector = new AvoInspector_1.AvoInspector({
168
- apiKey: "api-key-xxx",
169
- version: "0",
170
- // @ts-ignore
171
- env,
172
- });
173
- // Then
174
- expect(inspector.environment).toBe(AvoInspectorEnv_1.AvoInspectorEnv.Dev);
175
- });
176
- test("Version is set", () => {
177
- const version = "1";
178
- // When
179
- let inspector = new AvoInspector_1.AvoInspector({
180
- apiKey: "api-key-xxx",
181
- env: AvoInspectorEnv_1.AvoInspectorEnv.Prod,
182
- version,
183
- });
184
- // Then
185
- expect(inspector.version).toBe(version);
186
- });
187
- test("Error is thrown when version is not set", () => {
188
- // Given
189
- // @ts-ignore
190
- let version;
191
- // Then
192
- expect(() => {
193
- new AvoInspector_1.AvoInspector({
194
- apiKey: "api-key-xxx",
195
- env: AvoInspectorEnv_1.AvoInspectorEnv.Prod,
196
- // @ts-ignore
197
- version,
198
- });
199
- }).toThrow(constants_1.error.VERSION);
200
- });
201
- test("Error is thrown when version is set to empty string", () => {
202
- // Given
203
- const version = " ";
204
- // Then
205
- expect(() => {
206
- new AvoInspector_1.AvoInspector({
207
- apiKey: "api-key-xxx",
208
- env: AvoInspectorEnv_1.AvoInspectorEnv.Prod,
209
- version,
210
- });
211
- }).toThrow(constants_1.error.VERSION);
212
- });
213
- test("Error is thrown when version is set to null", () => {
214
- // Given
215
- const version = null;
216
- // Then
217
- expect(() => {
218
- new AvoInspector_1.AvoInspector({
219
- apiKey: "api-key-xxx",
220
- env: AvoInspectorEnv_1.AvoInspectorEnv.Prod,
221
- // @ts-ignore
222
- version,
223
- });
224
- }).toThrow(constants_1.error.VERSION);
225
- });
226
- test("publicEncryptionKey is forwarded to AvoNetworkCallsHandler when provided", () => {
227
- const inspectorVersion = process.env.npm_package_version || "";
228
- AvoNetworkCallsHandler_1.AvoNetworkCallsHandler.mockClear();
229
- let inspector = new AvoInspector_1.AvoInspector({
230
- apiKey: "api-key-xxx",
231
- env: AvoInspectorEnv_1.AvoInspectorEnv.Dev,
232
- version: "1",
233
- publicEncryptionKey: "my-public-key-123",
234
- });
235
- expect(AvoNetworkCallsHandler_1.AvoNetworkCallsHandler).toHaveBeenCalledWith("api-key-xxx", AvoInspectorEnv_1.AvoInspectorEnv.Dev, "", "1", inspectorVersion, "my-public-key-123");
236
- });
237
- test("publicEncryptionKey is forwarded as undefined to AvoNetworkCallsHandler when not provided", () => {
238
- const inspectorVersion = process.env.npm_package_version || "";
239
- AvoNetworkCallsHandler_1.AvoNetworkCallsHandler.mockClear();
240
- let inspector = new AvoInspector_1.AvoInspector({
241
- apiKey: "api-key-xxx",
242
- env: AvoInspectorEnv_1.AvoInspectorEnv.Dev,
243
- version: "1",
244
- });
245
- expect(AvoNetworkCallsHandler_1.AvoNetworkCallsHandler).toHaveBeenCalledWith("api-key-xxx", AvoInspectorEnv_1.AvoInspectorEnv.Dev, "", "1", inspectorVersion, undefined);
246
- });
247
- test("warns when publicEncryptionKey is malformed in dev/staging", () => {
248
- const consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation(() => { });
249
- new AvoInspector_1.AvoInspector({
250
- apiKey: "api-key-xxx",
251
- env: AvoInspectorEnv_1.AvoInspectorEnv.Dev,
252
- version: "1",
253
- publicEncryptionKey: "not-valid-hex",
254
- });
255
- expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining("publicEncryptionKey does not look like a valid"));
256
- consoleWarnSpy.mockRestore();
257
- });
258
- test("does not warn when publicEncryptionKey is a valid 130-char uncompressed hex key in dev/staging", () => {
259
- const consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation(() => { });
260
- const validKey = "04" + "ab".repeat(64); // 2 + 128 = 130 hex chars
261
- new AvoInspector_1.AvoInspector({
262
- apiKey: "api-key-xxx",
263
- env: AvoInspectorEnv_1.AvoInspectorEnv.Dev,
264
- version: "1",
265
- publicEncryptionKey: validKey,
266
- });
267
- expect(consoleWarnSpy).not.toHaveBeenCalled();
268
- consoleWarnSpy.mockRestore();
269
- });
270
- test("does not warn when publicEncryptionKey is a valid 66-char compressed hex key in dev/staging", () => {
271
- const consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation(() => { });
272
- const validKey = "02" + "4e".repeat(32); // 2 + 64 = 66 hex chars
273
- new AvoInspector_1.AvoInspector({
274
- apiKey: "api-key-xxx",
275
- env: AvoInspectorEnv_1.AvoInspectorEnv.Dev,
276
- version: "1",
277
- publicEncryptionKey: validKey,
278
- });
279
- expect(consoleWarnSpy).not.toHaveBeenCalled();
280
- consoleWarnSpy.mockRestore();
281
- });
282
- test("constructor works without publicEncryptionKey (backwards compatible)", () => {
283
- expect(() => {
284
- new AvoInspector_1.AvoInspector({
285
- apiKey: "api-key-xxx",
286
- env: AvoInspectorEnv_1.AvoInspectorEnv.Dev,
287
- version: "1",
288
- });
289
- }).not.toThrow();
290
- });
291
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,55 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const AvoStreamId_1 = require("../AvoStreamId");
4
- describe("AvoStreamId", () => {
5
- let consoleWarnSpy;
6
- beforeEach(() => {
7
- consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation(() => { });
8
- });
9
- afterEach(() => {
10
- jest.restoreAllMocks();
11
- });
12
- test("streamId getter returns empty string by default", () => {
13
- const avoStreamId = new AvoStreamId_1.AvoStreamId();
14
- expect(avoStreamId.streamId).toBe("");
15
- });
16
- test("streamId getter returns the value passed to constructor", () => {
17
- const avoStreamId = new AvoStreamId_1.AvoStreamId("my-stream-id");
18
- expect(avoStreamId.streamId).toBe("my-stream-id");
19
- });
20
- test("streamId containing ':' logs a warning", () => {
21
- const avoStreamId = new AvoStreamId_1.AvoStreamId("invalid:stream:id");
22
- const id = avoStreamId.streamId;
23
- expect(consoleWarnSpy).toHaveBeenCalledWith("[Avo Inspector] Warning: streamId contains ':' which is not supported");
24
- expect(id).toBe("invalid:stream:id");
25
- });
26
- test("streamId without ':' does not log a warning", () => {
27
- const avoStreamId = new AvoStreamId_1.AvoStreamId("valid-stream-id");
28
- const id = avoStreamId.streamId;
29
- expect(consoleWarnSpy).not.toHaveBeenCalled();
30
- expect(id).toBe("valid-stream-id");
31
- });
32
- test("empty streamId does not log a warning", () => {
33
- const avoStreamId = new AvoStreamId_1.AvoStreamId("");
34
- const id = avoStreamId.streamId;
35
- expect(consoleWarnSpy).not.toHaveBeenCalled();
36
- expect(id).toBe("");
37
- });
38
- test("explicit undefined arg returns empty string and does not warn", () => {
39
- const avoStreamId = new AvoStreamId_1.AvoStreamId(undefined);
40
- const id = avoStreamId.streamId;
41
- expect(consoleWarnSpy).not.toHaveBeenCalled();
42
- expect(id).toBe("");
43
- });
44
- test("warning is only logged once per instance, not on every .streamId access", () => {
45
- const avoStreamId = new AvoStreamId_1.AvoStreamId("bad:id");
46
- // The warning is logged in the constructor, so it's already been called once
47
- expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
48
- // Access streamId multiple times
49
- avoStreamId.streamId;
50
- avoStreamId.streamId;
51
- avoStreamId.streamId;
52
- // Should still be only one warning total
53
- expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
54
- });
55
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,102 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- const AvoDeduplicator_1 = require("../AvoDeduplicator");
13
- const utils_1 = require("../utils");
14
- const AvoInspector_1 = require("../AvoInspector");
15
- const constants_1 = require("./constants");
16
- jest
17
- .useFakeTimers()
18
- .setSystemTime(new Date('2020-01-01'));
19
- describe("Deduplicator", () => {
20
- const deduplicator = new AvoDeduplicator_1.AvoDeduplicator();
21
- const testObject = {
22
- "0": "some string",
23
- "1": [1, 2, 3],
24
- 2: [["str", true]],
25
- 3: { avo: [1.1, 2.2, 3.3] },
26
- };
27
- test(`AvoDeduplicator.deepEqual tests`, () => {
28
- const secondObject = {
29
- "0": "some string",
30
- "1": [1, 2, 3],
31
- 2: [["str", true]],
32
- 3: { avo: [1.1, 2.2, 3.3] },
33
- };
34
- expect((0, utils_1.deepEquals)(testObject, secondObject)).toBe(true);
35
- expect((0, utils_1.deepEquals)(testObject, Object.assign(Object.assign({}, secondObject), { "4": "4" }))).toBe(false);
36
- expect((0, utils_1.deepEquals)(testObject, Object.assign(Object.assign({}, secondObject), { 3: Object.assign(Object.assign({}, secondObject[3]), { avo: [1.1] }) }))).toBe(false);
37
- expect((0, utils_1.deepEquals)(testObject, Object.assign(Object.assign({}, secondObject), { 0: "other string" }))).toBe(false);
38
- });
39
- test(`Detects duplications when track in avo and then manually`, () => {
40
- const shouldRegisterFromAvo = deduplicator.shouldRegisterEvent("Test", testObject, true);
41
- const shouldRegisterManual = deduplicator.shouldRegisterEvent("Test", testObject, false);
42
- expect(shouldRegisterFromAvo).toBe(true);
43
- expect(shouldRegisterManual).toBe(false);
44
- });
45
- test(`Detects duplications when track manually and then in avo`, () => {
46
- const shouldRegisterManual = deduplicator.shouldRegisterEvent("Test", testObject, false);
47
- const shouldRegisterFromAvo = deduplicator.shouldRegisterEvent("Test", testObject, true);
48
- expect(shouldRegisterManual).toBe(true);
49
- expect(shouldRegisterFromAvo).toBe(false);
50
- });
51
- test(`Inspector deduplicates only one event when track manually, in avo and then manually again`, () => __awaiter(void 0, void 0, void 0, function* () {
52
- const inspector = new AvoInspector_1.AvoInspector(constants_1.defaultOptions);
53
- inspector.enableLogging(false);
54
- const manuallyTrackedSchema = yield inspector.trackSchemaFromEvent("test", testObject);
55
- // @ts-ignore
56
- const avoTrackedSchema = yield inspector._avoFunctionTrackSchemaFromEvent("test", testObject, "eventId", "eventhash");
57
- const manuallyTrackedSchemaAgain = yield inspector.trackSchemaFromEvent("test", testObject);
58
- expect(manuallyTrackedSchema.length).toBe(4);
59
- expect(manuallyTrackedSchema.length + avoTrackedSchema.length + manuallyTrackedSchemaAgain.length).toBe(8);
60
- }));
61
- test(`Inspector deduplicates only one event when track in avo, manually and then in avo again`, () => __awaiter(void 0, void 0, void 0, function* () {
62
- const inspector = new AvoInspector_1.AvoInspector(constants_1.defaultOptions);
63
- inspector.enableLogging(false);
64
- // @ts-ignore
65
- const avoTrackedSchema = yield inspector._avoFunctionTrackSchemaFromEvent("test", testObject, "eventId", "eventhash");
66
- const manuallyTrackedSchema = yield inspector.trackSchemaFromEvent("test", testObject);
67
- // @ts-ignore
68
- const avoTrackedSchemaAgain = yield inspector._avoFunctionTrackSchemaFromEvent("test", testObject, "eventId", "eventhash");
69
- expect(avoTrackedSchema.length).toBe(4);
70
- expect(manuallyTrackedSchema.length).toBe(0);
71
- expect(avoTrackedSchemaAgain.length).toBe(4);
72
- }));
73
- test(`Allows two same manual events in a row`, () => __awaiter(void 0, void 0, void 0, function* () {
74
- const inspector = new AvoInspector_1.AvoInspector(constants_1.defaultOptions);
75
- inspector.enableLogging(false);
76
- const manuallyTrackedSchema = yield inspector.trackSchemaFromEvent("test", testObject);
77
- const manuallyTrackedSchemaAgain = yield inspector.trackSchemaFromEvent("test", testObject);
78
- expect(manuallyTrackedSchema.length).toBe(4);
79
- expect(manuallyTrackedSchemaAgain.length).toBe(4);
80
- }));
81
- test(`Allows two same avo events in a row`, () => __awaiter(void 0, void 0, void 0, function* () {
82
- const inspector = new AvoInspector_1.AvoInspector(constants_1.defaultOptions);
83
- inspector.enableLogging(false);
84
- // @ts-ignore
85
- const avoTrackedSchema = yield inspector._avoFunctionTrackSchemaFromEvent("test", testObject, "eventId", "eventhash");
86
- // @ts-ignore
87
- const avoTrackedSchemaAgain = yield inspector._avoFunctionTrackSchemaFromEvent("test", testObject, "eventId", "eventhash");
88
- expect(avoTrackedSchema.length).toBe(4);
89
- expect(avoTrackedSchemaAgain.length).toBe(4);
90
- }));
91
- test(`Does not deduplicate if more than 500ms pass`, () => {
92
- const shouldRegisterFromAvo = deduplicator.shouldRegisterEvent("Test", testObject, true);
93
- const now = new Date();
94
- const dateNowSpy = jest
95
- .spyOn(Date, "now")
96
- .mockImplementation(() => now.setMilliseconds(now.getMilliseconds() + 501));
97
- const shouldRegisterManual = deduplicator.shouldRegisterEvent("Test", testObject, false);
98
- expect(shouldRegisterFromAvo).toBe(true);
99
- expect(shouldRegisterManual).toBe(true);
100
- dateNowSpy.mockRestore();
101
- });
102
- });
@@ -1 +0,0 @@
1
- export {};