@typespec/emitter-framework 0.6.0-dev.4 → 0.6.0-dev.6

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 (92) hide show
  1. package/dist/src/core/context/name-policy-context.js +1 -2
  2. package/dist/src/core/index.js +1 -2
  3. package/dist/src/core/transport-name-policy.js +1 -2
  4. package/dist/src/core/write-output.js +1 -2
  5. package/dist/src/lib.js +1 -2
  6. package/dist/src/testing/index.js +1 -2
  7. package/dist/src/testing/scenario-test/harness.js +1 -2
  8. package/dist/src/testing/scenario-test/index.js +1 -2
  9. package/dist/src/testing/scenario-test/snippet-extractor.js +1 -2
  10. package/dist/src/testing/scenario-test/test-host.js +1 -2
  11. package/dist/src/typescript/components/array-expression.js +1 -2
  12. package/dist/src/typescript/components/arrow-function.js +2 -5
  13. package/dist/src/typescript/components/class-method.js +2 -4
  14. package/dist/src/typescript/components/enum-declaration.js +2 -4
  15. package/dist/src/typescript/components/function-declaration.js +2 -4
  16. package/dist/src/typescript/components/function-expression.js +2 -5
  17. package/dist/src/typescript/components/function-type.js +2 -5
  18. package/dist/src/typescript/components/index.js +1 -2
  19. package/dist/src/typescript/components/interface-declaration.js +2 -5
  20. package/dist/src/typescript/components/interface-member.js +2 -4
  21. package/dist/src/typescript/components/interface-method.d.ts.map +1 -1
  22. package/dist/src/typescript/components/interface-method.js +5 -8
  23. package/dist/src/typescript/components/record-expression.js +1 -2
  24. package/dist/src/typescript/components/static-serializers.js +1 -2
  25. package/dist/src/typescript/components/type-alias-declaration.js +2 -5
  26. package/dist/src/typescript/components/type-declaration.js +2 -4
  27. package/dist/src/typescript/components/type-expression.js +2 -4
  28. package/dist/src/typescript/components/type-transform.js +2 -4
  29. package/dist/src/typescript/components/union-declaration.js +2 -4
  30. package/dist/src/typescript/components/union-expression.js +2 -4
  31. package/dist/src/typescript/components/value-expression.js +2 -4
  32. package/dist/src/typescript/index.js +1 -2
  33. package/dist/src/typescript/lib.js +1 -2
  34. package/dist/src/typescript/utils/operation.js +1 -2
  35. package/dist/test/testing/snippet-extractor-csharp.test.js +96 -0
  36. package/dist/test/testing/snippet-extractor-java.test.js +104 -0
  37. package/dist/test/testing/snippet-extractor-python.test.js +33 -0
  38. package/dist/test/testing/snippet-extractor-typescript.test.js +161 -0
  39. package/dist/test/typescript/components/arrow-function.test.js +88 -0
  40. package/dist/test/typescript/components/enum-declaration.test.js +118 -0
  41. package/dist/test/typescript/components/function-declaration.test.js +246 -0
  42. package/dist/test/typescript/components/function-expression.test.js +88 -0
  43. package/dist/test/typescript/components/function-type.test.js +85 -0
  44. package/dist/test/typescript/components/interface-declaration.test.js +775 -0
  45. package/dist/test/typescript/components/interface-method.test.js +272 -0
  46. package/dist/test/typescript/components/member-expression.test.js +155 -0
  47. package/dist/test/typescript/components/type-alias-declaration.test.js +155 -0
  48. package/dist/test/typescript/components/type-transform.test.js +682 -0
  49. package/dist/test/typescript/components/union-declaration.test.js +205 -0
  50. package/dist/test/typescript/components/value-expression.test.js +199 -0
  51. package/dist/test/typescript/test-host.js +40 -0
  52. package/dist/test/utils.js +18 -0
  53. package/package.json +5 -10
  54. package/src/typescript/components/interface-method.tsx +2 -4
  55. package/test/typescript/components/interface-method.test.tsx +167 -2
  56. package/vitest.config.ts +2 -9
  57. package/babel.config.js +0 -4
  58. package/dist/src/core/context/index.js.map +0 -1
  59. package/dist/src/core/context/name-policy-context.js.map +0 -1
  60. package/dist/src/core/index.js.map +0 -1
  61. package/dist/src/core/transport-name-policy.js.map +0 -1
  62. package/dist/src/core/write-output.js.map +0 -1
  63. package/dist/src/lib.js.map +0 -1
  64. package/dist/src/testing/index.js.map +0 -1
  65. package/dist/src/testing/scenario-test/harness.js.map +0 -1
  66. package/dist/src/testing/scenario-test/index.js.map +0 -1
  67. package/dist/src/testing/scenario-test/snippet-extractor.js.map +0 -1
  68. package/dist/src/testing/scenario-test/test-host.js.map +0 -1
  69. package/dist/src/typescript/components/array-expression.js.map +0 -1
  70. package/dist/src/typescript/components/arrow-function.js.map +0 -1
  71. package/dist/src/typescript/components/class-method.js.map +0 -1
  72. package/dist/src/typescript/components/enum-declaration.js.map +0 -1
  73. package/dist/src/typescript/components/function-declaration.js.map +0 -1
  74. package/dist/src/typescript/components/function-expression.js.map +0 -1
  75. package/dist/src/typescript/components/function-type.js.map +0 -1
  76. package/dist/src/typescript/components/index.js.map +0 -1
  77. package/dist/src/typescript/components/interface-declaration.js.map +0 -1
  78. package/dist/src/typescript/components/interface-member.js.map +0 -1
  79. package/dist/src/typescript/components/interface-method.js.map +0 -1
  80. package/dist/src/typescript/components/record-expression.js.map +0 -1
  81. package/dist/src/typescript/components/static-serializers.js.map +0 -1
  82. package/dist/src/typescript/components/type-alias-declaration.js.map +0 -1
  83. package/dist/src/typescript/components/type-declaration.js.map +0 -1
  84. package/dist/src/typescript/components/type-expression.js.map +0 -1
  85. package/dist/src/typescript/components/type-transform.js.map +0 -1
  86. package/dist/src/typescript/components/union-declaration.js.map +0 -1
  87. package/dist/src/typescript/components/union-expression.js.map +0 -1
  88. package/dist/src/typescript/components/value-expression.js.map +0 -1
  89. package/dist/src/typescript/index.js.map +0 -1
  90. package/dist/src/typescript/lib.js.map +0 -1
  91. package/dist/src/typescript/utils/index.js.map +0 -1
  92. package/dist/src/typescript/utils/operation.js.map +0 -1
@@ -0,0 +1,682 @@
1
+ import { createComponent as _$createComponent, memo as _$memo } from "@alloy-js/core/jsx-runtime";
2
+ import { code, Output, render } from "@alloy-js/core";
3
+ import { d } from "@alloy-js/core/testing";
4
+ import * as ts from "@alloy-js/typescript";
5
+ import { SourceFile } from "@alloy-js/typescript";
6
+ import { assert, beforeEach, describe, expect, it } from "vitest";
7
+ import { ArraySerializer, DateDeserializer, RecordSerializer } from "../../../src/typescript/components/static-serializers.js";
8
+ import { getTypeTransformerRefkey, ModelTransformExpression, TypeTransformCall, TypeTransformDeclaration } from "../../../src/typescript/components/type-transform.js";
9
+ import { TypeDeclaration } from "../../../src/typescript/index.js";
10
+ import { createEmitterFrameworkTestRunner } from "../test-host.js";
11
+ describe.skip("Typescript Type Transform", () => {
12
+ let testRunner;
13
+ const namePolicy = ts.createTSNamePolicy();
14
+ beforeEach(async () => {
15
+ testRunner = await createEmitterFrameworkTestRunner();
16
+ });
17
+ describe("Model Transforms", () => {
18
+ describe("ModelTransformExpression", () => {
19
+ it("should render a transform expression to client", async () => {
20
+ const spec = `
21
+ namespace DemoService;
22
+ @test model Widget {
23
+ id: string;
24
+ birth_year: int32;
25
+ color: "blue" | "red";
26
+ }
27
+ `;
28
+ const {
29
+ Widget
30
+ } = await testRunner.compile(spec);
31
+ const res = render(_$createComponent(Output, {
32
+ namePolicy: namePolicy,
33
+ get children() {
34
+ return _$createComponent(SourceFile, {
35
+ path: "test.ts",
36
+ get children() {
37
+ return [code`
38
+ const wireWidget = {id: "1", birth_year: 1988, color: "blue"};
39
+ `, "const clientWidget =", " ", _$createComponent(ModelTransformExpression, {
40
+ type: Widget,
41
+ target: "application",
42
+ itemPath: ["wireWidget"]
43
+ })];
44
+ }
45
+ });
46
+ }
47
+ }));
48
+ const testFile = res.contents.find(file => file.path === "test.ts");
49
+ assert(testFile, "test.ts file not rendered");
50
+ const actualContent = testFile.contents;
51
+ const expectedContent = d`
52
+ const wireWidget = {id: "1", birth_year: 1988, color: "blue"};
53
+ const clientWidget = {
54
+ "id": wireWidget.id,
55
+ "birthYear": wireWidget.birth_year,
56
+ "color": wireWidget.color
57
+ }`;
58
+ expect(actualContent).toBe(expectedContent);
59
+ });
60
+ it("should render a transform expression to wire", async () => {
61
+ const spec = `
62
+ namespace DemoService;
63
+ @test model Widget {
64
+ id: string;
65
+ birth_year: int32;
66
+ color: "blue" | "red";
67
+ }
68
+ `;
69
+ const {
70
+ Widget
71
+ } = await testRunner.compile(spec);
72
+ const res = render(_$createComponent(Output, {
73
+ namePolicy: namePolicy,
74
+ get children() {
75
+ return _$createComponent(SourceFile, {
76
+ path: "test.ts",
77
+ get children() {
78
+ return [code`
79
+ const clientWidget = {id: "1", birthYear: 1988, color: "blue"};
80
+ `, "const wireWidget =", " ", _$createComponent(ModelTransformExpression, {
81
+ type: Widget,
82
+ target: "transport",
83
+ itemPath: ["clientWidget"]
84
+ })];
85
+ }
86
+ });
87
+ }
88
+ }));
89
+ const testFile = res.contents.find(file => file.path === "test.ts");
90
+ assert(testFile, "test.ts file not rendered");
91
+ const actualContent = testFile.contents;
92
+ const expectedContent = d`
93
+ const clientWidget = {id: "1", birthYear: 1988, color: "blue"};
94
+ const wireWidget = {
95
+ "id": clientWidget.id,
96
+ "birth_year": clientWidget.birthYear,
97
+ "color": clientWidget.color
98
+ }`;
99
+ expect(actualContent).toBe(expectedContent);
100
+ });
101
+ it("should render a transform expression that contains a utcDateTime to client", async () => {
102
+ const spec = `
103
+ namespace DemoService;
104
+ @test model Widget {
105
+ id: string;
106
+ birth_date: utcDateTime;
107
+ color: "blue" | "red";
108
+ }
109
+ `;
110
+ const {
111
+ Widget
112
+ } = await testRunner.compile(spec);
113
+ const res = render(_$createComponent(Output, {
114
+ namePolicy: namePolicy,
115
+ get children() {
116
+ return [_$createComponent(SourceFile, {
117
+ path: "static-serializers.ts",
118
+ get children() {
119
+ return _$createComponent(DateDeserializer, {});
120
+ }
121
+ }), _$createComponent(SourceFile, {
122
+ path: "test.ts",
123
+ get children() {
124
+ return [code`
125
+ const wireWidget = {id: "1", birth_date: "1988-04-29T19:30:00Z", color: "blue"};
126
+ `, "const clientWidget =", " ", _$createComponent(ModelTransformExpression, {
127
+ type: Widget,
128
+ target: "application",
129
+ itemPath: ["wireWidget"]
130
+ })];
131
+ }
132
+ })];
133
+ }
134
+ }));
135
+ const testFile = res.contents.find(file => file.path === "test.ts");
136
+ assert(testFile, "test.ts file not rendered");
137
+ const actualContent = testFile.contents;
138
+ const expectedContent = d`
139
+ import { dateDeserializer } from "./static-serializers.js";
140
+
141
+ const wireWidget = {id: "1", birth_date: "1988-04-29T19:30:00Z", color: "blue"};
142
+ const clientWidget = {
143
+ "id": wireWidget.id,
144
+ "birthDate": dateDeserializer(wireWidget.birth_date),
145
+ "color": wireWidget.color
146
+ }`;
147
+ expect(actualContent).toBe(expectedContent);
148
+ });
149
+ });
150
+ describe("TypeTransformDeclaration", () => {
151
+ it("should render a transform functions for a model containing array", async () => {
152
+ const spec = `
153
+ namespace DemoService;
154
+ @test model Widget {
155
+ id: string;
156
+ my_color: "blue" | "red";
157
+ simple?: string[];
158
+ complex: Widget[];
159
+ nested: Widget[][];
160
+ optionalString?: string;
161
+ }
162
+ `;
163
+ const {
164
+ Widget
165
+ } = await testRunner.compile(spec);
166
+ const res = render(_$createComponent(Output, {
167
+ namePolicy: namePolicy,
168
+ get children() {
169
+ return [_$createComponent(SourceFile, {
170
+ path: "serializers.ts",
171
+ get children() {
172
+ return _$createComponent(ArraySerializer, {});
173
+ }
174
+ }), _$createComponent(SourceFile, {
175
+ path: "test.ts",
176
+ get children() {
177
+ return [_$createComponent(TypeDeclaration, {
178
+ "export": true,
179
+ type: Widget
180
+ }), _$createComponent(TypeTransformDeclaration, {
181
+ type: Widget,
182
+ target: "application"
183
+ }), _$createComponent(TypeTransformDeclaration, {
184
+ type: Widget,
185
+ target: "transport"
186
+ })];
187
+ }
188
+ })];
189
+ }
190
+ }));
191
+ const testFile = res.contents.find(file => file.path === "test.ts");
192
+ assert(testFile, "test.ts file not rendered");
193
+ const actualContent = testFile.contents;
194
+ const expectedContent = d`
195
+ import { arraySerializer } from "./serializers.js";
196
+
197
+ export interface Widget {
198
+ "id": string;
199
+ "myColor": "blue" | "red";
200
+ "simple"?: Array<string>;
201
+ "complex": Array<Widget>;
202
+ "nested": Array<Array<Widget>>;
203
+ "optionalString"?: string;
204
+ }
205
+ export function widgetToApplication(item: any) {
206
+ return {
207
+ "id": item.id,
208
+ "myColor": item.my_color,
209
+ "simple": item.simple ? arraySerializer(item.simple, ) : item.simple,
210
+ "complex": arraySerializer(item.complex, widgetToApplication),
211
+ "nested": arraySerializer(item.nested, (i: any) => arraySerializer(i, widgetToApplication)),
212
+ "optionalString": item.optionalString
213
+ };
214
+ }
215
+ export function widgetToTransport(item: Widget) {
216
+ return {
217
+ "id": item.id,
218
+ "my_color": item.myColor,
219
+ "simple": item.simple ? arraySerializer(item.simple, ) : item.simple,
220
+ "complex": arraySerializer(item.complex, widgetToTransport),
221
+ "nested": arraySerializer(item.nested, (i: any) => arraySerializer(i, widgetToTransport)),
222
+ "optionalString": item.optionalString
223
+ };
224
+ }
225
+ `;
226
+ expect(actualContent).toBe(expectedContent);
227
+ });
228
+ it("should render a transform functions for a model containing record", async () => {
229
+ const spec = `
230
+ namespace DemoService;
231
+ @test model Widget {
232
+ id: string;
233
+ my_color: "blue" | "red";
234
+ simple: Record<string>;
235
+ complex: Record<Widget>;
236
+ nested: Record<Record<Widget>>;
237
+ }
238
+ `;
239
+ const {
240
+ Widget
241
+ } = await testRunner.compile(spec);
242
+ const res = render(_$createComponent(Output, {
243
+ namePolicy: namePolicy,
244
+ get children() {
245
+ return [_$createComponent(SourceFile, {
246
+ path: "serializers.ts",
247
+ get children() {
248
+ return _$createComponent(RecordSerializer, {});
249
+ }
250
+ }), _$createComponent(SourceFile, {
251
+ path: "test.ts",
252
+ get children() {
253
+ return [_$createComponent(TypeDeclaration, {
254
+ "export": true,
255
+ type: Widget
256
+ }), _$createComponent(TypeTransformDeclaration, {
257
+ type: Widget,
258
+ target: "application"
259
+ }), _$createComponent(TypeTransformDeclaration, {
260
+ type: Widget,
261
+ target: "transport"
262
+ })];
263
+ }
264
+ })];
265
+ }
266
+ }));
267
+ const testFile = res.contents.find(file => file.path === "test.ts");
268
+ assert(testFile, "test.ts file not rendered");
269
+ const actualContent = testFile.contents;
270
+ const expectedContent = d`
271
+ import { recordSerializer } from "./serializers.js";
272
+
273
+ export interface Widget {
274
+ "id": string;
275
+ "myColor": "blue" | "red";
276
+ "simple": Record<string, string>;
277
+ "complex": Record<string, Widget>;
278
+ "nested": Record<string, Record<string, Widget>>;
279
+ }
280
+ export function widgetToApplication(item: any) {
281
+ return {
282
+ "id": item.id,
283
+ "myColor": item.my_color,
284
+ "simple": recordSerializer(item.simple, ),
285
+ "complex": recordSerializer(item.complex, widgetToApplication),
286
+ "nested": recordSerializer(item.nested, (i: any) => recordSerializer(i, widgetToApplication))
287
+ };
288
+ }
289
+ export function widgetToTransport(item: Widget) {
290
+ return {
291
+ "id": item.id,
292
+ "my_color": item.myColor,
293
+ "simple": recordSerializer(item.simple, ),
294
+ "complex": recordSerializer(item.complex, widgetToTransport),
295
+ "nested": recordSerializer(item.nested, (i: any) => recordSerializer(i, widgetToTransport))
296
+ };
297
+ }
298
+ `;
299
+ expect(actualContent).toBe(expectedContent);
300
+ });
301
+ it("should render a transform functions for a model", async () => {
302
+ const spec = `
303
+ namespace DemoService;
304
+ @test model Widget {
305
+ id: string;
306
+ my_color: "blue" | "red";
307
+ }
308
+ `;
309
+ const {
310
+ Widget
311
+ } = await testRunner.compile(spec);
312
+ const res = render(_$createComponent(Output, {
313
+ namePolicy: namePolicy,
314
+ get children() {
315
+ return _$createComponent(SourceFile, {
316
+ path: "test.ts",
317
+ get children() {
318
+ return [_$createComponent(TypeDeclaration, {
319
+ "export": true,
320
+ type: Widget
321
+ }), _$createComponent(TypeTransformDeclaration, {
322
+ type: Widget,
323
+ target: "application"
324
+ }), _$createComponent(TypeTransformDeclaration, {
325
+ type: Widget,
326
+ target: "transport"
327
+ })];
328
+ }
329
+ });
330
+ }
331
+ }));
332
+ const testFile = res.contents.find(file => file.path === "test.ts");
333
+ assert(testFile, "test.ts file not rendered");
334
+ const actualContent = testFile.contents;
335
+ const expectedContent = d`
336
+ export interface Widget {
337
+ "id": string;
338
+ "myColor": "blue" | "red";
339
+ }
340
+ export function widgetToApplication(item: any) {
341
+ return {
342
+ "id": item.id,
343
+ "myColor": item.my_color
344
+ };
345
+ }
346
+ export function widgetToTransport(item: Widget) {
347
+ return {
348
+ "id": item.id,
349
+ "my_color": item.myColor
350
+ };
351
+ }
352
+ `;
353
+ expect(actualContent).toBe(expectedContent);
354
+ });
355
+ });
356
+ describe("Calling a model transform functions", () => {
357
+ it("should collapse a model with single property", async () => {
358
+ const spec = `
359
+ namespace DemoService;
360
+ @test model Widget {
361
+ id: string;
362
+ }
363
+ `;
364
+ const {
365
+ Widget
366
+ } = await testRunner.compile(spec);
367
+ const res = render(_$createComponent(Output, {
368
+ namePolicy: namePolicy,
369
+ get children() {
370
+ return _$createComponent(SourceFile, {
371
+ path: "test.ts",
372
+ get children() {
373
+ return code`
374
+ const clientWidget = {id: "1", my_color: "blue"};
375
+ const wireWidget = ${_$createComponent(TypeTransformCall, {
376
+ itemPath: ["clientWidget"],
377
+ type: Widget,
378
+ collapse: true,
379
+ target: "transport"
380
+ })}
381
+ `;
382
+ }
383
+ });
384
+ }
385
+ }));
386
+ const testFile = res.contents.find(file => file.path === "test.ts");
387
+ assert(testFile, "test.ts file not rendered");
388
+ const actualContent = testFile.contents;
389
+ const expectedContent = d`
390
+ const clientWidget = {id: "1", my_color: "blue"};
391
+ const wireWidget = clientWidget.id
392
+ `;
393
+ expect(actualContent).toBe(expectedContent);
394
+ });
395
+ it("should call transform functions for a model", async () => {
396
+ const spec = `
397
+ namespace DemoService;
398
+ @test model Widget {
399
+ id: string;
400
+ my_color: "blue" | "red";
401
+ }
402
+ `;
403
+ const {
404
+ Widget
405
+ } = await testRunner.compile(spec);
406
+ const res = render(_$createComponent(Output, {
407
+ namePolicy: namePolicy,
408
+ get children() {
409
+ return [_$createComponent(SourceFile, {
410
+ path: "types.ts",
411
+ get children() {
412
+ return [_$createComponent(TypeDeclaration, {
413
+ "export": true,
414
+ type: Widget
415
+ }), _$createComponent(TypeTransformDeclaration, {
416
+ type: Widget,
417
+ target: "application"
418
+ }), _$createComponent(TypeTransformDeclaration, {
419
+ type: Widget,
420
+ target: "transport"
421
+ })];
422
+ }
423
+ }), _$createComponent(SourceFile, {
424
+ path: "test.ts",
425
+ get children() {
426
+ return code`
427
+ const wireWidget = {id: "1", my_color: "blue"};
428
+ const clientWidget = ${_$createComponent(ts.FunctionCallExpression, {
429
+ get target() {
430
+ return getTypeTransformerRefkey(Widget, "application");
431
+ },
432
+ get args() {
433
+ return [["wireWidget"]];
434
+ }
435
+ })};
436
+ const wireWidget2 = ${_$createComponent(ts.FunctionCallExpression, {
437
+ get target() {
438
+ return getTypeTransformerRefkey(Widget, "transport");
439
+ },
440
+ args: ["clientWidget"]
441
+ })};
442
+ `;
443
+ }
444
+ })];
445
+ }
446
+ }));
447
+ const testFile = res.contents.find(file => file.path === "test.ts");
448
+ assert(testFile, "test.ts file not rendered");
449
+ const actualContent = testFile.contents;
450
+ const expectedContent = d`
451
+ import { widgetToApplication, widgetToTransport } from "./types.js";
452
+
453
+ const wireWidget = {id: "1", my_color: "blue"};
454
+ const clientWidget = widgetToApplication(wireWidget);
455
+ const wireWidget2 = widgetToTransport(clientWidget);
456
+ `;
457
+ expect(actualContent).toBe(expectedContent);
458
+ });
459
+ });
460
+ });
461
+ describe("Discriminated Model Transforms", () => {
462
+ it("should handle a discriminated union", async () => {
463
+ const {
464
+ Pet,
465
+ Cat,
466
+ Dog
467
+ } = await testRunner.compile(`
468
+ @discriminator("kind")
469
+ @test model Pet {
470
+ kind: string;
471
+ }
472
+
473
+ @test model Cat extends Pet {
474
+ kind: "cat";
475
+ }
476
+
477
+ @test model Dog extends Pet {
478
+ kind: "dog";
479
+ }
480
+ `);
481
+ const res = render(_$createComponent(Output, {
482
+ namePolicy: namePolicy,
483
+ get children() {
484
+ return _$createComponent(SourceFile, {
485
+ path: "test.ts",
486
+ get children() {
487
+ return [_$createComponent(TypeDeclaration, {
488
+ "export": true,
489
+ type: Pet
490
+ }), _$createComponent(TypeDeclaration, {
491
+ "export": true,
492
+ type: Dog
493
+ }), _$createComponent(TypeDeclaration, {
494
+ "export": true,
495
+ type: Cat
496
+ }), _$createComponent(TypeTransformDeclaration, {
497
+ type: Dog,
498
+ target: "application"
499
+ }), _$createComponent(TypeTransformDeclaration, {
500
+ type: Dog,
501
+ target: "transport"
502
+ }), _$createComponent(TypeTransformDeclaration, {
503
+ type: Cat,
504
+ target: "application"
505
+ }), _$createComponent(TypeTransformDeclaration, {
506
+ type: Cat,
507
+ target: "transport"
508
+ }), _$createComponent(TypeTransformDeclaration, {
509
+ type: Pet,
510
+ target: "application"
511
+ }), _$createComponent(TypeTransformDeclaration, {
512
+ type: Pet,
513
+ target: "transport"
514
+ })];
515
+ }
516
+ });
517
+ }
518
+ }));
519
+ const testFile = res.contents.find(file => file.path === "test.ts");
520
+ assert(testFile, "test.ts file not rendered");
521
+ const actualContent = testFile.contents;
522
+ const expectedContent = d`
523
+ export interface Pet {
524
+ "kind": string;
525
+ }
526
+ export interface Dog extends Pet {
527
+ "kind": "dog";
528
+ }
529
+ export interface Cat extends Pet {
530
+ "kind": "cat";
531
+ }
532
+ export function dogToApplication(item: any): Dog {
533
+ return {
534
+ "kind": item.kind
535
+ };
536
+ }
537
+ export function dogToTransport(item: Dog) {
538
+ return {
539
+ "kind": item.kind
540
+ };
541
+ }
542
+ export function catToApplication(item: any) {
543
+ return {
544
+ "kind": item.kind
545
+ };
546
+ }
547
+ export function catToTransport(item: Cat) {
548
+ return {
549
+ "kind": item.kind
550
+ };
551
+ }
552
+ export function petToApplication(item: any) {
553
+ if(item.kind === "cat") {
554
+ return catToApplication(item)
555
+ }
556
+ if(item.kind === "dog") {
557
+ return dogToApplication(item)
558
+ }
559
+ }
560
+ export function petToTransport(item: Pet) {
561
+ if(item.kind === "cat") {
562
+ return catToTransport(item)
563
+ }
564
+ if(item.kind === "dog") {
565
+ return dogToTransport(item)
566
+ }
567
+ }
568
+ `;
569
+ expect(actualContent).toBe(expectedContent);
570
+ });
571
+ });
572
+ describe("Discriminated Union Transforms", () => {
573
+ it("should handle a discriminated union", async () => {
574
+ const {
575
+ Pet,
576
+ Cat,
577
+ Dog
578
+ } = await testRunner.compile(`
579
+ @discriminator("kind")
580
+ @test union Pet {
581
+ cat: Cat;
582
+ dog: Dog;
583
+ }
584
+
585
+ @test model Cat {
586
+ kind: "cat";
587
+ }
588
+
589
+ @test model Dog {
590
+ kind: "dog";
591
+ }
592
+ `);
593
+ const res = render(_$createComponent(Output, {
594
+ namePolicy: namePolicy,
595
+ get children() {
596
+ return _$createComponent(SourceFile, {
597
+ path: "test.ts",
598
+ get children() {
599
+ return [_$createComponent(TypeDeclaration, {
600
+ "export": true,
601
+ type: Pet
602
+ }), _$createComponent(TypeDeclaration, {
603
+ "export": true,
604
+ type: Dog
605
+ }), _$createComponent(TypeDeclaration, {
606
+ "export": true,
607
+ type: Cat
608
+ }), _$createComponent(TypeTransformDeclaration, {
609
+ type: Dog,
610
+ target: "application"
611
+ }), _$createComponent(TypeTransformDeclaration, {
612
+ type: Dog,
613
+ target: "transport"
614
+ }), _$createComponent(TypeTransformDeclaration, {
615
+ type: Cat,
616
+ target: "application"
617
+ }), _$createComponent(TypeTransformDeclaration, {
618
+ type: Cat,
619
+ target: "transport"
620
+ }), _$createComponent(TypeTransformDeclaration, {
621
+ type: Pet,
622
+ target: "application"
623
+ }), _$createComponent(TypeTransformDeclaration, {
624
+ type: Pet,
625
+ target: "transport"
626
+ })];
627
+ }
628
+ });
629
+ }
630
+ }));
631
+ const testFile = res.contents.find(file => file.path === "test.ts");
632
+ assert(testFile, "test.ts file not rendered");
633
+ const actualContent = testFile.contents;
634
+ const expectedContent = d`
635
+ export type Pet = Cat | Dog;
636
+ export interface Dog {
637
+ "kind": "dog";
638
+ }
639
+ export interface Cat {
640
+ "kind": "cat";
641
+ }
642
+ export function dogToApplication(item: any): Dog {
643
+ return {
644
+ "kind": item.kind
645
+ };
646
+ }
647
+ export function dogToTransport(item: Dog) {
648
+ return {
649
+ "kind": item.kind
650
+ };
651
+ }
652
+ export function catToApplication(item: any) {
653
+ return {
654
+ "kind": item.kind
655
+ };
656
+ }
657
+ export function catToTransport(item: Cat) {
658
+ return {
659
+ "kind": item.kind
660
+ };
661
+ }
662
+ export function petToApplication(item: any) {
663
+ if(item.kind === "cat") {
664
+ return catToApplication(item)
665
+ }
666
+ if(item.kind === "dog") {
667
+ return dogToApplication(item)
668
+ }
669
+ }
670
+ export function petToTransport(item: Pet) {
671
+ if(item.kind === "cat") {
672
+ return catToTransport(item)
673
+ }
674
+ if(item.kind === "dog") {
675
+ return dogToTransport(item)
676
+ }
677
+ }
678
+ `;
679
+ expect(actualContent).toBe(expectedContent);
680
+ });
681
+ });
682
+ });