@workos/oagen-emitters 0.2.1 → 0.4.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 (136) hide show
  1. package/.husky/pre-commit +1 -0
  2. package/.release-please-manifest.json +1 -1
  3. package/CHANGELOG.md +15 -0
  4. package/README.md +129 -0
  5. package/dist/index.d.mts +13 -1
  6. package/dist/index.d.mts.map +1 -1
  7. package/dist/index.mjs +14549 -3385
  8. package/dist/index.mjs.map +1 -1
  9. package/docs/sdk-architecture/dotnet.md +336 -0
  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 +328 -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 +45 -12
  18. package/smoke/sdk-go.ts +116 -42
  19. package/smoke/sdk-php.ts +28 -26
  20. package/smoke/sdk-python.ts +5 -2
  21. package/src/dotnet/client.ts +89 -0
  22. package/src/dotnet/enums.ts +323 -0
  23. package/src/dotnet/fixtures.ts +236 -0
  24. package/src/dotnet/index.ts +246 -0
  25. package/src/dotnet/manifest.ts +36 -0
  26. package/src/dotnet/models.ts +344 -0
  27. package/src/dotnet/naming.ts +330 -0
  28. package/src/dotnet/resources.ts +622 -0
  29. package/src/dotnet/tests.ts +693 -0
  30. package/src/dotnet/type-map.ts +201 -0
  31. package/src/dotnet/wrappers.ts +186 -0
  32. package/src/go/client.ts +141 -0
  33. package/src/go/enums.ts +196 -0
  34. package/src/go/fixtures.ts +212 -0
  35. package/src/go/index.ts +84 -0
  36. package/src/go/manifest.ts +36 -0
  37. package/src/go/models.ts +254 -0
  38. package/src/go/naming.ts +179 -0
  39. package/src/go/resources.ts +827 -0
  40. package/src/go/tests.ts +751 -0
  41. package/src/go/type-map.ts +82 -0
  42. package/src/go/wrappers.ts +261 -0
  43. package/src/index.ts +4 -0
  44. package/src/kotlin/client.ts +53 -0
  45. package/src/kotlin/enums.ts +162 -0
  46. package/src/kotlin/index.ts +92 -0
  47. package/src/kotlin/manifest.ts +55 -0
  48. package/src/kotlin/models.ts +395 -0
  49. package/src/kotlin/naming.ts +223 -0
  50. package/src/kotlin/overrides.ts +25 -0
  51. package/src/kotlin/resources.ts +667 -0
  52. package/src/kotlin/tests.ts +1019 -0
  53. package/src/kotlin/type-map.ts +123 -0
  54. package/src/kotlin/wrappers.ts +168 -0
  55. package/src/node/client.ts +128 -115
  56. package/src/node/enums.ts +9 -0
  57. package/src/node/errors.ts +37 -232
  58. package/src/node/field-plan.ts +726 -0
  59. package/src/node/fixtures.ts +9 -1
  60. package/src/node/index.ts +3 -9
  61. package/src/node/models.ts +178 -21
  62. package/src/node/naming.ts +49 -111
  63. package/src/node/resources.ts +527 -397
  64. package/src/node/sdk-errors.ts +41 -0
  65. package/src/node/tests.ts +69 -19
  66. package/src/node/type-map.ts +4 -2
  67. package/src/node/utils.ts +13 -71
  68. package/src/node/wrappers.ts +151 -0
  69. package/src/php/client.ts +179 -0
  70. package/src/php/enums.ts +67 -0
  71. package/src/php/errors.ts +9 -0
  72. package/src/php/fixtures.ts +181 -0
  73. package/src/php/index.ts +96 -0
  74. package/src/php/manifest.ts +36 -0
  75. package/src/php/models.ts +310 -0
  76. package/src/php/naming.ts +279 -0
  77. package/src/php/resources.ts +636 -0
  78. package/src/php/tests.ts +609 -0
  79. package/src/php/type-map.ts +90 -0
  80. package/src/php/utils.ts +18 -0
  81. package/src/php/wrappers.ts +152 -0
  82. package/src/python/client.ts +345 -0
  83. package/src/python/enums.ts +313 -0
  84. package/src/python/fixtures.ts +196 -0
  85. package/src/python/index.ts +95 -0
  86. package/src/python/manifest.ts +38 -0
  87. package/src/python/models.ts +688 -0
  88. package/src/python/naming.ts +189 -0
  89. package/src/python/resources.ts +1322 -0
  90. package/src/python/tests.ts +1335 -0
  91. package/src/python/type-map.ts +93 -0
  92. package/src/python/wrappers.ts +191 -0
  93. package/src/shared/model-utils.ts +472 -0
  94. package/src/shared/naming-utils.ts +154 -0
  95. package/src/shared/non-spec-services.ts +54 -0
  96. package/src/shared/resolved-ops.ts +109 -0
  97. package/src/shared/wrapper-utils.ts +70 -0
  98. package/test/dotnet/client.test.ts +121 -0
  99. package/test/dotnet/enums.test.ts +193 -0
  100. package/test/dotnet/errors.test.ts +9 -0
  101. package/test/dotnet/manifest.test.ts +82 -0
  102. package/test/dotnet/models.test.ts +260 -0
  103. package/test/dotnet/resources.test.ts +255 -0
  104. package/test/dotnet/tests.test.ts +202 -0
  105. package/test/go/client.test.ts +92 -0
  106. package/test/go/enums.test.ts +132 -0
  107. package/test/go/errors.test.ts +9 -0
  108. package/test/go/models.test.ts +265 -0
  109. package/test/go/resources.test.ts +408 -0
  110. package/test/go/tests.test.ts +143 -0
  111. package/test/kotlin/models.test.ts +135 -0
  112. package/test/kotlin/tests.test.ts +176 -0
  113. package/test/node/client.test.ts +92 -12
  114. package/test/node/enums.test.ts +2 -0
  115. package/test/node/errors.test.ts +2 -41
  116. package/test/node/models.test.ts +2 -0
  117. package/test/node/naming.test.ts +23 -0
  118. package/test/node/resources.test.ts +315 -84
  119. package/test/node/serializers.test.ts +3 -1
  120. package/test/node/type-map.test.ts +11 -0
  121. package/test/php/client.test.ts +95 -0
  122. package/test/php/enums.test.ts +173 -0
  123. package/test/php/errors.test.ts +9 -0
  124. package/test/php/models.test.ts +497 -0
  125. package/test/php/resources.test.ts +682 -0
  126. package/test/php/tests.test.ts +185 -0
  127. package/test/python/client.test.ts +200 -0
  128. package/test/python/enums.test.ts +228 -0
  129. package/test/python/errors.test.ts +16 -0
  130. package/test/python/manifest.test.ts +74 -0
  131. package/test/python/models.test.ts +716 -0
  132. package/test/python/resources.test.ts +617 -0
  133. package/test/python/tests.test.ts +202 -0
  134. package/src/node/common.ts +0 -273
  135. package/src/node/config.ts +0 -71
  136. package/src/node/serializers.ts +0 -746
@@ -0,0 +1,315 @@
1
+ # PHP SDK Architecture
2
+
3
+ ## Overview
4
+
5
+ A PHP 8.2+ SDK using readonly classes, backed enums, Guzzle for HTTP, and PHPUnit for testing. PSR-4 autoloading with Composer.
6
+
7
+ ## Naming Conventions
8
+
9
+ | IR Name | PHP Convention | Example |
10
+ | --------------------- | -------------- | ----------------- |
11
+ | `UserProfile` (class) | PascalCase | `UserProfile` |
12
+ | `UserProfile` (file) | PascalCase.php | `UserProfile.php` |
13
+ | `listUsers` (method) | camelCase | `listUsers` |
14
+ | `user_id` (field) | camelCase | `userId` |
15
+ | `ACTIVE` (enum case) | PascalCase | `Active` |
16
+
17
+ ## Type Mapping
18
+
19
+ | IR TypeRef | PHP Type Hint | PHPDoc Type |
20
+ | -------------------- | -------------------- | -------------------- |
21
+ | `string` | `string` | `string` |
22
+ | `string` (date) | `string` | `string` |
23
+ | `string` (date-time) | `\DateTimeImmutable` | `\DateTimeImmutable` |
24
+ | `string` (uuid) | `string` | `string` |
25
+ | `string` (binary) | `string` | `string` |
26
+ | `integer` | `int` | `int` |
27
+ | `number` | `float` | `float` |
28
+ | `boolean` | `bool` | `bool` |
29
+ | `unknown` | `mixed` | `mixed` |
30
+ | `array<T>` | `array` | `array<T>` |
31
+ | `model Foo` | `Foo` | `Foo` |
32
+ | `enum Foo` | `Foo` | `Foo` |
33
+ | `nullable<T>` | `?T` | `T\|null` |
34
+ | `union<A,B>` | `A\|B` | `A\|B` |
35
+ | `map<string,V>` | `array` | `array<string, V>` |
36
+ | `literal "foo"` | `string` | `string` |
37
+
38
+ ## Model Pattern
39
+
40
+ Readonly classes with constructor promotion, `fromArray()` factory, and `toArray()` serialization:
41
+
42
+ ```php
43
+ <?php
44
+
45
+ namespace WorkOS\Models;
46
+
47
+ readonly class Organization implements \JsonSerializable
48
+ {
49
+ public function __construct(
50
+ public string $id,
51
+ public string $name,
52
+ public ?string $slug = null,
53
+ public ?\DateTimeImmutable $createdAt = null,
54
+ ) {}
55
+
56
+ public static function fromArray(array $data): static
57
+ {
58
+ return new static(
59
+ id: $data['id'],
60
+ name: $data['name'],
61
+ slug: $data['slug'] ?? null,
62
+ createdAt: isset($data['created_at'])
63
+ ? new \DateTimeImmutable($data['created_at'])
64
+ : null,
65
+ );
66
+ }
67
+
68
+ public function toArray(): array
69
+ {
70
+ return array_filter([
71
+ 'id' => $this->id,
72
+ 'name' => $this->name,
73
+ 'slug' => $this->slug,
74
+ 'created_at' => $this->createdAt?->format(\DateTimeInterface::RFC3339_EXTENDED),
75
+ ], fn ($v) => $v !== null);
76
+ }
77
+
78
+ public function jsonSerialize(): array
79
+ {
80
+ return $this->toArray();
81
+ }
82
+ }
83
+ ```
84
+
85
+ ## Enum Pattern
86
+
87
+ PHP 8.1+ backed enums:
88
+
89
+ ```php
90
+ <?php
91
+
92
+ namespace WorkOS\Enums;
93
+
94
+ enum OrganizationStatus: string
95
+ {
96
+ case Active = 'active';
97
+ case Inactive = 'inactive';
98
+
99
+ public static function tryFromValue(string $value): self|string
100
+ {
101
+ return self::tryFrom($value) ?? $value;
102
+ }
103
+ }
104
+ ```
105
+
106
+ ## Resource Pattern
107
+
108
+ Resource classes with typed methods, injected HTTP client:
109
+
110
+ ```php
111
+ <?php
112
+
113
+ namespace WorkOS\Resources;
114
+
115
+ use WorkOS\HttpClient;
116
+ use WorkOS\Models\Organization;
117
+ use WorkOS\PaginatedResponse;
118
+ use WorkOS\RequestOptions;
119
+
120
+ class Organizations
121
+ {
122
+ public function __construct(
123
+ private readonly HttpClient $client,
124
+ ) {}
125
+
126
+ public function get(string $id, ?RequestOptions $options = null): Organization
127
+ {
128
+ $response = $this->client->request(
129
+ method: 'GET',
130
+ path: "organizations/{$id}",
131
+ options: $options,
132
+ );
133
+ return Organization::fromArray($response);
134
+ }
135
+
136
+ public function list(
137
+ ?int $limit = null,
138
+ ?string $after = null,
139
+ ?RequestOptions $options = null,
140
+ ): PaginatedResponse
141
+ {
142
+ $response = $this->client->request(
143
+ method: 'GET',
144
+ path: 'organizations',
145
+ query: array_filter([
146
+ 'limit' => $limit,
147
+ 'after' => $after,
148
+ ], fn ($v) => $v !== null),
149
+ options: $options,
150
+ );
151
+ return PaginatedResponse::fromArray($response, Organization::class);
152
+ }
153
+ }
154
+ ```
155
+
156
+ ## Client Architecture
157
+
158
+ Main client with resource accessors:
159
+
160
+ ```php
161
+ <?php
162
+
163
+ namespace WorkOS;
164
+
165
+ class WorkOS
166
+ {
167
+ private HttpClient $httpClient;
168
+ private ?Resources\Organizations $organizations = null;
169
+
170
+ public function __construct(
171
+ string $apiKey = null,
172
+ string $baseUrl = 'https://api.workos.com',
173
+ int $timeout = 60,
174
+ int $maxRetries = 3,
175
+ ) {
176
+ $apiKey ??= getenv('WORKOS_API_KEY') ?: '';
177
+ $this->httpClient = new HttpClient($apiKey, $baseUrl, $timeout, $maxRetries);
178
+ }
179
+
180
+ public function organizations(): Resources\Organizations
181
+ {
182
+ return $this->organizations ??= new Resources\Organizations($this->httpClient);
183
+ }
184
+ }
185
+ ```
186
+
187
+ ## Error Handling
188
+
189
+ Exception hierarchy extending a base `ApiException`:
190
+
191
+ ```php
192
+ <?php
193
+
194
+ namespace WorkOS\Exceptions;
195
+
196
+ class ApiException extends \Exception { /* status_code, request_id, etc. */ }
197
+ class AuthenticationException extends ApiException {}
198
+ class BadRequestException extends ApiException {}
199
+ class NotFoundException extends ApiException {}
200
+ class UnprocessableEntityException extends ApiException {}
201
+ class RateLimitExceededException extends ApiException {}
202
+ class ServerException extends ApiException {}
203
+ class ConfigurationException extends \Exception {}
204
+ class ConnectionException extends \Exception {}
205
+ class TimeoutException extends \Exception {}
206
+ ```
207
+
208
+ ## Pagination
209
+
210
+ Generic paginated response with auto-iteration:
211
+
212
+ ```php
213
+ <?php
214
+
215
+ namespace WorkOS;
216
+
217
+ class PaginatedResponse implements \IteratorAggregate
218
+ {
219
+ public function __construct(
220
+ public readonly array $data,
221
+ public readonly array $listMetadata,
222
+ private readonly ?\Closure $fetchPage = null,
223
+ ) {}
224
+
225
+ public function hasMore(): bool { return ($this->listMetadata['after'] ?? null) !== null; }
226
+
227
+ public function getIterator(): \Generator
228
+ {
229
+ $page = $this;
230
+ while (true) {
231
+ yield from $page->data;
232
+ if (!$page->hasMore() || $page->fetchPage === null) break;
233
+ $page = ($page->fetchPage)(['after' => $page->listMetadata['after']]);
234
+ }
235
+ }
236
+ }
237
+ ```
238
+
239
+ ## Retry Logic
240
+
241
+ Exponential backoff with jitter. Retryable statuses: 429, 500, 502, 503, 504. Respects `Retry-After` header.
242
+
243
+ ## Testing
244
+
245
+ PHPUnit with Guzzle `MockHandler`:
246
+
247
+ ```php
248
+ <?php
249
+
250
+ namespace Tests\Resources;
251
+
252
+ use GuzzleHttp\Handler\MockHandler;
253
+ use GuzzleHttp\HandlerStack;
254
+ use GuzzleHttp\Psr7\Response;
255
+ use PHPUnit\Framework\TestCase;
256
+ use WorkOS\WorkOS;
257
+
258
+ class OrganizationsTest extends TestCase
259
+ {
260
+ public function testGet(): void
261
+ {
262
+ $fixture = json_decode(file_get_contents(__DIR__ . '/../Fixtures/organization.json'), true);
263
+ $mock = new MockHandler([new Response(200, [], json_encode($fixture))]);
264
+ $client = new WorkOS(apiKey: 'test', handler: HandlerStack::create($mock));
265
+
266
+ $result = $client->organizations()->get('org_01234');
267
+ $this->assertInstanceOf(\WorkOS\Models\Organization::class, $result);
268
+ }
269
+ }
270
+ ```
271
+
272
+ ## Structural Guidelines
273
+
274
+ | Category | Choice |
275
+ | ------------------ | -------------------------- |
276
+ | PHP Version | 8.2+ |
277
+ | HTTP Client | Guzzle 7 |
278
+ | Testing | PHPUnit 11 |
279
+ | HTTP Mocking | Guzzle MockHandler |
280
+ | Documentation | PHPDoc |
281
+ | Type Signatures | Native type hints + PHPDoc |
282
+ | Linting/Formatting | PHP CS Fixer |
283
+ | JSON Parsing | Native json_decode/encode |
284
+ | Package Manager | Composer |
285
+ | Build Tool | N/A (interpreted) |
286
+
287
+ ## Directory Structure
288
+
289
+ ```
290
+ src/
291
+ ├── {Namespace}.php # Main client class
292
+ ├── HttpClient.php # HTTP client with retry logic
293
+ ├── PaginatedResponse.php # Cursor pagination
294
+ ├── RequestOptions.php # Per-request options
295
+ ├── Enums/
296
+ │ └── {EnumName}.php
297
+ ├── Models/
298
+ │ └── {ModelName}.php
299
+ ├── Resources/
300
+ │ └── {ServiceName}.php
301
+ └── Exceptions/
302
+ ├── ApiException.php
303
+ ├── AuthenticationException.php
304
+ └── ...
305
+ tests/
306
+ ├── Fixtures/
307
+ │ └── {model_name}.json
308
+ ├── Resources/
309
+ │ └── {ServiceName}Test.php
310
+ ├── Models/
311
+ │ └── {ModelName}Test.php
312
+ └── ClientTest.php
313
+ composer.json
314
+ phpunit.xml
315
+ ```