@zapier/zapier-sdk-cli 0.16.1 → 0.16.4

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 (60) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/cli.cjs +7 -7
  3. package/dist/cli.mjs +7 -7
  4. package/dist/index.cjs +1 -1
  5. package/dist/index.mjs +1 -1
  6. package/dist/package.json +8 -2
  7. package/dist/src/cli.js +2 -1
  8. package/dist/src/utils/cli-generator.js +8 -7
  9. package/dist/tsconfig.tsbuildinfo +1 -1
  10. package/package.json +11 -5
  11. package/src/cli.test.ts +0 -28
  12. package/src/cli.ts +0 -96
  13. package/src/generators/ast-generator.test.ts +0 -908
  14. package/src/generators/ast-generator.ts +0 -774
  15. package/src/index.ts +0 -12
  16. package/src/plugins/add/index.test.ts +0 -58
  17. package/src/plugins/add/index.ts +0 -177
  18. package/src/plugins/add/schemas.ts +0 -35
  19. package/src/plugins/buildManifest/index.test.ts +0 -679
  20. package/src/plugins/buildManifest/index.ts +0 -131
  21. package/src/plugins/buildManifest/schemas.ts +0 -55
  22. package/src/plugins/bundleCode/index.ts +0 -128
  23. package/src/plugins/bundleCode/schemas.ts +0 -24
  24. package/src/plugins/generateAppTypes/index.test.ts +0 -679
  25. package/src/plugins/generateAppTypes/index.ts +0 -227
  26. package/src/plugins/generateAppTypes/schemas.ts +0 -61
  27. package/src/plugins/getLoginConfigPath/index.ts +0 -45
  28. package/src/plugins/getLoginConfigPath/schemas.ts +0 -10
  29. package/src/plugins/index.ts +0 -8
  30. package/src/plugins/login/index.ts +0 -135
  31. package/src/plugins/login/schemas.ts +0 -13
  32. package/src/plugins/logout/index.ts +0 -37
  33. package/src/plugins/logout/schemas.ts +0 -8
  34. package/src/plugins/mcp/index.ts +0 -43
  35. package/src/plugins/mcp/schemas.ts +0 -13
  36. package/src/sdk.ts +0 -45
  37. package/src/telemetry/builders.ts +0 -113
  38. package/src/telemetry/events.ts +0 -39
  39. package/src/types/sdk.ts +0 -8
  40. package/src/utils/api/client.ts +0 -44
  41. package/src/utils/auth/login.ts +0 -214
  42. package/src/utils/cli-generator-utils.ts +0 -169
  43. package/src/utils/cli-generator.test.ts +0 -347
  44. package/src/utils/cli-generator.ts +0 -807
  45. package/src/utils/constants.ts +0 -9
  46. package/src/utils/directory-detection.ts +0 -23
  47. package/src/utils/errors.ts +0 -26
  48. package/src/utils/getCallablePromise.ts +0 -21
  49. package/src/utils/log.ts +0 -23
  50. package/src/utils/manifest-helpers.ts +0 -25
  51. package/src/utils/package-manager-detector.ts +0 -83
  52. package/src/utils/parameter-resolver.ts +0 -1075
  53. package/src/utils/schema-formatter.ts +0 -153
  54. package/src/utils/serializeAsync.ts +0 -26
  55. package/src/utils/spinner.ts +0 -23
  56. package/src/utils/version-checker.test.ts +0 -239
  57. package/src/utils/version-checker.ts +0 -237
  58. package/tsconfig.build.json +0 -18
  59. package/tsconfig.json +0 -19
  60. package/tsup.config.ts +0 -23
@@ -1,679 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import { generateAppTypesPlugin } from "./index";
3
- import { GenerateAppTypesSchema } from "./schemas";
4
- import type { AppItem, Authentication } from "@zapier/zapier-sdk";
5
- import {
6
- createSdk,
7
- ZapierUnknownError,
8
- ZapierValidationError,
9
- } from "@zapier/zapier-sdk";
10
- import { mkdir, writeFile } from "fs/promises";
11
-
12
- vi.mock("fs/promises", () => ({
13
- mkdir: vi.fn(),
14
- writeFile: vi.fn(),
15
- }));
16
-
17
- let mockGenerateTypesImpl: ReturnType<typeof vi.fn>;
18
-
19
- vi.mock("../../generators/ast-generator", () => {
20
- const mockClass = vi.fn();
21
- return {
22
- AstTypeGenerator: mockClass,
23
- };
24
- });
25
-
26
- const mockSlackApp: AppItem = {
27
- key: "SlackCLIAPI",
28
- slug: "slack",
29
- title: "Slack",
30
- description: "Slack is a collaboration hub",
31
- version: "1.30.0",
32
- implementation_id: "SlackCLIAPI@1.30.0",
33
- };
34
-
35
- const mockGmailApp: AppItem = {
36
- key: "GmailCLIAPI",
37
- slug: "gmail",
38
- title: "Gmail",
39
- description: "Gmail is an email service",
40
- version: "2.5.0",
41
- implementation_id: "GmailCLIAPI@2.5.0",
42
- };
43
-
44
- const mockAppWithoutVersion: AppItem = {
45
- key: "BrokenAPI",
46
- slug: "broken",
47
- title: "Broken App",
48
- description: "An app without version",
49
- version: undefined,
50
- implementation_id: "BrokenAPI",
51
- };
52
-
53
- const mockAuthentication: Authentication = {
54
- id: 123,
55
- date: "2024-01-01T00:00:00Z",
56
- account_id: 456,
57
- is_invite_only: false,
58
- is_private: false,
59
- shared_with_all: false,
60
- selected_api: "SlackCLIAPI",
61
- app_key: "SlackCLIAPI",
62
- title: "Test Slack Auth",
63
- };
64
-
65
- describe("generateAppTypes plugin", () => {
66
- let mockListAppsItems: unknown;
67
- let mockListAuthenticationsItems: unknown;
68
-
69
- beforeEach(async () => {
70
- vi.clearAllMocks();
71
-
72
- mockGenerateTypesImpl = vi.fn().mockResolvedValue("// Generated types");
73
- const { AstTypeGenerator } = await import("../../generators/ast-generator");
74
- vi.mocked(AstTypeGenerator).mockImplementation(() => ({
75
- generateTypes: mockGenerateTypesImpl,
76
- }));
77
-
78
- mockListAppsItems = vi.fn();
79
- mockListAuthenticationsItems = vi.fn();
80
-
81
- vi.mocked(mkdir).mockResolvedValue(undefined);
82
- vi.mocked(writeFile).mockResolvedValue(undefined);
83
- });
84
-
85
- function createTestSdk(
86
- apps: AppItem[] = [mockSlackApp, mockGmailApp],
87
- authentications: Authentication[] = [],
88
- ) {
89
- // Mock async iterator for listApps
90
- mockListAppsItems.mockReturnValue({
91
- async *[Symbol.asyncIterator]() {
92
- for (const app of apps) {
93
- yield app;
94
- }
95
- },
96
- });
97
-
98
- // Mock async iterator for listAuthentications
99
- mockListAuthenticationsItems.mockReturnValue({
100
- async *[Symbol.asyncIterator]() {
101
- for (const auth of authentications) {
102
- yield auth;
103
- }
104
- },
105
- });
106
-
107
- return createSdk()
108
- .addPlugin(() => ({
109
- listApps: vi.fn().mockReturnValue({
110
- items: mockListAppsItems,
111
- }),
112
- listAuthentications: vi.fn().mockReturnValue({
113
- items: mockListAuthenticationsItems,
114
- }),
115
- listActions: vi.fn(),
116
- listInputFields: vi.fn(),
117
- }))
118
- .addPlugin(generateAppTypesPlugin);
119
- }
120
-
121
- describe("schema validation", () => {
122
- it("should accept valid options with skipWrite true", () => {
123
- const result = GenerateAppTypesSchema.safeParse({
124
- appKeys: ["slack", "gmail"],
125
- skipWrite: true,
126
- });
127
-
128
- expect(result.success).toBe(true);
129
- if (result.success) {
130
- expect(result.data.skipWrite).toBe(true);
131
- }
132
- });
133
-
134
- it("should accept valid options with skipWrite false and typesOutputDirectory", () => {
135
- const result = GenerateAppTypesSchema.safeParse({
136
- appKeys: ["slack"],
137
- skipWrite: false,
138
- typesOutputDirectory: "/path/to/types",
139
- });
140
-
141
- expect(result.success).toBe(true);
142
- if (result.success) {
143
- expect(result.data.skipWrite).toBe(false);
144
- expect(result.data.typesOutputDirectory).toBe("/path/to/types");
145
- }
146
- });
147
-
148
- it("should accept options with authenticationIds", () => {
149
- const result = GenerateAppTypesSchema.safeParse({
150
- appKeys: ["slack"],
151
- authenticationIds: ["123", "456"],
152
- skipWrite: true,
153
- });
154
-
155
- expect(result.success).toBe(true);
156
- if (result.success) {
157
- expect(result.data.authenticationIds).toEqual(["123", "456"]);
158
- }
159
- });
160
-
161
- it("should require at least one appKey", () => {
162
- const result = GenerateAppTypesSchema.safeParse({
163
- appKeys: [],
164
- });
165
-
166
- expect(result.success).toBe(false);
167
- });
168
-
169
- it("should reject empty string appKeys", () => {
170
- const result = GenerateAppTypesSchema.safeParse({
171
- appKeys: ["slack", ""],
172
- });
173
-
174
- expect(result.success).toBe(false);
175
- });
176
- });
177
-
178
- describe("type generation with skipWrite: true", () => {
179
- it("should generate types without writing to disk", async () => {
180
- const sdk = createTestSdk();
181
-
182
- const result = await sdk.generateAppTypes({
183
- appKeys: ["slack", "gmail"],
184
- skipWrite: true,
185
- });
186
-
187
- expect(result.typeDefinitions).toBeDefined();
188
- expect(result.typeDefinitions.slack).toBe("// Generated types");
189
- expect(result.typeDefinitions.gmail).toBe("// Generated types");
190
- expect(result.writtenFiles).toBeUndefined();
191
-
192
- // Should not write files
193
- expect(mkdir).not.toHaveBeenCalled();
194
- expect(writeFile).not.toHaveBeenCalled();
195
- });
196
-
197
- it("should return empty result when no apps found", async () => {
198
- const sdk = createTestSdk([]);
199
-
200
- const result = await sdk.generateAppTypes({
201
- appKeys: ["nonexistent"],
202
- skipWrite: true,
203
- });
204
-
205
- expect(result.typeDefinitions).toEqual({});
206
- expect(result.writtenFiles).toBeUndefined();
207
- });
208
- });
209
-
210
- describe("type generation with skipWrite: false", () => {
211
- it("should generate types and write to disk at default directory", async () => {
212
- const sdk = createTestSdk();
213
-
214
- const result = await sdk.generateAppTypes({
215
- appKeys: ["slack", "gmail"],
216
- });
217
-
218
- expect(result.typeDefinitions).toBeDefined();
219
- expect(result.typeDefinitions.slack).toBe("// Generated types");
220
- expect(result.typeDefinitions.gmail).toBe("// Generated types");
221
-
222
- expect(result.writtenFiles).toBeDefined();
223
- expect(result.writtenFiles?.slack).toMatch(
224
- /\/zapier\/apps\/slack\.d\.ts$/,
225
- );
226
- expect(result.writtenFiles?.gmail).toMatch(
227
- /\/zapier\/apps\/gmail\.d\.ts$/,
228
- );
229
-
230
- // Should create directory
231
- expect(mkdir).toHaveBeenCalledWith(
232
- expect.stringContaining("/zapier/apps"),
233
- { recursive: true },
234
- );
235
-
236
- // Should write files (test only that the path contains /zapier/apps/slack.d.ts and /zapier/apps/gmail.d.ts)
237
- expect(writeFile).toHaveBeenCalledWith(
238
- expect.stringContaining("/zapier/apps/slack.d.ts"),
239
- "// Generated types",
240
- "utf8",
241
- );
242
- expect(writeFile).toHaveBeenCalledWith(
243
- expect.stringContaining("/zapier/apps/gmail.d.ts"),
244
- "// Generated types",
245
- "utf8",
246
- );
247
- });
248
-
249
- it("should generate types and write to disk at specified directory", async () => {
250
- const sdk = createTestSdk();
251
-
252
- const result = await sdk.generateAppTypes({
253
- appKeys: ["slack", "gmail"],
254
- typesOutputDirectory: "/path/to/types",
255
- });
256
-
257
- expect(result.typeDefinitions).toBeDefined();
258
- expect(result.typeDefinitions.slack).toBe("// Generated types");
259
- expect(result.typeDefinitions.gmail).toBe("// Generated types");
260
-
261
- expect(result.writtenFiles).toBeDefined();
262
- expect(result.writtenFiles?.slack).toBe("/path/to/types/slack.d.ts");
263
- expect(result.writtenFiles?.gmail).toBe("/path/to/types/gmail.d.ts");
264
-
265
- // Should create directory
266
- expect(mkdir).toHaveBeenCalledWith("/path/to/types", { recursive: true });
267
-
268
- // Should write files
269
- expect(writeFile).toHaveBeenCalledWith(
270
- "/path/to/types/slack.d.ts",
271
- "// Generated types",
272
- "utf8",
273
- );
274
- expect(writeFile).toHaveBeenCalledWith(
275
- "/path/to/types/gmail.d.ts",
276
- "// Generated types",
277
- "utf8",
278
- );
279
- });
280
- });
281
-
282
- describe("authentication handling", () => {
283
- it("should fetch and match authentications", async () => {
284
- const sdk = createTestSdk([mockSlackApp], [mockAuthentication]);
285
- const onProgress = vi.fn();
286
-
287
- await sdk.generateAppTypes({
288
- appKeys: ["slack"],
289
- authenticationIds: ["123"],
290
- skipWrite: true,
291
- onProgress,
292
- });
293
-
294
- expect(onProgress).toHaveBeenCalledWith({
295
- type: "authentications_lookup_start",
296
- count: 1,
297
- });
298
-
299
- expect(onProgress).toHaveBeenCalledWith({
300
- type: "authentications_lookup_complete",
301
- count: 1,
302
- });
303
-
304
- expect(onProgress).toHaveBeenCalledWith({
305
- type: "authentication_matched",
306
- appKey: "SlackCLIAPI",
307
- authenticationId: 123,
308
- authenticationTitle: "Test Slack Auth",
309
- });
310
- });
311
-
312
- it("should emit authentication_not_matched when no match found", async () => {
313
- const authWithDifferentApp = {
314
- ...mockAuthentication,
315
- app_key: "DifferentAPI",
316
- };
317
- const sdk = createTestSdk([mockSlackApp], [authWithDifferentApp]);
318
- const onProgress = vi.fn();
319
-
320
- await sdk.generateAppTypes({
321
- appKeys: ["slack"],
322
- authenticationIds: ["123"],
323
- skipWrite: true,
324
- onProgress,
325
- });
326
-
327
- expect(onProgress).toHaveBeenCalledWith({
328
- type: "authentication_not_matched",
329
- appKey: "SlackCLIAPI",
330
- });
331
- });
332
-
333
- it("should not fetch authentications when authenticationIds not provided", async () => {
334
- const sdk = createTestSdk();
335
- const onProgress = vi.fn();
336
-
337
- await sdk.generateAppTypes({
338
- appKeys: ["slack"],
339
- skipWrite: true,
340
- onProgress,
341
- });
342
-
343
- const progressEvents = onProgress.mock.calls.map((call) => call[0].type);
344
- expect(progressEvents).not.toContain("authentications_lookup_start");
345
- });
346
- });
347
-
348
- describe("progress events", () => {
349
- it("should emit apps_lookup_start event", async () => {
350
- const sdk = createTestSdk();
351
- const onProgress = vi.fn();
352
-
353
- await sdk.generateAppTypes({
354
- appKeys: ["slack", "gmail"],
355
- skipWrite: true,
356
- onProgress,
357
- });
358
-
359
- expect(onProgress).toHaveBeenCalledWith({
360
- type: "apps_lookup_start",
361
- count: 2,
362
- });
363
- });
364
-
365
- it("should emit app_found event for each app", async () => {
366
- const sdk = createTestSdk();
367
- const onProgress = vi.fn();
368
-
369
- await sdk.generateAppTypes({
370
- appKeys: ["slack", "gmail"],
371
- skipWrite: true,
372
- onProgress,
373
- });
374
-
375
- expect(onProgress).toHaveBeenCalledWith({
376
- type: "app_found",
377
- app: mockSlackApp,
378
- });
379
-
380
- expect(onProgress).toHaveBeenCalledWith({
381
- type: "app_found",
382
- app: mockGmailApp,
383
- });
384
- });
385
-
386
- it("should emit type_generated event", async () => {
387
- const sdk = createTestSdk([mockSlackApp]);
388
- const onProgress = vi.fn();
389
-
390
- await sdk.generateAppTypes({
391
- appKeys: ["slack"],
392
- skipWrite: true,
393
- onProgress,
394
- });
395
-
396
- expect(onProgress).toHaveBeenCalledWith({
397
- type: "type_generated",
398
- manifestKey: "slack",
399
- sizeBytes: "// Generated types".length,
400
- });
401
- });
402
-
403
- it("should emit file_written event when writing to disk", async () => {
404
- const sdk = createTestSdk([mockSlackApp]);
405
- const onProgress = vi.fn();
406
-
407
- await sdk.generateAppTypes({
408
- appKeys: ["slack"],
409
- skipWrite: false,
410
- typesOutputDirectory: "/path/to/types",
411
- onProgress,
412
- });
413
-
414
- expect(onProgress).toHaveBeenCalledWith({
415
- type: "file_written",
416
- manifestKey: "slack",
417
- filePath: "/path/to/types/slack.d.ts",
418
- });
419
- });
420
-
421
- it("should emit app_processing_complete event", async () => {
422
- const sdk = createTestSdk([mockSlackApp]);
423
- const onProgress = vi.fn();
424
-
425
- await sdk.generateAppTypes({
426
- appKeys: ["slack"],
427
- skipWrite: true,
428
- onProgress,
429
- });
430
-
431
- expect(onProgress).toHaveBeenCalledWith({
432
- type: "app_processing_complete",
433
- appKey: "SlackCLIAPI",
434
- });
435
- });
436
- });
437
-
438
- describe("error handling", () => {
439
- it("should throw ZapierValidationError when app.version is missing", async () => {
440
- const sdk = createTestSdk([mockAppWithoutVersion]);
441
-
442
- await expect(
443
- sdk.generateAppTypes({
444
- appKeys: ["broken"],
445
- skipWrite: true,
446
- }),
447
- ).rejects.toThrow(ZapierValidationError);
448
-
449
- await expect(
450
- sdk.generateAppTypes({
451
- appKeys: ["broken"],
452
- skipWrite: true,
453
- }),
454
- ).rejects.toThrow(/Invalid implementation ID format/);
455
- });
456
-
457
- it("should include implementation_id in validation error details", async () => {
458
- const sdk = createTestSdk([mockAppWithoutVersion]);
459
-
460
- try {
461
- await sdk.generateAppTypes({
462
- appKeys: ["broken"],
463
- skipWrite: true,
464
- });
465
- expect.fail("Should have thrown");
466
- } catch (error) {
467
- expect(error).toBeInstanceOf(ZapierValidationError);
468
- if (error instanceof ZapierValidationError) {
469
- expect(error.details).toMatchObject({
470
- appKey: "BrokenAPI",
471
- implementationId: "BrokenAPI",
472
- });
473
- }
474
- }
475
- });
476
-
477
- it("should emit app_processing_error event before throwing", async () => {
478
- const sdk = createTestSdk([mockAppWithoutVersion]);
479
- const onProgress = vi.fn();
480
-
481
- await expect(
482
- sdk.generateAppTypes({
483
- appKeys: ["broken"],
484
- skipWrite: true,
485
- onProgress,
486
- }),
487
- ).rejects.toThrow();
488
-
489
- expect(onProgress).toHaveBeenCalledWith({
490
- type: "app_processing_error",
491
- appKey: "BrokenAPI",
492
- error: expect.stringContaining("Invalid implementation ID format"),
493
- });
494
- });
495
-
496
- it("should throw immediately on first error and not continue processing", async () => {
497
- const sdk = createTestSdk([mockAppWithoutVersion, mockSlackApp]);
498
-
499
- await expect(
500
- sdk.generateAppTypes({
501
- appKeys: ["broken", "slack"],
502
- skipWrite: true,
503
- }),
504
- ).rejects.toThrow(ZapierValidationError);
505
-
506
- // AstTypeGenerator should not be called at all since validation happens first
507
- const { AstTypeGenerator } = await import(
508
- "../../generators/ast-generator"
509
- );
510
- expect(vi.mocked(AstTypeGenerator)).not.toHaveBeenCalled();
511
- });
512
-
513
- it("should throw ZapierUnknownError when type generation fails", async () => {
514
- const { AstTypeGenerator } = await import(
515
- "../../generators/ast-generator"
516
- );
517
- vi.mocked(AstTypeGenerator).mockImplementationOnce(() => ({
518
- generateTypes: vi
519
- .fn()
520
- .mockRejectedValue(new Error("Generation failed")),
521
- }));
522
-
523
- const sdk = createTestSdk([mockSlackApp]);
524
-
525
- await expect(
526
- sdk.generateAppTypes({
527
- appKeys: ["slack"],
528
- skipWrite: true,
529
- }),
530
- ).rejects.toThrow(ZapierUnknownError);
531
- });
532
-
533
- it("should include original error as cause", async () => {
534
- const originalError = new Error("Generation failed");
535
- const { AstTypeGenerator } = await import(
536
- "../../generators/ast-generator"
537
- );
538
- vi.mocked(AstTypeGenerator).mockImplementationOnce(() => ({
539
- generateTypes: vi.fn().mockRejectedValue(originalError),
540
- }));
541
-
542
- const sdk = createTestSdk([mockSlackApp]);
543
-
544
- try {
545
- await sdk.generateAppTypes({
546
- appKeys: ["slack"],
547
- skipWrite: true,
548
- });
549
- expect.fail("Should have thrown");
550
- } catch (error) {
551
- expect(error).toBeInstanceOf(ZapierUnknownError);
552
- if (error instanceof ZapierUnknownError) {
553
- expect(error.cause).toBe(originalError);
554
- expect(error.message).toContain("Failed to process app SlackCLIAPI");
555
- expect(error.message).toContain("Generation failed");
556
- }
557
- }
558
- });
559
-
560
- it("should throw ZapierUnknownError when file writing fails", async () => {
561
- vi.mocked(writeFile).mockRejectedValueOnce(new Error("Write failed"));
562
- const sdk = createTestSdk([mockSlackApp]);
563
-
564
- await expect(
565
- sdk.generateAppTypes({
566
- appKeys: ["slack"],
567
- skipWrite: false,
568
- typesOutputDirectory: "/path/to/types",
569
- }),
570
- ).rejects.toThrow(ZapierUnknownError);
571
- });
572
-
573
- it("should preserve ZapierValidationError if thrown from underlying code", async () => {
574
- const validationError = new ZapierValidationError(
575
- "Invalid type definition",
576
- );
577
- const { AstTypeGenerator } = await import(
578
- "../../generators/ast-generator"
579
- );
580
- vi.mocked(AstTypeGenerator).mockImplementationOnce(() => ({
581
- generateTypes: vi.fn().mockRejectedValue(validationError),
582
- }));
583
-
584
- const sdk = createTestSdk([mockSlackApp]);
585
-
586
- await expect(
587
- sdk.generateAppTypes({
588
- appKeys: ["slack"],
589
- skipWrite: true,
590
- }),
591
- ).rejects.toThrow(ZapierValidationError);
592
- });
593
-
594
- it("should stop processing after first app error", async () => {
595
- const { AstTypeGenerator } = await import(
596
- "../../generators/ast-generator"
597
- );
598
- vi.mocked(AstTypeGenerator)
599
- .mockImplementationOnce(() => ({
600
- generateTypes: vi.fn().mockRejectedValue(new Error("First error")),
601
- }))
602
- .mockImplementationOnce(() => ({
603
- generateTypes: vi.fn().mockResolvedValue("// Types for second app"),
604
- }));
605
-
606
- const sdk = createTestSdk([mockSlackApp, mockGmailApp]);
607
-
608
- await expect(
609
- sdk.generateAppTypes({
610
- appKeys: ["slack", "gmail"],
611
- skipWrite: true,
612
- }),
613
- ).rejects.toThrow(ZapierUnknownError);
614
-
615
- // Should only instantiate generator once (for first app that fails)
616
- expect(vi.mocked(AstTypeGenerator)).toHaveBeenCalledTimes(1);
617
- });
618
- });
619
-
620
- describe("context and metadata", () => {
621
- it("should provide context with meta information", () => {
622
- const sdk = createTestSdk();
623
- const context = sdk.getContext();
624
-
625
- expect(context.meta.generateAppTypes).toBeDefined();
626
- expect(context.meta.generateAppTypes.inputSchema).toBeDefined();
627
- expect(context.meta.generateAppTypes.categories).toEqual(["utility"]);
628
- });
629
-
630
- it("should expose GenerateAppTypesSchema in metadata", () => {
631
- const sdk = createTestSdk();
632
- const context = sdk.getContext();
633
-
634
- expect(context.meta.generateAppTypes.inputSchema).toBe(
635
- GenerateAppTypesSchema,
636
- );
637
- });
638
- });
639
-
640
- describe("edge cases", () => {
641
- it("should handle apps without slug", async () => {
642
- const appWithoutSlug: AppItem = {
643
- ...mockSlackApp,
644
- slug: undefined as unknown as string,
645
- };
646
- const sdk = createTestSdk([appWithoutSlug]);
647
- const onProgress = vi.fn();
648
-
649
- await sdk.generateAppTypes({
650
- appKeys: ["slack"],
651
- skipWrite: true,
652
- onProgress,
653
- });
654
-
655
- expect(onProgress).toHaveBeenCalledWith({
656
- type: "app_processing_start",
657
- appKey: "SlackCLIAPI",
658
- slug: undefined,
659
- });
660
- });
661
-
662
- it("should not emit authentication_not_matched when authenticationIds provided but returns empty", async () => {
663
- const sdk = createTestSdk([mockSlackApp], []);
664
- const onProgress = vi.fn();
665
-
666
- await sdk.generateAppTypes({
667
- appKeys: ["slack"],
668
- authenticationIds: ["123"],
669
- skipWrite: true,
670
- onProgress,
671
- });
672
-
673
- // When authentications are fetched but the array is empty (no authentications found),
674
- // the code checks if authentications.length > 0, which is false, so it skips the matching logic entirely
675
- const progressEvents = onProgress.mock.calls.map((call) => call[0].type);
676
- expect(progressEvents).not.toContain("authentication_not_matched");
677
- });
678
- });
679
- });