@azure-tools/typespec-rust 0.20.0 → 0.22.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.
- package/dist/src/codegen/cargotoml.d.ts.map +1 -1
- package/dist/src/codegen/cargotoml.js +3 -1
- package/dist/src/codegen/cargotoml.js.map +1 -1
- package/dist/src/codegen/clients.d.ts.map +1 -1
- package/dist/src/codegen/clients.js +272 -69
- package/dist/src/codegen/clients.js.map +1 -1
- package/dist/src/codegen/context.d.ts +10 -0
- package/dist/src/codegen/context.d.ts.map +1 -1
- package/dist/src/codegen/context.js +44 -2
- package/dist/src/codegen/context.js.map +1 -1
- package/dist/src/codegen/docTests.d.ts +12 -0
- package/dist/src/codegen/docTests.d.ts.map +1 -0
- package/dist/src/codegen/docTests.js +46 -0
- package/dist/src/codegen/docTests.js.map +1 -0
- package/dist/src/codegen/headerTraits.d.ts.map +1 -1
- package/dist/src/codegen/headerTraits.js +5 -0
- package/dist/src/codegen/headerTraits.js.map +1 -1
- package/dist/src/codegen/helpers.d.ts +38 -3
- package/dist/src/codegen/helpers.d.ts.map +1 -1
- package/dist/src/codegen/helpers.js +66 -5
- package/dist/src/codegen/helpers.js.map +1 -1
- package/dist/src/codegen/lib.d.ts.map +1 -1
- package/dist/src/codegen/lib.js +2 -0
- package/dist/src/codegen/lib.js.map +1 -1
- package/dist/src/codegen/models.d.ts.map +1 -1
- package/dist/src/codegen/models.js +172 -9
- package/dist/src/codegen/models.js.map +1 -1
- package/dist/src/codemodel/client.d.ts +38 -5
- package/dist/src/codemodel/client.d.ts.map +1 -1
- package/dist/src/codemodel/client.js +21 -1
- package/dist/src/codemodel/client.js.map +1 -1
- package/dist/src/codemodel/crate.js.map +1 -1
- package/dist/src/codemodel/types.d.ts +33 -11
- package/dist/src/codemodel/types.d.ts.map +1 -1
- package/dist/src/codemodel/types.js +16 -3
- package/dist/src/codemodel/types.js.map +1 -1
- package/dist/src/emitter.d.ts.map +1 -1
- package/dist/src/emitter.js +7 -1
- package/dist/src/emitter.js.map +1 -1
- package/dist/src/tcgcadapter/adapter.d.ts +11 -0
- package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
- package/dist/src/tcgcadapter/adapter.js +156 -44
- package/dist/src/tcgcadapter/adapter.js.map +1 -1
- package/dist/src/tcgcadapter/helpers.js +1 -1
- package/dist/src/tcgcadapter/helpers.js.map +1 -1
- package/package.json +29 -29
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/tcgcadapter/adapter.ts"],"names":[],"mappings":"AASA,OAAO,EAAyB,gBAAgB,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAIpG,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG/C,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAE9C,oDAAoD;AACpD,MAAM,MAAM,SAAS;AACnB,qFAAqF;AACrF,eAAe;AAEf,mDAAmD;AACnD,iBAAiB;AAEjB;;;GAGG;AACH,eAAe;AAEf,sEAAsE;AACtE,gBAAgB,CAAC;AAEnB;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,QAAQ,CAAC;gBAExC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB;CAKxE;AAED,2DAA2D;AAC3D,qBAAa,OAAO;IAClB;;;;;OAKG;WACU,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/tcgcadapter/adapter.ts"],"names":[],"mappings":"AASA,OAAO,EAAyB,gBAAgB,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAIpG,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG/C,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAE9C,oDAAoD;AACpD,MAAM,MAAM,SAAS;AACnB,qFAAqF;AACrF,eAAe;AAEf,mDAAmD;AACnD,iBAAiB;AAEjB;;;GAGG;AACH,eAAe;AAEf,sEAAsE;AACtE,gBAAgB,CAAC;AAEnB;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,QAAQ,CAAC;gBAExC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB;CAKxE;AAED;;;GAGG;AACH,qBAAa,aAAc,SAAQ,KAAK;CAAG;AAE3C,2DAA2D;AAC3D,qBAAa,OAAO;IAClB;;;;;OAKG;WACU,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAuB/E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAG7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAG/C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAoC;IAGvE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;IAG7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0E;IAEpG,OAAO;IAgBP,wDAAwD;IACxD,WAAW,IAAI,IAAI,CAAC,KAAK;IAqCzB,gDAAgD;IAChD,OAAO,CAAC,SAAS;IAajB,4DAA4D;IAC5D,OAAO,CAAC,UAAU;IAyBlB;;;;;OAKG;IACH,OAAO,CAAC,OAAO;IAoBf;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAWpB;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ;IA+FhB,OAAO,CAAC,yBAAyB;IAIjC;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IA8CrB;;;;;;OAMG;IACH,OAAO,CAAC,OAAO;IAoIf,yBAAyB;IACzB,OAAO,CAAC,UAAU;IAUlB,+DAA+D;IAC/D,OAAO,CAAC,eAAe;IAWvB,sCAAsC;IACtC,OAAO,CAAC,UAAU;IAWlB,wDAAwD;IACxD,OAAO,CAAC,aAAa;IAUrB,kDAAkD;IAClD,OAAO,CAAC,UAAU;IAUlB,qDAAqD;IACrD,OAAO,CAAC,SAAS;IAgDjB,4CAA4C;IAC5C,OAAO,CAAC,QAAQ;IAUhB,yCAAyC;IACzC,OAAO,CAAC,cAAc;IAUtB,mCAAmC;IACnC,OAAO,CAAC,aAAa;IAWrB,iCAAiC;IACjC,OAAO,CAAC,WAAW;IAWnB,0BAA0B;IAC1B,OAAO,CAAC,MAAM;IAWd;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAoClB,4EAA4E;IAC5E,OAAO,CAAC,YAAY;IASpB;;;;;;;;OAQG;IACH,OAAO,CAAC,SAAS;IAOjB;;;;;;;OAOG;IACH,OAAO,CAAC,oBAAoB;IAiP5B;;;;;;OAMG;IACH,OAAO,CAAC,yBAAyB;IAmBjC;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB;IA4C5B;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IA+UnB;;;;;;;OAOG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;;;;;;;OAQG;IACH,OAAO,CAAC,yBAAyB;IAiEjC;;;;;;;OAOG;IACH,OAAO,CAAC,2BAA2B;IA+EnC;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAoK5B;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IA4C5B;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IA2BtB;;;;;;;OAOG;IACH,OAAO,CAAC,0BAA0B;IA2BlC;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;CAa/B"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
// cspell: ignore responseheader subclients lropaging
|
|
5
|
+
// cspell: ignore addl responseheader subclients lropaging
|
|
6
6
|
import * as codegen from '@azure-tools/codegen';
|
|
7
7
|
import { values } from '@azure-tools/linq';
|
|
8
8
|
import { NoTarget } from '@typespec/compiler';
|
|
@@ -23,6 +23,12 @@ export class AdapterError extends Error {
|
|
|
23
23
|
this.target = target !== null && target !== void 0 ? target : NoTarget;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* ExternalError is thrown when an external component reports a
|
|
28
|
+
* diagnostic error that would prevent the emitter from proceeding.
|
|
29
|
+
*/
|
|
30
|
+
export class ExternalError extends Error {
|
|
31
|
+
}
|
|
26
32
|
/** Adapter converts the tcgc code model to a Rust Crate */
|
|
27
33
|
export class Adapter {
|
|
28
34
|
/**
|
|
@@ -40,6 +46,15 @@ export class Adapter {
|
|
|
40
46
|
disableUsageAccessPropagationToBase: true,
|
|
41
47
|
});
|
|
42
48
|
context.program.reportDiagnostics(ctx.diagnostics);
|
|
49
|
+
for (const diag of ctx.diagnostics) {
|
|
50
|
+
if (diag.severity === 'error') {
|
|
51
|
+
// there's no point in continuing if tcgc
|
|
52
|
+
// has reported diagnostic errors, so exit.
|
|
53
|
+
// this prevents spurious crashes in the
|
|
54
|
+
// emitter as our input state is invalid.
|
|
55
|
+
throw new ExternalError();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
43
58
|
return new Adapter(ctx, context.options);
|
|
44
59
|
}
|
|
45
60
|
constructor(ctx, options) {
|
|
@@ -173,7 +188,7 @@ export class Adapter {
|
|
|
173
188
|
* @returns a Rust model
|
|
174
189
|
*/
|
|
175
190
|
getModel(model, stack) {
|
|
176
|
-
var _a, _b;
|
|
191
|
+
var _a, _b, _c, _d;
|
|
177
192
|
if (model.name.length === 0) {
|
|
178
193
|
throw new AdapterError('InternalError', 'unnamed model', (_a = model.__raw) === null || _a === void 0 ? void 0 : _a.node); // TODO: this might no longer be an issue
|
|
179
194
|
}
|
|
@@ -204,6 +219,7 @@ export class Adapter {
|
|
|
204
219
|
for (const prop of model.properties) {
|
|
205
220
|
allProps.push(prop);
|
|
206
221
|
}
|
|
222
|
+
let addlProps = model.additionalProperties;
|
|
207
223
|
let parent = model.baseModel;
|
|
208
224
|
while (parent) {
|
|
209
225
|
for (const parentProp of parent.properties) {
|
|
@@ -215,7 +231,14 @@ export class Adapter {
|
|
|
215
231
|
}
|
|
216
232
|
allProps.push(parentProp);
|
|
217
233
|
}
|
|
218
|
-
//
|
|
234
|
+
// propagate parent's additional properties if we don't yet have any.
|
|
235
|
+
// if we do, ensure that their kinds match.
|
|
236
|
+
if (!addlProps) {
|
|
237
|
+
addlProps = parent.additionalProperties;
|
|
238
|
+
}
|
|
239
|
+
else if (parent.additionalProperties && addlProps.kind !== parent.additionalProperties.kind) {
|
|
240
|
+
throw new AdapterError('UnsupportedTsp', `model ${model.name} has additional properties kind ${addlProps.kind} which conflicts with parent model ${parent.name} additional properties kind ${parent.additionalProperties.kind}`, (_b = model.__raw) === null || _b === void 0 ? void 0 : _b.node);
|
|
241
|
+
}
|
|
219
242
|
parent = parent.baseModel;
|
|
220
243
|
}
|
|
221
244
|
for (const property of allProps) {
|
|
@@ -231,15 +254,25 @@ export class Adapter {
|
|
|
231
254
|
// we just adapt it here as a regular model field.
|
|
232
255
|
}
|
|
233
256
|
else {
|
|
234
|
-
throw new AdapterError('UnsupportedTsp', `model property kind ${property.kind} NYI`, (
|
|
257
|
+
throw new AdapterError('UnsupportedTsp', `model property kind ${(_c = property.__raw) === null || _c === void 0 ? void 0 : _c.kind} NYI`, (_d = property.__raw) === null || _d === void 0 ? void 0 : _d.node);
|
|
235
258
|
}
|
|
236
259
|
}
|
|
237
260
|
const structField = this.getModelField(property, rustModel.visibility, stack);
|
|
238
261
|
rustModel.fields.push(structField);
|
|
239
262
|
}
|
|
263
|
+
if (addlProps) {
|
|
264
|
+
const addlPropsType = this.getHashMap(this.typeToWireType(this.getType(addlProps)));
|
|
265
|
+
const addlPropsField = new rust.ModelAdditionalProperties('additional_properties', 'pub', this.getOptionType(addlPropsType));
|
|
266
|
+
addlPropsField.docs.summary = 'contains unnamed additional properties';
|
|
267
|
+
rustModel.fields.push(addlPropsField);
|
|
268
|
+
}
|
|
240
269
|
stack.pop();
|
|
241
270
|
return rustModel;
|
|
242
271
|
}
|
|
272
|
+
getSerializedPropertyName(property) {
|
|
273
|
+
var _a, _b, _c, _d, _e;
|
|
274
|
+
return property.kind === 'property' ? (_d = (_b = (_a = property.serializationOptions.json) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : (_c = property.serializationOptions.xml) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : (_e = property.serializationOptions.multipart) === null || _e === void 0 ? void 0 : _e.name : undefined;
|
|
275
|
+
}
|
|
243
276
|
/**
|
|
244
277
|
* converts a tcgc model property to a model field
|
|
245
278
|
*
|
|
@@ -249,17 +282,19 @@ export class Adapter {
|
|
|
249
282
|
* @returns a Rust model field
|
|
250
283
|
*/
|
|
251
284
|
getModelField(property, modelVisibility, stack) {
|
|
285
|
+
var _a;
|
|
252
286
|
let fieldType = this.getType(property.type, stack);
|
|
253
287
|
// if the field's type is a model and it's in the type stack then
|
|
254
288
|
// box it. this is to avoid infinitely recursive type definitions.
|
|
255
289
|
if (fieldType.kind === 'model' && stack.includes(fieldType.name)) {
|
|
256
|
-
fieldType =
|
|
290
|
+
fieldType = this.getBoxType(fieldType);
|
|
257
291
|
}
|
|
258
292
|
// for public models each field is always an Option<T>.
|
|
259
293
|
if (modelVisibility === 'pub' || property.optional) {
|
|
260
|
-
fieldType =
|
|
294
|
+
fieldType = this.getOptionType(fieldType.kind === 'box' ? fieldType : this.typeToWireType(fieldType));
|
|
261
295
|
}
|
|
262
|
-
const
|
|
296
|
+
const serializedName = (_a = this.getSerializedPropertyName(property)) !== null && _a !== void 0 ? _a : property.name;
|
|
297
|
+
const modelField = new rust.ModelField(naming.getEscapedReservedName(snakeCaseName(property.name), 'prop'), serializedName, modelVisibility, fieldType, property.optional);
|
|
263
298
|
modelField.docs = this.adaptDocs(property.summary, property.doc);
|
|
264
299
|
// if this is a literal, add a doc comment explaining its behavior
|
|
265
300
|
const unwrappedType = shared.unwrapOption(fieldType);
|
|
@@ -423,6 +458,16 @@ export class Adapter {
|
|
|
423
458
|
throw new AdapterError('UnsupportedTsp', `unhandled tcgc type ${type.kind}`, (_b = type.__raw) === null || _b === void 0 ? void 0 : _b.node);
|
|
424
459
|
}
|
|
425
460
|
}
|
|
461
|
+
/** returns a Box type */
|
|
462
|
+
getBoxType(type) {
|
|
463
|
+
const typeKey = recursiveKeyName('box', type);
|
|
464
|
+
let boxType = this.types.get(typeKey);
|
|
465
|
+
if (!boxType) {
|
|
466
|
+
boxType = new rust.Box(type);
|
|
467
|
+
this.types.set(typeKey, boxType);
|
|
468
|
+
}
|
|
469
|
+
return boxType;
|
|
470
|
+
}
|
|
426
471
|
/** returns an EncodedBytes type with the specified encoding */
|
|
427
472
|
getEncodedBytes(encoding, asSlice) {
|
|
428
473
|
const keyName = `encodedBytes-${encoding}${asSlice ? '-slice' : ''}`;
|
|
@@ -445,6 +490,16 @@ export class Adapter {
|
|
|
445
490
|
this.types.set(keyName, hashmapType);
|
|
446
491
|
return hashmapType;
|
|
447
492
|
}
|
|
493
|
+
/** returns an Option<T> where T is specified in type */
|
|
494
|
+
getOptionType(type) {
|
|
495
|
+
const typeKey = recursiveKeyName('option', type);
|
|
496
|
+
let optionType = this.types.get(typeKey);
|
|
497
|
+
if (!optionType) {
|
|
498
|
+
optionType = new rust.Option(type);
|
|
499
|
+
this.types.set(typeKey, optionType);
|
|
500
|
+
}
|
|
501
|
+
return optionType;
|
|
502
|
+
}
|
|
448
503
|
/** returns the specified type wrapped in a Ref */
|
|
449
504
|
getRefType(type) {
|
|
450
505
|
const typeKey = recursiveKeyName('ref', type);
|
|
@@ -633,7 +688,7 @@ export class Adapter {
|
|
|
633
688
|
var _a, _b, _c, _d, _e;
|
|
634
689
|
let clientName = client.name;
|
|
635
690
|
// NOTE: if the client has the @clientName decorator applied then use that verbatim
|
|
636
|
-
if (parent && !client.decorators
|
|
691
|
+
if (parent && !hasClientNameDecorator(client.decorators)) {
|
|
637
692
|
// for hierarchical clients, the child client names are built
|
|
638
693
|
// from the parent client name. this is because tsp allows subclients
|
|
639
694
|
// with the same name. consider the following example.
|
|
@@ -747,12 +802,13 @@ export class Adapter {
|
|
|
747
802
|
if (i === 0) {
|
|
748
803
|
// the first template arg is always the endpoint parameter.
|
|
749
804
|
// note that the types of the param and the field are different.
|
|
750
|
-
//
|
|
751
|
-
//
|
|
752
|
-
const
|
|
805
|
+
// we default to "endpoint" and will use the defined name IFF
|
|
806
|
+
// it has the @clientName decorator applied
|
|
807
|
+
const endpointName = hasClientNameDecorator(templateArg.decorators) ? snakeCaseName(templateArg.name) : 'endpoint';
|
|
808
|
+
const adaptedParam = new rust.ClientEndpointParameter(endpointName);
|
|
753
809
|
adaptedParam.docs = this.adaptDocs(param.summary, param.doc);
|
|
754
810
|
ctorParams.push(adaptedParam);
|
|
755
|
-
rustClient.fields.push(new rust.StructField(
|
|
811
|
+
rustClient.fields.push(new rust.StructField(endpointName, 'pubCrate', new rust.Url(this.crate)));
|
|
756
812
|
// if the server's URL is *only* the endpoint parameter then we're done.
|
|
757
813
|
// this is the param.type.kind === 'endpoint' case.
|
|
758
814
|
if (endpointType.serverUrl === `{${templateArg.serializedName}}`) {
|
|
@@ -777,7 +833,7 @@ export class Adapter {
|
|
|
777
833
|
continue;
|
|
778
834
|
}
|
|
779
835
|
const clientParam = this.adaptClientParameter(templateArg, rustClient.constructable);
|
|
780
|
-
if (clientParam.kind !== '
|
|
836
|
+
if (clientParam.kind !== 'clientSupplementalEndpoint') {
|
|
781
837
|
throw new AdapterError('InternalError', `unexpected client parameter kind ${clientParam.kind}`, (_b = templateArg.__raw) === null || _b === void 0 ? void 0 : _b.node);
|
|
782
838
|
}
|
|
783
839
|
(_c = rustClient.constructable.endpoint) === null || _c === void 0 ? void 0 : _c.parameters.push(clientParam);
|
|
@@ -833,19 +889,21 @@ export class Adapter {
|
|
|
833
889
|
this.adaptClientAccessor(client, child, rustClient, subClient);
|
|
834
890
|
}
|
|
835
891
|
for (const method of client.methods) {
|
|
836
|
-
if (method.kind === '
|
|
837
|
-
// skip LROs for now so that codegen is unblocked
|
|
892
|
+
if (method.kind === 'lropaging') {
|
|
893
|
+
// skip Paging LROs for now so that codegen is unblocked
|
|
838
894
|
// TODO: https://github.com/Azure/typespec-rust/issues/188
|
|
839
895
|
this.ctx.program.reportDiagnostic({
|
|
840
|
-
code: '
|
|
896
|
+
code: 'LroPagingNotSupported',
|
|
841
897
|
severity: 'warning',
|
|
842
|
-
message: `skip emitting LRO ${method.name}`,
|
|
898
|
+
message: `skip emitting Paging LRO ${method.name}`,
|
|
843
899
|
target: (_e = (_d = method.__raw) === null || _d === void 0 ? void 0 : _d.node) !== null && _e !== void 0 ? _e : NoTarget,
|
|
844
900
|
});
|
|
845
901
|
continue;
|
|
846
902
|
}
|
|
847
903
|
this.adaptMethod(method, rustClient);
|
|
848
904
|
}
|
|
905
|
+
// Set the tracing namespace for tracing based on the client's namespace
|
|
906
|
+
rustClient.languageIndependentName = client.crossLanguageDefinitionId;
|
|
849
907
|
this.crate.clients.push(rustClient);
|
|
850
908
|
return rustClient;
|
|
851
909
|
}
|
|
@@ -868,7 +926,7 @@ export class Adapter {
|
|
|
868
926
|
throw new AdapterError('InternalError', 'scopes must contain at least one entry', cred.model);
|
|
869
927
|
}
|
|
870
928
|
const ctorTokenCredential = new rust.Constructor('new');
|
|
871
|
-
const tokenCredParam = new rust.
|
|
929
|
+
const tokenCredParam = new rust.ClientCredentialParameter('credential', new rust.Arc(new rust.TokenCredential(this.crate, scopes)));
|
|
872
930
|
tokenCredParam.docs.summary = `An implementation of [\`TokenCredential\`](azure_core::credentials::TokenCredential) that can provide an Entra ID token to use when authenticating.`;
|
|
873
931
|
ctorTokenCredential.params.push(tokenCredParam);
|
|
874
932
|
ctorTokenCredential.docs.summary = `Creates a new ${rustClient.name}, using Entra ID authentication.`;
|
|
@@ -915,7 +973,7 @@ export class Adapter {
|
|
|
915
973
|
adaptedParam = new rust.ClientMethodParameter(paramName, paramType, optional);
|
|
916
974
|
break;
|
|
917
975
|
case 'path':
|
|
918
|
-
adaptedParam = new rust.
|
|
976
|
+
adaptedParam = new rust.ClientSupplementalEndpointParameter(paramName, paramType, optional, param.serializedName);
|
|
919
977
|
break;
|
|
920
978
|
}
|
|
921
979
|
adaptedParam.docs = this.adaptDocs(param.summary, param.doc);
|
|
@@ -959,7 +1017,7 @@ export class Adapter {
|
|
|
959
1017
|
* @param rustClient the client to which the method belongs
|
|
960
1018
|
*/
|
|
961
1019
|
adaptMethod(method, rustClient) {
|
|
962
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
1020
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
963
1021
|
let srcMethodName = method.name;
|
|
964
1022
|
if (method.kind === 'paging' && !srcMethodName.match(/^list/i)) {
|
|
965
1023
|
const chunks = codegen.deconstruct(srcMethodName);
|
|
@@ -987,6 +1045,12 @@ export class Adapter {
|
|
|
987
1045
|
const methodOptionsField = new rust.StructField('method_options', 'pub', clientMethodOptions);
|
|
988
1046
|
methodOptionsField.docs.summary = 'Allows customization of the method call.';
|
|
989
1047
|
methodOptionsStruct.fields.push(methodOptionsField);
|
|
1048
|
+
if (method.kind === 'lro') {
|
|
1049
|
+
const pollerOptions = new rust.ExternalType(this.crate, 'PollerOptions', 'azure_core::http::poller');
|
|
1050
|
+
const pollerOptionsField = new rust.StructField('poller_options', 'pub', pollerOptions);
|
|
1051
|
+
pollerOptionsField.docs.summary = 'Allows customization of the [`Poller`](azure_core::http::poller::Poller).';
|
|
1052
|
+
methodOptionsStruct.fields.push(pollerOptionsField);
|
|
1053
|
+
}
|
|
990
1054
|
const pub = method.access === 'public' ? 'pub' : 'pubCrate';
|
|
991
1055
|
const methodOptions = new rust.MethodOptions(methodOptionsStruct);
|
|
992
1056
|
const httpMethod = method.operation.verb;
|
|
@@ -1009,6 +1073,9 @@ export class Adapter {
|
|
|
1009
1073
|
case 'paging':
|
|
1010
1074
|
rustMethod = new rust.PageableMethod(methodName, languageIndependentName, rustClient, pub, methodOptions, httpMethod, httpPath);
|
|
1011
1075
|
break;
|
|
1076
|
+
case 'lro':
|
|
1077
|
+
rustMethod = new rust.LroMethod(methodName, languageIndependentName, rustClient, pub, methodOptions, httpMethod, httpPath);
|
|
1078
|
+
break;
|
|
1012
1079
|
default:
|
|
1013
1080
|
throw new AdapterError('UnsupportedTsp', `method kind ${method.kind} NYI`, (_d = method.__raw) === null || _d === void 0 ? void 0 : _d.node);
|
|
1014
1081
|
}
|
|
@@ -1047,8 +1114,11 @@ export class Adapter {
|
|
|
1047
1114
|
else {
|
|
1048
1115
|
adaptedParam = this.adaptMethodParameter(opParam);
|
|
1049
1116
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1117
|
+
switch (adaptedParam.kind) {
|
|
1118
|
+
case 'headerScalar':
|
|
1119
|
+
case 'queryScalar':
|
|
1120
|
+
paramsMap.set(param, adaptedParam);
|
|
1121
|
+
break;
|
|
1052
1122
|
}
|
|
1053
1123
|
adaptedParam.docs = this.adaptDocs(param.summary, param.doc);
|
|
1054
1124
|
rustMethod.params.push(adaptedParam);
|
|
@@ -1069,7 +1139,7 @@ export class Adapter {
|
|
|
1069
1139
|
fieldType = field.type;
|
|
1070
1140
|
}
|
|
1071
1141
|
else {
|
|
1072
|
-
fieldType =
|
|
1142
|
+
fieldType = this.getOptionType(adaptedParam.type);
|
|
1073
1143
|
}
|
|
1074
1144
|
const optionsField = new rust.StructField(adaptedParam.name, 'pub', fieldType);
|
|
1075
1145
|
optionsField.docs = adaptedParam.docs;
|
|
@@ -1166,13 +1236,13 @@ export class Adapter {
|
|
|
1166
1236
|
let serde;
|
|
1167
1237
|
switch (responseFormat) {
|
|
1168
1238
|
case 'JsonFormat':
|
|
1169
|
-
if (!segment.serializationOptions.json) {
|
|
1239
|
+
if (segment.kind !== 'property' || !segment.serializationOptions.json) {
|
|
1170
1240
|
throw new AdapterError('InternalError', `paged method ${method.name} is missing JSON serialization data`, (_k = method.__raw) === null || _k === void 0 ? void 0 : _k.node);
|
|
1171
1241
|
}
|
|
1172
1242
|
serde = segment.serializationOptions.json.name;
|
|
1173
1243
|
break;
|
|
1174
1244
|
case 'XmlFormat':
|
|
1175
|
-
if (!segment.serializationOptions.xml) {
|
|
1245
|
+
if (segment.kind !== 'property' || !segment.serializationOptions.xml) {
|
|
1176
1246
|
throw new AdapterError('InternalError', `paged method ${method.name} is missing XML serialization data`, (_l = method.__raw) === null || _l === void 0 ? void 0 : _l.node);
|
|
1177
1247
|
}
|
|
1178
1248
|
serde = segment.serializationOptions.xml.name;
|
|
@@ -1180,11 +1250,14 @@ export class Adapter {
|
|
|
1180
1250
|
}
|
|
1181
1251
|
for (let i = 0; i < typeToUnwrap.fields.length; ++i) {
|
|
1182
1252
|
const field = typeToUnwrap.fields[i];
|
|
1253
|
+
if (field.kind === 'additionalProperties') {
|
|
1254
|
+
continue;
|
|
1255
|
+
}
|
|
1183
1256
|
if (field.serde === serde) {
|
|
1184
1257
|
// check if this has already been unwrapped (e.g. type is shared across operations)
|
|
1185
1258
|
if (field.type.kind === 'option') {
|
|
1186
|
-
|
|
1187
|
-
|
|
1259
|
+
field.type = (field.type).type;
|
|
1260
|
+
field.flags |= rust.ModelFieldFlags.PageItems;
|
|
1188
1261
|
}
|
|
1189
1262
|
// move to the next segment
|
|
1190
1263
|
if (field.type.kind === 'model') {
|
|
@@ -1206,6 +1279,29 @@ export class Adapter {
|
|
|
1206
1279
|
rustMethod.returns = new rust.Result(this.crate, new rust.Pager(this.crate, new rust.Response(this.crate, synthesizedModel, responseFormat)));
|
|
1207
1280
|
}
|
|
1208
1281
|
}
|
|
1282
|
+
else if (method.kind === 'lro') {
|
|
1283
|
+
const format = responseFormat === 'NoFormat' ? 'JsonFormat' : responseFormat;
|
|
1284
|
+
const responseType = this.typeToWireType(this.getModel(method.lroMetadata.logicalResult));
|
|
1285
|
+
if (responseType.kind !== 'model') {
|
|
1286
|
+
throw new AdapterError('InternalError', `envelope result for ${method.name} is not a model`, (_o = method.__raw) === null || _o === void 0 ? void 0 : _o.node);
|
|
1287
|
+
}
|
|
1288
|
+
const pushModels = (model, crate) => {
|
|
1289
|
+
if (crate.models.some(m => m === model)) {
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
crate.models.push(model);
|
|
1293
|
+
for (const field of model.fields) {
|
|
1294
|
+
let fieldType = field.type;
|
|
1295
|
+
fieldType = fieldType.kind === 'option' ? fieldType.type : fieldType;
|
|
1296
|
+
fieldType = fieldType.kind === 'Vec' ? fieldType.type : fieldType;
|
|
1297
|
+
if (fieldType.kind === 'model') {
|
|
1298
|
+
pushModels(fieldType, crate);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
};
|
|
1302
|
+
pushModels(responseType, this.crate);
|
|
1303
|
+
rustMethod.returns = new rust.Result(this.crate, new rust.Poller(this.crate, new rust.Response(this.crate, responseType, format)));
|
|
1304
|
+
}
|
|
1209
1305
|
else if (method.response.type && !(method.response.type.kind === 'bytes' && method.response.type.encode === 'bytes')) {
|
|
1210
1306
|
const response = new rust.Response(this.crate, this.typeToWireType(this.getType(method.response.type)), responseFormat);
|
|
1211
1307
|
rustMethod.returns = new rust.Result(this.crate, response);
|
|
@@ -1220,7 +1316,7 @@ export class Adapter {
|
|
|
1220
1316
|
}
|
|
1221
1317
|
else if (method.response.type && method.response.type.kind === 'bytes' && method.response.type.encode === 'bytes') {
|
|
1222
1318
|
// bytes encoding indicates a streaming binary response
|
|
1223
|
-
rustMethod.returns = new rust.Result(this.crate, new rust.
|
|
1319
|
+
rustMethod.returns = new rust.Result(this.crate, new rust.BufResponse(this.crate));
|
|
1224
1320
|
}
|
|
1225
1321
|
else {
|
|
1226
1322
|
rustMethod.returns = new rust.Result(this.crate, new rust.Response(this.crate, this.getUnitType(), responseFormat));
|
|
@@ -1304,6 +1400,7 @@ export class Adapter {
|
|
|
1304
1400
|
switch (method.returns.type.kind) {
|
|
1305
1401
|
case 'pageIterator':
|
|
1306
1402
|
case 'pager':
|
|
1403
|
+
case 'poller':
|
|
1307
1404
|
implFor = method.returns.type.type;
|
|
1308
1405
|
break;
|
|
1309
1406
|
case 'response':
|
|
@@ -1316,7 +1413,7 @@ export class Adapter {
|
|
|
1316
1413
|
implFor = method.returns.type;
|
|
1317
1414
|
break;
|
|
1318
1415
|
default:
|
|
1319
|
-
// this is
|
|
1416
|
+
// this is BufResponse which should have been previously skipped
|
|
1320
1417
|
throw new AdapterError('InternalError', `unexpected method return kind ${method.returns.type.kind}`);
|
|
1321
1418
|
}
|
|
1322
1419
|
const traitName = `${recursiveTypeName(implFor.content)}Headers`;
|
|
@@ -1335,7 +1432,7 @@ export class Adapter {
|
|
|
1335
1432
|
* @returns the pageable strategy
|
|
1336
1433
|
*/
|
|
1337
1434
|
adaptPageableMethodStrategy(method, paramsMap, respHeadersMap) {
|
|
1338
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
1435
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
1339
1436
|
if (method.pagingMetadata.nextLinkOperation) {
|
|
1340
1437
|
// TODO: https://github.com/Azure/autorest.rust/issues/103
|
|
1341
1438
|
throw new AdapterError('UnsupportedTsp', 'next page operation NYI', (_a = method.__raw) === null || _a === void 0 ? void 0 : _a.node);
|
|
@@ -1403,12 +1500,12 @@ export class Adapter {
|
|
|
1403
1500
|
break;
|
|
1404
1501
|
}
|
|
1405
1502
|
default:
|
|
1406
|
-
throw new AdapterError('InternalError', `
|
|
1503
|
+
throw new AdapterError('InternalError', `missing continuation token`, (_l = method.__raw) === null || _l === void 0 ? void 0 : _l.node);
|
|
1407
1504
|
}
|
|
1408
1505
|
return new rust.PageableStrategyContinuationToken(requestToken, responseToken);
|
|
1409
1506
|
}
|
|
1410
1507
|
else {
|
|
1411
|
-
throw new AdapterError('InternalError', `unknown paging strategy for operation ${method.name}`, (
|
|
1508
|
+
throw new AdapterError('InternalError', `unknown paging strategy for operation ${method.name}`, (_m = method.__raw) === null || _m === void 0 ? void 0 : _m.node);
|
|
1412
1509
|
}
|
|
1413
1510
|
}
|
|
1414
1511
|
/**
|
|
@@ -1520,14 +1617,12 @@ export class Adapter {
|
|
|
1520
1617
|
{
|
|
1521
1618
|
paramType = this.typeToWireType(paramType);
|
|
1522
1619
|
let style = 'simple';
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
style = tspStyleString;
|
|
1530
|
-
}
|
|
1620
|
+
const tspStyleString = param.style;
|
|
1621
|
+
if (!['simple', 'path', 'label', 'matrix'].includes(tspStyleString)) {
|
|
1622
|
+
throw new AdapterError('InternalError', `unsupported style ${tspStyleString} for parameter ${param.serializedName}`, (_f = param.__raw) === null || _f === void 0 ? void 0 : _f.node);
|
|
1623
|
+
}
|
|
1624
|
+
else {
|
|
1625
|
+
style = tspStyleString;
|
|
1531
1626
|
}
|
|
1532
1627
|
if (isRefSlice(paramType)) {
|
|
1533
1628
|
adaptedParam = new rust.PathCollectionParameter(paramName, param.serializedName, paramLoc, param.optional, paramType, param.allowReserved, style, param.explode);
|
|
@@ -1679,8 +1774,8 @@ export class Adapter {
|
|
|
1679
1774
|
// find the corresponding field within the model so we can get its index
|
|
1680
1775
|
let serializedName;
|
|
1681
1776
|
for (const property of opParamType.properties) {
|
|
1682
|
-
if (property.name === param.name) {
|
|
1683
|
-
serializedName = property
|
|
1777
|
+
if (property.kind === 'property' && property.name === param.name) {
|
|
1778
|
+
serializedName = this.getSerializedPropertyName(property);
|
|
1684
1779
|
break;
|
|
1685
1780
|
}
|
|
1686
1781
|
}
|
|
@@ -1783,17 +1878,18 @@ function snakeCaseName(name) {
|
|
|
1783
1878
|
* this is idempotent so providing the same type will create
|
|
1784
1879
|
* the same key.
|
|
1785
1880
|
*
|
|
1786
|
-
*
|
|
1881
|
+
* type is recursively unwrapped, and each layer is used to construct
|
|
1787
1882
|
* the key. e.g. if obj is a HashMap<String, Vec<i32>> this would
|
|
1788
1883
|
* unwrap to hashmap-Vec-i32.
|
|
1789
1884
|
*
|
|
1790
1885
|
* @param root the starting value for the key
|
|
1791
|
-
* @param
|
|
1886
|
+
* @param type the type for which to create the key
|
|
1792
1887
|
* @returns a string containing the complete map key
|
|
1793
1888
|
*/
|
|
1794
1889
|
function recursiveKeyName(root, type) {
|
|
1795
1890
|
switch (type.kind) {
|
|
1796
1891
|
case 'Vec':
|
|
1892
|
+
case 'box':
|
|
1797
1893
|
return recursiveKeyName(`${root}-${type.kind}`, type.type);
|
|
1798
1894
|
case 'encodedBytes':
|
|
1799
1895
|
return `${root}-${type.kind}-${type.encoding}${type.slice ? '-slice' : ''}`;
|
|
@@ -1806,9 +1902,16 @@ function recursiveKeyName(root, type) {
|
|
|
1806
1902
|
case 'offsetDateTime':
|
|
1807
1903
|
return `${root}-${type.kind}-${type.encoding}${type.utc ? '-utc' : ''}`;
|
|
1808
1904
|
case 'model':
|
|
1905
|
+
case 'struct':
|
|
1809
1906
|
return `${root}-${type.kind}-${type.name}`;
|
|
1907
|
+
case 'literal':
|
|
1908
|
+
return `${recursiveKeyName(`${root}-${type.kind}`, type.valueKind)}-${type.value}`;
|
|
1909
|
+
case 'payload':
|
|
1910
|
+
return recursiveKeyName(`${root}-${type.kind}-${type.format}`, type.type);
|
|
1810
1911
|
case 'ref':
|
|
1811
1912
|
return recursiveKeyName(`${root}-${type.kind}`, type.type);
|
|
1913
|
+
case 'requestContent':
|
|
1914
|
+
return recursiveKeyName(`${root}-${type.kind}`, type.content);
|
|
1812
1915
|
case 'safeint':
|
|
1813
1916
|
case 'decimal':
|
|
1814
1917
|
return `${root}-${type.kind}${type.stringEncoding ? '-string' : ''}`;
|
|
@@ -1872,4 +1975,13 @@ function getXMLKind(decorators, field) {
|
|
|
1872
1975
|
}
|
|
1873
1976
|
return undefined;
|
|
1874
1977
|
}
|
|
1978
|
+
/**
|
|
1979
|
+
* returns true if decorators contains `@clientName`
|
|
1980
|
+
*
|
|
1981
|
+
* @param decorators the array of decorators to inspect
|
|
1982
|
+
* @returns true if `@clientName` is found in decorators
|
|
1983
|
+
*/
|
|
1984
|
+
function hasClientNameDecorator(decorators) {
|
|
1985
|
+
return decorators.find((decorator) => decorator.name === 'Azure.ClientGenerator.Core.@clientName') !== undefined;
|
|
1986
|
+
}
|
|
1875
1987
|
//# sourceMappingURL=adapter.js.map
|