@azure-tools/typespec-go 0.1.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 (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +16 -0
  3. package/dist/codegen.go/src/clientFactory.d.ts +3 -0
  4. package/dist/codegen.go/src/clientFactory.d.ts.map +1 -0
  5. package/dist/codegen.go/src/clientFactory.js +77 -0
  6. package/dist/codegen.go/src/clientFactory.js.map +1 -0
  7. package/dist/codegen.go/src/constants.d.ts +3 -0
  8. package/dist/codegen.go/src/constants.d.ts.map +1 -0
  9. package/dist/codegen.go/src/constants.js +59 -0
  10. package/dist/codegen.go/src/constants.js.map +1 -0
  11. package/dist/codegen.go/src/fake/factory.d.ts +3 -0
  12. package/dist/codegen.go/src/fake/factory.d.ts.map +1 -0
  13. package/dist/codegen.go/src/fake/factory.js +69 -0
  14. package/dist/codegen.go/src/fake/factory.js.map +1 -0
  15. package/dist/codegen.go/src/fake/internal.d.ts +14 -0
  16. package/dist/codegen.go/src/fake/internal.d.ts.map +1 -0
  17. package/dist/codegen.go/src/fake/internal.js +197 -0
  18. package/dist/codegen.go/src/fake/internal.js.map +1 -0
  19. package/dist/codegen.go/src/fake/servers.d.ts +14 -0
  20. package/dist/codegen.go/src/fake/servers.d.ts.map +1 -0
  21. package/dist/codegen.go/src/fake/servers.js +1255 -0
  22. package/dist/codegen.go/src/fake/servers.js.map +1 -0
  23. package/dist/codegen.go/src/gomod.d.ts +3 -0
  24. package/dist/codegen.go/src/gomod.d.ts.map +1 -0
  25. package/dist/codegen.go/src/gomod.js +55 -0
  26. package/dist/codegen.go/src/gomod.js.map +1 -0
  27. package/dist/codegen.go/src/helpers.d.ts +32 -0
  28. package/dist/codegen.go/src/helpers.d.ts.map +1 -0
  29. package/dist/codegen.go/src/helpers.js +586 -0
  30. package/dist/codegen.go/src/helpers.js.map +1 -0
  31. package/dist/codegen.go/src/imports.d.ts +11 -0
  32. package/dist/codegen.go/src/imports.d.ts.map +1 -0
  33. package/dist/codegen.go/src/imports.js +65 -0
  34. package/dist/codegen.go/src/imports.js.map +1 -0
  35. package/dist/codegen.go/src/interfaces.d.ts +3 -0
  36. package/dist/codegen.go/src/interfaces.d.ts.map +1 -0
  37. package/dist/codegen.go/src/interfaces.js +36 -0
  38. package/dist/codegen.go/src/interfaces.js.map +1 -0
  39. package/dist/codegen.go/src/models.d.ts +9 -0
  40. package/dist/codegen.go/src/models.d.ts.map +1 -0
  41. package/dist/codegen.go/src/models.js +849 -0
  42. package/dist/codegen.go/src/models.js.map +1 -0
  43. package/dist/codegen.go/src/operations.d.ts +9 -0
  44. package/dist/codegen.go/src/operations.d.ts.map +1 -0
  45. package/dist/codegen.go/src/operations.js +1337 -0
  46. package/dist/codegen.go/src/operations.js.map +1 -0
  47. package/dist/codegen.go/src/options.d.ts +3 -0
  48. package/dist/codegen.go/src/options.d.ts.map +1 -0
  49. package/dist/codegen.go/src/options.js +64 -0
  50. package/dist/codegen.go/src/options.js.map +1 -0
  51. package/dist/codegen.go/src/polymorphics.d.ts +3 -0
  52. package/dist/codegen.go/src/polymorphics.d.ts.map +1 -0
  53. package/dist/codegen.go/src/polymorphics.js +169 -0
  54. package/dist/codegen.go/src/polymorphics.js.map +1 -0
  55. package/dist/codegen.go/src/responses.d.ts +7 -0
  56. package/dist/codegen.go/src/responses.d.ts.map +1 -0
  57. package/dist/codegen.go/src/responses.js +167 -0
  58. package/dist/codegen.go/src/responses.js.map +1 -0
  59. package/dist/codegen.go/src/time.d.ts +8 -0
  60. package/dist/codegen.go/src/time.d.ts.map +1 -0
  61. package/dist/codegen.go/src/time.js +511 -0
  62. package/dist/codegen.go/src/time.js.map +1 -0
  63. package/dist/codemodel.go/src/client.d.ts +96 -0
  64. package/dist/codemodel.go/src/client.d.ts.map +1 -0
  65. package/dist/codemodel.go/src/client.js +114 -0
  66. package/dist/codemodel.go/src/client.js.map +1 -0
  67. package/dist/codemodel.go/src/index.d.ts +6 -0
  68. package/dist/codemodel.go/src/index.d.ts.map +1 -0
  69. package/dist/codemodel.go/src/index.js +10 -0
  70. package/dist/codemodel.go/src/index.js.map +1 -0
  71. package/dist/codemodel.go/src/package.d.ts +49 -0
  72. package/dist/codemodel.go/src/package.d.ts.map +1 -0
  73. package/dist/codemodel.go/src/package.js +86 -0
  74. package/dist/codemodel.go/src/package.js.map +1 -0
  75. package/dist/codemodel.go/src/param.d.ts +162 -0
  76. package/dist/codemodel.go/src/param.d.ts.map +1 -0
  77. package/dist/codemodel.go/src/param.js +189 -0
  78. package/dist/codemodel.go/src/param.js.map +1 -0
  79. package/dist/codemodel.go/src/result.d.ts +102 -0
  80. package/dist/codemodel.go/src/result.d.ts.map +1 -0
  81. package/dist/codemodel.go/src/result.js +119 -0
  82. package/dist/codemodel.go/src/result.js.map +1 -0
  83. package/dist/codemodel.go/src/type.d.ts +181 -0
  84. package/dist/codemodel.go/src/type.d.ts.map +1 -0
  85. package/dist/codemodel.go/src/type.js +242 -0
  86. package/dist/codemodel.go/src/type.js.map +1 -0
  87. package/dist/naming.go/src/mappings.d.ts +3 -0
  88. package/dist/naming.go/src/mappings.d.ts.map +1 -0
  89. package/dist/naming.go/src/mappings.js +128 -0
  90. package/dist/naming.go/src/mappings.js.map +1 -0
  91. package/dist/naming.go/src/naming.d.ts +10 -0
  92. package/dist/naming.go/src/naming.d.ts.map +1 -0
  93. package/dist/naming.go/src/naming.js +114 -0
  94. package/dist/naming.go/src/naming.js.map +1 -0
  95. package/dist/typespec-go/src/emitter.d.ts +5 -0
  96. package/dist/typespec-go/src/emitter.d.ts.map +1 -0
  97. package/dist/typespec-go/src/emitter.js +122 -0
  98. package/dist/typespec-go/src/emitter.js.map +1 -0
  99. package/dist/typespec-go/src/index.d.ts +3 -0
  100. package/dist/typespec-go/src/index.d.ts.map +1 -0
  101. package/dist/typespec-go/src/index.js +7 -0
  102. package/dist/typespec-go/src/index.js.map +1 -0
  103. package/dist/typespec-go/src/lib.d.ts +25 -0
  104. package/dist/typespec-go/src/lib.d.ts.map +1 -0
  105. package/dist/typespec-go/src/lib.js +36 -0
  106. package/dist/typespec-go/src/lib.js.map +1 -0
  107. package/dist/typespec-go/src/tcgcadapter/adapter.d.ts +5 -0
  108. package/dist/typespec-go/src/tcgcadapter/adapter.d.ts.map +1 -0
  109. package/dist/typespec-go/src/tcgcadapter/adapter.js +119 -0
  110. package/dist/typespec-go/src/tcgcadapter/adapter.js.map +1 -0
  111. package/dist/typespec-go/src/tcgcadapter/clients.d.ts +26 -0
  112. package/dist/typespec-go/src/tcgcadapter/clients.d.ts.map +1 -0
  113. package/dist/typespec-go/src/tcgcadapter/clients.js +621 -0
  114. package/dist/typespec-go/src/tcgcadapter/clients.js.map +1 -0
  115. package/dist/typespec-go/src/tcgcadapter/types.d.ts +29 -0
  116. package/dist/typespec-go/src/tcgcadapter/types.d.ts.map +1 -0
  117. package/dist/typespec-go/src/tcgcadapter/types.js +975 -0
  118. package/dist/typespec-go/src/tcgcadapter/types.js.map +1 -0
  119. package/package.json +77 -0
@@ -0,0 +1,975 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import * as naming from '../../../naming.go/src/naming.js';
6
+ import * as go from '../../../codemodel.go/src/index.js';
7
+ import * as tcgc from '@azure-tools/typespec-client-generator-core';
8
+ import * as tsp from '@typespec/compiler';
9
+ import * as http from '@typespec/http';
10
+ import { values } from '@azure-tools/linq';
11
+ import { uncapitalize } from '@azure-tools/codegen';
12
+ // used to convert SDK types to Go code model types
13
+ export class typeAdapter {
14
+ constructor(codeModel) {
15
+ this.codeModel = codeModel;
16
+ this.types = new Map();
17
+ this.constValues = new Map();
18
+ this.unreferencedEnums = new Set();
19
+ this.unreferencedModels = new Set();
20
+ }
21
+ // converts all model/enum SDK types to Go code model types
22
+ adaptTypes(sdkContext, removeUnreferencedTypes) {
23
+ if (removeUnreferencedTypes) {
24
+ // this is a superset of flagUnreferencedBaseModels
25
+ this.flagUnreferencedTypes(sdkContext);
26
+ }
27
+ else {
28
+ this.flagUnreferencedBaseModels(sdkContext);
29
+ }
30
+ for (const enumType of sdkContext.experimental_sdkPackage.enums) {
31
+ if (enumType.usage === tcgc.UsageFlags.ApiVersionEnum) {
32
+ // we have a pipeline policy for controlling the api-version
33
+ continue;
34
+ }
35
+ else if (this.unreferencedEnums.has(enumType.name)) {
36
+ // skip unreferenced type
37
+ continue;
38
+ }
39
+ const constType = this.getConstantType(enumType);
40
+ this.codeModel.constants.push(constType);
41
+ }
42
+ // we must adapt all interface/model types first. this is because models can contain cyclic references
43
+ const modelTypes = new Array();
44
+ const ifaceTypes = new Array();
45
+ for (const modelType of sdkContext.experimental_sdkPackage.models) {
46
+ if (this.unreferencedModels.has(modelType.name)) {
47
+ // skip unreferenced type
48
+ continue;
49
+ }
50
+ if (modelType.discriminatedSubtypes) {
51
+ // this is a root discriminated type
52
+ const iface = this.getInterfaceType(modelType);
53
+ this.codeModel.interfaceTypes.push(iface);
54
+ ifaceTypes.push({ go: iface, tcgc: modelType });
55
+ }
56
+ // TODO: what's the equivalent of x-ms-external?
57
+ const model = this.getModel(modelType);
58
+ modelTypes.push({ go: model, tcgc: modelType });
59
+ }
60
+ // add the synthesized models from TCGC for paged results
61
+ const pagedResponses = this.getPagedResponses(sdkContext);
62
+ for (const pagedResponse of pagedResponses) {
63
+ // tsp allows custom paged responses, so we must check both the synthesized list and the models list
64
+ if (values(modelTypes).any(each => { return each.tcgc.name === pagedResponse.name; })) {
65
+ continue;
66
+ }
67
+ const model = this.getModel(pagedResponse);
68
+ modelTypes.push({ go: model, tcgc: pagedResponse });
69
+ }
70
+ // now that the interface/model types have been generated, we can populate the rootType and possibleTypes
71
+ for (const ifaceType of ifaceTypes) {
72
+ ifaceType.go.rootType = this.getModel(ifaceType.tcgc);
73
+ for (const subType of values(ifaceType.tcgc.discriminatedSubtypes)) {
74
+ const possibleType = this.getModel(subType);
75
+ ifaceType.go.possibleTypes.push(possibleType);
76
+ }
77
+ }
78
+ // now adapt model fields
79
+ for (const modelType of modelTypes) {
80
+ const content = aggregateProperties(modelType.tcgc);
81
+ for (const prop of values(content.props)) {
82
+ if (prop.kind === 'header') {
83
+ // the common case here is the @header decorator specifying
84
+ // the content-type for the model. we can just skip it.
85
+ // TODO: follow up with tcgc to see if we can remove the entry.
86
+ continue;
87
+ }
88
+ const field = this.getModelField(prop, modelType.tcgc);
89
+ modelType.go.fields.push(field);
90
+ }
91
+ if (content.addlProps) {
92
+ const annotations = new go.ModelFieldAnnotations(false, false, true, false);
93
+ const addlPropsType = new go.MapType(this.getPossibleType(content.addlProps, false, false), isTypePassedByValue(content.addlProps));
94
+ const addlProps = new go.ModelField('AdditionalProperties', addlPropsType, true, '', annotations);
95
+ modelType.go.fields.push(addlProps);
96
+ }
97
+ this.codeModel.models.push(modelType.go);
98
+ }
99
+ }
100
+ // returns the synthesized paged response types
101
+ getPagedResponses(sdkContext) {
102
+ const pagedResponses = new Array();
103
+ const recursiveWalkClients = function (client) {
104
+ for (const sdkMethod of client.methods) {
105
+ if (sdkMethod.kind === 'clientaccessor') {
106
+ recursiveWalkClients(sdkMethod.response);
107
+ continue;
108
+ }
109
+ else if (sdkMethod.kind !== 'paging') {
110
+ continue;
111
+ }
112
+ for (const httpResp of sdkMethod.operation.responses.values()) {
113
+ if (!httpResp.type || httpResp.type.kind !== 'model') {
114
+ continue;
115
+ }
116
+ if (!values(pagedResponses).any(each => { return each.name === httpResp.type.name; })) {
117
+ pagedResponses.push(httpResp.type);
118
+ }
119
+ }
120
+ }
121
+ };
122
+ for (const sdkClient of sdkContext.experimental_sdkPackage.clients) {
123
+ recursiveWalkClients(sdkClient);
124
+ }
125
+ return pagedResponses;
126
+ }
127
+ // returns the Go code model type for the specified SDK type.
128
+ // the operation is idempotent, so getting the same type multiple times
129
+ // returns the same instance of the converted type.
130
+ getPossibleType(type, elementTypeByValue, substituteDiscriminator) {
131
+ switch (type.kind) {
132
+ case 'any':
133
+ case 'armId':
134
+ case 'azureLocation':
135
+ case 'boolean':
136
+ case 'bytes':
137
+ case 'decimal':
138
+ case 'decimal128':
139
+ case 'eTag':
140
+ case 'float':
141
+ case 'float32':
142
+ case 'float64':
143
+ case 'guid':
144
+ case 'int8':
145
+ case 'int16':
146
+ case 'int32':
147
+ case 'int64':
148
+ case 'uint8':
149
+ case 'uint16':
150
+ case 'uint32':
151
+ case 'uint64':
152
+ case 'plainDate':
153
+ case 'plainTime':
154
+ case 'string':
155
+ case 'uri':
156
+ case 'url':
157
+ case 'uuid':
158
+ return this.getBuiltInType(type);
159
+ case 'array': {
160
+ let elementType = type.valueType;
161
+ let nullable = false;
162
+ if (elementType.kind === 'nullable') {
163
+ // unwrap the nullable type
164
+ elementType = elementType.type;
165
+ nullable = true;
166
+ }
167
+ // prefer elementTypeByValue. if false, then if the array elements have been explicitly marked as nullable then prefer that, else fall back to our usual algorithm
168
+ const myElementTypeByValue = elementTypeByValue ? true : nullable ? false : this.codeModel.options.sliceElementsByval || isTypePassedByValue(elementType);
169
+ const keyName = recursiveKeyName(`array-${myElementTypeByValue}`, elementType, substituteDiscriminator);
170
+ let arrayType = this.types.get(keyName);
171
+ if (arrayType) {
172
+ return arrayType;
173
+ }
174
+ arrayType = new go.SliceType(this.getPossibleType(elementType, elementTypeByValue, substituteDiscriminator), myElementTypeByValue);
175
+ this.types.set(keyName, arrayType);
176
+ return arrayType;
177
+ }
178
+ case 'endpoint': {
179
+ const stringKey = 'string';
180
+ let stringType = this.types.get(stringKey);
181
+ if (stringType) {
182
+ return stringType;
183
+ }
184
+ stringType = new go.PrimitiveType('string');
185
+ this.types.set(stringKey, stringType);
186
+ return stringType;
187
+ }
188
+ case 'enum':
189
+ return this.getConstantType(type);
190
+ case 'constant':
191
+ case 'enumvalue':
192
+ return this.getLiteralValue(type);
193
+ case 'offsetDateTime':
194
+ return this.getTimeType(type.encode, false);
195
+ case 'utcDateTime':
196
+ return this.getTimeType(type.encode, true);
197
+ case 'dict': {
198
+ const valueTypeByValue = isTypePassedByValue(type.valueType);
199
+ const keyName = recursiveKeyName(`dict-${valueTypeByValue}`, type.valueType, substituteDiscriminator);
200
+ let mapType = this.types.get(keyName);
201
+ if (mapType) {
202
+ return mapType;
203
+ }
204
+ mapType = new go.MapType(this.getPossibleType(type.valueType, elementTypeByValue, substituteDiscriminator), valueTypeByValue);
205
+ this.types.set(keyName, mapType);
206
+ return mapType;
207
+ }
208
+ case 'duration': {
209
+ switch (type.wireType.kind) {
210
+ case 'float':
211
+ case 'float32':
212
+ case 'float64':
213
+ case 'int32':
214
+ case 'int64':
215
+ case 'string':
216
+ return this.getBuiltInType(type.wireType);
217
+ default:
218
+ throw new Error(`unhandled duration wireType.kind ${type.wireType.kind}`);
219
+ }
220
+ }
221
+ case 'model':
222
+ if (type.discriminatedSubtypes && substituteDiscriminator) {
223
+ return this.getInterfaceType(type);
224
+ }
225
+ return this.getModel(type);
226
+ case 'nullable':
227
+ return this.getPossibleType(type.type, elementTypeByValue, substituteDiscriminator);
228
+ default:
229
+ throw new Error(`unhandled property kind ${type.kind}`);
230
+ }
231
+ }
232
+ getTimeType(encode, utc) {
233
+ const encoding = getDateTimeEncoding(encode);
234
+ let datetime = this.types.get(encoding);
235
+ if (datetime) {
236
+ return datetime;
237
+ }
238
+ datetime = new go.TimeType(encoding, utc);
239
+ this.types.set(encoding, datetime);
240
+ return datetime;
241
+ }
242
+ // returns the Go code model type for an io.ReadSeekCloser
243
+ getReadSeekCloser(sliceOf) {
244
+ let keyName = 'io-readseekcloser';
245
+ if (sliceOf) {
246
+ keyName = 'sliceof-' + keyName;
247
+ }
248
+ let rsc = this.types.get(keyName);
249
+ if (!rsc) {
250
+ rsc = new go.QualifiedType('ReadSeekCloser', 'io');
251
+ if (sliceOf) {
252
+ rsc = new go.SliceType(rsc, true);
253
+ }
254
+ this.types.set(keyName, rsc);
255
+ }
256
+ return rsc;
257
+ }
258
+ // returns the Go code model type for streaming.MultipartContent
259
+ getMultipartContent(sliceOf) {
260
+ let keyName = 'streaming-multipartcontent';
261
+ if (sliceOf) {
262
+ keyName = 'sliceof-' + keyName;
263
+ }
264
+ let rsc = this.types.get(keyName);
265
+ if (!rsc) {
266
+ rsc = new go.QualifiedType('MultipartContent', 'github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming');
267
+ if (sliceOf) {
268
+ rsc = new go.SliceType(rsc, true);
269
+ }
270
+ this.types.set(keyName, rsc);
271
+ }
272
+ return rsc;
273
+ }
274
+ getBuiltInType(type) {
275
+ switch (type.kind) {
276
+ case 'any': {
277
+ if (this.codeModel.options.rawJSONAsBytes) {
278
+ const anyRawJSONKey = 'any-raw-json';
279
+ let anyRawJSON = this.types.get(anyRawJSONKey);
280
+ if (anyRawJSON) {
281
+ return anyRawJSON;
282
+ }
283
+ anyRawJSON = new go.SliceType(new go.PrimitiveType('byte'), true);
284
+ anyRawJSON.rawJSONAsBytes = true;
285
+ this.types.set(anyRawJSONKey, anyRawJSON);
286
+ return anyRawJSON;
287
+ }
288
+ let anyType = this.types.get('any');
289
+ if (anyType) {
290
+ return anyType;
291
+ }
292
+ anyType = new go.PrimitiveType('any');
293
+ this.types.set('any', anyType);
294
+ return anyType;
295
+ }
296
+ case 'boolean': {
297
+ const boolKey = 'boolean';
298
+ let primitiveBool = this.types.get(boolKey);
299
+ if (primitiveBool) {
300
+ return primitiveBool;
301
+ }
302
+ primitiveBool = new go.PrimitiveType('bool');
303
+ this.types.set(boolKey, primitiveBool);
304
+ return primitiveBool;
305
+ }
306
+ case 'bytes':
307
+ return this.adaptBytesType(type);
308
+ case 'plainDate': {
309
+ const dateKey = 'dateType';
310
+ let date = this.types.get(dateKey);
311
+ if (date) {
312
+ return date;
313
+ }
314
+ date = new go.TimeType('dateType', false);
315
+ this.types.set(dateKey, date);
316
+ return date;
317
+ }
318
+ case 'decimal':
319
+ case 'decimal128': {
320
+ const decimalKey = 'float64';
321
+ let decimalType = this.types.get(decimalKey);
322
+ if (decimalType) {
323
+ return decimalType;
324
+ }
325
+ decimalType = new go.PrimitiveType(decimalKey);
326
+ this.types.set(decimalKey, decimalType);
327
+ return decimalType;
328
+ }
329
+ case 'eTag': {
330
+ const etagKey = 'etag';
331
+ let etag = this.types.get(etagKey);
332
+ if (etag) {
333
+ return etag;
334
+ }
335
+ etag = new go.QualifiedType('ETag', 'github.com/Azure/azure-sdk-for-go/sdk/azcore');
336
+ this.types.set(etagKey, etag);
337
+ return etag;
338
+ }
339
+ case 'float': // C# and Java define float as 32 bits so we're following suit
340
+ case 'float32': {
341
+ const float32Key = 'float32';
342
+ let float32 = this.types.get(float32Key);
343
+ if (float32) {
344
+ return float32;
345
+ }
346
+ float32 = new go.PrimitiveType(float32Key);
347
+ this.types.set(float32Key, float32);
348
+ return float32;
349
+ }
350
+ case 'float64': {
351
+ const float64Key = 'float64';
352
+ let float64 = this.types.get(float64Key);
353
+ if (float64) {
354
+ return float64;
355
+ }
356
+ float64 = new go.PrimitiveType(float64Key);
357
+ this.types.set(float64Key, float64);
358
+ return float64;
359
+ }
360
+ case 'int8':
361
+ case 'int16':
362
+ case 'int32':
363
+ case 'int64':
364
+ case 'uint8':
365
+ case 'uint16':
366
+ case 'uint32':
367
+ case 'uint64': {
368
+ const keyName = type.kind;
369
+ let intType = this.types.get(keyName);
370
+ if (intType) {
371
+ return intType;
372
+ }
373
+ intType = new go.PrimitiveType(type.kind);
374
+ this.types.set(keyName, intType);
375
+ return intType;
376
+ }
377
+ case 'armId':
378
+ case 'azureLocation':
379
+ case 'guid':
380
+ case 'string':
381
+ case 'uuid':
382
+ case 'uri':
383
+ case 'url': {
384
+ const stringKey = 'string';
385
+ let stringType = this.types.get(stringKey);
386
+ if (stringType) {
387
+ return stringType;
388
+ }
389
+ stringType = new go.PrimitiveType('string');
390
+ this.types.set(stringKey, stringType);
391
+ return stringType;
392
+ }
393
+ case 'plainTime': {
394
+ if (type.encode !== 'rfc3339') {
395
+ throw new Error(`unsupported time encoding ${type.encode}`);
396
+ }
397
+ const encoding = 'timeRFC3339';
398
+ let time = this.types.get(encoding);
399
+ if (time) {
400
+ return time;
401
+ }
402
+ time = new go.TimeType(encoding, false);
403
+ this.types.set(encoding, time);
404
+ return time;
405
+ }
406
+ default:
407
+ throw new Error(`unhandled property kind ${type.kind}`);
408
+ }
409
+ }
410
+ // converts an SdkEnumType to a go.ConstantType
411
+ getConstantType(enumType) {
412
+ let constTypeName = naming.ensureNameCase(enumType.name);
413
+ if (enumType.access === 'internal') {
414
+ constTypeName = naming.getEscapedReservedName(uncapitalize(constTypeName), 'Type');
415
+ }
416
+ let constType = this.types.get(constTypeName);
417
+ if (constType) {
418
+ return constType;
419
+ }
420
+ constType = new go.ConstantType(constTypeName, getPrimitiveType(enumType.valueType.kind), `Possible${constTypeName}Values`);
421
+ constType.values = this.getConstantValues(constType, enumType.values);
422
+ constType.description = enumType.description;
423
+ this.types.set(constTypeName, constType);
424
+ return constType;
425
+ }
426
+ getInterfaceType(model, parent) {
427
+ if (model.name.length === 0) {
428
+ throw new Error('unnamed model');
429
+ }
430
+ if (!model.discriminatedSubtypes) {
431
+ throw new Error(`type ${model.name} isn't a discriminator root`);
432
+ }
433
+ let ifaceName = naming.createPolymorphicInterfaceName(naming.ensureNameCase(model.name));
434
+ if (model.access === 'internal') {
435
+ ifaceName = uncapitalize(ifaceName);
436
+ }
437
+ let iface = this.types.get(ifaceName);
438
+ if (iface) {
439
+ return iface;
440
+ }
441
+ // find the discriminator field
442
+ let discriminatorField;
443
+ for (const prop of model.properties) {
444
+ if (prop.kind === 'property' && prop.discriminator) {
445
+ discriminatorField = prop.serializedName;
446
+ break;
447
+ }
448
+ }
449
+ if (!discriminatorField) {
450
+ throw new Error(`failed to find discriminator field for type ${model.name}`);
451
+ }
452
+ iface = new go.InterfaceType(ifaceName, discriminatorField);
453
+ if (parent) {
454
+ iface.parent = parent;
455
+ }
456
+ this.types.set(ifaceName, iface);
457
+ return iface;
458
+ }
459
+ // converts an SdkModelType to a go.ModelType or go.PolymorphicType if the model is polymorphic
460
+ getModel(model) {
461
+ let modelName = model.name;
462
+ if (modelName.length === 0) {
463
+ throw new Error('unnamed model');
464
+ }
465
+ modelName = naming.ensureNameCase(modelName);
466
+ if (model.access === 'internal') {
467
+ modelName = naming.getEscapedReservedName(uncapitalize(modelName), 'Model');
468
+ }
469
+ let modelType = this.types.get(modelName);
470
+ if (modelType) {
471
+ return modelType;
472
+ }
473
+ let usage = go.UsageFlags.None;
474
+ if (model.usage & tsp.UsageFlags.Input) {
475
+ usage = go.UsageFlags.Input;
476
+ }
477
+ if (model.usage & tsp.UsageFlags.Output) {
478
+ usage |= go.UsageFlags.Output;
479
+ }
480
+ const annotations = new go.ModelAnnotations(false, model.isFormDataType);
481
+ if (model.discriminatedSubtypes || model.discriminatorValue) {
482
+ let iface;
483
+ let discriminatorLiteral;
484
+ if (model.discriminatedSubtypes) {
485
+ // root type, we can get the InterfaceType directly from it
486
+ iface = this.getInterfaceType(model);
487
+ }
488
+ else {
489
+ // walk the parents until we find the first root type
490
+ let parent = model.baseModel;
491
+ while (parent) {
492
+ if (parent.discriminatedSubtypes) {
493
+ iface = this.getInterfaceType(parent);
494
+ break;
495
+ }
496
+ parent = parent.baseModel;
497
+ }
498
+ if (!iface) {
499
+ throw new Error(`failed to find discriminator interface name for type ${model.name}`);
500
+ }
501
+ // find the discriminator property and create the discriminator literal based on it
502
+ for (const prop of model.properties) {
503
+ if (prop.kind === 'property' && prop.discriminator) {
504
+ discriminatorLiteral = this.getDiscriminatorLiteral(prop);
505
+ break;
506
+ }
507
+ }
508
+ }
509
+ modelType = new go.PolymorphicType(modelName, iface, annotations, usage);
510
+ modelType.discriminatorValue = discriminatorLiteral;
511
+ }
512
+ else {
513
+ // TODO: hard-coded format
514
+ modelType = new go.ModelType(modelName, 'json', annotations, usage);
515
+ // polymorphic types don't have XMLInfo
516
+ // TODO: XMLInfo
517
+ }
518
+ if (model.description) {
519
+ modelType.description = model.description;
520
+ if (!modelType.description.startsWith(modelName)) {
521
+ modelType.description = `${modelName} - ${modelType.description}`;
522
+ }
523
+ }
524
+ this.types.set(modelName, modelType);
525
+ return modelType;
526
+ }
527
+ getDiscriminatorLiteral(sdkProp) {
528
+ switch (sdkProp.type.kind) {
529
+ case 'constant':
530
+ case 'enumvalue':
531
+ return this.getLiteralValue(sdkProp.type);
532
+ default:
533
+ throw new Error(`unhandled kind ${sdkProp.type.kind} for discriminator property ${sdkProp.name}`);
534
+ }
535
+ }
536
+ getModelField(prop, modelType) {
537
+ if (prop.kind !== 'path' && prop.kind !== 'property') {
538
+ throw new Error(`unexpected kind ${prop.kind} for property ${prop.name} in model ${modelType.name}`);
539
+ }
540
+ const annotations = new go.ModelFieldAnnotations(prop.optional === false, false, false, false);
541
+ // for multipart/form data containing models, default to fields not being pointer-to-type as we
542
+ // don't have to deal with JSON patch shenanigans. only the optional fields will be pointer-to-type.
543
+ const isMultipartFormData = (modelType.usage & tcgc.UsageFlags.MultipartFormData) === tcgc.UsageFlags.MultipartFormData;
544
+ let fieldByValue = isMultipartFormData ? true : isTypePassedByValue(prop.type);
545
+ if (isMultipartFormData && prop.kind === 'property' && prop.optional) {
546
+ fieldByValue = false;
547
+ }
548
+ let type = this.getPossibleType(prop.type, isMultipartFormData, true);
549
+ if (prop.kind === 'property') {
550
+ if (prop.isMultipartFileInput) {
551
+ type = this.getMultipartContent(prop.type.kind === 'array');
552
+ }
553
+ if (prop.visibility) {
554
+ // the field is read-only IFF the only visibility attribute present is Read.
555
+ // a field can have Read & Create set which means it's required on input and
556
+ // returned on output.
557
+ if (prop.visibility.length === 1 && prop.visibility[0] === http.Visibility.Read) {
558
+ annotations.readOnly = true;
559
+ }
560
+ }
561
+ }
562
+ const field = new go.ModelField(naming.capitalize(naming.ensureNameCase(prop.name)), type, fieldByValue, prop.serializedName, annotations);
563
+ field.description = prop.description;
564
+ if (prop.kind === 'path') {
565
+ // for ARM resources, a property of kind path is usually the model
566
+ // key and will be exposed as a discrete method parameter. this also
567
+ // means that the value is read-only.
568
+ annotations.readOnly = true;
569
+ }
570
+ else if (prop.discriminator && modelType.discriminatorValue) {
571
+ // the presence of modelType.discriminatorValue tells us that this
572
+ // property is on a model that's not the root discriminator
573
+ annotations.isDiscriminator = true;
574
+ field.defaultValue = this.getDiscriminatorLiteral(prop);
575
+ }
576
+ // TODO: XMLInfo
577
+ //field.xml = adaptXMLInfo(prop.schema);
578
+ return field;
579
+ }
580
+ getConstantValues(type, valueTypes) {
581
+ const values = new Array();
582
+ for (const valueType of valueTypes) {
583
+ let valueTypeName = `${type.name}${naming.ensureNameCase(valueType.name)}`;
584
+ if (valueType.enumType.access === 'internal') {
585
+ valueTypeName = naming.getEscapedReservedName(uncapitalize(valueTypeName), 'Type');
586
+ }
587
+ let value = this.constValues.get(valueTypeName);
588
+ if (!value) {
589
+ value = new go.ConstantValue(valueTypeName, type, valueType.value);
590
+ value.description = valueType.description;
591
+ this.constValues.set(valueTypeName, value);
592
+ }
593
+ values.push(value);
594
+ }
595
+ return values;
596
+ }
597
+ adaptBytesType(sdkType) {
598
+ let format = 'Std';
599
+ if (sdkType.encode === 'base64url') {
600
+ format = 'URL';
601
+ }
602
+ const keyName = `bytes-${format}`;
603
+ let bytesType = this.types.get(keyName);
604
+ if (bytesType) {
605
+ return bytesType;
606
+ }
607
+ bytesType = new go.BytesType(format);
608
+ this.types.set(keyName, bytesType);
609
+ return bytesType;
610
+ }
611
+ getLiteralValue(constType) {
612
+ if (constType.kind === 'enumvalue') {
613
+ const valueName = `${naming.ensureNameCase(constType.enumType.name)}${naming.ensureNameCase(constType.name)}`;
614
+ const keyName = `literal-${valueName}`;
615
+ let literalConst = this.types.get(keyName);
616
+ if (literalConst) {
617
+ return literalConst;
618
+ }
619
+ const constValue = this.constValues.get(valueName);
620
+ if (!constValue) {
621
+ throw new Error(`failed to find const value for ${constType.name} in enum ${constType.enumType.name}`);
622
+ }
623
+ literalConst = new go.LiteralValue(this.getConstantType(constType.enumType), constValue);
624
+ this.types.set(keyName, literalConst);
625
+ return literalConst;
626
+ }
627
+ switch (constType.valueType.kind) {
628
+ case 'boolean': {
629
+ const keyName = `literal-boolean-${constType.value}`;
630
+ let literalBool = this.types.get(keyName);
631
+ if (literalBool) {
632
+ return literalBool;
633
+ }
634
+ literalBool = new go.LiteralValue(new go.PrimitiveType('bool'), constType.value);
635
+ this.types.set(keyName, literalBool);
636
+ return literalBool;
637
+ }
638
+ case 'bytes': {
639
+ const keyName = `literal-bytes-${constType.value}`;
640
+ let literalByteArray = this.types.get(keyName);
641
+ if (literalByteArray) {
642
+ return literalByteArray;
643
+ }
644
+ literalByteArray = new go.LiteralValue(this.adaptBytesType(constType.valueType), constType.value);
645
+ this.types.set(keyName, literalByteArray);
646
+ return literalByteArray;
647
+ }
648
+ case 'decimal':
649
+ case 'decimal128': {
650
+ const keyName = `literal-${constType.valueType.kind}-${constType.value}`;
651
+ let literalDecimal = this.types.get(keyName);
652
+ if (literalDecimal) {
653
+ return literalDecimal;
654
+ }
655
+ literalDecimal = new go.LiteralValue(new go.PrimitiveType('float64'), constType.value);
656
+ this.types.set(keyName, literalDecimal);
657
+ return literalDecimal;
658
+ }
659
+ /*case 'date':
660
+ case 'datetime': {
661
+ // TODO: tcgc doesn't expose the encoding for date/datetime constant types
662
+ const encoding = getDateTimeEncoding(constType.encode);
663
+ const keyName = `literal-${encoding}-${constType.value}`;
664
+ let literalTime = this.types.get(keyName);
665
+ if (literalTime) {
666
+ return <go.LiteralValue>literalTime;
667
+ }
668
+ literalTime = new go.LiteralValue(new go.TimeType(encoding), constType.value);
669
+ this.types.set(keyName, literalTime);
670
+ return literalTime;
671
+ }*/
672
+ case 'int8':
673
+ case 'int16':
674
+ case 'int32':
675
+ case 'int64':
676
+ case 'uint8':
677
+ case 'uint16':
678
+ case 'uint32':
679
+ case 'uint64': {
680
+ const keyName = `literal-${constType.valueType.kind}-${constType.value}`;
681
+ let literalInt = this.types.get(keyName);
682
+ if (literalInt) {
683
+ return literalInt;
684
+ }
685
+ literalInt = new go.LiteralValue(new go.PrimitiveType(constType.valueType.kind), constType.value);
686
+ this.types.set(keyName, literalInt);
687
+ return literalInt;
688
+ }
689
+ case 'float32':
690
+ case 'float64': {
691
+ const keyName = `literal-${constType.valueType.kind}-${constType.value}`;
692
+ let literalFloat = this.types.get(keyName);
693
+ if (literalFloat) {
694
+ return literalFloat;
695
+ }
696
+ literalFloat = new go.LiteralValue(new go.PrimitiveType(constType.valueType.kind), constType.value);
697
+ this.types.set(keyName, literalFloat);
698
+ return literalFloat;
699
+ }
700
+ case 'string':
701
+ case 'guid':
702
+ case 'uuid':
703
+ case 'uri':
704
+ case 'url': {
705
+ const keyName = `literal-string-${constType.value}`;
706
+ let literalString = this.types.get(keyName);
707
+ if (literalString) {
708
+ return literalString;
709
+ }
710
+ literalString = new go.LiteralValue(new go.PrimitiveType('string'), constType.value);
711
+ this.types.set(keyName, literalString);
712
+ return literalString;
713
+ }
714
+ default:
715
+ throw new Error(`unsupported kind ${constType.valueType.kind} for LiteralValue`);
716
+ }
717
+ // TODO: tcgc doesn't support duration as a literal value
718
+ }
719
+ // updates this.unreferencedEnums and this.unreferencedModels
720
+ flagUnreferencedTypes(sdkContext) {
721
+ const referencedEnums = new Set();
722
+ const referencedModels = new Set();
723
+ const recursiveAddReferencedType = function (type) {
724
+ switch (type.kind) {
725
+ case 'array':
726
+ case 'dict':
727
+ recursiveAddReferencedType(type.valueType);
728
+ break;
729
+ case 'enum':
730
+ if (!referencedEnums.has(type.name)) {
731
+ referencedEnums.add(type.name);
732
+ }
733
+ break;
734
+ case 'enumvalue':
735
+ if (!referencedEnums.has(type.enumType.name)) {
736
+ referencedEnums.add(type.enumType.name);
737
+ }
738
+ break;
739
+ case 'model':
740
+ if (!referencedModels.has(type.name)) {
741
+ referencedModels.add(type.name);
742
+ const aggregateProps = aggregateProperties(type);
743
+ for (const prop of aggregateProps.props) {
744
+ recursiveAddReferencedType(prop.type);
745
+ }
746
+ if (aggregateProps.addlProps) {
747
+ recursiveAddReferencedType(aggregateProps.addlProps);
748
+ }
749
+ if (type.discriminatedSubtypes) {
750
+ for (const subType of values(type.discriminatedSubtypes)) {
751
+ recursiveAddReferencedType(subType);
752
+ }
753
+ }
754
+ }
755
+ break;
756
+ case 'nullable':
757
+ return recursiveAddReferencedType(type.type);
758
+ }
759
+ };
760
+ const recursiveWalkClients = function (client) {
761
+ for (const method of client.methods) {
762
+ if (method.kind === 'clientaccessor') {
763
+ recursiveWalkClients(method.response);
764
+ continue;
765
+ }
766
+ for (const param of method.parameters) {
767
+ recursiveAddReferencedType(param.type);
768
+ }
769
+ if (method.response.type) {
770
+ recursiveAddReferencedType(method.response.type);
771
+ }
772
+ }
773
+ };
774
+ // traverse all client initialization params and methods to find the set of referenced enums and models
775
+ for (const client of sdkContext.experimental_sdkPackage.clients) {
776
+ for (const param of client.initialization.properties) {
777
+ if (param.kind === 'endpoint' && param.type.kind === 'endpoint') {
778
+ for (const templateArg of param.type.templateArguments) {
779
+ recursiveAddReferencedType(templateArg.type);
780
+ }
781
+ }
782
+ }
783
+ recursiveWalkClients(client);
784
+ }
785
+ const pagedResponses = this.getPagedResponses(sdkContext);
786
+ for (const pagedResponse of pagedResponses) {
787
+ recursiveAddReferencedType(pagedResponse);
788
+ }
789
+ // now that we have the referenced set, update the unreferenced set
790
+ for (const sdkEnum of sdkContext.experimental_sdkPackage.enums) {
791
+ if (!referencedEnums.has(sdkEnum.name)) {
792
+ this.unreferencedEnums.add(sdkEnum.name);
793
+ }
794
+ }
795
+ for (const model of sdkContext.experimental_sdkPackage.models) {
796
+ if (!referencedModels.has(model.name)) {
797
+ this.unreferencedModels.add(model.name);
798
+ }
799
+ }
800
+ }
801
+ // updates this.unreferencedModels
802
+ flagUnreferencedBaseModels(sdkContext) {
803
+ const baseModels = new Set();
804
+ const referencedBaseModels = new Set();
805
+ const visitedModels = new Set(); // avoids infinite recursion
806
+ const recursiveAddReferencedBaseModel = function (type) {
807
+ switch (type.kind) {
808
+ case 'array':
809
+ case 'dict':
810
+ recursiveAddReferencedBaseModel(type.valueType);
811
+ break;
812
+ case 'model':
813
+ if (baseModels.has(type.name)) {
814
+ if (!referencedBaseModels.has(type.name)) {
815
+ referencedBaseModels.add(type.name);
816
+ }
817
+ }
818
+ else if (!visitedModels.has(type.name)) {
819
+ visitedModels.add(type.name);
820
+ const aggregateProps = aggregateProperties(type);
821
+ for (const prop of aggregateProps.props) {
822
+ recursiveAddReferencedBaseModel(prop.type);
823
+ }
824
+ if (aggregateProps.addlProps) {
825
+ recursiveAddReferencedBaseModel(aggregateProps.addlProps);
826
+ }
827
+ if (type.discriminatedSubtypes) {
828
+ for (const subType of values(type.discriminatedSubtypes)) {
829
+ recursiveAddReferencedBaseModel(subType);
830
+ }
831
+ }
832
+ }
833
+ break;
834
+ case 'nullable':
835
+ return recursiveAddReferencedBaseModel(type.type);
836
+ }
837
+ };
838
+ // collect all the base model types
839
+ for (const model of sdkContext.experimental_sdkPackage.models) {
840
+ let parent = model.baseModel;
841
+ while (parent) {
842
+ // exclude any polymorphic root type from the check
843
+ // as we always need to include the root type even
844
+ // if it's not referenced.
845
+ if (!parent.discriminatedSubtypes && !baseModels.has(parent.name)) {
846
+ baseModels.add(parent.name);
847
+ }
848
+ parent = parent.baseModel;
849
+ }
850
+ }
851
+ // traverse all methods to find any references to a base model type.
852
+ // NOTE: it's possible for there to be no base types.
853
+ if (baseModels.size > 0) {
854
+ const recursiveWalkClients = function (client) {
855
+ for (const method of client.methods) {
856
+ if (method.kind === 'clientaccessor') {
857
+ recursiveWalkClients(method.response);
858
+ continue;
859
+ }
860
+ for (const param of method.parameters) {
861
+ recursiveAddReferencedBaseModel(param.type);
862
+ }
863
+ if (method.response.type) {
864
+ recursiveAddReferencedBaseModel(method.response.type);
865
+ }
866
+ }
867
+ };
868
+ for (const client of sdkContext.experimental_sdkPackage.clients) {
869
+ recursiveWalkClients(client);
870
+ }
871
+ const pagedResponses = this.getPagedResponses(sdkContext);
872
+ for (const pagedResponse of pagedResponses) {
873
+ recursiveAddReferencedBaseModel(pagedResponse);
874
+ }
875
+ }
876
+ // now that we have the referenced set, update the unreferenced set
877
+ for (const baseModel of baseModels) {
878
+ if (!referencedBaseModels.has(baseModel)) {
879
+ this.unreferencedModels.add(baseModel);
880
+ }
881
+ }
882
+ }
883
+ }
884
+ function getPrimitiveType(kind) {
885
+ switch (kind) {
886
+ case 'boolean':
887
+ return 'bool';
888
+ case 'float32':
889
+ case 'float64':
890
+ case 'int32':
891
+ case 'int64':
892
+ case 'string':
893
+ return kind;
894
+ default:
895
+ throw new Error(`unhandled tcgc.SdkBuiltInKinds: ${kind}`);
896
+ }
897
+ }
898
+ function getDateTimeEncoding(encoding) {
899
+ switch (encoding) {
900
+ case 'rfc3339':
901
+ return 'dateTimeRFC3339';
902
+ case 'rfc7231':
903
+ return 'dateTimeRFC1123';
904
+ case 'unixTimestamp':
905
+ return 'timeUnix';
906
+ }
907
+ }
908
+ function recursiveKeyName(root, obj, substituteDiscriminator) {
909
+ switch (obj.kind) {
910
+ case 'array':
911
+ return recursiveKeyName(`${root}-array`, obj.valueType, substituteDiscriminator);
912
+ case 'enum':
913
+ return `${root}-${obj.name}`;
914
+ case 'enumvalue':
915
+ return `${root}-${obj.enumType.name}-${obj.value}`;
916
+ case 'dict':
917
+ return recursiveKeyName(`${root}-dict`, obj.valueType, substituteDiscriminator);
918
+ case 'plainDate':
919
+ return `${root}-dateType`;
920
+ case 'utcDateTime':
921
+ return `${root}-${getDateTimeEncoding(obj.encode)}`;
922
+ case 'duration':
923
+ return `${root}-${obj.wireType.kind}`;
924
+ case 'model':
925
+ if (substituteDiscriminator) {
926
+ return `${root}-${naming.createPolymorphicInterfaceName(obj.name)}`;
927
+ }
928
+ return `${root}-${obj.name}`;
929
+ case 'nullable':
930
+ return recursiveKeyName(root, obj.type, substituteDiscriminator);
931
+ case 'plainTime':
932
+ if (obj.encode !== 'rfc3339') {
933
+ throw new Error(`unsupported time encoding ${obj.encode}`);
934
+ }
935
+ return `${root}-timeRFC3339`;
936
+ default:
937
+ return `${root}-${obj.kind}`;
938
+ }
939
+ }
940
+ export function isTypePassedByValue(type) {
941
+ if (type.kind === 'nullable') {
942
+ type = type.type;
943
+ }
944
+ return type.kind === 'any' || type.kind === 'array' ||
945
+ type.kind === 'bytes' || type.kind === 'dict' ||
946
+ (type.kind === 'model' && !!type.discriminatedSubtypes);
947
+ }
948
+ // aggregate the properties from the provided type and its parent types.
949
+ // this includes any inherited additional properties.
950
+ function aggregateProperties(model) {
951
+ const allProps = new Array();
952
+ for (const prop of model.properties) {
953
+ allProps.push(prop);
954
+ }
955
+ let addlProps = model.additionalProperties;
956
+ let parent = model.baseModel;
957
+ while (parent) {
958
+ for (const parentProp of parent.properties) {
959
+ const exists = values(allProps).where(p => { return p.name === parentProp.name; }).first();
960
+ if (exists) {
961
+ // don't add the duplicate. the TS compiler has better enforcement than OpenAPI
962
+ // to ensure that duplicate fields with different types aren't added.
963
+ continue;
964
+ }
965
+ allProps.push(parentProp);
966
+ }
967
+ // if we haven't found additional properties yet and the parent has it, use it
968
+ if (!addlProps && parent.additionalProperties) {
969
+ addlProps = parent.additionalProperties;
970
+ }
971
+ parent = parent.baseModel;
972
+ }
973
+ return { props: allProps, addlProps: addlProps };
974
+ }
975
+ //# sourceMappingURL=types.js.map