@azure-tools/typespec-ts 0.55.0-dev.10 → 0.55.0-dev.11
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/package.json
CHANGED
|
@@ -316,12 +316,36 @@ function prepareExampleParameters(
|
|
|
316
316
|
|
|
317
317
|
let subscriptionIdValue = `"00000000-0000-0000-0000-000000000000"`;
|
|
318
318
|
let isSubscriptionIdAdded = false;
|
|
319
|
-
|
|
319
|
+
|
|
320
|
+
// Map each HTTP parameter to its method parameter via `methodParameterSegments`
|
|
321
|
+
// and place its example value at that path, yielding one argument per method
|
|
322
|
+
// parameter regardless of flat, nested, or grouped shape. Client- and
|
|
323
|
+
// body-carried roots are emitted by their own sections and skipped here.
|
|
324
|
+
const bodyParam = method.operation.bodyParam;
|
|
325
|
+
let bodyRootName: string | undefined;
|
|
326
|
+
if (
|
|
327
|
+
bodyParam &&
|
|
328
|
+
!isSpreadBodyParameter(bodyParam) &&
|
|
329
|
+
bodyParam.methodParameterSegments.length === 1 &&
|
|
330
|
+
bodyParam.methodParameterSegments[0] !== undefined &&
|
|
331
|
+
bodyParam.methodParameterSegments[0].length >= 1
|
|
332
|
+
) {
|
|
333
|
+
bodyRootName = bodyParam.methodParameterSegments[0][0]!.name;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const methodArguments = new Map<
|
|
337
|
+
string,
|
|
338
|
+
{ name: string; isOptional: boolean; value: ValueTreeNode | string }
|
|
339
|
+
>();
|
|
320
340
|
for (const param of method.operation.parameters) {
|
|
321
|
-
if (param.
|
|
341
|
+
if (param.type.kind === "constant" || param.clientDefaultValue) {
|
|
322
342
|
continue;
|
|
323
343
|
}
|
|
324
|
-
|
|
344
|
+
const path = param.methodParameterSegments[0];
|
|
345
|
+
if (path === undefined || path.length === 0) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
const root = path[0]!;
|
|
325
349
|
const exampleValue = parameterMap[param.serializedName];
|
|
326
350
|
|
|
327
351
|
// Handle subscriptionId parameter separately for ARM clients
|
|
@@ -343,28 +367,27 @@ function prepareExampleParameters(
|
|
|
343
367
|
continue;
|
|
344
368
|
}
|
|
345
369
|
|
|
370
|
+
// Roots emitted by the client and body sections.
|
|
371
|
+
if (root.onClient || (bodyRootName !== undefined && root.name === bodyRootName)) {
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
|
|
346
375
|
if (!exampleValue || !exampleValue.value) {
|
|
347
376
|
// report diagnostic if required parameter is missing
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
377
|
+
if (path.length === 1 && !param.optional) {
|
|
378
|
+
reportDiagnostic(dpgContext.program, {
|
|
379
|
+
code: "required-sample-parameter",
|
|
380
|
+
format: {
|
|
381
|
+
exampleName: method.oriName ?? method.name,
|
|
382
|
+
paramName: param.name,
|
|
383
|
+
},
|
|
384
|
+
target: NoTarget,
|
|
385
|
+
});
|
|
386
|
+
}
|
|
356
387
|
continue;
|
|
357
388
|
}
|
|
358
389
|
|
|
359
|
-
|
|
360
|
-
prepareExampleValue(
|
|
361
|
-
dpgContext,
|
|
362
|
-
exampleValue.parameter.name,
|
|
363
|
-
exampleValue.value,
|
|
364
|
-
param.optional,
|
|
365
|
-
param.onClient,
|
|
366
|
-
),
|
|
367
|
-
);
|
|
390
|
+
placeMethodArgument(methodArguments, path, getParameterValue(dpgContext, exampleValue.value));
|
|
368
391
|
}
|
|
369
392
|
|
|
370
393
|
// If client-level subscriptionId is needed on the client for this method, then add it
|
|
@@ -381,7 +404,6 @@ function prepareExampleParameters(
|
|
|
381
404
|
}
|
|
382
405
|
|
|
383
406
|
// required/optional body parameters
|
|
384
|
-
const bodyParam = method.operation.bodyParam;
|
|
385
407
|
const bodySerializeName = bodyParam?.serializedName;
|
|
386
408
|
const bodyExample = parameterMap[bodySerializeName ?? ""];
|
|
387
409
|
if (bodyParam && bodyExample && bodyExample.value) {
|
|
@@ -441,28 +463,87 @@ function prepareExampleParameters(
|
|
|
441
463
|
}
|
|
442
464
|
}
|
|
443
465
|
}
|
|
444
|
-
//
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
result.push(
|
|
453
|
-
prepareExampleValue(
|
|
454
|
-
dpgContext,
|
|
455
|
-
param.parameter.name,
|
|
456
|
-
param.value,
|
|
457
|
-
true,
|
|
458
|
-
param.parameter.onClient,
|
|
459
|
-
),
|
|
460
|
-
);
|
|
466
|
+
// Emit one argument per top-level method parameter. A normal parameter carries
|
|
467
|
+
// a scalar value; a parameter with nested leaves carries an object literal.
|
|
468
|
+
for (const arg of methodArguments.values()) {
|
|
469
|
+
result.push({
|
|
470
|
+
name: normalizeName(arg.name, NameType.Parameter, true),
|
|
471
|
+
value: serializeNestedValue(arg.value),
|
|
472
|
+
isOptional: arg.isOptional,
|
|
473
|
+
onClient: false,
|
|
461
474
|
});
|
|
475
|
+
}
|
|
462
476
|
|
|
463
477
|
return result;
|
|
464
478
|
}
|
|
465
479
|
|
|
480
|
+
/** A nested value tree: leaves are TypeScript value expressions, interior nodes are objects. */
|
|
481
|
+
interface ValueTreeNode {
|
|
482
|
+
[key: string]: ValueTreeNode | string;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Records `leaf` for the method parameter addressed by `path`. `path[0]` is the
|
|
487
|
+
* top-level method parameter (the argument key); a single-segment path stores a
|
|
488
|
+
* scalar, a longer path stores the leaf inside a nested object merged with
|
|
489
|
+
* sibling leaves sharing the same root.
|
|
490
|
+
*/
|
|
491
|
+
function placeMethodArgument(
|
|
492
|
+
methodArguments: Map<
|
|
493
|
+
string,
|
|
494
|
+
{ name: string; isOptional: boolean; value: ValueTreeNode | string }
|
|
495
|
+
>,
|
|
496
|
+
path: readonly { name: string; optional?: boolean }[],
|
|
497
|
+
leaf: string,
|
|
498
|
+
): void {
|
|
499
|
+
const root = path[0]!;
|
|
500
|
+
let arg = methodArguments.get(root.name);
|
|
501
|
+
if (!arg) {
|
|
502
|
+
arg = { name: root.name, isOptional: Boolean(root.optional), value: {} };
|
|
503
|
+
methodArguments.set(root.name, arg);
|
|
504
|
+
}
|
|
505
|
+
if (path.length === 1) {
|
|
506
|
+
arg.value = leaf;
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
if (typeof arg.value !== "object") {
|
|
510
|
+
arg.value = {};
|
|
511
|
+
}
|
|
512
|
+
setNestedValue(arg.value, path.slice(1), leaf);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/** Places `leaf` at `path` (segments after the root), creating intermediate objects as needed. */
|
|
516
|
+
function setNestedValue(
|
|
517
|
+
root: ValueTreeNode,
|
|
518
|
+
path: readonly { name: string }[],
|
|
519
|
+
leaf: string,
|
|
520
|
+
): void {
|
|
521
|
+
let node = root;
|
|
522
|
+
for (let i = 0; i < path.length; i++) {
|
|
523
|
+
const key = normalizeName(path[i]!.name, NameType.Property, true);
|
|
524
|
+
if (i === path.length - 1) {
|
|
525
|
+
node[key] = leaf;
|
|
526
|
+
} else {
|
|
527
|
+
const existing = node[key];
|
|
528
|
+
if (typeof existing !== "object" || existing === null) {
|
|
529
|
+
node[key] = {};
|
|
530
|
+
}
|
|
531
|
+
node = node[key] as ValueTreeNode;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/** Serializes a {@link ValueTreeNode} into a TypeScript object literal string. */
|
|
537
|
+
function serializeNestedValue(node: ValueTreeNode | string): string {
|
|
538
|
+
if (typeof node === "string") {
|
|
539
|
+
return node;
|
|
540
|
+
}
|
|
541
|
+
const entries = Object.entries(node).map(
|
|
542
|
+
([key, value]) => `${key}: ${serializeNestedValue(value)}`,
|
|
543
|
+
);
|
|
544
|
+
return `{ ${entries.join(", ")} }`;
|
|
545
|
+
}
|
|
546
|
+
|
|
466
547
|
function getCredentialExampleValue(
|
|
467
548
|
_dpgContext: SdkContext,
|
|
468
549
|
initialization: SdkClientInitializationType,
|