@azure-tools/typespec-ts 0.49.0 → 0.49.1

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 (106) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/src/framework/hooks/binder.d.ts.map +1 -1
  3. package/dist/src/framework/hooks/binder.js +8 -17
  4. package/dist/src/framework/hooks/binder.js.map +1 -1
  5. package/dist/src/index.d.ts.map +1 -1
  6. package/dist/src/index.js +13 -11
  7. package/dist/src/index.js.map +1 -1
  8. package/dist/src/lib.d.ts +8 -0
  9. package/dist/src/lib.d.ts.map +1 -1
  10. package/dist/src/lib.js +10 -0
  11. package/dist/src/lib.js.map +1 -1
  12. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  13. package/dist/src/modular/buildOperations.js +10 -5
  14. package/dist/src/modular/buildOperations.js.map +1 -1
  15. package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
  16. package/dist/src/modular/buildProjectFiles.js +13 -10
  17. package/dist/src/modular/buildProjectFiles.js.map +1 -1
  18. package/dist/src/modular/emitModels.d.ts.map +1 -1
  19. package/dist/src/modular/emitModels.js +43 -40
  20. package/dist/src/modular/emitModels.js.map +1 -1
  21. package/dist/src/modular/emitSamples.d.ts.map +1 -1
  22. package/dist/src/modular/emitSamples.js +9 -0
  23. package/dist/src/modular/emitSamples.js.map +1 -1
  24. package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
  25. package/dist/src/modular/helpers/clientHelpers.js +4 -1
  26. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  27. package/dist/src/modular/helpers/namingHelpers.d.ts +7 -0
  28. package/dist/src/modular/helpers/namingHelpers.d.ts.map +1 -1
  29. package/dist/src/modular/helpers/namingHelpers.js +15 -0
  30. package/dist/src/modular/helpers/namingHelpers.js.map +1 -1
  31. package/dist/src/modular/helpers/operationHelpers.d.ts +19 -2
  32. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  33. package/dist/src/modular/helpers/operationHelpers.js +410 -39
  34. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  35. package/dist/src/modular/serialization/buildDeserializerFunction.d.ts.map +1 -1
  36. package/dist/src/modular/serialization/buildDeserializerFunction.js +9 -3
  37. package/dist/src/modular/serialization/buildDeserializerFunction.js.map +1 -1
  38. package/dist/src/modular/serialization/buildXmlSerializerFunction.d.ts +12 -0
  39. package/dist/src/modular/serialization/buildXmlSerializerFunction.d.ts.map +1 -1
  40. package/dist/src/modular/serialization/buildXmlSerializerFunction.js +259 -18
  41. package/dist/src/modular/serialization/buildXmlSerializerFunction.js.map +1 -1
  42. package/dist/src/modular/static-helpers-metadata.d.ts +10 -0
  43. package/dist/src/modular/static-helpers-metadata.d.ts.map +1 -1
  44. package/dist/src/modular/static-helpers-metadata.js +10 -0
  45. package/dist/src/modular/static-helpers-metadata.js.map +1 -1
  46. package/dist/src/modular/type-expressions/get-model-expression.d.ts +3 -1
  47. package/dist/src/modular/type-expressions/get-model-expression.d.ts.map +1 -1
  48. package/dist/src/modular/type-expressions/get-model-expression.js +50 -9
  49. package/dist/src/modular/type-expressions/get-model-expression.js.map +1 -1
  50. package/dist/src/modular/type-expressions/get-nullable-expression.d.ts.map +1 -1
  51. package/dist/src/modular/type-expressions/get-nullable-expression.js +8 -0
  52. package/dist/src/modular/type-expressions/get-nullable-expression.js.map +1 -1
  53. package/dist/src/modular/type-expressions/get-type-expression.d.ts +3 -2
  54. package/dist/src/modular/type-expressions/get-type-expression.d.ts.map +1 -1
  55. package/dist/src/modular/type-expressions/get-type-expression.js.map +1 -1
  56. package/dist/src/transform/transform.d.ts.map +1 -1
  57. package/dist/src/transform/transform.js +10 -10
  58. package/dist/src/transform/transform.js.map +1 -1
  59. package/dist/src/transform/transformSchemas.d.ts.map +1 -1
  60. package/dist/src/transform/transformSchemas.js +4 -4
  61. package/dist/src/transform/transformSchemas.js.map +1 -1
  62. package/dist/src/transform/transfromRLCOptions.d.ts +1 -1
  63. package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
  64. package/dist/src/transform/transfromRLCOptions.js +37 -24
  65. package/dist/src/transform/transfromRLCOptions.js.map +1 -1
  66. package/dist/src/utils/clientUtils.d.ts +1 -1
  67. package/dist/src/utils/clientUtils.d.ts.map +1 -1
  68. package/dist/src/utils/clientUtils.js +40 -17
  69. package/dist/src/utils/clientUtils.js.map +1 -1
  70. package/dist/src/utils/crossLanguageDef.d.ts.map +1 -1
  71. package/dist/src/utils/crossLanguageDef.js +9 -3
  72. package/dist/src/utils/crossLanguageDef.js.map +1 -1
  73. package/dist/src/utils/interfaces.d.ts +2 -1
  74. package/dist/src/utils/interfaces.d.ts.map +1 -1
  75. package/dist/src/utils/modelUtils.d.ts +2 -2
  76. package/dist/src/utils/modelUtils.d.ts.map +1 -1
  77. package/dist/src/utils/modelUtils.js +15 -16
  78. package/dist/src/utils/modelUtils.js.map +1 -1
  79. package/dist/tsconfig.tsbuildinfo +1 -1
  80. package/package.json +22 -22
  81. package/src/framework/hooks/binder.ts +12 -22
  82. package/src/index.ts +17 -10
  83. package/src/lib.ts +20 -0
  84. package/src/modular/buildOperations.ts +12 -4
  85. package/src/modular/buildProjectFiles.ts +19 -16
  86. package/src/modular/emitModels.ts +72 -44
  87. package/src/modular/emitSamples.ts +11 -1
  88. package/src/modular/helpers/clientHelpers.ts +5 -1
  89. package/src/modular/helpers/namingHelpers.ts +19 -0
  90. package/src/modular/helpers/operationHelpers.ts +533 -40
  91. package/src/modular/serialization/buildDeserializerFunction.ts +11 -2
  92. package/src/modular/serialization/buildXmlSerializerFunction.ts +375 -24
  93. package/src/modular/static-helpers-metadata.ts +10 -0
  94. package/src/modular/type-expressions/get-model-expression.ts +78 -13
  95. package/src/modular/type-expressions/get-nullable-expression.ts +9 -0
  96. package/src/modular/type-expressions/get-type-expression.ts +3 -1
  97. package/src/transform/transform.ts +5 -2
  98. package/src/transform/transformSchemas.ts +4 -1
  99. package/src/transform/transfromRLCOptions.ts +65 -24
  100. package/src/utils/clientUtils.ts +49 -16
  101. package/src/utils/crossLanguageDef.ts +8 -0
  102. package/src/utils/interfaces.ts +2 -1
  103. package/src/utils/modelUtils.ts +22 -18
  104. package/static/static-helpers/serialization/serialize-record.ts +3 -3
  105. package/static/static-helpers/serialization/xml-helpers.ts +91 -36
  106. package/static/static-helpers/urlTemplate.ts +5 -5
@@ -2,6 +2,7 @@
2
2
  // Licensed under the MIT License.
3
3
 
4
4
  import { XMLBuilder, XMLParser, XmlBuilderOptions } from "fast-xml-parser";
5
+ import { uint8ArrayToString, stringToUint8Array } from "@azure/core-util";
5
6
 
6
7
  /**
7
8
  * XML serialization options for a property or model
@@ -41,6 +42,10 @@ export interface XmlPropertyMetadata {
41
42
  type?: "array" | "object" | "primitive" | "date" | "bytes" | "dict";
42
43
  /** Date encoding format */
43
44
  dateEncoding?: "rfc3339" | "rfc7231" | "unixTimestamp";
45
+ /** Bytes encoding format (base64 or base64url) */
46
+ bytesEncoding?: "base64" | "base64url";
47
+ /** For arrays - type of each item for special handling */
48
+ itemType?: "primitive" | "date" | "bytes";
44
49
  }
45
50
 
46
51
  /**
@@ -57,6 +62,10 @@ export interface XmlPropertyDeserializeMetadata {
57
62
  type?: "array" | "object" | "primitive" | "date" | "bytes" | "dict";
58
63
  /** Date encoding format */
59
64
  dateEncoding?: "rfc3339" | "rfc7231" | "unixTimestamp";
65
+ /** Bytes encoding format (base64 or base64url) */
66
+ bytesEncoding?: "base64" | "base64url";
67
+ /** For arrays - type of each item for special handling */
68
+ itemType?: "primitive" | "date" | "bytes";
60
69
  }
61
70
 
62
71
  /**
@@ -97,7 +106,7 @@ const defaultBuilderOptions: Partial<XmlBuilderOptions> = {
97
106
  ignoreAttributes: false,
98
107
  attributeNamePrefix: "@_",
99
108
  textNodeName: "#text",
100
- format: true,
109
+ format: false,
101
110
  suppressEmptyNode: true
102
111
  };
103
112
 
@@ -165,7 +174,8 @@ function collectNamespaces(
165
174
  function serializePrimitiveValue(
166
175
  value: any,
167
176
  type?: "array" | "object" | "primitive" | "date" | "bytes" | "dict",
168
- dateEncoding?: "rfc3339" | "rfc7231" | "unixTimestamp"
177
+ dateEncoding?: "rfc3339" | "rfc7231" | "unixTimestamp",
178
+ bytesEncoding?: "base64" | "base64url"
169
179
  ): string | number | boolean {
170
180
  if (value === null || value === undefined) {
171
181
  return "";
@@ -184,8 +194,7 @@ function serializePrimitiveValue(
184
194
  }
185
195
 
186
196
  if (type === "bytes" && value instanceof Uint8Array) {
187
- // Convert bytes to base64
188
- return btoa(String.fromCharCode(...value));
197
+ return uint8ArrayToString(value, bytesEncoding ?? "base64");
189
198
  }
190
199
 
191
200
  if (typeof value === "boolean" || typeof value === "number") {
@@ -212,7 +221,12 @@ function serializeArrayProperty(
212
221
  if (serializer) {
213
222
  return serializer(item);
214
223
  }
215
- return serializePrimitiveValue(item, metadata.type, metadata.dateEncoding);
224
+ return serializePrimitiveValue(
225
+ item,
226
+ metadata.itemType ?? metadata.type,
227
+ metadata.dateEncoding,
228
+ metadata.bytesEncoding
229
+ );
216
230
  });
217
231
 
218
232
  if (xmlOptions.unwrapped) {
@@ -268,7 +282,8 @@ export function serializeModelToXml(
268
282
  attributes[attrName] = serializePrimitiveValue(
269
283
  value,
270
284
  type,
271
- prop.dateEncoding
285
+ prop.dateEncoding,
286
+ prop.bytesEncoding
272
287
  );
273
288
  } else if (type === "dict" && value !== null && typeof value === "object") {
274
289
  // Serialize dictionary - each key-value pair becomes an element
@@ -295,13 +310,19 @@ export function serializeModelToXml(
295
310
  result[elementName] = serializer(value);
296
311
  } else if (xmlOptions.unwrapped && !Array.isArray(value)) {
297
312
  // Unwrapped primitive - this becomes the text content of the parent element
298
- result["#text"] = serializePrimitiveValue(value, type, prop.dateEncoding);
313
+ result["#text"] = serializePrimitiveValue(
314
+ value,
315
+ type,
316
+ prop.dateEncoding,
317
+ prop.bytesEncoding
318
+ );
299
319
  } else {
300
320
  // Serialize primitive
301
321
  result[elementName] = serializePrimitiveValue(
302
322
  value,
303
323
  type,
304
- prop.dateEncoding
324
+ prop.dateEncoding,
325
+ prop.bytesEncoding
305
326
  );
306
327
  }
307
328
  }
@@ -328,7 +349,11 @@ export function xmlObjectToString(
328
349
  ...options
329
350
  });
330
351
 
331
- return builder.build(xmlObject);
352
+ const xmlData: string = builder.build(xmlObject);
353
+ if (!xmlData) {
354
+ return "";
355
+ }
356
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${xmlData}`;
332
357
  }
333
358
 
334
359
  /**
@@ -366,7 +391,8 @@ export function parseXmlString(
366
391
  function deserializePrimitiveValue(
367
392
  value: any,
368
393
  type?: "array" | "object" | "primitive" | "date" | "bytes" | "dict",
369
- dateEncoding?: "rfc3339" | "rfc7231" | "unixTimestamp"
394
+ dateEncoding?: "rfc3339" | "rfc7231" | "unixTimestamp",
395
+ bytesEncoding?: "base64" | "base64url"
370
396
  ): any {
371
397
  if (value === null || value === undefined || value === "") {
372
398
  return undefined;
@@ -380,13 +406,7 @@ function deserializePrimitiveValue(
380
406
  }
381
407
 
382
408
  if (type === "bytes" && typeof value === "string") {
383
- // Convert base64 to bytes
384
- const binaryString = atob(value);
385
- const bytes = new Uint8Array(binaryString.length);
386
- for (let i = 0; i < binaryString.length; i++) {
387
- bytes[i] = binaryString.charCodeAt(i);
388
- }
389
- return bytes;
409
+ return stringToUint8Array(value, bytesEncoding ?? "base64");
390
410
  }
391
411
 
392
412
  return value;
@@ -479,7 +499,12 @@ function deserializeArrayProperty(
479
499
  if (deserializer) {
480
500
  return deserializer(unwrappedItem);
481
501
  }
482
- return deserializePrimitiveValue(unwrappedItem, type, dateEncoding);
502
+ return deserializePrimitiveValue(
503
+ unwrappedItem,
504
+ metadata.itemType ?? type,
505
+ dateEncoding,
506
+ metadata.bytesEncoding
507
+ );
483
508
  });
484
509
  }
485
510
 
@@ -501,6 +526,41 @@ export function deserializeXmlToModel<T = Record<string, any>>(
501
526
  let content = xmlObject[rootElementName] ?? xmlObject[rootName] ?? xmlObject;
502
527
  content = unwrapSingleElementArray(content);
503
528
 
529
+ return deserializeXmlObject<T>(content, properties);
530
+ }
531
+
532
+ /**
533
+ * Full deserialization: XML string to model
534
+ */
535
+ export function deserializeFromXml<T = Record<string, any>>(
536
+ xmlString: string,
537
+ properties: XmlPropertyDeserializeMetadata[],
538
+ rootName: string,
539
+ rootNs?: { namespace: string; prefix: string },
540
+ parserOptions?: Partial<typeof defaultParserOptions>
541
+ ): T {
542
+ const xmlObject = parseXmlString(xmlString, parserOptions);
543
+ return deserializeXmlToModel<T>(xmlObject, properties, rootName, rootNs);
544
+ }
545
+
546
+ /**
547
+ * Deserializes a pre-parsed XML object to a model.
548
+ * This is used for nested objects where the XML has already been parsed
549
+ * and we have the object content directly (without a root element wrapper).
550
+ * Unlike deserializeFromXml, this does not parse XML strings and does not
551
+ * expect a root element to unwrap.
552
+ */
553
+ export function deserializeXmlObject<T = Record<string, any>>(
554
+ xmlObject: Record<string, unknown>,
555
+ properties: XmlPropertyDeserializeMetadata[]
556
+ ): T {
557
+ if (!xmlObject) {
558
+ return {} as T;
559
+ }
560
+
561
+ // Unwrap if parser wrapped in single-element array
562
+ const content = unwrapSingleElementArray(xmlObject);
563
+
504
564
  const result: Record<string, any> = {};
505
565
 
506
566
  for (const prop of properties) {
@@ -529,7 +589,8 @@ export function deserializeXmlToModel<T = Record<string, any>>(
529
589
  result[propertyName] = deserializePrimitiveValue(
530
590
  rawValue,
531
591
  type,
532
- dateEncoding
592
+ dateEncoding,
593
+ prop.bytesEncoding
533
594
  );
534
595
  }
535
596
  } else {
@@ -540,15 +601,23 @@ export function deserializeXmlToModel<T = Record<string, any>>(
540
601
  continue;
541
602
  }
542
603
 
543
- if (deserializer && typeof rawValue === "object") {
604
+ if (deserializer) {
544
605
  // Deserialize nested object
545
- result[propertyName] = deserializer(rawValue);
606
+ if (typeof rawValue === "object") {
607
+ result[propertyName] = deserializer(rawValue);
608
+ } else {
609
+ // When the XML element only contains text content (like <Name>text</Name>),
610
+ // the parser returns the text as a string. Wrap it in an object with #text
611
+ // so the nested deserializer can extract unwrapped text content properly.
612
+ result[propertyName] = deserializer({ "#text": rawValue });
613
+ }
546
614
  } else {
547
615
  // Deserialize primitive
548
616
  result[propertyName] = deserializePrimitiveValue(
549
617
  rawValue,
550
618
  type,
551
- dateEncoding
619
+ dateEncoding,
620
+ prop.bytesEncoding
552
621
  );
553
622
  }
554
623
  }
@@ -557,20 +626,6 @@ export function deserializeXmlToModel<T = Record<string, any>>(
557
626
  return result as T;
558
627
  }
559
628
 
560
- /**
561
- * Full deserialization: XML string to model
562
- */
563
- export function deserializeFromXml<T = Record<string, any>>(
564
- xmlString: string,
565
- properties: XmlPropertyDeserializeMetadata[],
566
- rootName: string,
567
- rootNs?: { namespace: string; prefix: string },
568
- parserOptions?: Partial<typeof defaultParserOptions>
569
- ): T {
570
- const xmlObject = parseXmlString(xmlString, parserOptions);
571
- return deserializeXmlToModel<T>(xmlObject, properties, rootName, rootNs);
572
- }
573
-
574
629
  /**
575
630
  * Utility to check if a content type is XML
576
631
  */
@@ -187,14 +187,14 @@ export function expandUrlTemplate(
187
187
  expr = expr.slice(1);
188
188
  }
189
189
  const varList = expr.split(/,/g);
190
- const result = [];
190
+ const innerResult = [];
191
191
  for (const varSpec of varList) {
192
192
  const varMatch = /([^:*]*)(?::(\d+)|(\*))?/.exec(varSpec);
193
193
  if (!varMatch || !varMatch[1]) {
194
194
  continue;
195
195
  }
196
196
  const varValue = getVarValue({
197
- isFirst: result.length === 0,
197
+ isFirst: innerResult.length === 0,
198
198
  op,
199
199
  varValue: context[varMatch[1]],
200
200
  varName: varMatch[1],
@@ -202,10 +202,10 @@ export function expandUrlTemplate(
202
202
  reserved: option?.allowReserved
203
203
  });
204
204
  if (varValue) {
205
- result.push(varValue);
205
+ innerResult.push(varValue);
206
206
  }
207
207
  }
208
- return result.join("");
208
+ return innerResult.join("");
209
209
  });
210
210
 
211
211
  return normalizeUnreserved(result);
@@ -219,7 +219,7 @@ function normalizeUnreserved(uri: string): string {
219
219
  return uri.replace(/%([0-9A-Fa-f]{2})/g, (match, hex) => {
220
220
  const char = String.fromCharCode(parseInt(hex, 16));
221
221
  // Decode only if it's unreserved
222
- if (/[\-.~]/.test(char)) {
222
+ if (/[.~-]/.test(char)) {
223
223
  return char;
224
224
  }
225
225
  return match; // leave other encodings intact