@workos/oagen-emitters 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/.husky/pre-commit +1 -0
  2. package/.oxfmtrc.json +8 -1
  3. package/.release-please-manifest.json +1 -1
  4. package/CHANGELOG.md +15 -0
  5. package/README.md +129 -0
  6. package/dist/index.d.mts +10 -1
  7. package/dist/index.d.mts.map +1 -1
  8. package/dist/index.mjs +11943 -2728
  9. package/dist/index.mjs.map +1 -1
  10. package/docs/sdk-architecture/go.md +338 -0
  11. package/docs/sdk-architecture/php.md +315 -0
  12. package/docs/sdk-architecture/python.md +511 -0
  13. package/oagen.config.ts +298 -2
  14. package/package.json +9 -5
  15. package/scripts/generate-php.js +13 -0
  16. package/scripts/git-push-with-published-oagen.sh +21 -0
  17. package/smoke/sdk-dotnet.ts +17 -3
  18. package/smoke/sdk-elixir.ts +17 -3
  19. package/smoke/sdk-go.ts +137 -46
  20. package/smoke/sdk-kotlin.ts +23 -4
  21. package/smoke/sdk-node.ts +15 -3
  22. package/smoke/sdk-php.ts +28 -26
  23. package/smoke/sdk-python.ts +5 -2
  24. package/smoke/sdk-ruby.ts +17 -3
  25. package/smoke/sdk-rust.ts +16 -3
  26. package/src/go/client.ts +141 -0
  27. package/src/go/enums.ts +196 -0
  28. package/src/go/fixtures.ts +212 -0
  29. package/src/go/index.ts +81 -0
  30. package/src/go/manifest.ts +36 -0
  31. package/src/go/models.ts +254 -0
  32. package/src/go/naming.ts +191 -0
  33. package/src/go/resources.ts +827 -0
  34. package/src/go/tests.ts +751 -0
  35. package/src/go/type-map.ts +82 -0
  36. package/src/go/wrappers.ts +261 -0
  37. package/src/index.ts +3 -0
  38. package/src/node/client.ts +167 -122
  39. package/src/node/enums.ts +13 -4
  40. package/src/node/errors.ts +42 -233
  41. package/src/node/field-plan.ts +726 -0
  42. package/src/node/fixtures.ts +15 -5
  43. package/src/node/index.ts +65 -16
  44. package/src/node/models.ts +264 -96
  45. package/src/node/naming.ts +52 -25
  46. package/src/node/resources.ts +621 -172
  47. package/src/node/sdk-errors.ts +41 -0
  48. package/src/node/tests.ts +71 -27
  49. package/src/node/type-map.ts +4 -2
  50. package/src/node/utils.ts +56 -64
  51. package/src/node/wrappers.ts +151 -0
  52. package/src/php/client.ts +171 -0
  53. package/src/php/enums.ts +67 -0
  54. package/src/php/errors.ts +9 -0
  55. package/src/php/fixtures.ts +181 -0
  56. package/src/php/index.ts +96 -0
  57. package/src/php/manifest.ts +36 -0
  58. package/src/php/models.ts +310 -0
  59. package/src/php/naming.ts +298 -0
  60. package/src/php/resources.ts +561 -0
  61. package/src/php/tests.ts +533 -0
  62. package/src/php/type-map.ts +90 -0
  63. package/src/php/utils.ts +18 -0
  64. package/src/php/wrappers.ts +151 -0
  65. package/src/python/client.ts +337 -0
  66. package/src/python/enums.ts +313 -0
  67. package/src/python/fixtures.ts +196 -0
  68. package/src/python/index.ts +95 -0
  69. package/src/python/manifest.ts +38 -0
  70. package/src/python/models.ts +688 -0
  71. package/src/python/naming.ts +209 -0
  72. package/src/python/resources.ts +1322 -0
  73. package/src/python/tests.ts +1335 -0
  74. package/src/python/type-map.ts +93 -0
  75. package/src/python/wrappers.ts +191 -0
  76. package/src/shared/model-utils.ts +255 -0
  77. package/src/shared/naming-utils.ts +107 -0
  78. package/src/shared/non-spec-services.ts +54 -0
  79. package/src/shared/resolved-ops.ts +109 -0
  80. package/src/shared/wrapper-utils.ts +59 -0
  81. package/test/go/client.test.ts +92 -0
  82. package/test/go/enums.test.ts +132 -0
  83. package/test/go/errors.test.ts +9 -0
  84. package/test/go/models.test.ts +265 -0
  85. package/test/go/resources.test.ts +408 -0
  86. package/test/go/tests.test.ts +143 -0
  87. package/test/node/client.test.ts +199 -94
  88. package/test/node/enums.test.ts +75 -3
  89. package/test/node/errors.test.ts +2 -41
  90. package/test/node/models.test.ts +109 -20
  91. package/test/node/naming.test.ts +37 -4
  92. package/test/node/resources.test.ts +662 -30
  93. package/test/node/serializers.test.ts +36 -7
  94. package/test/node/type-map.test.ts +11 -0
  95. package/test/php/client.test.ts +94 -0
  96. package/test/php/enums.test.ts +173 -0
  97. package/test/php/errors.test.ts +9 -0
  98. package/test/php/models.test.ts +497 -0
  99. package/test/php/resources.test.ts +644 -0
  100. package/test/php/tests.test.ts +118 -0
  101. package/test/python/client.test.ts +200 -0
  102. package/test/python/enums.test.ts +228 -0
  103. package/test/python/errors.test.ts +16 -0
  104. package/test/python/manifest.test.ts +74 -0
  105. package/test/python/models.test.ts +716 -0
  106. package/test/python/resources.test.ts +617 -0
  107. package/test/python/tests.test.ts +202 -0
  108. package/src/node/common.ts +0 -273
  109. package/src/node/config.ts +0 -71
  110. package/src/node/serializers.ts +0 -744
@@ -2,6 +2,7 @@ import { describe, it, expect } from 'vitest';
2
2
  import { generateClient } from '../../src/node/client.js';
3
3
  import { isServiceCoveredByExisting } from '../../src/node/utils.js';
4
4
  import type { EmitterContext, ApiSpec, Service, Model, Enum } from '@workos/oagen';
5
+ import { defaultSdkBehavior } from '@workos/oagen';
5
6
  import type { ApiSurface } from '@workos/oagen/compat';
6
7
 
7
8
  const service: Service = {
@@ -11,7 +12,13 @@ const service: Service = {
11
12
  name: 'getOrganization',
12
13
  httpMethod: 'get',
13
14
  path: '/organizations/{id}',
14
- pathParams: [{ name: 'id', type: { kind: 'primitive', type: 'string' }, required: true }],
15
+ pathParams: [
16
+ {
17
+ name: 'id',
18
+ type: { kind: 'primitive', type: 'string' },
19
+ required: true,
20
+ },
21
+ ],
15
22
  queryParams: [],
16
23
  headerParams: [],
17
24
  response: { kind: 'model', name: 'Organization' },
@@ -25,7 +32,11 @@ const model: Model = {
25
32
  name: 'Organization',
26
33
  fields: [
27
34
  { name: 'id', type: { kind: 'primitive', type: 'string' }, required: true },
28
- { name: 'name', type: { kind: 'primitive', type: 'string' }, required: true },
35
+ {
36
+ name: 'name',
37
+ type: { kind: 'primitive', type: 'string' },
38
+ required: true,
39
+ },
29
40
  ],
30
41
  };
31
42
 
@@ -36,6 +47,7 @@ const spec: ApiSpec = {
36
47
  services: [service],
37
48
  models: [model],
38
49
  enums: [],
50
+ sdk: defaultSdkBehavior(),
39
51
  };
40
52
 
41
53
  const ctx: EmitterContext = {
@@ -88,21 +100,16 @@ describe('generateClient', () => {
88
100
  expect(serviceBarrel!.skipIfExists).toBe(true);
89
101
  });
90
102
 
91
- it('generates package.json and tsconfig.json', () => {
103
+ it('does not generate package.json, tsconfig.json, or worker barrel (now hand-maintained)', () => {
92
104
  const files = generateClient(spec, ctx);
93
- const pkg = files.find((f) => f.path === 'package.json');
94
- const tsconfig = files.find((f) => f.path === 'tsconfig.json');
95
-
96
- expect(pkg).toBeDefined();
97
- expect(pkg!.skipIfExists).toBe(true);
98
-
99
- expect(tsconfig).toBeDefined();
100
- expect(tsconfig!.skipIfExists).toBe(true);
105
+ expect(files.find((f) => f.path === 'package.json')).toBeUndefined();
106
+ expect(files.find((f) => f.path === 'tsconfig.json')).toBeUndefined();
107
+ expect(files.find((f) => f.path === 'src/index.worker.ts')).toBeUndefined();
101
108
  });
102
109
 
103
110
  it('uses overlay-resolved names for imports and accessors', () => {
104
111
  const mfaService: Service = {
105
- name: 'MultiFactorAuth',
112
+ name: 'Billing',
106
113
  operations: [
107
114
  {
108
115
  name: 'enrollFactor',
@@ -120,7 +127,13 @@ describe('generateClient', () => {
120
127
 
121
128
  const mfaModel: Model = {
122
129
  name: 'AuthenticationFactor',
123
- fields: [{ name: 'id', type: { kind: 'primitive', type: 'string' }, required: true }],
130
+ fields: [
131
+ {
132
+ name: 'id',
133
+ type: { kind: 'primitive', type: 'string' },
134
+ required: true,
135
+ },
136
+ ],
124
137
  };
125
138
 
126
139
  const overlaySpec: ApiSpec = {
@@ -130,6 +143,7 @@ describe('generateClient', () => {
130
143
  services: [mfaService],
131
144
  models: [mfaModel],
132
145
  enums: [],
146
+ sdk: defaultSdkBehavior(),
133
147
  };
134
148
 
135
149
  const overlayCtx: EmitterContext = {
@@ -140,7 +154,12 @@ describe('generateClient', () => {
140
154
  methodByOperation: new Map([
141
155
  [
142
156
  'POST /auth/factors/enroll',
143
- { className: 'Mfa', methodName: 'enrollFactor', params: [], returnType: 'void' },
157
+ {
158
+ className: 'Mfa',
159
+ methodName: 'enrollFactor',
160
+ params: [],
161
+ returnType: 'void',
162
+ },
144
163
  ],
145
164
  ]),
146
165
  httpKeyByMethod: new Map(),
@@ -209,14 +228,28 @@ describe('generateClient', () => {
209
228
  const eventModel: Model = {
210
229
  name: 'Event',
211
230
  fields: [
212
- { name: 'id', type: { kind: 'primitive', type: 'string' }, required: true },
213
- { name: 'event', type: { kind: 'primitive', type: 'string' }, required: true },
231
+ {
232
+ name: 'id',
233
+ type: { kind: 'primitive', type: 'string' },
234
+ required: true,
235
+ },
236
+ {
237
+ name: 'event',
238
+ type: { kind: 'primitive', type: 'string' },
239
+ required: true,
240
+ },
214
241
  ],
215
242
  };
216
243
 
217
244
  const otherModel: Model = {
218
245
  name: 'EventCursor',
219
- fields: [{ name: 'cursor', type: { kind: 'primitive', type: 'string' }, required: true }],
246
+ fields: [
247
+ {
248
+ name: 'cursor',
249
+ type: { kind: 'primitive', type: 'string' },
250
+ required: true,
251
+ },
252
+ ],
220
253
  };
221
254
 
222
255
  const eventSpec: ApiSpec = {
@@ -226,6 +259,7 @@ describe('generateClient', () => {
226
259
  services: [eventService],
227
260
  models: [eventModel, otherModel],
228
261
  enums: [],
262
+ sdk: defaultSdkBehavior(),
229
263
  };
230
264
 
231
265
  const surface: ApiSurface = {
@@ -265,9 +299,10 @@ describe('generateClient', () => {
265
299
  expect(content).not.toContain('export type { Event,');
266
300
  expect(content).not.toContain('export type { Event }');
267
301
 
268
- // EventCursor is NOT in apiSurface.exports, so it should still be exported
269
- // (via common barrel wildcard since it's unassigned to any service)
270
- expect(content).toContain("export * from './common/interfaces'");
302
+ // EventCursor is unreachable (not referenced by any service), so it should
303
+ // NOT be exported oagen only generates interface files for reachable models
304
+ expect(content).not.toContain("export * from './common/interfaces'");
305
+ expect(content).not.toContain('EventCursor');
271
306
 
272
307
  // The resource class export should still be present
273
308
  expect(content).toContain("export { Events } from './events/events'");
@@ -289,6 +324,7 @@ describe('generateClient', () => {
289
324
  ],
290
325
  },
291
326
  ],
327
+ sdk: defaultSdkBehavior(),
292
328
  };
293
329
 
294
330
  const surface: ApiSurface = {
@@ -361,17 +397,21 @@ describe('generateClient', () => {
361
397
  ],
362
398
  };
363
399
  const enumService: Service = {
364
- name: 'Connections',
400
+ name: 'Payments',
365
401
  operations: [
366
402
  {
367
- name: 'listConnections',
403
+ name: 'listPayments',
368
404
  httpMethod: 'get',
369
- path: '/connections',
405
+ path: '/payments',
370
406
  pathParams: [],
371
407
  queryParams: [
372
408
  {
373
409
  name: 'type',
374
- type: { kind: 'enum', name: 'ConnectionType', values: ['ADFSSAML', 'GoogleOAuth'] },
410
+ type: {
411
+ kind: 'enum',
412
+ name: 'ConnectionType',
413
+ values: ['ADFSSAML', 'GoogleOAuth'],
414
+ },
375
415
  required: false,
376
416
  },
377
417
  ],
@@ -383,17 +423,21 @@ describe('generateClient', () => {
383
423
  ],
384
424
  };
385
425
  const dirService: Service = {
386
- name: 'Directories',
426
+ name: 'Invoices',
387
427
  operations: [
388
428
  {
389
- name: 'listDirectories',
429
+ name: 'listInvoices',
390
430
  httpMethod: 'get',
391
- path: '/directories',
431
+ path: '/invoices',
392
432
  pathParams: [],
393
433
  queryParams: [
394
434
  {
395
435
  name: 'state',
396
- type: { kind: 'enum', name: 'DirectoryState', values: ['active', 'inactive'] },
436
+ type: {
437
+ kind: 'enum',
438
+ name: 'DirectoryState',
439
+ values: ['active', 'inactive'],
440
+ },
397
441
  required: false,
398
442
  },
399
443
  ],
@@ -411,6 +455,7 @@ describe('generateClient', () => {
411
455
  services: [service, enumService, dirService],
412
456
  models: [model],
413
457
  enums: [enumDef, aliasEnumDef],
458
+ sdk: defaultSdkBehavior(),
414
459
  };
415
460
  const enumCtx: EmitterContext = {
416
461
  namespace: 'workos',
@@ -439,21 +484,21 @@ describe('generateClient', () => {
439
484
 
440
485
  const content = barrel!.content;
441
486
  // Both enums are now re-exported via per-service barrel wildcards
442
- expect(content).toContain("export * from './connections/interfaces'");
443
- expect(content).toContain("export * from './directories/interfaces'");
487
+ expect(content).toContain("export * from './payments/interfaces'");
488
+ expect(content).toContain("export * from './invoices/interfaces'");
444
489
  // Individual enum exports should NOT appear (covered by wildcard)
445
490
  expect(content).not.toContain('export { ConnectionType }');
446
- expect(content).not.toContain('export type { DirectoryState }');
491
+ expect(content).not.toContain('export type { InvoiceState }');
447
492
  });
448
493
 
449
494
  it('skips services whose endpoints are fully covered by existing hand-written services', () => {
450
495
  const connectionsService: Service = {
451
- name: 'Connections',
496
+ name: 'Payments',
452
497
  operations: [
453
498
  {
454
- name: 'listConnections',
499
+ name: 'listPayments',
455
500
  httpMethod: 'get',
456
- path: '/connections',
501
+ path: '/payments',
457
502
  pathParams: [],
458
503
  queryParams: [],
459
504
  headerParams: [],
@@ -464,8 +509,14 @@ describe('generateClient', () => {
464
509
  {
465
510
  name: 'getConnection',
466
511
  httpMethod: 'get',
467
- path: '/connections/{id}',
468
- pathParams: [{ name: 'id', type: { kind: 'primitive', type: 'string' }, required: true }],
512
+ path: '/payments/{id}',
513
+ pathParams: [
514
+ {
515
+ name: 'id',
516
+ type: { kind: 'primitive', type: 'string' },
517
+ required: true,
518
+ },
519
+ ],
469
520
  queryParams: [],
470
521
  headerParams: [],
471
522
  response: { kind: 'model', name: 'Connection' },
@@ -478,8 +529,16 @@ describe('generateClient', () => {
478
529
  const connectionModel: Model = {
479
530
  name: 'Connection',
480
531
  fields: [
481
- { name: 'id', type: { kind: 'primitive', type: 'string' }, required: true },
482
- { name: 'name', type: { kind: 'primitive', type: 'string' }, required: true },
532
+ {
533
+ name: 'id',
534
+ type: { kind: 'primitive', type: 'string' },
535
+ required: true,
536
+ },
537
+ {
538
+ name: 'name',
539
+ type: { kind: 'primitive', type: 'string' },
540
+ required: true,
541
+ },
483
542
  ],
484
543
  };
485
544
 
@@ -502,7 +561,13 @@ describe('generateClient', () => {
502
561
 
503
562
  const radarModel: Model = {
504
563
  name: 'RadarResult',
505
- fields: [{ name: 'score', type: { kind: 'primitive', type: 'number' }, required: true }],
564
+ fields: [
565
+ {
566
+ name: 'score',
567
+ type: { kind: 'primitive', type: 'number' },
568
+ required: true,
569
+ },
570
+ ],
506
571
  };
507
572
 
508
573
  const coveredSpec: ApiSpec = {
@@ -512,6 +577,7 @@ describe('generateClient', () => {
512
577
  services: [connectionsService, radarService],
513
578
  models: [connectionModel, radarModel],
514
579
  enums: [],
580
+ sdk: defaultSdkBehavior(),
515
581
  };
516
582
 
517
583
  const coveredCtx: EmitterContext = {
@@ -600,19 +666,19 @@ describe('generateClient', () => {
600
666
  expect(barrelContent).not.toContain('export { Sso }');
601
667
  expect(barrelContent).not.toContain('export { Connections }');
602
668
 
603
- // But model types from the Connections service should still be exported
604
- // (via the service barrel wildcard for the resolved directory)
605
- expect(barrelContent).toContain("export * from './sso/interfaces'");
669
+ // Covered services don't generate barrel exports their types are
670
+ // already exported by the hand-written service's own barrel.
671
+ expect(barrelContent).not.toContain("export * from './sso/interfaces'");
606
672
  });
607
673
 
608
674
  it('does not skip services when only some operations are covered', () => {
609
675
  const partialService: Service = {
610
- name: 'Directories',
676
+ name: 'Invoices',
611
677
  operations: [
612
678
  {
613
- name: 'listDirectories',
679
+ name: 'listInvoices',
614
680
  httpMethod: 'get',
615
- path: '/directories',
681
+ path: '/invoices',
616
682
  pathParams: [],
617
683
  queryParams: [],
618
684
  headerParams: [],
@@ -621,13 +687,13 @@ describe('generateClient', () => {
621
687
  injectIdempotencyKey: false,
622
688
  },
623
689
  {
624
- name: 'createDirectory',
690
+ name: 'createInvoice',
625
691
  httpMethod: 'post',
626
- path: '/directories',
692
+ path: '/invoices',
627
693
  pathParams: [],
628
694
  queryParams: [],
629
695
  headerParams: [],
630
- response: { kind: 'model', name: 'Directory' },
696
+ response: { kind: 'model', name: 'Invoice' },
631
697
  errors: [],
632
698
  injectIdempotencyKey: false,
633
699
  },
@@ -635,8 +701,14 @@ describe('generateClient', () => {
635
701
  };
636
702
 
637
703
  const dirModel: Model = {
638
- name: 'Directory',
639
- fields: [{ name: 'id', type: { kind: 'primitive', type: 'string' }, required: true }],
704
+ name: 'Invoice',
705
+ fields: [
706
+ {
707
+ name: 'id',
708
+ type: { kind: 'primitive', type: 'string' },
709
+ required: true,
710
+ },
711
+ ],
640
712
  };
641
713
 
642
714
  const partialSpec: ApiSpec = {
@@ -646,6 +718,7 @@ describe('generateClient', () => {
646
718
  services: [partialService],
647
719
  models: [dirModel],
648
720
  enums: [],
721
+ sdk: defaultSdkBehavior(),
649
722
  };
650
723
 
651
724
  const partialCtx: EmitterContext = {
@@ -658,14 +731,14 @@ describe('generateClient', () => {
658
731
  extractedAt: '2024-01-01',
659
732
  interfaces: {},
660
733
  classes: {
661
- DirectorySync: {
662
- name: 'DirectorySync',
734
+ Billing: {
735
+ name: 'Billing',
663
736
  methods: {
664
- listDirectories: [
737
+ listInvoices: [
665
738
  {
666
- name: 'listDirectories',
739
+ name: 'listInvoices',
667
740
  params: [],
668
- returnType: 'Promise<AutoPaginatable<Directory>>',
741
+ returnType: 'Promise<AutoPaginatable<Invoice>>',
669
742
  async: true,
670
743
  },
671
744
  ],
@@ -681,12 +754,12 @@ describe('generateClient', () => {
681
754
  overlayLookup: {
682
755
  methodByOperation: new Map([
683
756
  [
684
- 'GET /directories',
757
+ 'GET /invoices',
685
758
  {
686
- className: 'DirectorySync',
687
- methodName: 'listDirectories',
759
+ className: 'Billing',
760
+ methodName: 'listInvoices',
688
761
  params: [],
689
- returnType: 'Promise<AutoPaginatable<Directory>>',
762
+ returnType: 'Promise<AutoPaginatable<Invoice>>',
690
763
  },
691
764
  ],
692
765
  ]),
@@ -704,7 +777,7 @@ describe('generateClient', () => {
704
777
  const content = workosFile.content;
705
778
 
706
779
  // Service should still be generated because it has an uncovered operation
707
- expect(content).toContain('DirectorySync');
780
+ expect(content).toContain('Billing');
708
781
  });
709
782
 
710
783
  it('does not skip services when no overlay is provided', () => {
@@ -715,7 +788,7 @@ describe('generateClient', () => {
715
788
 
716
789
  it('does not skip services when overlay exists but no apiSurface baseline', () => {
717
790
  const mfaService: Service = {
718
- name: 'MultiFactorAuth',
791
+ name: 'Analytics',
719
792
  operations: [
720
793
  {
721
794
  name: 'enrollFactor',
@@ -733,7 +806,13 @@ describe('generateClient', () => {
733
806
 
734
807
  const mfaModel: Model = {
735
808
  name: 'AuthenticationFactor',
736
- fields: [{ name: 'id', type: { kind: 'primitive', type: 'string' }, required: true }],
809
+ fields: [
810
+ {
811
+ name: 'id',
812
+ type: { kind: 'primitive', type: 'string' },
813
+ required: true,
814
+ },
815
+ ],
737
816
  };
738
817
 
739
818
  const mfaSpec: ApiSpec = {
@@ -743,6 +822,7 @@ describe('generateClient', () => {
743
822
  services: [mfaService],
744
823
  models: [mfaModel],
745
824
  enums: [],
825
+ sdk: defaultSdkBehavior(),
746
826
  };
747
827
 
748
828
  const namingOnlyCtx: EmitterContext = {
@@ -753,7 +833,12 @@ describe('generateClient', () => {
753
833
  methodByOperation: new Map([
754
834
  [
755
835
  'POST /auth/factors/enroll',
756
- { className: 'Mfa', methodName: 'enrollFactor', params: [], returnType: 'void' },
836
+ {
837
+ className: 'Analytics',
838
+ methodName: 'enrollFactor',
839
+ params: [],
840
+ returnType: 'void',
841
+ },
757
842
  ],
758
843
  ]),
759
844
  httpKeyByMethod: new Map(),
@@ -767,7 +852,7 @@ describe('generateClient', () => {
767
852
 
768
853
  const files = generateClient(mfaSpec, namingOnlyCtx);
769
854
  const workosFile = files.find((f) => f.path === 'src/workos.ts')!;
770
- expect(workosFile.content).toContain('readonly mfa = new Mfa(this);');
855
+ expect(workosFile.content).toContain('readonly analytics = new Analytics(this);');
771
856
  });
772
857
  });
773
858
 
@@ -779,16 +864,17 @@ describe('isServiceCoveredByExisting', () => {
779
864
  services: [],
780
865
  models: [],
781
866
  enums: [],
867
+ sdk: defaultSdkBehavior(),
782
868
  };
783
869
 
784
870
  it('returns false when no overlay is provided', () => {
785
871
  const svc: Service = {
786
- name: 'Connections',
872
+ name: 'Payments',
787
873
  operations: [
788
874
  {
789
- name: 'listConnections',
875
+ name: 'listPayments',
790
876
  httpMethod: 'get',
791
- path: '/connections',
877
+ path: '/payments',
792
878
  pathParams: [],
793
879
  queryParams: [],
794
880
  headerParams: [],
@@ -808,12 +894,12 @@ describe('isServiceCoveredByExisting', () => {
808
894
 
809
895
  it('returns false when overlay is empty', () => {
810
896
  const svc: Service = {
811
- name: 'Connections',
897
+ name: 'Payments',
812
898
  operations: [
813
899
  {
814
- name: 'listConnections',
900
+ name: 'listPayments',
815
901
  httpMethod: 'get',
816
- path: '/connections',
902
+ path: '/payments',
817
903
  pathParams: [],
818
904
  queryParams: [],
819
905
  headerParams: [],
@@ -859,7 +945,13 @@ describe('isServiceCoveredByExisting', () => {
859
945
  name: 'getConnection',
860
946
  httpMethod: 'get',
861
947
  path: '/connections/{id}',
862
- pathParams: [{ name: 'id', type: { kind: 'primitive', type: 'string' }, required: true }],
948
+ pathParams: [
949
+ {
950
+ name: 'id',
951
+ type: { kind: 'primitive', type: 'string' },
952
+ required: true,
953
+ },
954
+ ],
863
955
  queryParams: [],
864
956
  headerParams: [],
865
957
  response: { kind: 'model', name: 'Connection' },
@@ -923,12 +1015,12 @@ describe('isServiceCoveredByExisting', () => {
923
1015
 
924
1016
  it('returns false when only some operations are covered', () => {
925
1017
  const svc: Service = {
926
- name: 'Directories',
1018
+ name: 'Invoices',
927
1019
  operations: [
928
1020
  {
929
- name: 'listDirectories',
1021
+ name: 'listInvoices',
930
1022
  httpMethod: 'get',
931
- path: '/directories',
1023
+ path: '/invoices',
932
1024
  pathParams: [],
933
1025
  queryParams: [],
934
1026
  headerParams: [],
@@ -937,13 +1029,13 @@ describe('isServiceCoveredByExisting', () => {
937
1029
  injectIdempotencyKey: false,
938
1030
  },
939
1031
  {
940
- name: 'createDirectory',
1032
+ name: 'createInvoice',
941
1033
  httpMethod: 'post',
942
- path: '/directories',
1034
+ path: '/invoices',
943
1035
  pathParams: [],
944
1036
  queryParams: [],
945
1037
  headerParams: [],
946
- response: { kind: 'model', name: 'Directory' },
1038
+ response: { kind: 'model', name: 'Invoice' },
947
1039
  errors: [],
948
1040
  injectIdempotencyKey: false,
949
1041
  },
@@ -959,8 +1051,8 @@ describe('isServiceCoveredByExisting', () => {
959
1051
  extractedAt: '2024-01-01',
960
1052
  interfaces: {},
961
1053
  classes: {
962
- DirectorySync: {
963
- name: 'DirectorySync',
1054
+ Billing: {
1055
+ name: 'Billing',
964
1056
  methods: {},
965
1057
  properties: {},
966
1058
  constructorParams: [],
@@ -973,10 +1065,10 @@ describe('isServiceCoveredByExisting', () => {
973
1065
  overlayLookup: {
974
1066
  methodByOperation: new Map([
975
1067
  [
976
- 'GET /directories',
1068
+ 'GET /invoices',
977
1069
  {
978
- className: 'DirectorySync',
979
- methodName: 'listDirectories',
1070
+ className: 'Billing',
1071
+ methodName: 'listInvoices',
980
1072
  params: [],
981
1073
  returnType: 'Promise<AutoPaginatable<Directory>>',
982
1074
  },
@@ -1008,7 +1100,12 @@ describe('isServiceCoveredByExisting', () => {
1008
1100
  extractedAt: '2024-01-01',
1009
1101
  interfaces: {},
1010
1102
  classes: {
1011
- Other: { name: 'Other', methods: {}, properties: {}, constructorParams: [] },
1103
+ Other: {
1104
+ name: 'Other',
1105
+ methods: {},
1106
+ properties: {},
1107
+ constructorParams: [],
1108
+ },
1012
1109
  },
1013
1110
  enums: {},
1014
1111
  typeAliases: {},
@@ -1016,7 +1113,15 @@ describe('isServiceCoveredByExisting', () => {
1016
1113
  },
1017
1114
  overlayLookup: {
1018
1115
  methodByOperation: new Map([
1019
- ['GET /something', { className: 'Other', methodName: 'doSomething', params: [], returnType: 'void' }],
1116
+ [
1117
+ 'GET /something',
1118
+ {
1119
+ className: 'Other',
1120
+ methodName: 'doSomething',
1121
+ params: [],
1122
+ returnType: 'void',
1123
+ },
1124
+ ],
1020
1125
  ]),
1021
1126
  httpKeyByMethod: new Map(),
1022
1127
  interfaceByName: new Map(),
@@ -1031,12 +1136,12 @@ describe('isServiceCoveredByExisting', () => {
1031
1136
 
1032
1137
  it('returns false when overlay covers operations but target class is not in baseline', () => {
1033
1138
  const svc: Service = {
1034
- name: 'Connections',
1139
+ name: 'Payments',
1035
1140
  operations: [
1036
1141
  {
1037
- name: 'listConnections',
1142
+ name: 'listPayments',
1038
1143
  httpMethod: 'get',
1039
- path: '/connections',
1144
+ path: '/payments',
1040
1145
  pathParams: [],
1041
1146
  queryParams: [],
1042
1147
  headerParams: [],
@@ -1063,10 +1168,10 @@ describe('isServiceCoveredByExisting', () => {
1063
1168
  overlayLookup: {
1064
1169
  methodByOperation: new Map([
1065
1170
  [
1066
- 'GET /connections',
1171
+ 'GET /payments',
1067
1172
  {
1068
1173
  className: 'Sso',
1069
- methodName: 'listConnections',
1174
+ methodName: 'listPayments',
1070
1175
  params: [],
1071
1176
  returnType: 'Promise<AutoPaginatable<Connection>>',
1072
1177
  },
@@ -1085,12 +1190,12 @@ describe('isServiceCoveredByExisting', () => {
1085
1190
 
1086
1191
  it('returns false when no apiSurface is provided', () => {
1087
1192
  const svc: Service = {
1088
- name: 'Connections',
1193
+ name: 'Payments',
1089
1194
  operations: [
1090
1195
  {
1091
- name: 'listConnections',
1196
+ name: 'listPayments',
1092
1197
  httpMethod: 'get',
1093
- path: '/connections',
1198
+ path: '/payments',
1094
1199
  pathParams: [],
1095
1200
  queryParams: [],
1096
1201
  headerParams: [],
@@ -1107,10 +1212,10 @@ describe('isServiceCoveredByExisting', () => {
1107
1212
  overlayLookup: {
1108
1213
  methodByOperation: new Map([
1109
1214
  [
1110
- 'GET /connections',
1215
+ 'GET /payments',
1111
1216
  {
1112
1217
  className: 'Sso',
1113
- methodName: 'listConnections',
1218
+ methodName: 'listPayments',
1114
1219
  params: [],
1115
1220
  returnType: 'Promise<AutoPaginatable<Connection>>',
1116
1221
  },