@zapier/zapier-sdk 0.33.0 → 0.33.2

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 (128) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.cjs +2 -1
  3. package/dist/index.d.mts +9 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.mjs +2 -1
  7. package/dist/plugins/registry/index.d.ts.map +1 -1
  8. package/dist/plugins/registry/index.js +1 -0
  9. package/dist/types/sdk.d.ts +8 -0
  10. package/dist/types/sdk.d.ts.map +1 -1
  11. package/package.json +2 -2
  12. package/dist/api/auth.test.d.ts +0 -2
  13. package/dist/api/auth.test.d.ts.map +0 -1
  14. package/dist/api/auth.test.js +0 -220
  15. package/dist/api/client.test.d.ts +0 -2
  16. package/dist/api/client.test.d.ts.map +0 -1
  17. package/dist/api/client.test.js +0 -611
  18. package/dist/api/debug.test.d.ts +0 -2
  19. package/dist/api/debug.test.d.ts.map +0 -1
  20. package/dist/api/debug.test.js +0 -59
  21. package/dist/api/polling.test.d.ts +0 -2
  22. package/dist/api/polling.test.d.ts.map +0 -1
  23. package/dist/api/polling.test.js +0 -360
  24. package/dist/auth.test.d.ts +0 -2
  25. package/dist/auth.test.d.ts.map +0 -1
  26. package/dist/auth.test.js +0 -480
  27. package/dist/plugins/eventEmission/builders.test.d.ts +0 -2
  28. package/dist/plugins/eventEmission/builders.test.d.ts.map +0 -1
  29. package/dist/plugins/eventEmission/builders.test.js +0 -138
  30. package/dist/plugins/eventEmission/index.test.d.ts +0 -5
  31. package/dist/plugins/eventEmission/index.test.d.ts.map +0 -1
  32. package/dist/plugins/eventEmission/index.test.js +0 -712
  33. package/dist/plugins/eventEmission/transport.test.d.ts +0 -5
  34. package/dist/plugins/eventEmission/transport.test.d.ts.map +0 -1
  35. package/dist/plugins/eventEmission/transport.test.js +0 -164
  36. package/dist/plugins/fetch/index.test.d.ts +0 -2
  37. package/dist/plugins/fetch/index.test.d.ts.map +0 -1
  38. package/dist/plugins/fetch/index.test.js +0 -428
  39. package/dist/plugins/findFirstConnection/index.test.d.ts +0 -2
  40. package/dist/plugins/findFirstConnection/index.test.d.ts.map +0 -1
  41. package/dist/plugins/findFirstConnection/index.test.js +0 -177
  42. package/dist/plugins/findUniqueConnection/index.test.d.ts +0 -2
  43. package/dist/plugins/findUniqueConnection/index.test.d.ts.map +0 -1
  44. package/dist/plugins/findUniqueConnection/index.test.js +0 -159
  45. package/dist/plugins/getAction/index.test.d.ts +0 -2
  46. package/dist/plugins/getAction/index.test.d.ts.map +0 -1
  47. package/dist/plugins/getAction/index.test.js +0 -211
  48. package/dist/plugins/getApp/index.test.d.ts +0 -2
  49. package/dist/plugins/getApp/index.test.d.ts.map +0 -1
  50. package/dist/plugins/getApp/index.test.js +0 -157
  51. package/dist/plugins/getConnection/index.test.d.ts +0 -2
  52. package/dist/plugins/getConnection/index.test.d.ts.map +0 -1
  53. package/dist/plugins/getConnection/index.test.js +0 -124
  54. package/dist/plugins/getInputFieldsSchema/index.test.d.ts +0 -2
  55. package/dist/plugins/getInputFieldsSchema/index.test.d.ts.map +0 -1
  56. package/dist/plugins/getInputFieldsSchema/index.test.js +0 -291
  57. package/dist/plugins/listActions/index.test.d.ts +0 -2
  58. package/dist/plugins/listActions/index.test.d.ts.map +0 -1
  59. package/dist/plugins/listActions/index.test.js +0 -454
  60. package/dist/plugins/listApps/index.test.d.ts +0 -2
  61. package/dist/plugins/listApps/index.test.d.ts.map +0 -1
  62. package/dist/plugins/listApps/index.test.js +0 -124
  63. package/dist/plugins/listConnections/index.test.d.ts +0 -2
  64. package/dist/plugins/listConnections/index.test.d.ts.map +0 -1
  65. package/dist/plugins/listConnections/index.test.js +0 -920
  66. package/dist/plugins/listInputFieldChoices/index.test.d.ts +0 -2
  67. package/dist/plugins/listInputFieldChoices/index.test.d.ts.map +0 -1
  68. package/dist/plugins/listInputFieldChoices/index.test.js +0 -717
  69. package/dist/plugins/listInputFields/index.test.d.ts +0 -2
  70. package/dist/plugins/listInputFields/index.test.d.ts.map +0 -1
  71. package/dist/plugins/listInputFields/index.test.js +0 -359
  72. package/dist/plugins/manifest/index.test.d.ts +0 -2
  73. package/dist/plugins/manifest/index.test.d.ts.map +0 -1
  74. package/dist/plugins/manifest/index.test.js +0 -1179
  75. package/dist/plugins/request/index.test.d.ts +0 -2
  76. package/dist/plugins/request/index.test.d.ts.map +0 -1
  77. package/dist/plugins/request/index.test.js +0 -458
  78. package/dist/plugins/runAction/index.test.d.ts +0 -2
  79. package/dist/plugins/runAction/index.test.d.ts.map +0 -1
  80. package/dist/plugins/runAction/index.test.js +0 -350
  81. package/dist/resolvers/connectionId.test.d.ts +0 -2
  82. package/dist/resolvers/connectionId.test.d.ts.map +0 -1
  83. package/dist/resolvers/connectionId.test.js +0 -61
  84. package/dist/sdk.test.d.ts +0 -2
  85. package/dist/sdk.test.d.ts.map +0 -1
  86. package/dist/sdk.test.js +0 -260
  87. package/dist/types/domain.test.d.ts +0 -2
  88. package/dist/types/domain.test.d.ts.map +0 -1
  89. package/dist/types/domain.test.js +0 -39
  90. package/dist/utils/array-utils.test.d.ts +0 -2
  91. package/dist/utils/array-utils.test.d.ts.map +0 -1
  92. package/dist/utils/array-utils.test.js +0 -107
  93. package/dist/utils/batch-utils.test.d.ts +0 -2
  94. package/dist/utils/batch-utils.test.d.ts.map +0 -1
  95. package/dist/utils/batch-utils.test.js +0 -476
  96. package/dist/utils/domain-utils.test.d.ts +0 -2
  97. package/dist/utils/domain-utils.test.d.ts.map +0 -1
  98. package/dist/utils/domain-utils.test.js +0 -346
  99. package/dist/utils/file-utils.test.d.ts +0 -2
  100. package/dist/utils/file-utils.test.d.ts.map +0 -1
  101. package/dist/utils/file-utils.test.js +0 -51
  102. package/dist/utils/function-utils.test.d.ts +0 -2
  103. package/dist/utils/function-utils.test.d.ts.map +0 -1
  104. package/dist/utils/function-utils.test.js +0 -188
  105. package/dist/utils/id-utils.test.d.ts +0 -2
  106. package/dist/utils/id-utils.test.d.ts.map +0 -1
  107. package/dist/utils/id-utils.test.js +0 -22
  108. package/dist/utils/pagination-utils.test.d.ts +0 -17
  109. package/dist/utils/pagination-utils.test.d.ts.map +0 -1
  110. package/dist/utils/pagination-utils.test.js +0 -461
  111. package/dist/utils/retry-utils.test.d.ts +0 -2
  112. package/dist/utils/retry-utils.test.d.ts.map +0 -1
  113. package/dist/utils/retry-utils.test.js +0 -90
  114. package/dist/utils/string-utils.test.d.ts +0 -2
  115. package/dist/utils/string-utils.test.d.ts.map +0 -1
  116. package/dist/utils/string-utils.test.js +0 -59
  117. package/dist/utils/telemetry-context.test.d.ts +0 -2
  118. package/dist/utils/telemetry-context.test.d.ts.map +0 -1
  119. package/dist/utils/telemetry-context.test.js +0 -154
  120. package/dist/utils/telemetry-utils.test.d.ts +0 -2
  121. package/dist/utils/telemetry-utils.test.d.ts.map +0 -1
  122. package/dist/utils/telemetry-utils.test.js +0 -155
  123. package/dist/utils/url-utils.test.d.ts +0 -2
  124. package/dist/utils/url-utils.test.d.ts.map +0 -1
  125. package/dist/utils/url-utils.test.js +0 -103
  126. package/dist/utils/validation.test.d.ts +0 -2
  127. package/dist/utils/validation.test.d.ts.map +0 -1
  128. package/dist/utils/validation.test.js +0 -44
package/dist/auth.test.js DELETED
@@ -1,480 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
- import * as auth from "./auth";
3
- import { resetDeprecationWarnings } from "./utils/logging";
4
- // Mock both CLI login import paths (SDK tries @zapier/zapier-sdk-cli/login
5
- // first, then falls back to @zapier/zapier-sdk-cli-login)
6
- const mockGetToken = vi.fn();
7
- vi.mock("@zapier/zapier-sdk-cli/login", () => ({
8
- getToken: mockGetToken,
9
- }));
10
- vi.mock("@zapier/zapier-sdk-cli-login", () => ({
11
- getToken: mockGetToken,
12
- }));
13
- // Mock fetch for client credentials tests
14
- const mockFetch = vi.fn();
15
- describe("auth", () => {
16
- beforeEach(() => {
17
- vi.clearAllMocks();
18
- auth.clearTokenCache();
19
- resetDeprecationWarnings();
20
- // Clear all ZAPIER_* env vars
21
- delete process.env.ZAPIER_CREDENTIALS;
22
- delete process.env.ZAPIER_CREDENTIALS_CLIENT_ID;
23
- delete process.env.ZAPIER_CREDENTIALS_CLIENT_SECRET;
24
- delete process.env.ZAPIER_CREDENTIALS_BASE_URL;
25
- delete process.env.ZAPIER_TOKEN;
26
- delete process.env.ZAPIER_AUTH_CLIENT_ID;
27
- delete process.env.ZAPIER_AUTH_BASE_URL;
28
- });
29
- afterEach(() => {
30
- auth.clearTokenCache();
31
- });
32
- describe("getTokenFromCliLogin", () => {
33
- it("should pass options to CLI login package getToken", async () => {
34
- mockGetToken.mockResolvedValue("cli-token");
35
- const options = {
36
- baseUrl: "https://api.custom.zapier.com",
37
- onEvent: vi.fn(),
38
- fetch: vi.fn(),
39
- };
40
- const result = await auth.getTokenFromCliLogin(options);
41
- expect(result).toBe("cli-token");
42
- expect(mockGetToken).toHaveBeenCalled();
43
- });
44
- it("should propagate errors from CLI login package getToken", async () => {
45
- mockGetToken.mockRejectedValue(new Error("Token refresh failed"));
46
- await expect(auth.getTokenFromCliLogin({})).rejects.toThrow("Token refresh failed");
47
- });
48
- it("should set isCliLoginAvailable to true when import succeeds", async () => {
49
- mockGetToken.mockResolvedValue("cli-token");
50
- await auth.getTokenFromCliLogin({});
51
- expect(auth.isCliLoginAvailable()).toBe(true);
52
- });
53
- });
54
- describe("resolveAuthToken", () => {
55
- it("should return string credentials directly", async () => {
56
- const result = await auth.resolveAuthToken({
57
- credentials: "my-token",
58
- });
59
- expect(result).toBe("my-token");
60
- });
61
- it("should use deprecated token option with warning", async () => {
62
- const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
63
- const result = await auth.resolveAuthToken({
64
- token: "deprecated-token",
65
- });
66
- expect(result).toBe("deprecated-token");
67
- expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("deprecated"));
68
- warnSpy.mockRestore();
69
- });
70
- it("should resolve credentials from env var (string token)", async () => {
71
- // Set env var and re-import to pick up the new value
72
- process.env.ZAPIER_CREDENTIALS = "env-token";
73
- vi.resetModules();
74
- const freshAuth = await import("./auth");
75
- const result = await freshAuth.resolveAuthToken({});
76
- expect(result).toBe("env-token");
77
- });
78
- it("should resolve credentials from ZAPIER_TOKEN with deprecation warning", async () => {
79
- // Set env var and re-import to pick up the new value
80
- process.env.ZAPIER_TOKEN = "legacy-token";
81
- vi.resetModules();
82
- const freshAuth = await import("./auth");
83
- const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
84
- const result = await freshAuth.resolveAuthToken({});
85
- expect(result).toBe("legacy-token");
86
- expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("ZAPIER_TOKEN is deprecated"));
87
- warnSpy.mockRestore();
88
- });
89
- it("should fall back to CLI login when no credentials provided", async () => {
90
- mockGetToken.mockResolvedValue("cli-stored-token");
91
- const result = await auth.resolveAuthToken({});
92
- expect(result).toBe("cli-stored-token");
93
- expect(mockGetToken).toHaveBeenCalled();
94
- });
95
- it("should return undefined when no credentials found", async () => {
96
- mockGetToken.mockResolvedValue(undefined);
97
- const result = await auth.resolveAuthToken({});
98
- expect(result).toBeUndefined();
99
- });
100
- it("should call credentials function and use result", async () => {
101
- const credentialsFn = vi.fn().mockResolvedValue("dynamic-token");
102
- const result = await auth.resolveAuthToken({
103
- credentials: credentialsFn,
104
- });
105
- expect(result).toBe("dynamic-token");
106
- expect(credentialsFn).toHaveBeenCalled();
107
- });
108
- it("should throw if credentials function returns another function", async () => {
109
- const credentialsFn = vi.fn().mockResolvedValue(() => "nested");
110
- await expect(auth.resolveAuthToken({
111
- credentials: credentialsFn,
112
- })).rejects.toThrow("Credentials function returned another function");
113
- });
114
- });
115
- describe("client credentials flow", () => {
116
- it("should exchange client credentials for token with scope and audience", async () => {
117
- mockFetch.mockResolvedValue({
118
- ok: true,
119
- json: () => Promise.resolve({
120
- access_token: "exchanged-token",
121
- expires_in: 3600,
122
- }),
123
- });
124
- const result = await auth.resolveAuthToken({
125
- credentials: {
126
- type: "client_credentials",
127
- clientId: "test-client-id",
128
- clientSecret: "test-client-secret",
129
- },
130
- fetch: mockFetch,
131
- });
132
- expect(result).toBe("exchanged-token");
133
- expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining("/oauth/token/"), expect.objectContaining({
134
- method: "POST",
135
- body: expect.any(URLSearchParams),
136
- }));
137
- // Verify the body includes required parameters
138
- const callArgs = mockFetch.mock.calls[0];
139
- const body = callArgs[1].body;
140
- expect(body.get("grant_type")).toBe("client_credentials");
141
- expect(body.get("client_id")).toBe("test-client-id");
142
- expect(body.get("client_secret")).toBe("test-client-secret");
143
- expect(body.get("scope")).toBe("external");
144
- expect(body.get("audience")).toBe("zapier.com");
145
- });
146
- it("should cache token from client credentials exchange", async () => {
147
- mockFetch.mockResolvedValue({
148
- ok: true,
149
- json: () => Promise.resolve({
150
- access_token: "cached-token",
151
- expires_in: 3600,
152
- }),
153
- });
154
- // First call - should exchange
155
- const result1 = await auth.resolveAuthToken({
156
- credentials: {
157
- type: "client_credentials",
158
- clientId: "cache-test-client",
159
- clientSecret: "secret",
160
- },
161
- fetch: mockFetch,
162
- });
163
- // Second call - should use cache
164
- const result2 = await auth.resolveAuthToken({
165
- credentials: {
166
- type: "client_credentials",
167
- clientId: "cache-test-client",
168
- clientSecret: "secret",
169
- },
170
- fetch: mockFetch,
171
- });
172
- expect(result1).toBe("cached-token");
173
- expect(result2).toBe("cached-token");
174
- expect(mockFetch).toHaveBeenCalledTimes(1); // Only called once due to cache
175
- });
176
- it("should deduplicate concurrent client credentials exchanges", async () => {
177
- let resolveExchange;
178
- const exchangePromise = new Promise((resolve) => {
179
- resolveExchange = resolve;
180
- });
181
- mockFetch.mockReturnValue(exchangePromise);
182
- // Start two concurrent requests - they will both start executing
183
- const promise1 = auth.resolveAuthToken({
184
- credentials: {
185
- type: "client_credentials",
186
- clientId: "concurrent-test-client",
187
- clientSecret: "secret",
188
- },
189
- fetch: mockFetch,
190
- });
191
- const promise2 = auth.resolveAuthToken({
192
- credentials: {
193
- type: "client_credentials",
194
- clientId: "concurrent-test-client",
195
- clientSecret: "secret",
196
- },
197
- fetch: mockFetch,
198
- });
199
- // Let microtasks run so both promises start
200
- await new Promise((r) => setTimeout(r, 0));
201
- // Now resolve the exchange
202
- resolveExchange({
203
- ok: true,
204
- json: () => Promise.resolve({
205
- access_token: "concurrent-token",
206
- expires_in: 3600,
207
- }),
208
- });
209
- const [result1, result2] = await Promise.all([promise1, promise2]);
210
- expect(result1).toBe("concurrent-token");
211
- expect(result2).toBe("concurrent-token");
212
- expect(mockFetch).toHaveBeenCalledTimes(1); // Only one exchange despite two concurrent calls
213
- });
214
- it("should throw on client credentials exchange failure", async () => {
215
- mockFetch.mockResolvedValue({
216
- ok: false,
217
- status: 401,
218
- statusText: "Unauthorized",
219
- text: () => Promise.resolve("Invalid credentials"),
220
- });
221
- await expect(auth.resolveAuthToken({
222
- credentials: {
223
- type: "client_credentials",
224
- clientId: "bad-client",
225
- clientSecret: "bad-secret",
226
- },
227
- fetch: mockFetch,
228
- })).rejects.toThrow("Client credentials exchange failed");
229
- });
230
- it("should merge requiredScopes with credentials scope", async () => {
231
- mockFetch.mockResolvedValue({
232
- ok: true,
233
- json: () => Promise.resolve({
234
- access_token: "merged-scope-token",
235
- expires_in: 3600,
236
- }),
237
- });
238
- await auth.resolveAuthToken({
239
- credentials: {
240
- type: "client_credentials",
241
- clientId: "scope-test-client",
242
- clientSecret: "secret",
243
- scope: "external",
244
- },
245
- requiredScopes: ["credentials"],
246
- fetch: mockFetch,
247
- });
248
- const callArgs = mockFetch.mock.calls[0];
249
- const body = callArgs[1].body;
250
- // Scopes should be merged and sorted alphabetically
251
- expect(body.get("scope")).toBe("credentials external");
252
- });
253
- it("should always include external scope with requiredScopes", async () => {
254
- mockFetch.mockResolvedValue({
255
- ok: true,
256
- json: () => Promise.resolve({
257
- access_token: "required-scope-token",
258
- expires_in: 3600,
259
- }),
260
- });
261
- await auth.resolveAuthToken({
262
- credentials: {
263
- type: "client_credentials",
264
- clientId: "required-scope-client",
265
- clientSecret: "secret",
266
- },
267
- requiredScopes: ["credentials"],
268
- fetch: mockFetch,
269
- });
270
- const callArgs = mockFetch.mock.calls[0];
271
- const body = callArgs[1].body;
272
- // Should include both external (always present) and credentials (required)
273
- expect(body.get("scope")).toBe("credentials external");
274
- });
275
- it("should cache tokens separately for different scope combinations", async () => {
276
- mockFetch.mockResolvedValue({
277
- ok: true,
278
- json: () => Promise.resolve({
279
- access_token: "first-scope-token",
280
- expires_in: 3600,
281
- }),
282
- });
283
- // First call with no requiredScopes
284
- const result1 = await auth.resolveAuthToken({
285
- credentials: {
286
- type: "client_credentials",
287
- clientId: "scope-cache-client",
288
- clientSecret: "secret",
289
- },
290
- fetch: mockFetch,
291
- });
292
- expect(result1).toBe("first-scope-token");
293
- expect(mockFetch).toHaveBeenCalledTimes(1);
294
- // Second call with different requiredScopes - should NOT use cache
295
- mockFetch.mockResolvedValue({
296
- ok: true,
297
- json: () => Promise.resolve({
298
- access_token: "second-scope-token",
299
- expires_in: 3600,
300
- }),
301
- });
302
- const result2 = await auth.resolveAuthToken({
303
- credentials: {
304
- type: "client_credentials",
305
- clientId: "scope-cache-client",
306
- clientSecret: "secret",
307
- },
308
- requiredScopes: ["credentials"],
309
- fetch: mockFetch,
310
- });
311
- expect(result2).toBe("second-scope-token");
312
- expect(mockFetch).toHaveBeenCalledTimes(2); // Should have made a new request
313
- // Third call with same requiredScopes as second - should use cache
314
- const result3 = await auth.resolveAuthToken({
315
- credentials: {
316
- type: "client_credentials",
317
- clientId: "scope-cache-client",
318
- clientSecret: "secret",
319
- },
320
- requiredScopes: ["credentials"],
321
- fetch: mockFetch,
322
- });
323
- expect(result3).toBe("second-scope-token");
324
- expect(mockFetch).toHaveBeenCalledTimes(2); // No new request
325
- });
326
- });
327
- describe("PKCE credentials", () => {
328
- it("should delegate PKCE credentials to CLI login", async () => {
329
- mockGetToken.mockResolvedValue("pkce-stored-token");
330
- const result = await auth.resolveAuthToken({
331
- credentials: {
332
- type: "pkce",
333
- clientId: "pkce-client",
334
- },
335
- });
336
- expect(result).toBe("pkce-stored-token");
337
- expect(mockGetToken).toHaveBeenCalled();
338
- });
339
- it("should throw when PKCE credentials have no stored token", async () => {
340
- mockGetToken.mockResolvedValue(undefined);
341
- await expect(auth.resolveAuthToken({
342
- credentials: {
343
- type: "pkce",
344
- clientId: "pkce-client",
345
- },
346
- })).rejects.toThrow("PKCE credentials require interactive login");
347
- });
348
- });
349
- describe("token cache management", () => {
350
- it("should invalidate cached token", async () => {
351
- mockFetch.mockResolvedValue({
352
- ok: true,
353
- json: () => Promise.resolve({
354
- access_token: "will-be-invalidated",
355
- expires_in: 3600,
356
- }),
357
- });
358
- // First call - cache the token
359
- await auth.resolveAuthToken({
360
- credentials: {
361
- type: "client_credentials",
362
- clientId: "invalidate-test",
363
- clientSecret: "secret",
364
- },
365
- fetch: mockFetch,
366
- });
367
- expect(mockFetch).toHaveBeenCalledTimes(1);
368
- // Invalidate the cache (default scope is "external")
369
- auth.invalidateCachedToken("invalidate-test", ["external"]);
370
- // Next call should fetch again
371
- mockFetch.mockResolvedValue({
372
- ok: true,
373
- json: () => Promise.resolve({
374
- access_token: "new-token-after-invalidation",
375
- expires_in: 3600,
376
- }),
377
- });
378
- const result = await auth.resolveAuthToken({
379
- credentials: {
380
- type: "client_credentials",
381
- clientId: "invalidate-test",
382
- clientSecret: "secret",
383
- },
384
- fetch: mockFetch,
385
- });
386
- expect(result).toBe("new-token-after-invalidation");
387
- expect(mockFetch).toHaveBeenCalledTimes(2);
388
- });
389
- it("should clear all cached tokens", async () => {
390
- mockFetch.mockResolvedValue({
391
- ok: true,
392
- json: () => Promise.resolve({
393
- access_token: "token",
394
- expires_in: 3600,
395
- }),
396
- });
397
- // Cache a token
398
- await auth.resolveAuthToken({
399
- credentials: {
400
- type: "client_credentials",
401
- clientId: "clear-test",
402
- clientSecret: "secret",
403
- },
404
- fetch: mockFetch,
405
- });
406
- // Clear all caches
407
- auth.clearTokenCache();
408
- // Should fetch again
409
- await auth.resolveAuthToken({
410
- credentials: {
411
- type: "client_credentials",
412
- clientId: "clear-test",
413
- clientSecret: "secret",
414
- },
415
- fetch: mockFetch,
416
- });
417
- expect(mockFetch).toHaveBeenCalledTimes(2);
418
- });
419
- });
420
- describe("invalidateCredentialsToken", () => {
421
- it("should invalidate cached token for client credentials", async () => {
422
- const mockFetch = vi.fn().mockResolvedValue({
423
- ok: true,
424
- json: () => Promise.resolve({
425
- access_token: "cached-token",
426
- expires_in: 3600,
427
- }),
428
- });
429
- // First, get a token to populate the cache
430
- await auth.resolveAuthToken({
431
- credentials: {
432
- type: "client_credentials",
433
- clientId: "invalidate-test-client",
434
- clientSecret: "test-secret",
435
- },
436
- fetch: mockFetch,
437
- });
438
- expect(mockFetch).toHaveBeenCalledTimes(1);
439
- // Verify token is cached (no new fetch)
440
- const cachedToken = await auth.resolveAuthToken({
441
- credentials: {
442
- type: "client_credentials",
443
- clientId: "invalidate-test-client",
444
- clientSecret: "test-secret",
445
- },
446
- fetch: mockFetch,
447
- });
448
- expect(cachedToken).toBe("cached-token");
449
- expect(mockFetch).toHaveBeenCalledTimes(1);
450
- // Invalidate the token
451
- await auth.invalidateCredentialsToken({
452
- credentials: {
453
- type: "client_credentials",
454
- clientId: "invalidate-test-client",
455
- clientSecret: "test-secret",
456
- },
457
- });
458
- // Next request should fetch a new token
459
- await auth.resolveAuthToken({
460
- credentials: {
461
- type: "client_credentials",
462
- clientId: "invalidate-test-client",
463
- clientSecret: "test-secret",
464
- },
465
- fetch: mockFetch,
466
- });
467
- expect(mockFetch).toHaveBeenCalledTimes(2);
468
- });
469
- it("should do nothing for string credentials", async () => {
470
- // Should not throw
471
- await auth.invalidateCredentialsToken({
472
- credentials: "string-token",
473
- });
474
- });
475
- it("should do nothing when no credentials provided", async () => {
476
- // Should not throw
477
- await auth.invalidateCredentialsToken({});
478
- });
479
- });
480
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=builders.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"builders.test.d.ts","sourceRoot":"","sources":["../../../src/plugins/eventEmission/builders.test.ts"],"names":[],"mappings":""}
@@ -1,138 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { buildMethodCalledEvent, buildErrorEvent, buildApplicationLifecycleEvent, buildErrorEventWithContext, } from "./builders";
3
- describe("buildMethodCalledEvent", () => {
4
- it("should use data.selected_api when provided", () => {
5
- const event = buildMethodCalledEvent({
6
- method_name: "runAction",
7
- execution_duration_ms: 100,
8
- success_flag: true,
9
- argument_count: 1,
10
- selected_api: "SlackCLIAPI@1.0.0",
11
- });
12
- expect(event.selected_api).toBe("SlackCLIAPI@1.0.0");
13
- });
14
- it("should use data.operation_type and data.operation_key when provided", () => {
15
- const event = buildMethodCalledEvent({
16
- method_name: "runAction",
17
- execution_duration_ms: 100,
18
- success_flag: true,
19
- argument_count: 1,
20
- operation_type: "write",
21
- operation_key: "send_message",
22
- });
23
- expect(event.operation_type).toBe("write");
24
- expect(event.operation_key).toBe("send_message");
25
- });
26
- it("should fall back to null when data fields are not provided", () => {
27
- const event = buildMethodCalledEvent({
28
- method_name: "listApps",
29
- execution_duration_ms: 50,
30
- success_flag: true,
31
- argument_count: 0,
32
- });
33
- expect(event.selected_api).toBeNull();
34
- expect(event.operation_type).toBeNull();
35
- expect(event.operation_key).toBeNull();
36
- });
37
- it("should prefer data.selected_api over context.selected_api", () => {
38
- const event = buildMethodCalledEvent({
39
- method_name: "runAction",
40
- execution_duration_ms: 100,
41
- success_flag: true,
42
- argument_count: 1,
43
- selected_api: "SlackCLIAPI@2.0.0",
44
- }, { selected_api: "SlackCLIAPI@1.0.0" });
45
- expect(event.selected_api).toBe("SlackCLIAPI@2.0.0");
46
- });
47
- it("should fall back to context.selected_api when data.selected_api is not provided", () => {
48
- const event = buildMethodCalledEvent({
49
- method_name: "runAction",
50
- execution_duration_ms: 100,
51
- success_flag: true,
52
- argument_count: 1,
53
- }, { selected_api: "SlackCLIAPI@1.0.0" });
54
- expect(event.selected_api).toBe("SlackCLIAPI@1.0.0");
55
- });
56
- it("should default call_context to null (plugin layer overrides this)", () => {
57
- const event = buildMethodCalledEvent({
58
- method_name: "listApps",
59
- execution_duration_ms: 50,
60
- success_flag: true,
61
- argument_count: 0,
62
- });
63
- expect(event.call_context).toBeNull();
64
- });
65
- it("should populate sdk_version", () => {
66
- const event = buildMethodCalledEvent({
67
- method_name: "listApps",
68
- execution_duration_ms: 50,
69
- success_flag: true,
70
- argument_count: 0,
71
- });
72
- expect(event.sdk_version).toBe("unknown");
73
- });
74
- });
75
- describe("buildErrorEvent", () => {
76
- it("should build an error event with correct fields", () => {
77
- const event = buildErrorEvent({
78
- error_message: "Something went wrong",
79
- error_type: "RuntimeError",
80
- is_user_facing: false,
81
- }, { selected_api: "SlackCLIAPI@1.0.0" });
82
- expect(event.error_message).toBe("Something went wrong");
83
- expect(event.error_type).toBe("RuntimeError");
84
- expect(event.selected_api).toBe("SlackCLIAPI@1.0.0");
85
- expect(event.sdk_version).toBe("unknown");
86
- });
87
- it("should not allow sdk_version to be overwritten via data spread", () => {
88
- const event = buildErrorEvent({
89
- error_message: "test",
90
- error_type: "Error",
91
- is_user_facing: false,
92
- sdk_version: "evil-version",
93
- }, {});
94
- expect(event.sdk_version).not.toBe("evil-version");
95
- });
96
- });
97
- describe("buildApplicationLifecycleEvent", () => {
98
- it("should build a lifecycle event with correct fields", () => {
99
- const event = buildApplicationLifecycleEvent({
100
- lifecycle_event_type: "startup",
101
- }, { app_id: 123 });
102
- expect(event.lifecycle_event_type).toBe("startup");
103
- expect(event.app_id).toBe(123);
104
- expect(event.sdk_version).toBe("unknown");
105
- });
106
- it("should not allow sdk_version to be overwritten via data spread", () => {
107
- const event = buildApplicationLifecycleEvent({
108
- lifecycle_event_type: "startup",
109
- sdk_version: "evil-version",
110
- }, {});
111
- expect(event.sdk_version).not.toBe("evil-version");
112
- });
113
- });
114
- describe("buildErrorEventWithContext", () => {
115
- it("should build an error event with execution time", () => {
116
- const startTime = Date.now() - 500;
117
- const event = buildErrorEventWithContext({
118
- error_message: "Timeout",
119
- error_type: "TimeoutError",
120
- is_user_facing: false,
121
- execution_start_time: startTime,
122
- }, { selected_api: "SlackCLIAPI@1.0.0" });
123
- expect(event.error_message).toBe("Timeout");
124
- expect(event.error_type).toBe("TimeoutError");
125
- expect(event.selected_api).toBe("SlackCLIAPI@1.0.0");
126
- expect(event.sdk_version).toBe("unknown");
127
- expect(event.execution_time_before_error_ms).toBeGreaterThanOrEqual(400);
128
- });
129
- it("should not allow sdk_version to be overwritten via data spread", () => {
130
- const event = buildErrorEventWithContext({
131
- error_message: "test",
132
- error_type: "Error",
133
- is_user_facing: false,
134
- sdk_version: "evil-version",
135
- }, {});
136
- expect(event.sdk_version).not.toBe("evil-version");
137
- });
138
- });
@@ -1,5 +0,0 @@
1
- /**
2
- * Tests for Event Emission Plugin
3
- */
4
- export {};
5
- //# sourceMappingURL=index.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/plugins/eventEmission/index.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}