@azure/container-registry 1.1.1-alpha.20250619.1 → 1.1.1-alpha.20250722.2

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 (130) hide show
  1. package/dist/browser/containerRegistryChallengeHandler.js +6 -3
  2. package/dist/browser/containerRegistryChallengeHandler.js.map +1 -1
  3. package/dist/browser/containerRegistryClient.js +42 -50
  4. package/dist/browser/containerRegistryClient.js.map +1 -1
  5. package/dist/browser/containerRegistryTokenCredential.js +9 -1
  6. package/dist/browser/containerRegistryTokenCredential.js.map +1 -1
  7. package/dist/browser/containerRepository.js +41 -46
  8. package/dist/browser/containerRepository.js.map +1 -1
  9. package/dist/browser/content/containerRegistryContentClient.js +34 -32
  10. package/dist/browser/content/containerRegistryContentClient.js.map +1 -1
  11. package/dist/browser/generated/generatedClient.js +12 -3
  12. package/dist/browser/generated/generatedClient.js.map +1 -1
  13. package/dist/browser/generated/generatedClientContext.js +9 -2
  14. package/dist/browser/generated/generatedClientContext.js.map +1 -1
  15. package/dist/browser/generated/models/mappers.js +63 -29
  16. package/dist/browser/generated/models/mappers.js.map +1 -1
  17. package/dist/browser/generated/operations/authentication.js +1 -0
  18. package/dist/browser/generated/operations/authentication.js.map +1 -1
  19. package/dist/browser/generated/operations/containerRegistry.js +1 -0
  20. package/dist/browser/generated/operations/containerRegistry.js.map +1 -1
  21. package/dist/browser/generated/operations/containerRegistryBlob.js +1 -0
  22. package/dist/browser/generated/operations/containerRegistryBlob.js.map +1 -1
  23. package/dist/browser/registryArtifact.js +69 -53
  24. package/dist/browser/registryArtifact.js.map +1 -1
  25. package/dist/browser/transformations.js +13 -3
  26. package/dist/browser/transformations.js.map +1 -1
  27. package/dist/browser/utils/helpers.js +19 -35
  28. package/dist/browser/utils/helpers.js.map +1 -1
  29. package/dist/browser/utils/retriableReadableStream.js +64 -56
  30. package/dist/browser/utils/retriableReadableStream.js.map +1 -1
  31. package/dist/browser/utils/tokenCycler.js +7 -6
  32. package/dist/browser/utils/tokenCycler.js.map +1 -1
  33. package/dist/commonjs/containerRegistryChallengeHandler.js +6 -3
  34. package/dist/commonjs/containerRegistryChallengeHandler.js.map +1 -1
  35. package/dist/commonjs/containerRegistryClient.js +42 -50
  36. package/dist/commonjs/containerRegistryClient.js.map +1 -1
  37. package/dist/commonjs/containerRegistryTokenCredential.js +9 -1
  38. package/dist/commonjs/containerRegistryTokenCredential.js.map +1 -1
  39. package/dist/commonjs/containerRepository.js +41 -46
  40. package/dist/commonjs/containerRepository.js.map +1 -1
  41. package/dist/commonjs/content/containerRegistryContentClient.js +34 -31
  42. package/dist/commonjs/content/containerRegistryContentClient.js.map +1 -1
  43. package/dist/commonjs/generated/generatedClient.js +12 -3
  44. package/dist/commonjs/generated/generatedClient.js.map +1 -1
  45. package/dist/commonjs/generated/generatedClientContext.js +9 -2
  46. package/dist/commonjs/generated/generatedClientContext.js.map +1 -1
  47. package/dist/commonjs/generated/models/mappers.js +63 -29
  48. package/dist/commonjs/generated/models/mappers.js.map +1 -1
  49. package/dist/commonjs/generated/operations/authentication.js +1 -0
  50. package/dist/commonjs/generated/operations/authentication.js.map +1 -1
  51. package/dist/commonjs/generated/operations/containerRegistry.js +1 -0
  52. package/dist/commonjs/generated/operations/containerRegistry.js.map +1 -1
  53. package/dist/commonjs/generated/operations/containerRegistryBlob.js +1 -0
  54. package/dist/commonjs/generated/operations/containerRegistryBlob.js.map +1 -1
  55. package/dist/commonjs/registryArtifact.js +69 -53
  56. package/dist/commonjs/registryArtifact.js.map +1 -1
  57. package/dist/commonjs/transformations.js +13 -3
  58. package/dist/commonjs/transformations.js.map +1 -1
  59. package/dist/commonjs/tsdoc-metadata.json +11 -11
  60. package/dist/commonjs/utils/helpers.js +19 -35
  61. package/dist/commonjs/utils/helpers.js.map +1 -1
  62. package/dist/commonjs/utils/retriableReadableStream.js +64 -56
  63. package/dist/commonjs/utils/retriableReadableStream.js.map +1 -1
  64. package/dist/commonjs/utils/tokenCycler.js +7 -6
  65. package/dist/commonjs/utils/tokenCycler.js.map +1 -1
  66. package/dist/esm/containerRegistryChallengeHandler.js +6 -3
  67. package/dist/esm/containerRegistryChallengeHandler.js.map +1 -1
  68. package/dist/esm/containerRegistryClient.js +42 -50
  69. package/dist/esm/containerRegistryClient.js.map +1 -1
  70. package/dist/esm/containerRegistryTokenCredential.js +9 -1
  71. package/dist/esm/containerRegistryTokenCredential.js.map +1 -1
  72. package/dist/esm/containerRepository.js +41 -46
  73. package/dist/esm/containerRepository.js.map +1 -1
  74. package/dist/esm/content/containerRegistryContentClient.js +34 -32
  75. package/dist/esm/content/containerRegistryContentClient.js.map +1 -1
  76. package/dist/esm/generated/generatedClient.js +12 -3
  77. package/dist/esm/generated/generatedClient.js.map +1 -1
  78. package/dist/esm/generated/generatedClientContext.js +9 -2
  79. package/dist/esm/generated/generatedClientContext.js.map +1 -1
  80. package/dist/esm/generated/models/mappers.js +63 -29
  81. package/dist/esm/generated/models/mappers.js.map +1 -1
  82. package/dist/esm/generated/operations/authentication.js +1 -0
  83. package/dist/esm/generated/operations/authentication.js.map +1 -1
  84. package/dist/esm/generated/operations/containerRegistry.js +1 -0
  85. package/dist/esm/generated/operations/containerRegistry.js.map +1 -1
  86. package/dist/esm/generated/operations/containerRegistryBlob.js +1 -0
  87. package/dist/esm/generated/operations/containerRegistryBlob.js.map +1 -1
  88. package/dist/esm/registryArtifact.js +69 -53
  89. package/dist/esm/registryArtifact.js.map +1 -1
  90. package/dist/esm/transformations.js +13 -3
  91. package/dist/esm/transformations.js.map +1 -1
  92. package/dist/esm/utils/helpers.js +19 -35
  93. package/dist/esm/utils/helpers.js.map +1 -1
  94. package/dist/esm/utils/retriableReadableStream.js +64 -56
  95. package/dist/esm/utils/retriableReadableStream.js.map +1 -1
  96. package/dist/esm/utils/tokenCycler.js +7 -6
  97. package/dist/esm/utils/tokenCycler.js.map +1 -1
  98. package/dist/react-native/containerRegistryChallengeHandler.js +6 -3
  99. package/dist/react-native/containerRegistryChallengeHandler.js.map +1 -1
  100. package/dist/react-native/containerRegistryClient.js +42 -50
  101. package/dist/react-native/containerRegistryClient.js.map +1 -1
  102. package/dist/react-native/containerRegistryTokenCredential.js +9 -1
  103. package/dist/react-native/containerRegistryTokenCredential.js.map +1 -1
  104. package/dist/react-native/containerRepository.js +41 -46
  105. package/dist/react-native/containerRepository.js.map +1 -1
  106. package/dist/react-native/content/containerRegistryContentClient.js +34 -32
  107. package/dist/react-native/content/containerRegistryContentClient.js.map +1 -1
  108. package/dist/react-native/generated/generatedClient.js +12 -3
  109. package/dist/react-native/generated/generatedClient.js.map +1 -1
  110. package/dist/react-native/generated/generatedClientContext.js +9 -2
  111. package/dist/react-native/generated/generatedClientContext.js.map +1 -1
  112. package/dist/react-native/generated/models/mappers.js +63 -29
  113. package/dist/react-native/generated/models/mappers.js.map +1 -1
  114. package/dist/react-native/generated/operations/authentication.js +1 -0
  115. package/dist/react-native/generated/operations/authentication.js.map +1 -1
  116. package/dist/react-native/generated/operations/containerRegistry.js +1 -0
  117. package/dist/react-native/generated/operations/containerRegistry.js.map +1 -1
  118. package/dist/react-native/generated/operations/containerRegistryBlob.js +1 -0
  119. package/dist/react-native/generated/operations/containerRegistryBlob.js.map +1 -1
  120. package/dist/react-native/registryArtifact.js +69 -53
  121. package/dist/react-native/registryArtifact.js.map +1 -1
  122. package/dist/react-native/transformations.js +13 -3
  123. package/dist/react-native/transformations.js.map +1 -1
  124. package/dist/react-native/utils/helpers.js +19 -35
  125. package/dist/react-native/utils/helpers.js.map +1 -1
  126. package/dist/react-native/utils/retriableReadableStream.js +64 -56
  127. package/dist/react-native/utils/retriableReadableStream.js.map +1 -1
  128. package/dist/react-native/utils/tokenCycler.js +7 -6
  129. package/dist/react-native/utils/tokenCycler.js.map +1 -1
  130. package/package.json +2 -2
@@ -8,6 +8,17 @@ import { Readable } from "node:stream";
8
8
  * A Node.js ReadableStream will internally retry when internal ReadableStream unexpected ends.
9
9
  */
10
10
  export class RetriableReadableStream extends Readable {
11
+ source;
12
+ getter;
13
+ offset;
14
+ start;
15
+ end;
16
+ retries = 0;
17
+ maxRetryRequests;
18
+ onData;
19
+ onEnd;
20
+ onProgress;
21
+ options;
11
22
  /**
12
23
  * Creates an instance of RetriableReadableStream.
13
24
  *
@@ -23,62 +34,6 @@ export class RetriableReadableStream extends Readable {
23
34
  this.source = source;
24
35
  this.getter = getter;
25
36
  this.offset = offset;
26
- this.retries = 0;
27
- this.sourceDataHandler = (data) => {
28
- var _a, _b;
29
- if (this.options.doInjectErrorOnce) {
30
- this.options.doInjectErrorOnce = undefined;
31
- this.source.pause();
32
- this.sourceErrorOrEndHandler();
33
- this.source.destroy();
34
- return;
35
- }
36
- this.offset += data.length;
37
- if (this.offset > this.end + 1) {
38
- this.destroy(new Error(`Data corruption failure: Received more data than original request, data needed offset is ${this.end}, received offset: ${this.offset - 1}`));
39
- }
40
- (_a = this.onData) === null || _a === void 0 ? void 0 : _a.call(this, data);
41
- (_b = this.onProgress) === null || _b === void 0 ? void 0 : _b.call(this, { loadedBytes: this.offset - this.start });
42
- if (!this.push(data)) {
43
- this.source.pause();
44
- }
45
- };
46
- this.sourceAbortedHandler = () => {
47
- const abortError = new AbortError("The operation was aborted.");
48
- this.destroy(abortError);
49
- };
50
- this.sourceErrorOrEndHandler = (err) => {
51
- var _a;
52
- if (err && err.name === "AbortError") {
53
- this.destroy(err);
54
- return;
55
- }
56
- this.removeSourceEventHandlers();
57
- if (this.offset - 1 === this.end) {
58
- (_a = this.onEnd) === null || _a === void 0 ? void 0 : _a.call(this);
59
- this.push(null);
60
- }
61
- else if (this.offset <= this.end) {
62
- if (this.retries < this.maxRetryRequests) {
63
- this.retries += 1;
64
- this.getter(this.offset)
65
- .then((newSource) => {
66
- this.source = newSource;
67
- this.setSourceEventHandlers();
68
- return;
69
- })
70
- .catch((error) => {
71
- this.destroy(error);
72
- });
73
- }
74
- else {
75
- this.destroy(new Error(`Data corruption failure: received less data than required and reached maxRetires limitation. Received data offset: ${this.offset - 1}, data needed offset: ${this.end}, retries: ${this.retries}, max retries: ${this.maxRetryRequests}`));
76
- }
77
- }
78
- else {
79
- this.destroy(new Error(`Data corruption failure: Received more data than original request, data needed offset is ${this.end}, received offset: ${this.offset - 1}`));
80
- }
81
- };
82
37
  this.getter = getter;
83
38
  this.start = offset;
84
39
  this.end = offset + count - 1;
@@ -106,6 +61,59 @@ export class RetriableReadableStream extends Readable {
106
61
  this.source.removeListener("error", this.sourceErrorOrEndHandler);
107
62
  this.source.removeListener("aborted", this.sourceAbortedHandler);
108
63
  }
64
+ sourceDataHandler = (data) => {
65
+ if (this.options.doInjectErrorOnce) {
66
+ this.options.doInjectErrorOnce = undefined;
67
+ this.source.pause();
68
+ this.sourceErrorOrEndHandler();
69
+ this.source.destroy();
70
+ return;
71
+ }
72
+ this.offset += data.length;
73
+ if (this.offset > this.end + 1) {
74
+ this.destroy(new Error(`Data corruption failure: Received more data than original request, data needed offset is ${this.end}, received offset: ${this.offset - 1}`));
75
+ }
76
+ this.onData?.(data);
77
+ this.onProgress?.({ loadedBytes: this.offset - this.start });
78
+ if (!this.push(data)) {
79
+ this.source.pause();
80
+ }
81
+ };
82
+ sourceAbortedHandler = () => {
83
+ const abortError = new AbortError("The operation was aborted.");
84
+ this.destroy(abortError);
85
+ };
86
+ sourceErrorOrEndHandler = (err) => {
87
+ if (err && err.name === "AbortError") {
88
+ this.destroy(err);
89
+ return;
90
+ }
91
+ this.removeSourceEventHandlers();
92
+ if (this.offset - 1 === this.end) {
93
+ this.onEnd?.();
94
+ this.push(null);
95
+ }
96
+ else if (this.offset <= this.end) {
97
+ if (this.retries < this.maxRetryRequests) {
98
+ this.retries += 1;
99
+ this.getter(this.offset)
100
+ .then((newSource) => {
101
+ this.source = newSource;
102
+ this.setSourceEventHandlers();
103
+ return;
104
+ })
105
+ .catch((error) => {
106
+ this.destroy(error);
107
+ });
108
+ }
109
+ else {
110
+ this.destroy(new Error(`Data corruption failure: received less data than required and reached maxRetires limitation. Received data offset: ${this.offset - 1}, data needed offset: ${this.end}, retries: ${this.retries}, max retries: ${this.maxRetryRequests}`));
111
+ }
112
+ }
113
+ else {
114
+ this.destroy(new Error(`Data corruption failure: Received more data than original request, data needed offset is ${this.end}, received offset: ${this.offset - 1}`));
115
+ }
116
+ };
109
117
  _destroy(error, callback) {
110
118
  // remove listener from source and release source
111
119
  this.removeSourceEventHandlers();
@@ -1 +1 @@
1
- {"version":3,"file":"retriableReadableStream.js","sourceRoot":"","sources":["../../../src/utils/retriableReadableStream.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { AbortError } from \"@azure/abort-controller\";\nimport type { TransferProgressEvent } from \"@azure/core-rest-pipeline\";\nimport { Readable } from \"node:stream\";\n\nexport type ReadableStreamGetter = (offset: number) => Promise<NodeJS.ReadableStream>;\n\nexport interface RetriableReadableStreamOptions {\n /**\n * Max retry count (greater than or equal to 0), undefined or invalid value means no retry\n */\n maxRetryRequests?: number;\n\n /**\n * Read progress event handler\n */\n onProgress?: (progress: TransferProgressEvent) => void;\n\n /**\n * On data event handler\n */\n onData?: (data: Buffer) => void;\n\n /**\n * On end (success) event handler\n */\n onEnd?: () => void;\n\n /**\n * Debug purpose only. Used to inject an unexpected end to existing internal stream,\n * to test stream retry works well or not.\n *\n * When assign it to true, for next incoming \"data\" event of internal stream,\n * RetriableReadableStream will try to emit an \"end\" event to existing internal\n * stream to force it end and start retry from the breaking point.\n * The value will then update to \"undefined\", once the injection works.\n */\n doInjectErrorOnce?: boolean;\n\n /**\n * A threshold, not a limit. Dictates the amount of data that a stream buffers before it stops asking for more data.\n */\n highWaterMark?: number;\n}\n\n/**\n * ONLY AVAILABLE IN NODE.JS RUNTIME.\n *\n * A Node.js ReadableStream will internally retry when internal ReadableStream unexpected ends.\n */\nexport class RetriableReadableStream extends Readable {\n private start: number;\n private end: number;\n private retries: number = 0;\n private maxRetryRequests: number;\n private onData?: (data: Buffer) => void;\n private onEnd?: () => void;\n private onProgress?: (progress: TransferProgressEvent) => void;\n private options: RetriableReadableStreamOptions;\n\n /**\n * Creates an instance of RetriableReadableStream.\n *\n * @param source - The current ReadableStream returned from getter\n * @param getter - A method calling downloading request returning\n * a new ReadableStream from specified offset\n * @param offset - Offset position in original data source to read\n * @param count - How much data in original data source to read\n * @param options -\n */\n public constructor(\n private source: NodeJS.ReadableStream,\n private getter: ReadableStreamGetter,\n private offset: number,\n count: number,\n options: RetriableReadableStreamOptions = {},\n ) {\n super({ highWaterMark: options.highWaterMark });\n this.getter = getter;\n this.start = offset;\n this.end = offset + count - 1;\n this.maxRetryRequests =\n options.maxRetryRequests && options.maxRetryRequests >= 0 ? options.maxRetryRequests : 0;\n this.onData = options.onData;\n this.onEnd = options.onEnd;\n this.onProgress = options.onProgress;\n this.options = options;\n\n this.setSourceEventHandlers();\n }\n\n public _read(): void {\n this.source.resume();\n }\n\n private setSourceEventHandlers(): void {\n this.source.on(\"data\", this.sourceDataHandler);\n this.source.on(\"end\", this.sourceErrorOrEndHandler);\n this.source.on(\"error\", this.sourceErrorOrEndHandler);\n // needed for Node14\n this.source.on(\"aborted\", this.sourceAbortedHandler);\n }\n\n private removeSourceEventHandlers(): void {\n this.source.removeListener(\"data\", this.sourceDataHandler);\n this.source.removeListener(\"end\", this.sourceErrorOrEndHandler);\n this.source.removeListener(\"error\", this.sourceErrorOrEndHandler);\n this.source.removeListener(\"aborted\", this.sourceAbortedHandler);\n }\n\n private sourceDataHandler = (data: Buffer): void => {\n if (this.options.doInjectErrorOnce) {\n this.options.doInjectErrorOnce = undefined;\n this.source.pause();\n this.sourceErrorOrEndHandler();\n (this.source as Readable).destroy();\n return;\n }\n\n this.offset += data.length;\n\n if (this.offset > this.end + 1) {\n this.destroy(\n new Error(\n `Data corruption failure: Received more data than original request, data needed offset is ${\n this.end\n }, received offset: ${this.offset - 1}`,\n ),\n );\n }\n\n this.onData?.(data);\n this.onProgress?.({ loadedBytes: this.offset - this.start });\n\n if (!this.push(data)) {\n this.source.pause();\n }\n };\n\n private sourceAbortedHandler = (): void => {\n const abortError = new AbortError(\"The operation was aborted.\");\n this.destroy(abortError);\n };\n\n private sourceErrorOrEndHandler = (err?: Error): void => {\n if (err && err.name === \"AbortError\") {\n this.destroy(err);\n return;\n }\n\n this.removeSourceEventHandlers();\n if (this.offset - 1 === this.end) {\n this.onEnd?.();\n this.push(null);\n } else if (this.offset <= this.end) {\n if (this.retries < this.maxRetryRequests) {\n this.retries += 1;\n this.getter(this.offset)\n .then((newSource) => {\n this.source = newSource;\n this.setSourceEventHandlers();\n return;\n })\n .catch((error) => {\n this.destroy(error);\n });\n } else {\n this.destroy(\n new Error(\n `Data corruption failure: received less data than required and reached maxRetires limitation. Received data offset: ${\n this.offset - 1\n }, data needed offset: ${this.end}, retries: ${this.retries}, max retries: ${\n this.maxRetryRequests\n }`,\n ),\n );\n }\n } else {\n this.destroy(\n new Error(\n `Data corruption failure: Received more data than original request, data needed offset is ${\n this.end\n }, received offset: ${this.offset - 1}`,\n ),\n );\n }\n };\n\n _destroy(error: Error | null, callback: (error?: Error) => void): void {\n // remove listener from source and release source\n this.removeSourceEventHandlers();\n (this.source as Readable).destroy();\n\n callback(error === null ? undefined : error);\n }\n}\n"]}
1
+ {"version":3,"file":"retriableReadableStream.js","sourceRoot":"","sources":["../../../src/utils/retriableReadableStream.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { AbortError } from \"@azure/abort-controller\";\nimport type { TransferProgressEvent } from \"@azure/core-rest-pipeline\";\nimport { Readable } from \"node:stream\";\n\nexport type ReadableStreamGetter = (offset: number) => Promise<NodeJS.ReadableStream>;\n\nexport interface RetriableReadableStreamOptions {\n /**\n * Max retry count (greater than or equal to 0), undefined or invalid value means no retry\n */\n maxRetryRequests?: number;\n\n /**\n * Read progress event handler\n */\n onProgress?: (progress: TransferProgressEvent) => void;\n\n /**\n * On data event handler\n */\n onData?: (data: Buffer) => void;\n\n /**\n * On end (success) event handler\n */\n onEnd?: () => void;\n\n /**\n * Debug purpose only. Used to inject an unexpected end to existing internal stream,\n * to test stream retry works well or not.\n *\n * When assign it to true, for next incoming \"data\" event of internal stream,\n * RetriableReadableStream will try to emit an \"end\" event to existing internal\n * stream to force it end and start retry from the breaking point.\n * The value will then update to \"undefined\", once the injection works.\n */\n doInjectErrorOnce?: boolean;\n\n /**\n * A threshold, not a limit. Dictates the amount of data that a stream buffers before it stops asking for more data.\n */\n highWaterMark?: number;\n}\n\n/**\n * ONLY AVAILABLE IN NODE.JS RUNTIME.\n *\n * A Node.js ReadableStream will internally retry when internal ReadableStream unexpected ends.\n */\nexport class RetriableReadableStream extends Readable {\n private start: number;\n private end: number;\n private retries: number = 0;\n private maxRetryRequests: number;\n private onData?: (data: Buffer) => void;\n private onEnd?: () => void;\n private onProgress?: (progress: TransferProgressEvent) => void;\n private options: RetriableReadableStreamOptions;\n\n /**\n * Creates an instance of RetriableReadableStream.\n *\n * @param source - The current ReadableStream returned from getter\n * @param getter - A method calling downloading request returning\n * a new ReadableStream from specified offset\n * @param offset - Offset position in original data source to read\n * @param count - How much data in original data source to read\n * @param options -\n */\n public constructor(\n private source: NodeJS.ReadableStream,\n private getter: ReadableStreamGetter,\n private offset: number,\n count: number,\n options: RetriableReadableStreamOptions = {},\n ) {\n super({ highWaterMark: options.highWaterMark });\n this.getter = getter;\n this.start = offset;\n this.end = offset + count - 1;\n this.maxRetryRequests =\n options.maxRetryRequests && options.maxRetryRequests >= 0 ? options.maxRetryRequests : 0;\n this.onData = options.onData;\n this.onEnd = options.onEnd;\n this.onProgress = options.onProgress;\n this.options = options;\n\n this.setSourceEventHandlers();\n }\n\n public _read(): void {\n this.source.resume();\n }\n\n private setSourceEventHandlers(): void {\n this.source.on(\"data\", this.sourceDataHandler);\n this.source.on(\"end\", this.sourceErrorOrEndHandler);\n this.source.on(\"error\", this.sourceErrorOrEndHandler);\n // needed for Node14\n this.source.on(\"aborted\", this.sourceAbortedHandler);\n }\n\n private removeSourceEventHandlers(): void {\n this.source.removeListener(\"data\", this.sourceDataHandler);\n this.source.removeListener(\"end\", this.sourceErrorOrEndHandler);\n this.source.removeListener(\"error\", this.sourceErrorOrEndHandler);\n this.source.removeListener(\"aborted\", this.sourceAbortedHandler);\n }\n\n private sourceDataHandler = (data: Buffer): void => {\n if (this.options.doInjectErrorOnce) {\n this.options.doInjectErrorOnce = undefined;\n this.source.pause();\n this.sourceErrorOrEndHandler();\n (this.source as Readable).destroy();\n return;\n }\n\n this.offset += data.length;\n\n if (this.offset > this.end + 1) {\n this.destroy(\n new Error(\n `Data corruption failure: Received more data than original request, data needed offset is ${\n this.end\n }, received offset: ${this.offset - 1}`,\n ),\n );\n }\n\n this.onData?.(data);\n this.onProgress?.({ loadedBytes: this.offset - this.start });\n\n if (!this.push(data)) {\n this.source.pause();\n }\n };\n\n private sourceAbortedHandler = (): void => {\n const abortError = new AbortError(\"The operation was aborted.\");\n this.destroy(abortError);\n };\n\n private sourceErrorOrEndHandler = (err?: Error): void => {\n if (err && err.name === \"AbortError\") {\n this.destroy(err);\n return;\n }\n\n this.removeSourceEventHandlers();\n if (this.offset - 1 === this.end) {\n this.onEnd?.();\n this.push(null);\n } else if (this.offset <= this.end) {\n if (this.retries < this.maxRetryRequests) {\n this.retries += 1;\n this.getter(this.offset)\n .then((newSource) => {\n this.source = newSource;\n this.setSourceEventHandlers();\n return;\n })\n .catch((error) => {\n this.destroy(error);\n });\n } else {\n this.destroy(\n new Error(\n `Data corruption failure: received less data than required and reached maxRetires limitation. Received data offset: ${\n this.offset - 1\n }, data needed offset: ${this.end}, retries: ${this.retries}, max retries: ${\n this.maxRetryRequests\n }`,\n ),\n );\n }\n } else {\n this.destroy(\n new Error(\n `Data corruption failure: Received more data than original request, data needed offset is ${\n this.end\n }, received offset: ${this.offset - 1}`,\n ),\n );\n }\n };\n\n _destroy(error: Error | null, callback: (error?: Error) => void): void {\n // remove listener from source and release source\n this.removeSourceEventHandlers();\n (this.source as Readable).destroy();\n\n callback(error === null ? undefined : error);\n }\n}\n"]}
@@ -27,7 +27,7 @@ async function beginRefresh(getAccessToken, retryIntervalInMs, refreshTimeout) {
27
27
  try {
28
28
  return await getAccessToken();
29
29
  }
30
- catch (_a) {
30
+ catch {
31
31
  return null;
32
32
  }
33
33
  }
@@ -64,7 +64,10 @@ async function beginRefresh(getAccessToken, retryIntervalInMs, refreshTimeout) {
64
64
  export function createTokenCycler(credential, tokenCyclerOptions) {
65
65
  let refreshWorker = null;
66
66
  let token = null;
67
- const options = Object.assign(Object.assign({}, DEFAULT_CYCLER_OPTIONS), tokenCyclerOptions);
67
+ const options = {
68
+ ...DEFAULT_CYCLER_OPTIONS,
69
+ ...tokenCyclerOptions,
70
+ };
68
71
  /**
69
72
  * This little holder defines several predicates that we use to construct
70
73
  * the rules of refreshing the token.
@@ -81,9 +84,8 @@ export function createTokenCycler(credential, tokenCyclerOptions) {
81
84
  * window and not already refreshing)
82
85
  */
83
86
  get shouldRefresh() {
84
- var _a;
85
87
  return (!cycler.isRefreshing &&
86
- ((_a = token === null || token === void 0 ? void 0 : token.expiresOnTimestamp) !== null && _a !== void 0 ? _a : 0) - options.refreshWindowInMs < Date.now());
88
+ (token?.expiresOnTimestamp ?? 0) - options.refreshWindowInMs < Date.now());
87
89
  },
88
90
  /**
89
91
  * Produces true if the cycler MUST refresh (null or nearly-expired
@@ -98,7 +100,6 @@ export function createTokenCycler(credential, tokenCyclerOptions) {
98
100
  * running.
99
101
  */
100
102
  function refresh(scopes, getTokenOptions) {
101
- var _a;
102
103
  if (!cycler.isRefreshing) {
103
104
  // We bind `scopes` here to avoid passing it around a lot
104
105
  const tryGetAccessToken = () => credential.getToken(scopes, getTokenOptions);
@@ -106,7 +107,7 @@ export function createTokenCycler(credential, tokenCyclerOptions) {
106
107
  // before the refresh can be considered done.
107
108
  refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs,
108
109
  // If we don't have a token, then we should timeout immediately
109
- (_a = token === null || token === void 0 ? void 0 : token.expiresOnTimestamp) !== null && _a !== void 0 ? _a : Date.now())
110
+ token?.expiresOnTimestamp ?? Date.now())
110
111
  .then((_token) => {
111
112
  refreshWorker = null;
112
113
  token = _token;
@@ -1 +1 @@
1
- {"version":3,"file":"tokenCycler.js","sourceRoot":"","sources":["../../../src/utils/tokenCycler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nfunction delay<T>(t: number, value?: T): Promise<T | void> {\n return new Promise((resolve) => setTimeout(() => resolve(value), t));\n}\n/**\n * A function that gets a promise of an access token and allows providing\n * options.\n *\n * @param options - the options to pass to the underlying token provider\n */\nexport type AccessTokenGetter<T extends GetTokenOptions> = (\n scopes: string | string[],\n options: T,\n) => Promise<AccessToken>;\n\n/**\n * The response of the\n */\nexport interface AccessTokenRefresher<T extends GetTokenOptions> {\n cachedToken?: AccessToken;\n getToken: AccessTokenGetter<T>;\n}\n\nexport interface TokenCyclerOptions {\n /**\n * The window of time before token expiration during which the token will be\n * considered unusable due to risk of the token expiring before sending the\n * request.\n *\n * This will only become meaningful if the refresh fails for over\n * (refreshWindow - forcedRefreshWindow) milliseconds.\n */\n forcedRefreshWindowInMs: number;\n /**\n * Interval in milliseconds to retry failed token refreshes.\n */\n retryIntervalInMs: number;\n /**\n * The window of time before token expiration during which\n * we will attempt to refresh the token.\n */\n refreshWindowInMs: number;\n}\n\n// Default options for the cycler if none are provided\nexport const DEFAULT_CYCLER_OPTIONS: TokenCyclerOptions = {\n forcedRefreshWindowInMs: 1000, // Force waiting for a refresh 1s before the token expires\n retryIntervalInMs: 3000, // Allow refresh attempts every 3s\n refreshWindowInMs: 1000 * 60 * 2, // Start refreshing 2m before expiry\n};\n\n/**\n * Converts an an unreliable access token getter (which may resolve with null)\n * into an AccessTokenGetter by retrying the unreliable getter in a regular\n * interval.\n *\n * @param getAccessToken - A function that produces a promise of an access token that may fail by returning null.\n * @param retryIntervalInMs - The time (in milliseconds) to wait between retry attempts.\n * @param refreshTimeout - The timestamp after which the refresh attempt will fail, throwing an exception.\n * @returns - A promise that, if it resolves, will resolve with an access token.\n */\nasync function beginRefresh(\n getAccessToken: () => Promise<AccessToken | null>,\n retryIntervalInMs: number,\n refreshTimeout: number,\n): Promise<AccessToken> {\n // This wrapper handles exceptions gracefully as long as we haven't exceeded\n // the timeout.\n async function tryGetAccessToken(): Promise<AccessToken | null> {\n if (Date.now() < refreshTimeout) {\n try {\n return await getAccessToken();\n } catch {\n return null;\n }\n } else {\n const finalToken = await getAccessToken();\n\n // Timeout is up, so throw if it's still null\n if (finalToken === null) {\n throw new Error(\"Failed to refresh access token.\");\n }\n\n return finalToken;\n }\n }\n\n let token: AccessToken | null = await tryGetAccessToken();\n\n while (token === null) {\n await delay(retryIntervalInMs);\n\n token = await tryGetAccessToken();\n }\n\n return token;\n}\n\n/**\n * Creates a token cycler from a credential, scopes, and optional settings.\n *\n * A token cycler represents a way to reliably retrieve a valid access token\n * from a TokenCredential. It will handle initializing the token, refreshing it\n * when it nears expiration, and synchronizes refresh attempts to avoid\n * concurrency hazards.\n *\n * @param credential - the underlying TokenCredential that provides the access\n * token\n * @param tokenCyclerOptions - optionally override default settings for the cycler\n *\n * @returns - a function that reliably produces a valid access token\n */\nexport function createTokenCycler<T extends GetTokenOptions>(\n credential: TokenCredential,\n tokenCyclerOptions?: Partial<TokenCyclerOptions>,\n): AccessTokenRefresher<T> {\n let refreshWorker: Promise<AccessToken> | null = null;\n let token: AccessToken | null = null;\n\n const options = {\n ...DEFAULT_CYCLER_OPTIONS,\n ...tokenCyclerOptions,\n };\n\n /**\n * This little holder defines several predicates that we use to construct\n * the rules of refreshing the token.\n */\n const cycler = {\n /**\n * Produces true if a refresh job is currently in progress.\n */\n get isRefreshing(): boolean {\n return refreshWorker !== null;\n },\n /**\n * Produces true if the cycler SHOULD refresh (we are within the refresh\n * window and not already refreshing)\n */\n get shouldRefresh(): boolean {\n return (\n !cycler.isRefreshing &&\n (token?.expiresOnTimestamp ?? 0) - options.refreshWindowInMs < Date.now()\n );\n },\n /**\n * Produces true if the cycler MUST refresh (null or nearly-expired\n * token).\n */\n get mustRefresh(): boolean {\n return (\n token === null || token.expiresOnTimestamp - options.forcedRefreshWindowInMs < Date.now()\n );\n },\n };\n\n /**\n * Starts a refresh job or returns the existing job if one is already\n * running.\n */\n function refresh(scopes: string | string[], getTokenOptions: T): Promise<AccessToken> {\n if (!cycler.isRefreshing) {\n // We bind `scopes` here to avoid passing it around a lot\n const tryGetAccessToken = (): Promise<AccessToken | null> =>\n credential.getToken(scopes, getTokenOptions);\n\n // Take advantage of promise chaining to insert an assignment to `token`\n // before the refresh can be considered done.\n refreshWorker = beginRefresh(\n tryGetAccessToken,\n options.retryIntervalInMs,\n // If we don't have a token, then we should timeout immediately\n token?.expiresOnTimestamp ?? Date.now(),\n )\n .then((_token) => {\n refreshWorker = null;\n token = _token;\n return token;\n })\n .catch((reason) => {\n // We also should reset the refresher if we enter a failed state. All\n // existing awaiters will throw, but subsequent requests will start a\n // new retry chain.\n refreshWorker = null;\n token = null;\n throw reason;\n });\n }\n\n return refreshWorker as Promise<AccessToken>;\n }\n\n return {\n get cachedToken(): AccessToken | undefined {\n return token || undefined;\n },\n getToken: async (scopes: string | string[], tokenOptions: T): Promise<AccessToken> => {\n //\n // Simple rules:\n // - If we MUST refresh, then return the refresh task, blocking\n // the pipeline until a token is available.\n // - If we SHOULD refresh, then run refresh but don't return it\n // (we can still use the cached token).\n // - Return the token, since it's fine if we didn't return in\n // step 1.\n //\n if (cycler.mustRefresh) return refresh(scopes, tokenOptions);\n\n if (cycler.shouldRefresh) {\n refresh(scopes, tokenOptions);\n }\n\n return token as AccessToken;\n },\n };\n}\n"]}
1
+ {"version":3,"file":"tokenCycler.js","sourceRoot":"","sources":["../../../src/utils/tokenCycler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nfunction delay<T>(t: number, value?: T): Promise<T | void> {\n return new Promise((resolve) => setTimeout(() => resolve(value), t));\n}\n/**\n * A function that gets a promise of an access token and allows providing\n * options.\n *\n * @param options - the options to pass to the underlying token provider\n */\nexport type AccessTokenGetter<T extends GetTokenOptions> = (\n scopes: string | string[],\n options: T,\n) => Promise<AccessToken>;\n\n/**\n * The response of the\n */\nexport interface AccessTokenRefresher<T extends GetTokenOptions> {\n cachedToken?: AccessToken;\n getToken: AccessTokenGetter<T>;\n}\n\nexport interface TokenCyclerOptions {\n /**\n * The window of time before token expiration during which the token will be\n * considered unusable due to risk of the token expiring before sending the\n * request.\n *\n * This will only become meaningful if the refresh fails for over\n * (refreshWindow - forcedRefreshWindow) milliseconds.\n */\n forcedRefreshWindowInMs: number;\n /**\n * Interval in milliseconds to retry failed token refreshes.\n */\n retryIntervalInMs: number;\n /**\n * The window of time before token expiration during which\n * we will attempt to refresh the token.\n */\n refreshWindowInMs: number;\n}\n\n// Default options for the cycler if none are provided\nexport const DEFAULT_CYCLER_OPTIONS: TokenCyclerOptions = {\n forcedRefreshWindowInMs: 1000, // Force waiting for a refresh 1s before the token expires\n retryIntervalInMs: 3000, // Allow refresh attempts every 3s\n refreshWindowInMs: 1000 * 60 * 2, // Start refreshing 2m before expiry\n};\n\n/**\n * Converts an an unreliable access token getter (which may resolve with null)\n * into an AccessTokenGetter by retrying the unreliable getter in a regular\n * interval.\n *\n * @param getAccessToken - A function that produces a promise of an access token that may fail by returning null.\n * @param retryIntervalInMs - The time (in milliseconds) to wait between retry attempts.\n * @param refreshTimeout - The timestamp after which the refresh attempt will fail, throwing an exception.\n * @returns - A promise that, if it resolves, will resolve with an access token.\n */\nasync function beginRefresh(\n getAccessToken: () => Promise<AccessToken | null>,\n retryIntervalInMs: number,\n refreshTimeout: number,\n): Promise<AccessToken> {\n // This wrapper handles exceptions gracefully as long as we haven't exceeded\n // the timeout.\n async function tryGetAccessToken(): Promise<AccessToken | null> {\n if (Date.now() < refreshTimeout) {\n try {\n return await getAccessToken();\n } catch {\n return null;\n }\n } else {\n const finalToken = await getAccessToken();\n\n // Timeout is up, so throw if it's still null\n if (finalToken === null) {\n throw new Error(\"Failed to refresh access token.\");\n }\n\n return finalToken;\n }\n }\n\n let token: AccessToken | null = await tryGetAccessToken();\n\n while (token === null) {\n await delay(retryIntervalInMs);\n\n token = await tryGetAccessToken();\n }\n\n return token;\n}\n\n/**\n * Creates a token cycler from a credential, scopes, and optional settings.\n *\n * A token cycler represents a way to reliably retrieve a valid access token\n * from a TokenCredential. It will handle initializing the token, refreshing it\n * when it nears expiration, and synchronizes refresh attempts to avoid\n * concurrency hazards.\n *\n * @param credential - the underlying TokenCredential that provides the access\n * token\n * @param tokenCyclerOptions - optionally override default settings for the cycler\n *\n * @returns - a function that reliably produces a valid access token\n */\nexport function createTokenCycler<T extends GetTokenOptions>(\n credential: TokenCredential,\n tokenCyclerOptions?: Partial<TokenCyclerOptions>,\n): AccessTokenRefresher<T> {\n let refreshWorker: Promise<AccessToken> | null = null;\n let token: AccessToken | null = null;\n\n const options = {\n ...DEFAULT_CYCLER_OPTIONS,\n ...tokenCyclerOptions,\n };\n\n /**\n * This little holder defines several predicates that we use to construct\n * the rules of refreshing the token.\n */\n const cycler = {\n /**\n * Produces true if a refresh job is currently in progress.\n */\n get isRefreshing(): boolean {\n return refreshWorker !== null;\n },\n /**\n * Produces true if the cycler SHOULD refresh (we are within the refresh\n * window and not already refreshing)\n */\n get shouldRefresh(): boolean {\n return (\n !cycler.isRefreshing &&\n (token?.expiresOnTimestamp ?? 0) - options.refreshWindowInMs < Date.now()\n );\n },\n /**\n * Produces true if the cycler MUST refresh (null or nearly-expired\n * token).\n */\n get mustRefresh(): boolean {\n return (\n token === null || token.expiresOnTimestamp - options.forcedRefreshWindowInMs < Date.now()\n );\n },\n };\n\n /**\n * Starts a refresh job or returns the existing job if one is already\n * running.\n */\n function refresh(scopes: string | string[], getTokenOptions: T): Promise<AccessToken> {\n if (!cycler.isRefreshing) {\n // We bind `scopes` here to avoid passing it around a lot\n const tryGetAccessToken = (): Promise<AccessToken | null> =>\n credential.getToken(scopes, getTokenOptions);\n\n // Take advantage of promise chaining to insert an assignment to `token`\n // before the refresh can be considered done.\n refreshWorker = beginRefresh(\n tryGetAccessToken,\n options.retryIntervalInMs,\n // If we don't have a token, then we should timeout immediately\n token?.expiresOnTimestamp ?? Date.now(),\n )\n .then((_token) => {\n refreshWorker = null;\n token = _token;\n return token;\n })\n .catch((reason) => {\n // We also should reset the refresher if we enter a failed state. All\n // existing awaiters will throw, but subsequent requests will start a\n // new retry chain.\n refreshWorker = null;\n token = null;\n throw reason;\n });\n }\n\n return refreshWorker as Promise<AccessToken>;\n }\n\n return {\n get cachedToken(): AccessToken | undefined {\n return token || undefined;\n },\n getToken: async (scopes: string | string[], tokenOptions: T): Promise<AccessToken> => {\n //\n // Simple rules:\n // - If we MUST refresh, then return the refresh task, blocking\n // the pipeline until a token is available.\n // - If we SHOULD refresh, then run refresh but don't return it\n // (we can still use the cached token).\n // - Return the token, since it's fine if we didn't return in\n // step 1.\n //\n if (cycler.mustRefresh) return refresh(scopes, tokenOptions);\n\n if (cycler.shouldRefresh) {\n refresh(scopes, tokenOptions);\n }\n\n return token as AccessToken;\n },\n };\n}\n"]}
@@ -25,6 +25,10 @@ const fiveMinutesInMs = 5 * 60 * 1000;
25
25
  *```
26
26
  */
27
27
  class ChallengeHandler {
28
+ credential;
29
+ options;
30
+ cycler;
31
+ cachedAcrAccessToken;
28
32
  constructor(credential, options = {}) {
29
33
  this.credential = credential;
30
34
  this.options = options;
@@ -43,9 +47,8 @@ class ChallengeHandler {
43
47
  * Updates the authentication context based on the challenge.
44
48
  */
45
49
  async authorizeRequestOnChallenge(options) {
46
- var _a;
47
50
  // Once we're here, we've completed Step 1.
48
- const challenge = (_a = options.response) === null || _a === void 0 ? void 0 : _a.headers.get("WWW-Authenticate");
51
+ const challenge = options.response?.headers.get("WWW-Authenticate");
49
52
  if (!challenge) {
50
53
  throw new Error("Failed to retrieve challenge from response headers");
51
54
  }
@@ -68,7 +71,7 @@ class ChallengeHandler {
68
71
  }
69
72
  else {
70
73
  grantType = "refresh_token";
71
- acrRefreshToken = (await this.cycler.getToken(scope, Object.assign(Object.assign({}, options), { service }))).token;
74
+ acrRefreshToken = (await this.cycler.getToken(scope, { ...options, service })).token;
72
75
  }
73
76
  // Step 4: Send in acrRefreshToken and get back acrAccessToken
74
77
  const acrAccessToken = await this.credential.tokenService.ExchangeAcrRefreshTokenForAcrAccessTokenAsync(acrRefreshToken, service, scope, grantType, this.options);
@@ -1 +1 @@
1
- {"version":3,"file":"containerRegistryChallengeHandler.js","sourceRoot":"","sources":["../../src/containerRegistryChallengeHandler.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC;;;AAQlC,+EAAwE;AAMxE,2DAA2D;AAE3D,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEtC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAa,gBAAgB;IAI3B,YACU,UAAmD,EACnD,UAA2B,EAAE;QAD7B,eAAU,GAAV,UAAU,CAAyC;QACnD,YAAO,GAAP,OAAO,CAAsB;QAErC,IAAI,CAAC,MAAM,GAAG,IAAA,kCAAiB,EAAC,UAAU,EAAE;YAC1C,iBAAiB,EAAE,eAAe;SACnC,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB,CAAC,OAAgC;QAC/C,iEAAiE;QACjE,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC9B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,2BAA2B,CAAC,OAA2C;;QAC3E,2CAA2C;QAC3C,MAAM,SAAS,GAAG,MAAA,OAAO,CAAC,QAAQ,0CAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QACpE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QACD,iGAAiG;QACjG,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,IAAA,+CAAoB,EAAC,SAAS,CAAC,CAAC;QAE3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,0DAA0D;QAC1D,sGAAsG;QACtG,0FAA0F;QAC1F,IAAI,SAAuC,CAAC;QAC5C,IAAI,eAAuB,CAAC;QAC5B,IAAI,IAAI,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC;YACtC,SAAS,GAAG,UAAU,CAAC;YACvB,eAAe,GAAG,EAAE,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,SAAS,GAAG,eAAe,CAAC;YAC5B,eAAe,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,kCAAO,OAAO,KAAE,OAAO,IAAG,CAAC,CAAC,KAAK,CAAC;QACvF,CAAC;QAED,8DAA8D;QAC9D,MAAM,cAAc,GAClB,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,6CAA6C,CAC9E,eAAe,EACf,OAAO,EACP,KAAK,EACL,SAAS,EACT,IAAI,CAAC,OAAO,CACb,CAAC;QAEJ,gGAAgG;QAChG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,cAAc,EAAE,CAAC,CAAC;QAEzE,IAAI,CAAC,oBAAoB,GAAG,cAAc,CAAC;QAE3C,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAxED,4CAwEC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { GetTokenOptions } from \"@azure/core-auth\";\nimport type {\n AuthorizeRequestOnChallengeOptions,\n ChallengeCallbacks,\n AuthorizeRequestOptions,\n} from \"@azure/core-rest-pipeline\";\nimport { parseWWWAuthenticate } from \"./utils/wwwAuthenticateParser.js\";\nimport type {\n ContainerRegistryGetTokenOptions,\n ContainerRegistryRefreshTokenCredential,\n} from \"./containerRegistryTokenCredential.js\";\nimport type { AccessTokenRefresher } from \"./utils/tokenCycler.js\";\nimport { createTokenCycler } from \"./utils/tokenCycler.js\";\n\nconst fiveMinutesInMs = 5 * 60 * 1000;\n\n/**\n * Handles challenge based authentication for Container Registry Service.\n *```\n * The challenge-based authorization flow for ACR is illustrated in the following steps.\n * For example, GET /api/v1/acr/repositories translates into the following calls.\n * Step 1: GET /api/v1/acr/repositories\n * Return Header: 401: www-authenticate header - Bearer realm=\"{url}\",service=\"{serviceName}\",scope=\"{scope}\",error=\"invalid_token\"\n * Step 2: Retrieve the serviceName, scope from the WWW-Authenticate header. (Parse the string.)\n * Step 3: POST /api/oauth2/exchange\n * Request Body : { service, scope, grant-type, aadToken with ARM scope }\n * Response Body: { acrRefreshToken }\n * Step 4: POST /api/oauth2/token\n * Request Body: { acrRefreshToken, scope, grant-type }\n * Response Body: { acrAccessToken }\n * Step 5: GET /api/v1/acr/repositories\n * Request Header: { Bearer acrTokenAccess }\n *```\n */\nexport class ChallengeHandler implements ChallengeCallbacks {\n private readonly cycler: AccessTokenRefresher<ContainerRegistryGetTokenOptions>;\n private cachedAcrAccessToken: string | undefined;\n\n constructor(\n private credential: ContainerRegistryRefreshTokenCredential,\n private options: GetTokenOptions = {},\n ) {\n this.cycler = createTokenCycler(credential, {\n refreshWindowInMs: fiveMinutesInMs,\n });\n }\n\n authorizeRequest(options: AuthorizeRequestOptions): Promise<void> {\n // Try using the existing token in case we don't need to refresh.\n if (this.cachedAcrAccessToken) {\n options.request.headers.set(\"Authorization\", `Bearer ${this.cachedAcrAccessToken}`);\n }\n\n return Promise.resolve();\n }\n\n /**\n * Updates the authentication context based on the challenge.\n */\n async authorizeRequestOnChallenge(options: AuthorizeRequestOnChallengeOptions): Promise<boolean> {\n // Once we're here, we've completed Step 1.\n const challenge = options.response?.headers.get(\"WWW-Authenticate\");\n if (!challenge) {\n throw new Error(\"Failed to retrieve challenge from response headers\");\n }\n // Step 2: Parse challenge string to retrieve serviceName and scope, where scope is the ACR Scope\n const { service, scope } = parseWWWAuthenticate(challenge);\n\n if (!service) {\n throw new Error(\"Failed to retrieve 'service' from challenge\");\n }\n\n if (!scope) {\n throw new Error(\"Failed to retrieve 'scope' from challenge\");\n }\n\n // Step 3: Exchange AAD Access Token for ACR Refresh Token\n // For anonymous access, we send the request with grant_type=password and an empty ACR refresh token\n // For non-anonymous access, we get an AAD token then exchange it for an ACR fresh token\n let grantType: \"password\" | \"refresh_token\";\n let acrRefreshToken: string;\n if (this.credential.isAnonymousAccess) {\n grantType = \"password\";\n acrRefreshToken = \"\";\n } else {\n grantType = \"refresh_token\";\n acrRefreshToken = (await this.cycler.getToken(scope, { ...options, service })).token;\n }\n\n // Step 4: Send in acrRefreshToken and get back acrAccessToken\n const acrAccessToken =\n await this.credential.tokenService.ExchangeAcrRefreshTokenForAcrAccessTokenAsync(\n acrRefreshToken,\n service,\n scope,\n grantType,\n this.options,\n );\n\n // Step 5 - Authorize Request. At this point we're done with AAD and using an ACR access token.\n options.request.headers.set(\"Authorization\", `Bearer ${acrAccessToken}`);\n\n this.cachedAcrAccessToken = acrAccessToken;\n\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"containerRegistryChallengeHandler.js","sourceRoot":"","sources":["../../src/containerRegistryChallengeHandler.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC;;;AAQlC,+EAAwE;AAMxE,2DAA2D;AAE3D,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEtC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAa,gBAAgB;IAKjB;IACA;IALO,MAAM,CAAyD;IACxE,oBAAoB,CAAqB;IAEjD,YACU,UAAmD,EACnD,UAA2B,EAAE;QAD7B,eAAU,GAAV,UAAU,CAAyC;QACnD,YAAO,GAAP,OAAO,CAAsB;QAErC,IAAI,CAAC,MAAM,GAAG,IAAA,kCAAiB,EAAC,UAAU,EAAE;YAC1C,iBAAiB,EAAE,eAAe;SACnC,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB,CAAC,OAAgC;QAC/C,iEAAiE;QACjE,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC9B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,2BAA2B,CAAC,OAA2C;QAC3E,2CAA2C;QAC3C,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QACpE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QACD,iGAAiG;QACjG,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,IAAA,+CAAoB,EAAC,SAAS,CAAC,CAAC;QAE3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,0DAA0D;QAC1D,sGAAsG;QACtG,0FAA0F;QAC1F,IAAI,SAAuC,CAAC;QAC5C,IAAI,eAAuB,CAAC;QAC5B,IAAI,IAAI,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC;YACtC,SAAS,GAAG,UAAU,CAAC;YACvB,eAAe,GAAG,EAAE,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,SAAS,GAAG,eAAe,CAAC;YAC5B,eAAe,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QACvF,CAAC;QAED,8DAA8D;QAC9D,MAAM,cAAc,GAClB,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,6CAA6C,CAC9E,eAAe,EACf,OAAO,EACP,KAAK,EACL,SAAS,EACT,IAAI,CAAC,OAAO,CACb,CAAC;QAEJ,gGAAgG;QAChG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,cAAc,EAAE,CAAC,CAAC;QAEzE,IAAI,CAAC,oBAAoB,GAAG,cAAc,CAAC;QAE3C,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAxED,4CAwEC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { GetTokenOptions } from \"@azure/core-auth\";\nimport type {\n AuthorizeRequestOnChallengeOptions,\n ChallengeCallbacks,\n AuthorizeRequestOptions,\n} from \"@azure/core-rest-pipeline\";\nimport { parseWWWAuthenticate } from \"./utils/wwwAuthenticateParser.js\";\nimport type {\n ContainerRegistryGetTokenOptions,\n ContainerRegistryRefreshTokenCredential,\n} from \"./containerRegistryTokenCredential.js\";\nimport type { AccessTokenRefresher } from \"./utils/tokenCycler.js\";\nimport { createTokenCycler } from \"./utils/tokenCycler.js\";\n\nconst fiveMinutesInMs = 5 * 60 * 1000;\n\n/**\n * Handles challenge based authentication for Container Registry Service.\n *```\n * The challenge-based authorization flow for ACR is illustrated in the following steps.\n * For example, GET /api/v1/acr/repositories translates into the following calls.\n * Step 1: GET /api/v1/acr/repositories\n * Return Header: 401: www-authenticate header - Bearer realm=\"{url}\",service=\"{serviceName}\",scope=\"{scope}\",error=\"invalid_token\"\n * Step 2: Retrieve the serviceName, scope from the WWW-Authenticate header. (Parse the string.)\n * Step 3: POST /api/oauth2/exchange\n * Request Body : { service, scope, grant-type, aadToken with ARM scope }\n * Response Body: { acrRefreshToken }\n * Step 4: POST /api/oauth2/token\n * Request Body: { acrRefreshToken, scope, grant-type }\n * Response Body: { acrAccessToken }\n * Step 5: GET /api/v1/acr/repositories\n * Request Header: { Bearer acrTokenAccess }\n *```\n */\nexport class ChallengeHandler implements ChallengeCallbacks {\n private readonly cycler: AccessTokenRefresher<ContainerRegistryGetTokenOptions>;\n private cachedAcrAccessToken: string | undefined;\n\n constructor(\n private credential: ContainerRegistryRefreshTokenCredential,\n private options: GetTokenOptions = {},\n ) {\n this.cycler = createTokenCycler(credential, {\n refreshWindowInMs: fiveMinutesInMs,\n });\n }\n\n authorizeRequest(options: AuthorizeRequestOptions): Promise<void> {\n // Try using the existing token in case we don't need to refresh.\n if (this.cachedAcrAccessToken) {\n options.request.headers.set(\"Authorization\", `Bearer ${this.cachedAcrAccessToken}`);\n }\n\n return Promise.resolve();\n }\n\n /**\n * Updates the authentication context based on the challenge.\n */\n async authorizeRequestOnChallenge(options: AuthorizeRequestOnChallengeOptions): Promise<boolean> {\n // Once we're here, we've completed Step 1.\n const challenge = options.response?.headers.get(\"WWW-Authenticate\");\n if (!challenge) {\n throw new Error(\"Failed to retrieve challenge from response headers\");\n }\n // Step 2: Parse challenge string to retrieve serviceName and scope, where scope is the ACR Scope\n const { service, scope } = parseWWWAuthenticate(challenge);\n\n if (!service) {\n throw new Error(\"Failed to retrieve 'service' from challenge\");\n }\n\n if (!scope) {\n throw new Error(\"Failed to retrieve 'scope' from challenge\");\n }\n\n // Step 3: Exchange AAD Access Token for ACR Refresh Token\n // For anonymous access, we send the request with grant_type=password and an empty ACR refresh token\n // For non-anonymous access, we get an AAD token then exchange it for an ACR fresh token\n let grantType: \"password\" | \"refresh_token\";\n let acrRefreshToken: string;\n if (this.credential.isAnonymousAccess) {\n grantType = \"password\";\n acrRefreshToken = \"\";\n } else {\n grantType = \"refresh_token\";\n acrRefreshToken = (await this.cycler.getToken(scope, { ...options, service })).token;\n }\n\n // Step 4: Send in acrRefreshToken and get back acrAccessToken\n const acrAccessToken =\n await this.credential.tokenService.ExchangeAcrRefreshTokenForAcrAccessTokenAsync(\n acrRefreshToken,\n service,\n scope,\n grantType,\n this.options,\n );\n\n // Step 5 - Authorize Request. At this point we're done with AAD and using an ACR access token.\n options.request.headers.set(\"Authorization\", `Bearer ${acrAccessToken}`);\n\n this.cachedAcrAccessToken = acrAccessToken;\n\n return true;\n }\n}\n"]}
@@ -3,7 +3,6 @@
3
3
  // Licensed under the MIT License.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.ContainerRegistryClient = void 0;
6
- const tslib_1 = require("tslib");
7
6
  const core_auth_1 = require("@azure/core-auth");
8
7
  const core_rest_pipeline_1 = require("@azure/core-rest-pipeline");
9
8
  const logger_js_1 = require("./logger.js");
@@ -18,8 +17,12 @@ const LATEST_API_VERSION = "2021-07-01";
18
17
  * The client class used to interact with the Container Registry service.
19
18
  */
20
19
  class ContainerRegistryClient {
20
+ /**
21
+ * The Azure Container Registry endpoint.
22
+ */
23
+ endpoint;
24
+ client;
21
25
  constructor(endpoint, credentialOrOptions, clientOptions = {}) {
22
- var _a, _b;
23
26
  if (!endpoint) {
24
27
  throw new Error("invalid endpoint");
25
28
  }
@@ -31,16 +34,19 @@ class ContainerRegistryClient {
31
34
  options = clientOptions;
32
35
  }
33
36
  else {
34
- options = credentialOrOptions !== null && credentialOrOptions !== void 0 ? credentialOrOptions : {};
37
+ options = credentialOrOptions ?? {};
35
38
  }
36
- const internalPipelineOptions = Object.assign(Object.assign({}, options), { loggingOptions: {
39
+ const internalPipelineOptions = {
40
+ ...options,
41
+ loggingOptions: {
37
42
  logger: logger_js_1.logger.info,
38
43
  // This array contains header names we want to log that are not already
39
44
  // included as safe. Unknown/unsafe headers are logged as "<REDACTED>".
40
45
  additionalAllowedQueryParameters: ["last", "n", "orderby", "digest"],
41
- } });
42
- const defaultScope = `${(_a = options.audience) !== null && _a !== void 0 ? _a : "https://containerregistry.azure.net"}/.default`;
43
- const serviceVersion = (_b = options.serviceVersion) !== null && _b !== void 0 ? _b : LATEST_API_VERSION;
46
+ },
47
+ };
48
+ const defaultScope = `${options.audience ?? "https://containerregistry.azure.net"}/.default`;
49
+ const serviceVersion = options.serviceVersion ?? LATEST_API_VERSION;
44
50
  const authClient = new index_js_1.GeneratedClient(endpoint, serviceVersion, internalPipelineOptions);
45
51
  this.client = new index_js_1.GeneratedClient(endpoint, serviceVersion, internalPipelineOptions);
46
52
  this.client.pipeline.addPolicy((0, core_rest_pipeline_1.bearerTokenAuthenticationPolicy)({
@@ -124,52 +130,38 @@ class ContainerRegistryClient {
124
130
  byPage: (settings = {}) => this.listRepositoriesPage(settings, options),
125
131
  };
126
132
  }
127
- listRepositoryItems() {
128
- return tslib_1.__asyncGenerator(this, arguments, function* listRepositoryItems_1(options = {}) {
129
- var _a, e_1, _b, _c;
130
- try {
131
- for (var _d = true, _e = tslib_1.__asyncValues(this.listRepositoriesPage({}, options)), _f; _f = yield tslib_1.__await(_e.next()), _a = _f.done, !_a; _d = true) {
132
- _c = _f.value;
133
- _d = false;
134
- const page = _c;
135
- yield tslib_1.__await(yield* tslib_1.__asyncDelegator(tslib_1.__asyncValues(page)));
136
- }
137
- }
138
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
139
- finally {
140
- try {
141
- if (!_d && !_a && (_b = _e.return)) yield tslib_1.__await(_b.call(_e));
142
- }
143
- finally { if (e_1) throw e_1.error; }
144
- }
145
- });
133
+ async *listRepositoryItems(options = {}) {
134
+ for await (const page of this.listRepositoriesPage({}, options)) {
135
+ yield* page;
136
+ }
146
137
  }
147
- listRepositoriesPage(continuationState_1) {
148
- return tslib_1.__asyncGenerator(this, arguments, function* listRepositoriesPage_1(continuationState, options = {}) {
149
- if (!continuationState.continuationToken) {
150
- const optionsComplete = Object.assign(Object.assign({}, options), { n: continuationState.maxPageSize });
151
- const currentPage = yield tslib_1.__await(this.client.containerRegistry.getRepositories(optionsComplete));
152
- continuationState.continuationToken = (0, helpers_js_1.extractNextLink)(currentPage.link);
153
- if (currentPage.repositories) {
154
- const array = currentPage.repositories;
155
- yield yield tslib_1.__await(Object.defineProperty(array, "continuationToken", {
156
- value: continuationState.continuationToken,
157
- enumerable: true,
158
- }));
159
- }
138
+ async *listRepositoriesPage(continuationState, options = {}) {
139
+ if (!continuationState.continuationToken) {
140
+ const optionsComplete = {
141
+ ...options,
142
+ n: continuationState.maxPageSize,
143
+ };
144
+ const currentPage = await this.client.containerRegistry.getRepositories(optionsComplete);
145
+ continuationState.continuationToken = (0, helpers_js_1.extractNextLink)(currentPage.link);
146
+ if (currentPage.repositories) {
147
+ const array = currentPage.repositories;
148
+ yield Object.defineProperty(array, "continuationToken", {
149
+ value: continuationState.continuationToken,
150
+ enumerable: true,
151
+ });
160
152
  }
161
- while (continuationState.continuationToken) {
162
- const currentPage = yield tslib_1.__await(this.client.containerRegistry.getRepositoriesNext(continuationState.continuationToken, options));
163
- continuationState.continuationToken = (0, helpers_js_1.extractNextLink)(currentPage.link);
164
- if (currentPage.repositories) {
165
- const array = currentPage.repositories;
166
- yield yield tslib_1.__await(Object.defineProperty(array, "continuationToken", {
167
- value: continuationState.continuationToken,
168
- enumerable: true,
169
- }));
170
- }
153
+ }
154
+ while (continuationState.continuationToken) {
155
+ const currentPage = await this.client.containerRegistry.getRepositoriesNext(continuationState.continuationToken, options);
156
+ continuationState.continuationToken = (0, helpers_js_1.extractNextLink)(currentPage.link);
157
+ if (currentPage.repositories) {
158
+ const array = currentPage.repositories;
159
+ yield Object.defineProperty(array, "continuationToken", {
160
+ value: continuationState.continuationToken,
161
+ enumerable: true,
162
+ });
171
163
  }
172
- });
164
+ }
173
165
  }
174
166
  }
175
167
  exports.ContainerRegistryClient = ContainerRegistryClient;
@@ -1 +1 @@
1
- {"version":3,"file":"containerRegistryClient.js","sourceRoot":"","sources":["../../src/containerRegistryClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { TokenCredential } from \"@azure/core-auth\";\nimport { isTokenCredential } from \"@azure/core-auth\";\nimport type { InternalPipelineOptions } from \"@azure/core-rest-pipeline\";\nimport { bearerTokenAuthenticationPolicy } from \"@azure/core-rest-pipeline\";\nimport type { CommonClientOptions, OperationOptions } from \"@azure/core-client\";\n\nimport type { PageSettings, PagedAsyncIterableIterator } from \"@azure/core-paging\";\n\nimport { logger } from \"./logger.js\";\nimport { GeneratedClient } from \"./generated/index.js\";\nimport { tracingClient } from \"./tracing.js\";\nimport type { RepositoryPageResponse } from \"./models.js\";\nimport { extractNextLink } from \"./utils/helpers.js\";\nimport { ChallengeHandler } from \"./containerRegistryChallengeHandler.js\";\nimport type { ContainerRepository, DeleteRepositoryOptions } from \"./containerRepository.js\";\nimport { ContainerRepositoryImpl } from \"./containerRepository.js\";\nimport type { RegistryArtifact } from \"./registryArtifact.js\";\nimport { ContainerRegistryRefreshTokenCredential } from \"./containerRegistryTokenCredential.js\";\n\nconst LATEST_API_VERSION = \"2021-07-01\";\n\n/**\n * Client options used to configure Container Registry Repository API requests.\n */\nexport interface ContainerRegistryClientOptions extends CommonClientOptions {\n /**\n * Gets or sets the audience to use for authentication with Azure Active Directory.\n * The authentication scope will be set from this audience.\n * See {@link KnownContainerRegistryAudience} for known audience values.\n */\n audience?: string;\n /**\n * The version of service API to make calls against.\n */\n serviceVersion?: \"2021-07-01\";\n}\n\n/**\n * Options for the `listRepositories` method of `ContainerRegistryClient`.\n */\nexport interface ListRepositoriesOptions extends OperationOptions {}\n\n/**\n * The client class used to interact with the Container Registry service.\n */\nexport class ContainerRegistryClient {\n /**\n * The Azure Container Registry endpoint.\n */\n public readonly endpoint: string;\n\n private client: GeneratedClient;\n\n /**\n * Creates an instance of a ContainerRegistryClient.\n *\n * Example usage:\n * ```ts snippet:ReadmeSampleCreateClient_Node\n * import { ContainerRegistryClient, KnownContainerRegistryAudience } from \"@azure/container-registry\";\n * import { DefaultAzureCredential } from \"@azure/identity\";\n *\n * const endpoint = \"https://myregistryname.azurecr.io\";\n * // Create a ContainerRegistryClient that will authenticate through Active Directory\n * const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), {\n * audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud,\n * });\n * ```\n * @param endpoint - the URL endpoint of the container registry\n * @param credential - used to authenticate requests to the service\n * @param options - optional configuration used to send requests to the service\n */\n constructor(\n endpoint: string,\n credential: TokenCredential,\n options?: ContainerRegistryClientOptions,\n );\n\n /**\n * Creates an instance of a ContainerRegistryClient to interact with\n * an Azure Container Registry that has anonymous pull access enabled.\n * Only operations that support anonymous access are enabled. Other service\n * methods will throw errors.\n *\n * Example usage:\n * ```ts snippet:ReadmeSampleCreateClient_Anonymous\n * import { ContainerRegistryClient, KnownContainerRegistryAudience } from \"@azure/container-registry\";\n *\n * const endpoint = \"https://myregistryname.azurecr.io\";\n * // Create a new ContainerRegistryClient for anonymous access\n * const client = new ContainerRegistryClient(endpoint, {\n * audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud,\n * });\n * ```\n * @param endpoint - the URL endpoint of the container registry\n * @param options - optional configuration used to send requests to the service\n */\n constructor(endpoint: string, options?: ContainerRegistryClientOptions);\n\n constructor(\n endpoint: string,\n credentialOrOptions?: TokenCredential | ContainerRegistryClientOptions,\n clientOptions: ContainerRegistryClientOptions = {},\n ) {\n if (!endpoint) {\n throw new Error(\"invalid endpoint\");\n }\n\n this.endpoint = endpoint;\n\n let credential: TokenCredential | undefined;\n let options: ContainerRegistryClientOptions | undefined;\n if (isTokenCredential(credentialOrOptions)) {\n credential = credentialOrOptions;\n options = clientOptions;\n } else {\n options = credentialOrOptions ?? {};\n }\n\n const internalPipelineOptions: InternalPipelineOptions = {\n ...options,\n loggingOptions: {\n logger: logger.info,\n // This array contains header names we want to log that are not already\n // included as safe. Unknown/unsafe headers are logged as \"<REDACTED>\".\n additionalAllowedQueryParameters: [\"last\", \"n\", \"orderby\", \"digest\"],\n },\n };\n\n const defaultScope = `${options.audience ?? \"https://containerregistry.azure.net\"}/.default`;\n const serviceVersion = options.serviceVersion ?? LATEST_API_VERSION;\n const authClient = new GeneratedClient(endpoint, serviceVersion, internalPipelineOptions);\n this.client = new GeneratedClient(endpoint, serviceVersion, internalPipelineOptions);\n this.client.pipeline.addPolicy(\n bearerTokenAuthenticationPolicy({\n credential,\n scopes: [defaultScope],\n challengeCallbacks: new ChallengeHandler(\n new ContainerRegistryRefreshTokenCredential(authClient, defaultScope, credential),\n ),\n }),\n );\n }\n\n /**\n * Deletes the repository identified by the given name and all associated artifacts.\n *\n * @param repositoryName - the name of repository to delete\n * @param options - optional configuration for the operation\n */\n public async deleteRepository(\n repositoryName: string,\n options: DeleteRepositoryOptions = {},\n ): Promise<void> {\n if (!repositoryName) {\n throw new Error(\"invalid repositoryName\");\n }\n\n return tracingClient.withSpan(\n \"ContainerRegistryClient.deleteRepository\",\n options,\n async (updatedOptions) => {\n await this.client.containerRegistry.deleteRepository(repositoryName, updatedOptions);\n },\n );\n }\n\n /**\n * Returns an instance of {@link RegistryArtifact} for calling service methods related to the artifact specified by `repositoryName` and `tagOrDigest`.\n *\n * @param repositoryName - the name of repository\n * @param tagOrDigest - tag or digest of the artifact to retrieve\n */\n public getArtifact(repositoryName: string, tagOrDigest: string): RegistryArtifact {\n if (!repositoryName) {\n throw new Error(\"invalid repositoryName\");\n }\n if (!tagOrDigest) {\n throw new Error(\"invalid tagOrDigest\");\n }\n\n return new ContainerRepositoryImpl(this.endpoint, repositoryName, this.client).getArtifact(\n tagOrDigest,\n );\n }\n\n /**\n * Returns an instance of {@link ContainerRepository} for calling service methods related to the repository specified by `repositoryName`.\n *\n * @param repositoryName - the name of repository\n */\n public getRepository(repositoryName: string): ContainerRepository {\n if (!repositoryName) {\n throw new Error(\"invalid repositoryName\");\n }\n\n return new ContainerRepositoryImpl(this.endpoint, repositoryName, this.client);\n }\n\n /**\n * Returns an async iterable iterator to list names of repositories in this registry.\n *\n * Example usage:\n * ```ts snippet:SampleReadmeListRepositories\n * import { ContainerRegistryClient, KnownContainerRegistryAudience } from \"@azure/container-registry\";\n * import { DefaultAzureCredential } from \"@azure/identity\";\n *\n * const endpoint = \"https://myregistryname.azurecr.io\";\n * const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), {\n * audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud,\n * });\n *\n * const iterator = client.listRepositoryNames();\n * for await (const repository of iterator) {\n * console.log(` repository: ${repository}`);\n * }\n * ```\n *\n * @param options - The options for the request\n */\n public listRepositoryNames(\n // eslint-disable-next-line @azure/azure-sdk/ts-naming-options\n options: ListRepositoriesOptions = {},\n ): PagedAsyncIterableIterator<string, RepositoryPageResponse> {\n const iter = this.listRepositoryItems(options);\n\n return {\n next() {\n return iter.next();\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n byPage: (settings: PageSettings = {}) => this.listRepositoriesPage(settings, options),\n };\n }\n\n private async *listRepositoryItems(\n options: ListRepositoriesOptions = {},\n ): AsyncIterableIterator<string> {\n for await (const page of this.listRepositoriesPage({}, options)) {\n yield* page;\n }\n }\n\n private async *listRepositoriesPage(\n continuationState: PageSettings,\n options: ListRepositoriesOptions = {},\n ): AsyncIterableIterator<RepositoryPageResponse> {\n if (!continuationState.continuationToken) {\n const optionsComplete = {\n ...options,\n n: continuationState.maxPageSize,\n };\n const currentPage = await this.client.containerRegistry.getRepositories(optionsComplete);\n continuationState.continuationToken = extractNextLink(currentPage.link);\n if (currentPage.repositories) {\n const array = currentPage.repositories;\n yield Object.defineProperty(array, \"continuationToken\", {\n value: continuationState.continuationToken,\n enumerable: true,\n });\n }\n }\n while (continuationState.continuationToken) {\n const currentPage = await this.client.containerRegistry.getRepositoriesNext(\n continuationState.continuationToken,\n options,\n );\n continuationState.continuationToken = extractNextLink(currentPage.link);\n if (currentPage.repositories) {\n const array = currentPage.repositories;\n yield Object.defineProperty(array, \"continuationToken\", {\n value: continuationState.continuationToken,\n enumerable: true,\n });\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"containerRegistryClient.js","sourceRoot":"","sources":["../../src/containerRegistryClient.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC;;;AAGlC,gDAAqD;AAErD,kEAA4E;AAK5E,2CAAqC;AACrC,mDAAuD;AACvD,6CAA6C;AAE7C,mDAAqD;AACrD,iGAA0E;AAE1E,qEAAmE;AAEnE,+FAAgG;AAEhG,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAuBxC;;GAEG;AACH,MAAa,uBAAuB;IAClC;;OAEG;IACa,QAAQ,CAAS;IAEzB,MAAM,CAAkB;IA+ChC,YACE,QAAgB,EAChB,mBAAsE,EACtE,gBAAgD,EAAE;QAElD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtC,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,IAAI,UAAuC,CAAC;QAC5C,IAAI,OAAmD,CAAC;QACxD,IAAI,IAAA,6BAAiB,EAAC,mBAAmB,CAAC,EAAE,CAAC;YAC3C,UAAU,GAAG,mBAAmB,CAAC;YACjC,OAAO,GAAG,aAAa,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,mBAAmB,IAAI,EAAE,CAAC;QACtC,CAAC;QAED,MAAM,uBAAuB,GAA4B;YACvD,GAAG,OAAO;YACV,cAAc,EAAE;gBACd,MAAM,EAAE,kBAAM,CAAC,IAAI;gBACnB,uEAAuE;gBACvE,uEAAuE;gBACvE,gCAAgC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC;aACrE;SACF,CAAC;QAEF,MAAM,YAAY,GAAG,GAAG,OAAO,CAAC,QAAQ,IAAI,qCAAqC,WAAW,CAAC;QAC7F,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,kBAAkB,CAAC;QACpE,MAAM,UAAU,GAAG,IAAI,0BAAe,CAAC,QAAQ,EAAE,cAAc,EAAE,uBAAuB,CAAC,CAAC;QAC1F,IAAI,CAAC,MAAM,GAAG,IAAI,0BAAe,CAAC,QAAQ,EAAE,cAAc,EAAE,uBAAuB,CAAC,CAAC;QACrF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAC5B,IAAA,oDAA+B,EAAC;YAC9B,UAAU;YACV,MAAM,EAAE,CAAC,YAAY,CAAC;YACtB,kBAAkB,EAAE,IAAI,uDAAgB,CACtC,IAAI,6EAAuC,CAAC,UAAU,EAAE,YAAY,EAAE,UAAU,CAAC,CAClF;SACF,CAAC,CACH,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,gBAAgB,CAC3B,cAAsB,EACtB,UAAmC,EAAE;QAErC,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,0BAAa,CAAC,QAAQ,CAC3B,0CAA0C,EAC1C,OAAO,EACP,KAAK,EAAE,cAAc,EAAE,EAAE;YACvB,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;QACvF,CAAC,CACF,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACI,WAAW,CAAC,cAAsB,EAAE,WAAmB;QAC5D,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QACD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QAED,OAAO,IAAI,gDAAuB,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,WAAW,CACxF,WAAW,CACZ,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACI,aAAa,CAAC,cAAsB;QACzC,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,IAAI,gDAAuB,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACjF,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,mBAAmB;IACxB,8DAA8D;IAC9D,UAAmC,EAAE;QAErC,MAAM,IAAI,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAE/C,OAAO;YACL,IAAI;gBACF,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;YACrB,CAAC;YACD,CAAC,MAAM,CAAC,aAAa,CAAC;gBACpB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,EAAE,CAAC,WAAyB,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,OAAO,CAAC;SACtF,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,CAAC,mBAAmB,CAChC,UAAmC,EAAE;QAErC,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI,CAAC,oBAAoB,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,CAAC;YAChE,KAAK,CAAC,CAAC,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,CAAC,oBAAoB,CACjC,iBAA+B,EAC/B,UAAmC,EAAE;QAErC,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,CAAC;YACzC,MAAM,eAAe,GAAG;gBACtB,GAAG,OAAO;gBACV,CAAC,EAAE,iBAAiB,CAAC,WAAW;aACjC,CAAC;YACF,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;YACzF,iBAAiB,CAAC,iBAAiB,GAAG,IAAA,4BAAe,EAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACxE,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC;gBACvC,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE;oBACtD,KAAK,EAAE,iBAAiB,CAAC,iBAAiB;oBAC1C,UAAU,EAAE,IAAI;iBACjB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,iBAAiB,CAAC,iBAAiB,EAAE,CAAC;YAC3C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,mBAAmB,CACzE,iBAAiB,CAAC,iBAAiB,EACnC,OAAO,CACR,CAAC;YACF,iBAAiB,CAAC,iBAAiB,GAAG,IAAA,4BAAe,EAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACxE,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC;gBACvC,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE;oBACtD,KAAK,EAAE,iBAAiB,CAAC,iBAAiB;oBAC1C,UAAU,EAAE,IAAI;iBACjB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAzOD,0DAyOC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { TokenCredential } from \"@azure/core-auth\";\nimport { isTokenCredential } from \"@azure/core-auth\";\nimport type { InternalPipelineOptions } from \"@azure/core-rest-pipeline\";\nimport { bearerTokenAuthenticationPolicy } from \"@azure/core-rest-pipeline\";\nimport type { CommonClientOptions, OperationOptions } from \"@azure/core-client\";\n\nimport type { PageSettings, PagedAsyncIterableIterator } from \"@azure/core-paging\";\n\nimport { logger } from \"./logger.js\";\nimport { GeneratedClient } from \"./generated/index.js\";\nimport { tracingClient } from \"./tracing.js\";\nimport type { RepositoryPageResponse } from \"./models.js\";\nimport { extractNextLink } from \"./utils/helpers.js\";\nimport { ChallengeHandler } from \"./containerRegistryChallengeHandler.js\";\nimport type { ContainerRepository, DeleteRepositoryOptions } from \"./containerRepository.js\";\nimport { ContainerRepositoryImpl } from \"./containerRepository.js\";\nimport type { RegistryArtifact } from \"./registryArtifact.js\";\nimport { ContainerRegistryRefreshTokenCredential } from \"./containerRegistryTokenCredential.js\";\n\nconst LATEST_API_VERSION = \"2021-07-01\";\n\n/**\n * Client options used to configure Container Registry Repository API requests.\n */\nexport interface ContainerRegistryClientOptions extends CommonClientOptions {\n /**\n * Gets or sets the audience to use for authentication with Azure Active Directory.\n * The authentication scope will be set from this audience.\n * See {@link KnownContainerRegistryAudience} for known audience values.\n */\n audience?: string;\n /**\n * The version of service API to make calls against.\n */\n serviceVersion?: \"2021-07-01\";\n}\n\n/**\n * Options for the `listRepositories` method of `ContainerRegistryClient`.\n */\nexport interface ListRepositoriesOptions extends OperationOptions {}\n\n/**\n * The client class used to interact with the Container Registry service.\n */\nexport class ContainerRegistryClient {\n /**\n * The Azure Container Registry endpoint.\n */\n public readonly endpoint: string;\n\n private client: GeneratedClient;\n\n /**\n * Creates an instance of a ContainerRegistryClient.\n *\n * Example usage:\n * ```ts snippet:ReadmeSampleCreateClient_Node\n * import { ContainerRegistryClient, KnownContainerRegistryAudience } from \"@azure/container-registry\";\n * import { DefaultAzureCredential } from \"@azure/identity\";\n *\n * const endpoint = \"https://myregistryname.azurecr.io\";\n * // Create a ContainerRegistryClient that will authenticate through Active Directory\n * const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), {\n * audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud,\n * });\n * ```\n * @param endpoint - the URL endpoint of the container registry\n * @param credential - used to authenticate requests to the service\n * @param options - optional configuration used to send requests to the service\n */\n constructor(\n endpoint: string,\n credential: TokenCredential,\n options?: ContainerRegistryClientOptions,\n );\n\n /**\n * Creates an instance of a ContainerRegistryClient to interact with\n * an Azure Container Registry that has anonymous pull access enabled.\n * Only operations that support anonymous access are enabled. Other service\n * methods will throw errors.\n *\n * Example usage:\n * ```ts snippet:ReadmeSampleCreateClient_Anonymous\n * import { ContainerRegistryClient, KnownContainerRegistryAudience } from \"@azure/container-registry\";\n *\n * const endpoint = \"https://myregistryname.azurecr.io\";\n * // Create a new ContainerRegistryClient for anonymous access\n * const client = new ContainerRegistryClient(endpoint, {\n * audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud,\n * });\n * ```\n * @param endpoint - the URL endpoint of the container registry\n * @param options - optional configuration used to send requests to the service\n */\n constructor(endpoint: string, options?: ContainerRegistryClientOptions);\n\n constructor(\n endpoint: string,\n credentialOrOptions?: TokenCredential | ContainerRegistryClientOptions,\n clientOptions: ContainerRegistryClientOptions = {},\n ) {\n if (!endpoint) {\n throw new Error(\"invalid endpoint\");\n }\n\n this.endpoint = endpoint;\n\n let credential: TokenCredential | undefined;\n let options: ContainerRegistryClientOptions | undefined;\n if (isTokenCredential(credentialOrOptions)) {\n credential = credentialOrOptions;\n options = clientOptions;\n } else {\n options = credentialOrOptions ?? {};\n }\n\n const internalPipelineOptions: InternalPipelineOptions = {\n ...options,\n loggingOptions: {\n logger: logger.info,\n // This array contains header names we want to log that are not already\n // included as safe. Unknown/unsafe headers are logged as \"<REDACTED>\".\n additionalAllowedQueryParameters: [\"last\", \"n\", \"orderby\", \"digest\"],\n },\n };\n\n const defaultScope = `${options.audience ?? \"https://containerregistry.azure.net\"}/.default`;\n const serviceVersion = options.serviceVersion ?? LATEST_API_VERSION;\n const authClient = new GeneratedClient(endpoint, serviceVersion, internalPipelineOptions);\n this.client = new GeneratedClient(endpoint, serviceVersion, internalPipelineOptions);\n this.client.pipeline.addPolicy(\n bearerTokenAuthenticationPolicy({\n credential,\n scopes: [defaultScope],\n challengeCallbacks: new ChallengeHandler(\n new ContainerRegistryRefreshTokenCredential(authClient, defaultScope, credential),\n ),\n }),\n );\n }\n\n /**\n * Deletes the repository identified by the given name and all associated artifacts.\n *\n * @param repositoryName - the name of repository to delete\n * @param options - optional configuration for the operation\n */\n public async deleteRepository(\n repositoryName: string,\n options: DeleteRepositoryOptions = {},\n ): Promise<void> {\n if (!repositoryName) {\n throw new Error(\"invalid repositoryName\");\n }\n\n return tracingClient.withSpan(\n \"ContainerRegistryClient.deleteRepository\",\n options,\n async (updatedOptions) => {\n await this.client.containerRegistry.deleteRepository(repositoryName, updatedOptions);\n },\n );\n }\n\n /**\n * Returns an instance of {@link RegistryArtifact} for calling service methods related to the artifact specified by `repositoryName` and `tagOrDigest`.\n *\n * @param repositoryName - the name of repository\n * @param tagOrDigest - tag or digest of the artifact to retrieve\n */\n public getArtifact(repositoryName: string, tagOrDigest: string): RegistryArtifact {\n if (!repositoryName) {\n throw new Error(\"invalid repositoryName\");\n }\n if (!tagOrDigest) {\n throw new Error(\"invalid tagOrDigest\");\n }\n\n return new ContainerRepositoryImpl(this.endpoint, repositoryName, this.client).getArtifact(\n tagOrDigest,\n );\n }\n\n /**\n * Returns an instance of {@link ContainerRepository} for calling service methods related to the repository specified by `repositoryName`.\n *\n * @param repositoryName - the name of repository\n */\n public getRepository(repositoryName: string): ContainerRepository {\n if (!repositoryName) {\n throw new Error(\"invalid repositoryName\");\n }\n\n return new ContainerRepositoryImpl(this.endpoint, repositoryName, this.client);\n }\n\n /**\n * Returns an async iterable iterator to list names of repositories in this registry.\n *\n * Example usage:\n * ```ts snippet:SampleReadmeListRepositories\n * import { ContainerRegistryClient, KnownContainerRegistryAudience } from \"@azure/container-registry\";\n * import { DefaultAzureCredential } from \"@azure/identity\";\n *\n * const endpoint = \"https://myregistryname.azurecr.io\";\n * const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), {\n * audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud,\n * });\n *\n * const iterator = client.listRepositoryNames();\n * for await (const repository of iterator) {\n * console.log(` repository: ${repository}`);\n * }\n * ```\n *\n * @param options - The options for the request\n */\n public listRepositoryNames(\n // eslint-disable-next-line @azure/azure-sdk/ts-naming-options\n options: ListRepositoriesOptions = {},\n ): PagedAsyncIterableIterator<string, RepositoryPageResponse> {\n const iter = this.listRepositoryItems(options);\n\n return {\n next() {\n return iter.next();\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n byPage: (settings: PageSettings = {}) => this.listRepositoriesPage(settings, options),\n };\n }\n\n private async *listRepositoryItems(\n options: ListRepositoriesOptions = {},\n ): AsyncIterableIterator<string> {\n for await (const page of this.listRepositoriesPage({}, options)) {\n yield* page;\n }\n }\n\n private async *listRepositoriesPage(\n continuationState: PageSettings,\n options: ListRepositoriesOptions = {},\n ): AsyncIterableIterator<RepositoryPageResponse> {\n if (!continuationState.continuationToken) {\n const optionsComplete = {\n ...options,\n n: continuationState.maxPageSize,\n };\n const currentPage = await this.client.containerRegistry.getRepositories(optionsComplete);\n continuationState.continuationToken = extractNextLink(currentPage.link);\n if (currentPage.repositories) {\n const array = currentPage.repositories;\n yield Object.defineProperty(array, \"continuationToken\", {\n value: continuationState.continuationToken,\n enumerable: true,\n });\n }\n }\n while (continuationState.continuationToken) {\n const currentPage = await this.client.containerRegistry.getRepositoriesNext(\n continuationState.continuationToken,\n options,\n );\n continuationState.continuationToken = extractNextLink(currentPage.link);\n if (currentPage.repositories) {\n const array = currentPage.repositories;\n yield Object.defineProperty(array, \"continuationToken\", {\n value: continuationState.continuationToken,\n enumerable: true,\n });\n }\n }\n }\n}\n"]}
@@ -5,6 +5,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.ContainerRegistryTokenService = exports.ContainerRegistryRefreshTokenCredential = void 0;
6
6
  const base64_js_1 = require("./utils/base64.js");
7
7
  class ContainerRegistryRefreshTokenCredential {
8
+ authenticationScope;
9
+ credential;
10
+ tokenService;
11
+ isAnonymousAccess;
8
12
  constructor(authClient, authenticationScope, credential) {
9
13
  this.authenticationScope = authenticationScope;
10
14
  this.credential = credential;
@@ -24,11 +28,15 @@ class ContainerRegistryRefreshTokenCredential {
24
28
  }
25
29
  exports.ContainerRegistryRefreshTokenCredential = ContainerRegistryRefreshTokenCredential;
26
30
  class ContainerRegistryTokenService {
31
+ authClient;
27
32
  constructor(authClient) {
28
33
  this.authClient = authClient;
29
34
  }
30
35
  async ExchangeAadAccessTokenForAcrRefreshTokenAsync(aadAccessToken, service, options) {
31
- const acrRefreshToken = await this.authClient.authentication.exchangeAadAccessTokenForAcrRefreshToken("access_token", service, Object.assign(Object.assign({}, options), { accessToken: aadAccessToken }));
36
+ const acrRefreshToken = await this.authClient.authentication.exchangeAadAccessTokenForAcrRefreshToken("access_token", service, {
37
+ ...options,
38
+ accessToken: aadAccessToken,
39
+ });
32
40
  if (!acrRefreshToken.refreshToken) {
33
41
  throw new Error("Failed to exchange AAD access token for an ACR refresh token.");
34
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"containerRegistryTokenCredential.js","sourceRoot":"","sources":["../../src/containerRegistryTokenCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport type { GeneratedClient } from \"./generated/index.js\";\nimport { base64decode } from \"./utils/base64.js\";\n\nexport interface ContainerRegistryGetTokenOptions extends GetTokenOptions {\n service: string;\n}\n\nexport class ContainerRegistryRefreshTokenCredential implements TokenCredential {\n readonly tokenService: ContainerRegistryTokenService;\n readonly isAnonymousAccess: boolean;\n constructor(\n authClient: GeneratedClient,\n private authenticationScope: string,\n private credential?: TokenCredential,\n ) {\n this.tokenService = new ContainerRegistryTokenService(authClient);\n this.isAnonymousAccess = !this.credential;\n }\n\n async getToken(\n _scopes: string | string[],\n options: ContainerRegistryGetTokenOptions,\n ): Promise<AccessToken | null> {\n if (!this.credential) {\n return null;\n }\n\n const aadToken = await this.credential.getToken(this.authenticationScope, options);\n if (!aadToken) {\n throw new Error(\"Failed to retrieve AAD token.\");\n }\n\n return this.tokenService.ExchangeAadAccessTokenForAcrRefreshTokenAsync(\n aadToken.token,\n options.service,\n options,\n );\n }\n}\n\nexport class ContainerRegistryTokenService {\n constructor(private authClient: GeneratedClient) {}\n\n async ExchangeAadAccessTokenForAcrRefreshTokenAsync(\n aadAccessToken: string,\n service: string,\n options: GetTokenOptions,\n ): Promise<AccessToken> {\n const acrRefreshToken =\n await this.authClient.authentication.exchangeAadAccessTokenForAcrRefreshToken(\n \"access_token\",\n service,\n {\n ...options,\n accessToken: aadAccessToken,\n },\n );\n if (!acrRefreshToken.refreshToken) {\n throw new Error(\"Failed to exchange AAD access token for an ACR refresh token.\");\n }\n\n // ACR refresh token expires after three hours\n const jwtParts = acrRefreshToken.refreshToken.split(\".\");\n if (jwtParts.length < 3) {\n throw new Error(\"Invalid JWT structure from ACR refresh token.\");\n }\n if (!jwtParts[1]) {\n throw new Error(\"Invalid JWT payload.\");\n }\n\n const jwtPayload = JSON.parse(base64decode(jwtParts[1]));\n if (!jwtPayload.exp) {\n throw new Error(\"Invalid JWT payload structure. No expiration.\");\n }\n\n // JWT expiry is in seconds\n const expiry = Number.parseInt(jwtPayload.exp) * 1000;\n return {\n token: acrRefreshToken.refreshToken,\n expiresOnTimestamp: expiry,\n };\n }\n\n async ExchangeAcrRefreshTokenForAcrAccessTokenAsync(\n acrRefreshToken: string,\n service: string,\n scope: string,\n grantType: \"refresh_token\" | \"password\",\n options: GetTokenOptions,\n ): Promise<string> {\n const acrAccessToken =\n await this.authClient.authentication.exchangeAcrRefreshTokenForAcrAccessToken(\n service,\n scope,\n acrRefreshToken,\n grantType,\n options,\n );\n\n if (!acrAccessToken.accessToken) {\n throw new Error(\"Failed to exchange ACR refresh token for an ACR access token\");\n }\n return acrAccessToken.accessToken;\n }\n}\n"]}
1
+ {"version":3,"file":"containerRegistryTokenCredential.js","sourceRoot":"","sources":["../../src/containerRegistryTokenCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport type { GeneratedClient } from \"./generated/index.js\";\nimport { base64decode } from \"./utils/base64.js\";\n\nexport interface ContainerRegistryGetTokenOptions extends GetTokenOptions {\n service: string;\n}\n\nexport class ContainerRegistryRefreshTokenCredential implements TokenCredential {\n readonly tokenService: ContainerRegistryTokenService;\n readonly isAnonymousAccess: boolean;\n constructor(\n authClient: GeneratedClient,\n private authenticationScope: string,\n private credential?: TokenCredential,\n ) {\n this.tokenService = new ContainerRegistryTokenService(authClient);\n this.isAnonymousAccess = !this.credential;\n }\n\n async getToken(\n _scopes: string | string[],\n options: ContainerRegistryGetTokenOptions,\n ): Promise<AccessToken | null> {\n if (!this.credential) {\n return null;\n }\n\n const aadToken = await this.credential.getToken(this.authenticationScope, options);\n if (!aadToken) {\n throw new Error(\"Failed to retrieve AAD token.\");\n }\n\n return this.tokenService.ExchangeAadAccessTokenForAcrRefreshTokenAsync(\n aadToken.token,\n options.service,\n options,\n );\n }\n}\n\nexport class ContainerRegistryTokenService {\n constructor(private authClient: GeneratedClient) {}\n\n async ExchangeAadAccessTokenForAcrRefreshTokenAsync(\n aadAccessToken: string,\n service: string,\n options: GetTokenOptions,\n ): Promise<AccessToken> {\n const acrRefreshToken =\n await this.authClient.authentication.exchangeAadAccessTokenForAcrRefreshToken(\n \"access_token\",\n service,\n {\n ...options,\n accessToken: aadAccessToken,\n },\n );\n if (!acrRefreshToken.refreshToken) {\n throw new Error(\"Failed to exchange AAD access token for an ACR refresh token.\");\n }\n\n // ACR refresh token expires after three hours\n const jwtParts = acrRefreshToken.refreshToken.split(\".\");\n if (jwtParts.length < 3) {\n throw new Error(\"Invalid JWT structure from ACR refresh token.\");\n }\n if (!jwtParts[1]) {\n throw new Error(\"Invalid JWT payload.\");\n }\n\n const jwtPayload = JSON.parse(base64decode(jwtParts[1]));\n if (!jwtPayload.exp) {\n throw new Error(\"Invalid JWT payload structure. No expiration.\");\n }\n\n // JWT expiry is in seconds\n const expiry = Number.parseInt(jwtPayload.exp) * 1000;\n return {\n token: acrRefreshToken.refreshToken,\n expiresOnTimestamp: expiry,\n };\n }\n\n async ExchangeAcrRefreshTokenForAcrAccessTokenAsync(\n acrRefreshToken: string,\n service: string,\n scope: string,\n grantType: \"refresh_token\" | \"password\",\n options: GetTokenOptions,\n ): Promise<string> {\n const acrAccessToken =\n await this.authClient.authentication.exchangeAcrRefreshTokenForAcrAccessToken(\n service,\n scope,\n acrRefreshToken,\n grantType,\n options,\n );\n\n if (!acrAccessToken.accessToken) {\n throw new Error(\"Failed to exchange ACR refresh token for an ACR access token\");\n }\n return acrAccessToken.accessToken;\n }\n}\n"]}