@azure/api-management-custom-widgets-tools 1.0.0-beta.1 → 1.0.0-beta.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.
- package/README.md +1 -1
- package/dist/index.js +30 -27
- package/dist/index.js.map +1 -1
- package/dist-esm/src/index.js.map +1 -1
- package/dist-esm/src/node/CustomWidgetBlobService.js +12 -5
- package/dist-esm/src/node/CustomWidgetBlobService.js.map +1 -1
- package/dist-esm/src/node/deploy.js +3 -3
- package/dist-esm/src/node/deploy.js.map +1 -1
- package/dist-esm/src/node/getStorageSasUrl.js +5 -5
- package/dist-esm/src/node/getStorageSasUrl.js.map +1 -1
- package/dist-esm/src/utils.js +1 -1
- package/dist-esm/src/utils.js.map +1 -1
- package/package.json +18 -23
- package/types/latest/api-management-custom-widgets-tools.d.ts +26 -3
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ the [official Azure documentation](https://aka.ms/apimdocs/portal/customwidgets)
|
|
|
12
12
|
|
|
13
13
|
### Currently supported environments
|
|
14
14
|
|
|
15
|
-
- [LTS versions of Node.js](https://
|
|
15
|
+
- [LTS versions of Node.js](https://github.com/nodejs/release#release-schedule)
|
|
16
16
|
- Latest versions of Safari, Chrome, Edge, and Firefox
|
|
17
17
|
|
|
18
18
|
### Prerequisites
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var tslib = require('tslib');
|
|
6
4
|
var storageBlob = require('@azure/storage-blob');
|
|
7
5
|
var mime = require('mime');
|
|
@@ -10,12 +8,6 @@ var identity = require('@azure/identity');
|
|
|
10
8
|
var coreClient = require('@azure-rest/core-client');
|
|
11
9
|
var path = require('path');
|
|
12
10
|
|
|
13
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
|
-
|
|
15
|
-
var mime__default = /*#__PURE__*/_interopDefaultLegacy(mime);
|
|
16
|
-
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
17
|
-
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
18
|
-
|
|
19
11
|
// Copyright (c) Microsoft Corporation.
|
|
20
12
|
// Licensed under the MIT license.
|
|
21
13
|
/**
|
|
@@ -71,7 +63,7 @@ function getValuesPure(valuesDefault, urlSearchParams) {
|
|
|
71
63
|
const urlValues = parseWidgetData(urlSearchParams).values;
|
|
72
64
|
Object.keys(values).forEach((key) => {
|
|
73
65
|
const value = urlValues[key];
|
|
74
|
-
if (value != null
|
|
66
|
+
if (value != null)
|
|
75
67
|
values[key] = value; // if value is specified in the URL, replace the default value
|
|
76
68
|
});
|
|
77
69
|
return values;
|
|
@@ -167,6 +159,7 @@ function buildBlobConfigPath(name) {
|
|
|
167
159
|
}
|
|
168
160
|
|
|
169
161
|
// Copyright (c) Microsoft Corporation.
|
|
162
|
+
// Licensed under the MIT license.
|
|
170
163
|
/**
|
|
171
164
|
* A service wrapping ContainerClient class to simplify blob handling
|
|
172
165
|
*/
|
|
@@ -191,7 +184,7 @@ class CustomWidgetBlobService {
|
|
|
191
184
|
if (!fileName)
|
|
192
185
|
throw new Error("a fileName was not found in the absolutePath");
|
|
193
186
|
return this.containerClient.getBlockBlobClient(absolutePath).upload(content, content.length, {
|
|
194
|
-
blobHTTPHeaders: { blobContentType:
|
|
187
|
+
blobHTTPHeaders: { blobContentType: mime.getType(fileName) || "application/octet-stream" },
|
|
195
188
|
});
|
|
196
189
|
}
|
|
197
190
|
async jsonUpload(absolutePath, json) {
|
|
@@ -201,17 +194,24 @@ class CustomWidgetBlobService {
|
|
|
201
194
|
return this.containerClient.getBlockBlobClient(absolutePath).downloadToBuffer();
|
|
202
195
|
}
|
|
203
196
|
async dirDelete(absolutePath) {
|
|
204
|
-
var e_1,
|
|
197
|
+
var _a, e_1, _b, _c;
|
|
205
198
|
try {
|
|
206
|
-
for (var
|
|
207
|
-
|
|
208
|
-
|
|
199
|
+
for (var _d = true, _e = tslib.__asyncValues(await this.containerClient.listBlobsFlat({ prefix: absolutePath })), _f; _f = await _e.next(), _a = _f.done, !_a;) {
|
|
200
|
+
_c = _f.value;
|
|
201
|
+
_d = false;
|
|
202
|
+
try {
|
|
203
|
+
const blob = _c;
|
|
204
|
+
await this.containerClient.deleteBlob(blob.name);
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
_d = true;
|
|
208
|
+
}
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
212
212
|
finally {
|
|
213
213
|
try {
|
|
214
|
-
if (
|
|
214
|
+
if (!_d && !_a && (_b = _e.return)) await _b.call(_e);
|
|
215
215
|
}
|
|
216
216
|
finally { if (e_1) throw e_1.error; }
|
|
217
217
|
}
|
|
@@ -233,8 +233,9 @@ class CustomWidgetBlobService {
|
|
|
233
233
|
var CustomWidgetBlobService$1 = CustomWidgetBlobService;
|
|
234
234
|
|
|
235
235
|
// Copyright (c) Microsoft Corporation.
|
|
236
|
-
|
|
237
|
-
|
|
236
|
+
// Licensed under the MIT license.
|
|
237
|
+
async function getAccessToken(managementApiEndpoint, options) {
|
|
238
|
+
const credentials = new identity.InteractiveBrowserCredential(options);
|
|
238
239
|
const scope = `${managementApiEndpoint}/user_impersonation`;
|
|
239
240
|
const { token } = await credentials.getToken(scope);
|
|
240
241
|
return `Bearer ${token}`;
|
|
@@ -244,7 +245,7 @@ async function getAccessToken(managementApiEndpoint) {
|
|
|
244
245
|
*
|
|
245
246
|
* @returns storage SAS URL
|
|
246
247
|
*/
|
|
247
|
-
async function getStorageSasUrl({ managementApiEndpoint, resourceId, apiVersion = "2019-01-01", tokenOverride, }) {
|
|
248
|
+
async function getStorageSasUrl({ managementApiEndpoint, resourceId, apiVersion = "2019-01-01", tokenOverride, }, interactiveBrowserCredentialOptions) {
|
|
248
249
|
var _a;
|
|
249
250
|
const httpClient = coreClient.getClient(`${managementApiEndpoint}/${resourceId}`, { apiVersion });
|
|
250
251
|
const response = await httpClient
|
|
@@ -253,7 +254,7 @@ async function getStorageSasUrl({ managementApiEndpoint, resourceId, apiVersion
|
|
|
253
254
|
headers: {
|
|
254
255
|
"If-Match": "*",
|
|
255
256
|
"Content-Type": "application/json",
|
|
256
|
-
Authorization: tokenOverride !== null && tokenOverride !== void 0 ? tokenOverride : (await getAccessToken(managementApiEndpoint)),
|
|
257
|
+
Authorization: tokenOverride !== null && tokenOverride !== void 0 ? tokenOverride : (await getAccessToken(managementApiEndpoint, interactiveBrowserCredentialOptions)),
|
|
257
258
|
},
|
|
258
259
|
});
|
|
259
260
|
if (!((_a = response === null || response === void 0 ? void 0 : response.body) === null || _a === void 0 ? void 0 : _a.containerSasUrl))
|
|
@@ -262,12 +263,13 @@ async function getStorageSasUrl({ managementApiEndpoint, resourceId, apiVersion
|
|
|
262
263
|
}
|
|
263
264
|
|
|
264
265
|
// Copyright (c) Microsoft Corporation.
|
|
266
|
+
// Licensed under the MIT license.
|
|
265
267
|
function readdir(dir, root) {
|
|
266
268
|
const results = [];
|
|
267
|
-
|
|
268
|
-
const stat =
|
|
269
|
+
fs.readdirSync(root + dir).forEach((file) => {
|
|
270
|
+
const stat = fs.statSync(root + dir + path.sep + file);
|
|
269
271
|
if (stat && stat.isDirectory()) {
|
|
270
|
-
results.push(...readdir(dir + file +
|
|
272
|
+
results.push(...readdir(dir + file + path.sep, root));
|
|
271
273
|
}
|
|
272
274
|
else {
|
|
273
275
|
results.push(dir + file);
|
|
@@ -277,19 +279,20 @@ function readdir(dir, root) {
|
|
|
277
279
|
}
|
|
278
280
|
|
|
279
281
|
// Copyright (c) Microsoft Corporation.
|
|
282
|
+
// Licensed under the MIT license.
|
|
280
283
|
/**
|
|
281
284
|
* Deploys everything from /dist folder to the API Management DevPortals' blob storage.
|
|
282
285
|
*
|
|
283
286
|
* @param serviceInformation - service information for deployment
|
|
284
287
|
* @param name - name of the widget to be deployed
|
|
285
288
|
* @param fallbackConfigPath - local path to the config file (by default "./static/config.msapim.json")
|
|
286
|
-
* @param
|
|
289
|
+
* @param config - optional config object
|
|
287
290
|
*/
|
|
288
|
-
async function deploy(serviceInformation, name, fallbackConfigPath = "./static/" + APIM_CONFIG_FILE_NAME, rootLocal = "./dist/") {
|
|
291
|
+
async function deploy(serviceInformation, name, fallbackConfigPath = "./static/" + APIM_CONFIG_FILE_NAME, { rootLocal = "./dist/", interactiveBrowserCredentialOptions = { redirectUri: "http://localhost:1337" }, } = {}) {
|
|
289
292
|
console.log("\n\n");
|
|
290
293
|
console.log("Starting deploy process of custom widget: " + name);
|
|
291
294
|
console.log("Please, sign in to your Azure account when prompted\n");
|
|
292
|
-
const blobStorageUrl = await getStorageSasUrl(serviceInformation);
|
|
295
|
+
const blobStorageUrl = await getStorageSasUrl(serviceInformation, interactiveBrowserCredentialOptions);
|
|
293
296
|
const customWidgetBlobService = new CustomWidgetBlobService$1(blobStorageUrl, name);
|
|
294
297
|
let config;
|
|
295
298
|
try {
|
|
@@ -301,7 +304,7 @@ async function deploy(serviceInformation, name, fallbackConfigPath = "./static/"
|
|
|
301
304
|
}
|
|
302
305
|
if (!config) {
|
|
303
306
|
console.log("Looking for a local config file in: " + fallbackConfigPath);
|
|
304
|
-
config = JSON.parse(
|
|
307
|
+
config = JSON.parse(fs.readFileSync(fallbackConfigPath).toString());
|
|
305
308
|
}
|
|
306
309
|
if (!config) {
|
|
307
310
|
throw new Error("Config file could not be loaded.");
|
|
@@ -312,7 +315,7 @@ async function deploy(serviceInformation, name, fallbackConfigPath = "./static/"
|
|
|
312
315
|
await customWidgetBlobService.cleanDataDir();
|
|
313
316
|
const promises = [];
|
|
314
317
|
files.forEach((file) => {
|
|
315
|
-
const content =
|
|
318
|
+
const content = fs.readFileSync(rootLocal + file);
|
|
316
319
|
const promise = customWidgetBlobService
|
|
317
320
|
.uploadWidgetDataFile(file, content)
|
|
318
321
|
.then(() => console.log("Uploaded file: " + file));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/utils.ts","../src/paths.ts","../src/node/CustomWidgetBlobService.ts","../src/node/getStorageSasUrl.ts","../src/node/readdir.ts","../src/node/deploy.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Key for a search param, from which editor data will be loaded from.\n */\nexport const APIM_EDITOR_DATA_KEY = \"editorData\";\n/**\n * Key for a post message object, it's used to propagate changes from editor to the DevPortal. Used to prevent interference with other applications.\n */\nexport const APIM_ON_CHANGE_MESSAGE_KEY = \"customInputValueChangedMSAPIM\";\n/**\n * Key for a post message object, it's used to request and send secrets - token and user id, from the DevPortal. Used to prevent interference with other applications.\n */\nexport const APIM_ASK_FOR_SECRETS_MESSAGE_KEY = \"askForSecretsMSAPIM\";\n\n/**\n * Base of a values obj\n */\nexport type ValuesCommon = Record<string, unknown>;\n/**\n * All possible runtime environments\n */\nexport type Environment = \"development\" | \"publishing\" | \"runtime\" | \"error\";\n\n/** Information about the widget instance received from the Dev Portal */\nexport interface PortalData {\n // /** web content's origin (URL) of your Dev Portal */\n // origin: string;\n /** current runtime environment */\n environment: Environment;\n /** ID of this particular instance of the widget */\n instanceId: string;\n}\n\n/** JSON object with all the data you'll receive from the Dev Portal */\nexport interface EditorData<Values extends ValuesCommon> extends PortalData {\n /** values you've set in the admin editor window */\n values: Partial<Values>;\n}\n\nfunction parseWidgetData<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): EditorData<Values> {\n try {\n const urlEditorParams: EditorData<Values> = JSON.parse(\n decodeURIComponent(urlSearchParams.get(APIM_EDITOR_DATA_KEY) ?? \"\")\n );\n\n // if (!(\"origin\" in urlEditorParams)) {\n // console.error(\n // \"Could not get 'origin' from the search params of the URL:\\n\" + self.location.href\n // );\n // }\n return urlEditorParams;\n } catch (e) {\n console.error(\n `Could not get '${APIM_EDITOR_DATA_KEY}' from the search params of the URL:\\n` +\n self.location,\n e\n );\n return { values: {}, environment: \"error\", instanceId: \"error\" };\n }\n}\n\nexport function getWidgetDataPure<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): EditorData<Values> {\n return parseWidgetData<Values>(urlSearchParams);\n}\n\n/**\n * Function to get all data related to the widget including technical values not expected to be needed in most cases.\n * Intended mostly for internal use, API might change. Consider using getValues or getEditorValues instead.\n */\nexport function getWidgetData<Values extends ValuesCommon>(): EditorData<Values> {\n return getWidgetDataPure(new URLSearchParams(self.location.search));\n}\n\nexport function getEditorValuesPure<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): Partial<Values> {\n return getWidgetDataPure<Values>(urlSearchParams).values;\n}\n\n/**\n * Function to get values you've set in the admin editor window.\n */\nexport function getEditorValues<Values extends ValuesCommon>(): Partial<Values> {\n return getEditorValuesPure<Values>(new URLSearchParams(self.location.search));\n}\n\nexport function getValuesPure<Values extends ValuesCommon>(\n valuesDefault: Values,\n urlSearchParams: URLSearchParams\n): Values {\n const values = { ...valuesDefault }; // set Obj to contain all possible values and prefill default value\n const urlValues = parseWidgetData<Values>(urlSearchParams).values;\n\n Object.keys(values).forEach((key: keyof Values) => {\n const value = urlValues[key];\n if (value != null && value !== \"\") values[key] = value as Values[typeof key]; // if value is specified in the URL, replace the default value\n });\n return values;\n}\n\n/**\n * Function to get values you've set in the admin editor window. Undefined/empty values are replaced with default values.\n *\n * @param valuesDefault - object with your default values to use, just import valuesDefault object from values.ts folder\n */\nexport function getValues<Values extends ValuesCommon>(valuesDefault: Values): Values {\n return getValuesPure(valuesDefault, new URLSearchParams(self.location.search));\n}\n\n/**\n * Type of the onChange function.\n */\nexport type OnChange<Values extends ValuesCommon> = (values: Partial<Values>) => void;\n\n/**\n * The onChange function itself with 'origin' provided as a param.\n *\n * @param origin - web content's origin (URL) of your Dev Portal to send changes to\n * @param instanceId - ID of this particular instance of the widget\n * @param values - values that changed\n */\nexport function onChangeWithOrigin<Values extends ValuesCommon>(\n origin: string,\n instanceId: string,\n values: Values\n): void {\n Object.entries(values).forEach(([key, value]) => {\n self.parent.postMessage({ [APIM_ON_CHANGE_MESSAGE_KEY]: { key, value, instanceId } }, origin);\n });\n}\n\n/**\n * Build onChange function, which you can use, to send changed data from the editor.\n */\nexport function buildOnChange<Values extends ValuesCommon>(): OnChange<Values> {\n const { instanceId } = getWidgetData();\n return (values: Partial<Values>) => onChangeWithOrigin(\"*\", instanceId, values);\n}\n\n/**\n * Possible target modules\n * \"app\" for main application which is embedded in your Dev Portal\n * \"editor\" for form in admin panel\n */\nexport type TargetModule = \"app\" | \"editor\";\n/**\n * Secrets needed for communication with Dev Portal back-end\n */\nexport type Secrets = {\n managementApiUrl: string;\n apiVersion: string;\n userId?: string;\n token?: string;\n};\n\n/**\n * Request secrets - token & userId, from the Dev portal parent window.\n *\n * @param targetModule - is the function invoke from the main \"app\" window or the admin \"editor\"?\n */\nexport async function askForSecrets(targetModule: TargetModule): Promise<Secrets> {\n let receiveSecrets: (e: MessageEvent) => void;\n\n const promise = new Promise<Secrets>((resolve, reject) => {\n const { instanceId, environment }: PortalData = getWidgetData();\n\n receiveSecrets = ({ data }) => {\n if (!(APIM_ASK_FOR_SECRETS_MESSAGE_KEY in data)) return;\n\n const secrets = data[APIM_ASK_FOR_SECRETS_MESSAGE_KEY];\n if (typeof secrets !== \"object\" || !(\"managementApiUrl\" in secrets)) {\n reject(\"Secrets send by Dev Portal are invalid\");\n }\n\n resolve(secrets);\n };\n\n self.addEventListener(\"message\", receiveSecrets);\n\n const message = {\n [APIM_ASK_FOR_SECRETS_MESSAGE_KEY]: {\n instanceId,\n origin: self.location.origin,\n targetModule,\n },\n };\n\n if (targetModule === \"app\" && environment === \"development\") {\n self.parent.parent.postMessage(message, \"*\");\n } else {\n self.parent.postMessage(message, \"*\");\n }\n });\n\n return promise.finally(() => self.removeEventListener(\"message\", receiveSecrets));\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/** root of the blob storage folder */\nexport const BLOB_ROOT = \"custom-widgets\";\n/** name of the blob storage folder with widget implementation */\nexport const BLOB_DATA_FOLDER = \"data\";\n/** name of the blob storage folder with widget configs */\nexport const BLOB_CONFIGS_FOLDER = \"configs\";\n/** name of the configuration file */\nexport const APIM_CONFIG_FILE_NAME = \"config.msapim.json\";\n\n/**\n * Generate relative path for widgets' data on the blob storage\n *\n * @param name - name of the widget\n */\nexport function buildBlobDataPath(name: string): string {\n return `${BLOB_ROOT}/${BLOB_DATA_FOLDER}/${name}/`;\n}\n\n/**\n * Generate relative path for widgets' config on the blob storage\n *\n * @param name - name of the widget\n */\nexport function buildBlobConfigPath(name: string): string {\n return `${BLOB_ROOT}/${BLOB_CONFIGS_FOLDER}/${name}/${APIM_CONFIG_FILE_NAME}`;\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { BlobServiceClient, BlockBlobUploadResponse } from \"@azure/storage-blob\";\nimport { buildBlobConfigPath, buildBlobDataPath } from \"../paths\";\nimport mime from \"mime\";\n\nexport type Config = Record<string, unknown>;\n\n/**\n * A service wrapping ContainerClient class to simplify blob handling\n */\nexport class CustomWidgetBlobService {\n readonly containerClient;\n readonly name;\n readonly pathWidget;\n readonly pathConfig;\n\n /**\n * @param blobStorageUrl - blob storage SAS URL\n * @param name - name of the custom widget to be taken care of\n */\n constructor(blobStorageUrl: string, name: string) {\n const container = \"content\";\n const blobServiceClient = new BlobServiceClient(blobStorageUrl.replace(`/${container}`, \"\"));\n this.containerClient = blobServiceClient.getContainerClient(container);\n this.name = name;\n this.pathWidget = buildBlobDataPath(name);\n this.pathConfig = buildBlobConfigPath(name);\n }\n\n private extractFileName(path: string): string | undefined {\n return path.split(\"/\").pop();\n }\n\n async blobUpload(absolutePath: string, content: Buffer): Promise<BlockBlobUploadResponse> {\n const fileName = this.extractFileName(absolutePath);\n if (!fileName) throw new Error(\"a fileName was not found in the absolutePath\");\n return this.containerClient.getBlockBlobClient(absolutePath).upload(content, content.length, {\n blobHTTPHeaders: { blobContentType: mime.getType(fileName) || \"application/octet-stream\" },\n });\n }\n\n async jsonUpload(\n absolutePath: string,\n json: Record<string, unknown>\n ): Promise<BlockBlobUploadResponse> {\n return this.blobUpload(absolutePath, Buffer.from(JSON.stringify(json)));\n }\n\n async blobDownload(absolutePath: string): Promise<Buffer> {\n return this.containerClient.getBlockBlobClient(absolutePath).downloadToBuffer();\n }\n\n async dirDelete(absolutePath: string): Promise<void> {\n for await (const blob of await this.containerClient.listBlobsFlat({ prefix: absolutePath })) {\n await this.containerClient.deleteBlob(blob.name);\n }\n }\n\n async uploadWidgetDataFile(file: string, content: Buffer): Promise<BlockBlobUploadResponse> {\n return this.blobUpload(this.pathWidget + file, content);\n }\n\n async cleanDataDir(): Promise<void> {\n return this.dirDelete(this.pathWidget);\n }\n\n async getConfig(): Promise<Config> {\n const buffer = await this.blobDownload(this.pathConfig);\n return JSON.parse(buffer.toString());\n }\n\n async uploadConfig(config: Config): Promise<BlockBlobUploadResponse> {\n return this.jsonUpload(this.pathConfig, config);\n }\n}\n\nexport default CustomWidgetBlobService;\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { InteractiveBrowserCredential } from \"@azure/identity\";\nimport { ServiceInformation } from \"./deploy\";\nimport { getClient } from \"@azure-rest/core-client\";\n\nasync function getAccessToken(managementApiEndpoint: string): Promise<string> {\n const credentials = new InteractiveBrowserCredential();\n const scope = `${managementApiEndpoint}/user_impersonation`;\n const { token } = await credentials.getToken(scope);\n return `Bearer ${token}`;\n}\n\n/**\n * Function to get storage SAS URL.\n *\n * @returns storage SAS URL\n */\nasync function getStorageSasUrl({\n managementApiEndpoint,\n resourceId,\n apiVersion = \"2019-01-01\",\n tokenOverride,\n}: ServiceInformation): Promise<string> {\n const httpClient = getClient(`${managementApiEndpoint}/${resourceId}`, { apiVersion });\n const response = await httpClient\n .pathUnchecked(`/portalSettings/mediaContent/listSecrets?apiVersion=${apiVersion}`) // TODO\n .post({\n headers: {\n \"If-Match\": \"*\",\n \"Content-Type\": \"application/json\",\n Authorization: tokenOverride ?? (await getAccessToken(managementApiEndpoint)),\n },\n });\n\n if (!response?.body?.containerSasUrl) throw new Error(\"Could not get storage SAS URL\");\n return response.body.containerSasUrl;\n}\n\nexport default getStorageSasUrl;\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport fs from \"fs\";\nimport path from \"path\";\n\nfunction readdir(dir: string, root: string): string[] {\n const results: string[] = [];\n\n fs.readdirSync(root + dir).forEach((file) => {\n const stat = fs.statSync(root + dir + path.sep + file);\n if (stat && stat.isDirectory()) {\n results.push(...readdir(dir + file + path.sep, root));\n } else {\n results.push(dir + file);\n }\n });\n\n return results;\n}\n\nexport default readdir;\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport CustomWidgetBlobService, { Config } from \"./CustomWidgetBlobService\";\nimport { APIM_CONFIG_FILE_NAME } from \"../paths\";\nimport fs from \"fs\";\nimport getStorageSasUrl from \"./getStorageSasUrl\";\nimport readdir from \"./readdir\";\n\n/**\n * resourceId - resource ID of API Management service \"subscriptions/[subscription-id]/resourceGroups/[resource-group-name]/providers/Microsoft.ApiManagement/service/[service-name]\"\n * managementApiEndpoint - URL with protocol (e.g. https://management.azure.com)\n * apiVersion - optional to override default (e.g. \"2019-01-01\")\n * tokenOverride - optional, provides token to use for auth, instead of 'az login' approach\n */\nexport type ServiceInformation = {\n resourceId: string;\n managementApiEndpoint: string;\n apiVersion?: string;\n tokenOverride?: string;\n};\n\n/**\n * Deploys everything from /dist folder to the API Management DevPortals' blob storage.\n *\n * @param serviceInformation - service information for deployment\n * @param name - name of the widget to be deployed\n * @param fallbackConfigPath - local path to the config file (by default \"./static/config.msapim.json\")\n * @param rootLocal - optional, root of the local folder with compiled project to be exported (by default \"./dist\")\n */\nasync function deploy(\n serviceInformation: ServiceInformation,\n name: string,\n fallbackConfigPath = \"./static/\" + APIM_CONFIG_FILE_NAME,\n rootLocal: string = \"./dist/\"\n): Promise<void> {\n console.log(\"\\n\\n\");\n console.log(\"Starting deploy process of custom widget: \" + name);\n console.log(\"Please, sign in to your Azure account when prompted\\n\");\n\n const blobStorageUrl = await getStorageSasUrl(serviceInformation);\n const customWidgetBlobService = new CustomWidgetBlobService(blobStorageUrl, name);\n\n let config: Config | undefined;\n try {\n console.log(\"Looking for config file in the Azure blob storage\");\n config = await customWidgetBlobService.getConfig();\n } catch (e) {\n console.log(\"Config not found.\");\n }\n if (!config) {\n console.log(\"Looking for a local config file in: \" + fallbackConfigPath);\n config = JSON.parse(fs.readFileSync(fallbackConfigPath).toString());\n }\n if (!config) {\n throw new Error(\"Config file could not be loaded.\");\n }\n\n console.log(\"Config file loaded\\n\");\n\n const files = readdir(\"\", rootLocal);\n\n console.log(\"Starting upload of data files from the '\" + rootLocal + \"' folder\\n\");\n\n await customWidgetBlobService.cleanDataDir();\n\n const promises: Promise<void>[] = [];\n files.forEach((file) => {\n const content = fs.readFileSync(rootLocal + file);\n const promise = customWidgetBlobService\n .uploadWidgetDataFile(file, content)\n .then(() => console.log(\"Uploaded file: \" + file));\n promises.push(promise);\n });\n await Promise.all(promises);\n\n console.log(files.length + \" files has been uploaded\\n\");\n\n config.deployedOn = new Date();\n await customWidgetBlobService.uploadConfig(config);\n console.log(\"Uploaded updated config\");\n}\n\nexport default deploy;\n"],"names":["BlobServiceClient","mime","__asyncValues","InteractiveBrowserCredential","getClient","fs","path","CustomWidgetBlobService"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/utils.ts","../src/paths.ts","../src/node/CustomWidgetBlobService.ts","../src/node/getStorageSasUrl.ts","../src/node/readdir.ts","../src/node/deploy.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Key for a search param, from which editor data will be loaded from.\n */\nexport const APIM_EDITOR_DATA_KEY = \"editorData\";\n/**\n * Key for a post message object, it's used to propagate changes from editor to the DevPortal. Used to prevent interference with other applications.\n */\nexport const APIM_ON_CHANGE_MESSAGE_KEY = \"customInputValueChangedMSAPIM\";\n/**\n * Key for a post message object, it's used to request and send secrets - token and user id, from the DevPortal. Used to prevent interference with other applications.\n */\nexport const APIM_ASK_FOR_SECRETS_MESSAGE_KEY = \"askForSecretsMSAPIM\";\n\n/**\n * Base of a values obj\n */\nexport type ValuesCommon = Record<string, unknown>;\n/**\n * All possible runtime environments\n */\nexport type Environment = \"development\" | \"publishing\" | \"runtime\" | \"error\";\n\n/** Information about the widget instance received from the Dev Portal */\nexport interface PortalData {\n // /** web content's origin (URL) of your Dev Portal */\n // origin: string;\n /** current runtime environment */\n environment: Environment;\n /** ID of this particular instance of the widget */\n instanceId: string;\n}\n\n/** JSON object with all the data you'll receive from the Dev Portal */\nexport interface EditorData<Values extends ValuesCommon> extends PortalData {\n /** values you've set in the admin editor window */\n values: Partial<Values>;\n}\n\nfunction parseWidgetData<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): EditorData<Values> {\n try {\n const urlEditorParams: EditorData<Values> = JSON.parse(\n decodeURIComponent(urlSearchParams.get(APIM_EDITOR_DATA_KEY) ?? \"\")\n );\n\n // if (!(\"origin\" in urlEditorParams)) {\n // console.error(\n // \"Could not get 'origin' from the search params of the URL:\\n\" + self.location.href\n // );\n // }\n return urlEditorParams;\n } catch (e) {\n console.error(\n `Could not get '${APIM_EDITOR_DATA_KEY}' from the search params of the URL:\\n` +\n self.location,\n e\n );\n return { values: {}, environment: \"error\", instanceId: \"error\" };\n }\n}\n\nexport function getWidgetDataPure<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): EditorData<Values> {\n return parseWidgetData<Values>(urlSearchParams);\n}\n\n/**\n * Function to get all data related to the widget including technical values not expected to be needed in most cases.\n * Intended mostly for internal use, API might change. Consider using getValues or getEditorValues instead.\n */\nexport function getWidgetData<Values extends ValuesCommon>(): EditorData<Values> {\n return getWidgetDataPure(new URLSearchParams(self.location.search));\n}\n\nexport function getEditorValuesPure<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): Partial<Values> {\n return getWidgetDataPure<Values>(urlSearchParams).values;\n}\n\n/**\n * Function to get values you've set in the admin editor window.\n */\nexport function getEditorValues<Values extends ValuesCommon>(): Partial<Values> {\n return getEditorValuesPure<Values>(new URLSearchParams(self.location.search));\n}\n\nexport function getValuesPure<Values extends ValuesCommon>(\n valuesDefault: Values,\n urlSearchParams: URLSearchParams\n): Values {\n const values = { ...valuesDefault }; // set Obj to contain all possible values and prefill default value\n const urlValues = parseWidgetData<Values>(urlSearchParams).values;\n\n Object.keys(values).forEach((key: keyof Values) => {\n const value = urlValues[key];\n if (value != null) values[key] = value as Values[typeof key]; // if value is specified in the URL, replace the default value\n });\n return values;\n}\n\n/**\n * Function to get values you've set in the admin editor window. Undefined/empty values are replaced with default values.\n *\n * @param valuesDefault - object with your default values to use, just import valuesDefault object from values.ts folder\n */\nexport function getValues<Values extends ValuesCommon>(valuesDefault: Values): Values {\n return getValuesPure(valuesDefault, new URLSearchParams(self.location.search));\n}\n\n/**\n * Type of the onChange function.\n */\nexport type OnChange<Values extends ValuesCommon> = (values: Partial<Values>) => void;\n\n/**\n * The onChange function itself with 'origin' provided as a param.\n *\n * @param origin - web content's origin (URL) of your Dev Portal to send changes to\n * @param instanceId - ID of this particular instance of the widget\n * @param values - values that changed\n */\nexport function onChangeWithOrigin<Values extends ValuesCommon>(\n origin: string,\n instanceId: string,\n values: Values\n): void {\n Object.entries(values).forEach(([key, value]) => {\n self.parent.postMessage({ [APIM_ON_CHANGE_MESSAGE_KEY]: { key, value, instanceId } }, origin);\n });\n}\n\n/**\n * Build onChange function, which you can use, to send changed data from the editor.\n */\nexport function buildOnChange<Values extends ValuesCommon>(): OnChange<Values> {\n const { instanceId } = getWidgetData();\n return (values: Partial<Values>) => onChangeWithOrigin(\"*\", instanceId, values);\n}\n\n/**\n * Possible target modules\n * \"app\" for main application which is embedded in your Dev Portal\n * \"editor\" for form in admin panel\n */\nexport type TargetModule = \"app\" | \"editor\";\n/**\n * Secrets needed for communication with Dev Portal back-end and other runtime data\n */\nexport type Secrets = {\n managementApiUrl: string;\n apiVersion: string;\n userId?: string;\n token?: string;\n parentLocation: {\n host: string;\n hostname: string;\n href: string;\n origin: string;\n pathname: string;\n port: string;\n protocol: string;\n search: string;\n };\n};\n\n/**\n * Request secrets - token & userId, from the Dev portal parent window.\n *\n * @param targetModule - is the function invoke from the main \"app\" window or the admin \"editor\"?\n */\nexport async function askForSecrets(targetModule: TargetModule): Promise<Secrets> {\n let receiveSecrets: (e: MessageEvent) => void;\n\n const promise = new Promise<Secrets>((resolve, reject) => {\n const { instanceId, environment }: PortalData = getWidgetData();\n\n receiveSecrets = ({ data }) => {\n if (!(APIM_ASK_FOR_SECRETS_MESSAGE_KEY in data)) return;\n\n const secrets = data[APIM_ASK_FOR_SECRETS_MESSAGE_KEY];\n if (typeof secrets !== \"object\" || !(\"managementApiUrl\" in secrets)) {\n reject(\"Secrets send by Dev Portal are invalid\");\n }\n\n resolve(secrets);\n };\n\n self.addEventListener(\"message\", receiveSecrets);\n\n const message = {\n [APIM_ASK_FOR_SECRETS_MESSAGE_KEY]: {\n instanceId,\n origin: self.location.origin,\n targetModule,\n },\n };\n\n if (targetModule === \"app\" && environment === \"development\") {\n self.parent.parent.postMessage(message, \"*\");\n } else {\n self.parent.postMessage(message, \"*\");\n }\n });\n\n return promise.finally(() => self.removeEventListener(\"message\", receiveSecrets));\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/** root of the blob storage folder */\nexport const BLOB_ROOT = \"custom-widgets\";\n/** name of the blob storage folder with widget implementation */\nexport const BLOB_DATA_FOLDER = \"data\";\n/** name of the blob storage folder with widget configs */\nexport const BLOB_CONFIGS_FOLDER = \"configs\";\n/** name of the configuration file */\nexport const APIM_CONFIG_FILE_NAME = \"config.msapim.json\";\n\n/**\n * Generate relative path for widgets' data on the blob storage\n *\n * @param name - name of the widget\n */\nexport function buildBlobDataPath(name: string): string {\n return `${BLOB_ROOT}/${BLOB_DATA_FOLDER}/${name}/`;\n}\n\n/**\n * Generate relative path for widgets' config on the blob storage\n *\n * @param name - name of the widget\n */\nexport function buildBlobConfigPath(name: string): string {\n return `${BLOB_ROOT}/${BLOB_CONFIGS_FOLDER}/${name}/${APIM_CONFIG_FILE_NAME}`;\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { BlobServiceClient, BlockBlobUploadResponse } from \"@azure/storage-blob\";\nimport { buildBlobConfigPath, buildBlobDataPath } from \"../paths\";\nimport mime from \"mime\";\n\nexport type Config = Record<string, unknown>;\n\n/**\n * A service wrapping ContainerClient class to simplify blob handling\n */\nexport class CustomWidgetBlobService {\n readonly containerClient;\n readonly name;\n readonly pathWidget;\n readonly pathConfig;\n\n /**\n * @param blobStorageUrl - blob storage SAS URL\n * @param name - name of the custom widget to be taken care of\n */\n constructor(blobStorageUrl: string, name: string) {\n const container = \"content\";\n const blobServiceClient = new BlobServiceClient(blobStorageUrl.replace(`/${container}`, \"\"));\n this.containerClient = blobServiceClient.getContainerClient(container);\n this.name = name;\n this.pathWidget = buildBlobDataPath(name);\n this.pathConfig = buildBlobConfigPath(name);\n }\n\n private extractFileName(path: string): string | undefined {\n return path.split(\"/\").pop();\n }\n\n async blobUpload(absolutePath: string, content: Buffer): Promise<BlockBlobUploadResponse> {\n const fileName = this.extractFileName(absolutePath);\n if (!fileName) throw new Error(\"a fileName was not found in the absolutePath\");\n return this.containerClient.getBlockBlobClient(absolutePath).upload(content, content.length, {\n blobHTTPHeaders: { blobContentType: mime.getType(fileName) || \"application/octet-stream\" },\n });\n }\n\n async jsonUpload(\n absolutePath: string,\n json: Record<string, unknown>\n ): Promise<BlockBlobUploadResponse> {\n return this.blobUpload(absolutePath, Buffer.from(JSON.stringify(json)));\n }\n\n async blobDownload(absolutePath: string): Promise<Buffer> {\n return this.containerClient.getBlockBlobClient(absolutePath).downloadToBuffer();\n }\n\n async dirDelete(absolutePath: string): Promise<void> {\n for await (const blob of await this.containerClient.listBlobsFlat({ prefix: absolutePath })) {\n await this.containerClient.deleteBlob(blob.name);\n }\n }\n\n async uploadWidgetDataFile(file: string, content: Buffer): Promise<BlockBlobUploadResponse> {\n return this.blobUpload(this.pathWidget + file, content);\n }\n\n async cleanDataDir(): Promise<void> {\n return this.dirDelete(this.pathWidget);\n }\n\n async getConfig(): Promise<Config> {\n const buffer = await this.blobDownload(this.pathConfig);\n return JSON.parse(buffer.toString());\n }\n\n async uploadConfig(config: Config): Promise<BlockBlobUploadResponse> {\n return this.jsonUpload(this.pathConfig, config);\n }\n}\n\nexport default CustomWidgetBlobService;\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport {\n InteractiveBrowserCredential,\n InteractiveBrowserCredentialNodeOptions as IBCNOptions,\n} from \"@azure/identity\";\nimport { ServiceInformation } from \"./deploy\";\nimport { getClient } from \"@azure-rest/core-client\";\n\nasync function getAccessToken(\n managementApiEndpoint: string,\n options?: IBCNOptions\n): Promise<string> {\n const credentials = new InteractiveBrowserCredential(options);\n const scope = `${managementApiEndpoint}/user_impersonation`;\n const { token } = await credentials.getToken(scope);\n return `Bearer ${token}`;\n}\n\n/**\n * Function to get storage SAS URL.\n *\n * @returns storage SAS URL\n */\nasync function getStorageSasUrl(\n {\n managementApiEndpoint,\n resourceId,\n apiVersion = \"2019-01-01\",\n tokenOverride,\n }: ServiceInformation,\n interactiveBrowserCredentialOptions?: IBCNOptions\n): Promise<string> {\n const httpClient = getClient(`${managementApiEndpoint}/${resourceId}`, { apiVersion });\n const response = await httpClient\n .pathUnchecked(`/portalSettings/mediaContent/listSecrets?apiVersion=${apiVersion}`) // TODO\n .post({\n headers: {\n \"If-Match\": \"*\",\n \"Content-Type\": \"application/json\",\n Authorization:\n tokenOverride ??\n (await getAccessToken(managementApiEndpoint, interactiveBrowserCredentialOptions)),\n },\n });\n\n if (!response?.body?.containerSasUrl) throw new Error(\"Could not get storage SAS URL\");\n return response.body.containerSasUrl;\n}\n\nexport default getStorageSasUrl;\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport fs from \"fs\";\nimport path from \"path\";\n\nfunction readdir(dir: string, root: string): string[] {\n const results: string[] = [];\n\n fs.readdirSync(root + dir).forEach((file) => {\n const stat = fs.statSync(root + dir + path.sep + file);\n if (stat && stat.isDirectory()) {\n results.push(...readdir(dir + file + path.sep, root));\n } else {\n results.push(dir + file);\n }\n });\n\n return results;\n}\n\nexport default readdir;\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport CustomWidgetBlobService, { Config } from \"./CustomWidgetBlobService\";\nimport { InteractiveBrowserCredentialNodeOptions } from \"@azure/identity\";\nimport { APIM_CONFIG_FILE_NAME } from \"../paths\";\nimport fs from \"fs\";\nimport getStorageSasUrl from \"./getStorageSasUrl\";\nimport readdir from \"./readdir\";\n\n/**\n * resourceId - resource ID of API Management service \"subscriptions/[subscription-id]/resourceGroups/[resource-group-name]/providers/Microsoft.ApiManagement/service/[service-name]\"\n * managementApiEndpoint - URL with protocol (e.g. https://management.azure.com)\n * apiVersion - optional to override default (e.g. \"2019-01-01\")\n * tokenOverride - optional, provides token to use for auth, instead of 'az login' approach\n */\nexport type ServiceInformation = {\n resourceId: string;\n managementApiEndpoint: string;\n apiVersion?: string;\n tokenOverride?: string;\n};\n\n/**\n * Optional options object for configuring the deployment function.\n *\n * @param rootLocal - optional, root of the local folder with compiled project to be exported (by default \"./dist\")\n * @param interactiveBrowserCredentialOptions - options for InteractiveBrowserCredential for Node or InBrowser from \\@azure/identity\n */\nexport type DeployConfig = {\n rootLocal?: string;\n interactiveBrowserCredentialOptions?: InteractiveBrowserCredentialNodeOptions;\n};\n\n/**\n * Deploys everything from /dist folder to the API Management DevPortals' blob storage.\n *\n * @param serviceInformation - service information for deployment\n * @param name - name of the widget to be deployed\n * @param fallbackConfigPath - local path to the config file (by default \"./static/config.msapim.json\")\n * @param config - optional config object\n */\nasync function deploy(\n serviceInformation: ServiceInformation,\n name: string,\n fallbackConfigPath = \"./static/\" + APIM_CONFIG_FILE_NAME,\n {\n rootLocal = \"./dist/\",\n interactiveBrowserCredentialOptions = { redirectUri: \"http://localhost:1337\" },\n }: DeployConfig = {}\n): Promise<void> {\n console.log(\"\\n\\n\");\n console.log(\"Starting deploy process of custom widget: \" + name);\n console.log(\"Please, sign in to your Azure account when prompted\\n\");\n\n const blobStorageUrl = await getStorageSasUrl(\n serviceInformation,\n interactiveBrowserCredentialOptions\n );\n const customWidgetBlobService = new CustomWidgetBlobService(blobStorageUrl, name);\n\n let config: Config | undefined;\n try {\n console.log(\"Looking for config file in the Azure blob storage\");\n config = await customWidgetBlobService.getConfig();\n } catch (e) {\n console.log(\"Config not found.\");\n }\n if (!config) {\n console.log(\"Looking for a local config file in: \" + fallbackConfigPath);\n config = JSON.parse(fs.readFileSync(fallbackConfigPath).toString());\n }\n if (!config) {\n throw new Error(\"Config file could not be loaded.\");\n }\n\n console.log(\"Config file loaded\\n\");\n\n const files = readdir(\"\", rootLocal);\n\n console.log(\"Starting upload of data files from the '\" + rootLocal + \"' folder\\n\");\n\n await customWidgetBlobService.cleanDataDir();\n\n const promises: Promise<void>[] = [];\n files.forEach((file) => {\n const content = fs.readFileSync(rootLocal + file);\n const promise = customWidgetBlobService\n .uploadWidgetDataFile(file, content)\n .then(() => console.log(\"Uploaded file: \" + file));\n promises.push(promise);\n });\n await Promise.all(promises);\n\n console.log(files.length + \" files has been uploaded\\n\");\n\n config.deployedOn = new Date();\n await customWidgetBlobService.uploadConfig(config);\n console.log(\"Uploaded updated config\");\n}\n\nexport default deploy;\n"],"names":["BlobServiceClient","__asyncValues","InteractiveBrowserCredential","getClient","CustomWidgetBlobService"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AAEH,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,gCAAgC,EAChC,aAAa,EACb,eAAe,EACf,SAAS,EACT,aAAa,EACb,aAAa,EACb,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAUjB,OAAO,EACL,SAAS,EACT,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,SAAS,CAAC;AAEjB,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * @packageDocumentation https://aka.ms/apimdocs/portal/customwidgets\n */\n\nexport {\n APIM_EDITOR_DATA_KEY,\n APIM_ON_CHANGE_MESSAGE_KEY,\n APIM_ASK_FOR_SECRETS_MESSAGE_KEY,\n getWidgetData,\n getEditorValues,\n getValues,\n askForSecrets,\n buildOnChange,\n onChangeWithOrigin,\n} from \"./utils\";\nexport type {\n PortalData,\n EditorData,\n OnChange,\n Secrets,\n TargetModule,\n ValuesCommon,\n Environment,\n} from \"./utils\";\nexport {\n BLOB_ROOT,\n APIM_CONFIG_FILE_NAME,\n BLOB_DATA_FOLDER,\n BLOB_CONFIGS_FOLDER,\n buildBlobDataPath,\n buildBlobConfigPath,\n} from \"./paths\";\n\nimport deployNodeJS from \"./node/deploy\";\nexport { deployNodeJS };\nexport type { ServiceInformation } from \"./node/deploy\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AAEH,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,gCAAgC,EAChC,aAAa,EACb,eAAe,EACf,SAAS,EACT,aAAa,EACb,aAAa,EACb,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAUjB,OAAO,EACL,SAAS,EACT,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,SAAS,CAAC;AAEjB,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * @packageDocumentation https://aka.ms/apimdocs/portal/customwidgets\n */\n\nexport {\n APIM_EDITOR_DATA_KEY,\n APIM_ON_CHANGE_MESSAGE_KEY,\n APIM_ASK_FOR_SECRETS_MESSAGE_KEY,\n getWidgetData,\n getEditorValues,\n getValues,\n askForSecrets,\n buildOnChange,\n onChangeWithOrigin,\n} from \"./utils\";\nexport type {\n PortalData,\n EditorData,\n OnChange,\n Secrets,\n TargetModule,\n ValuesCommon,\n Environment,\n} from \"./utils\";\nexport {\n BLOB_ROOT,\n APIM_CONFIG_FILE_NAME,\n BLOB_DATA_FOLDER,\n BLOB_CONFIGS_FOLDER,\n buildBlobDataPath,\n buildBlobConfigPath,\n} from \"./paths\";\n\nimport deployNodeJS from \"./node/deploy\";\nexport { deployNodeJS };\nexport type { ServiceInformation, DeployConfig } from \"./node/deploy\";\n"]}
|
|
@@ -38,17 +38,24 @@ export class CustomWidgetBlobService {
|
|
|
38
38
|
return this.containerClient.getBlockBlobClient(absolutePath).downloadToBuffer();
|
|
39
39
|
}
|
|
40
40
|
async dirDelete(absolutePath) {
|
|
41
|
-
var e_1,
|
|
41
|
+
var _a, e_1, _b, _c;
|
|
42
42
|
try {
|
|
43
|
-
for (var
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
for (var _d = true, _e = __asyncValues(await this.containerClient.listBlobsFlat({ prefix: absolutePath })), _f; _f = await _e.next(), _a = _f.done, !_a;) {
|
|
44
|
+
_c = _f.value;
|
|
45
|
+
_d = false;
|
|
46
|
+
try {
|
|
47
|
+
const blob = _c;
|
|
48
|
+
await this.containerClient.deleteBlob(blob.name);
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
_d = true;
|
|
52
|
+
}
|
|
46
53
|
}
|
|
47
54
|
}
|
|
48
55
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
49
56
|
finally {
|
|
50
57
|
try {
|
|
51
|
-
if (
|
|
58
|
+
if (!_d && !_a && (_b = _e.return)) await _b.call(_e);
|
|
52
59
|
}
|
|
53
60
|
finally { if (e_1) throw e_1.error; }
|
|
54
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomWidgetBlobService.js","sourceRoot":"","sources":["../../../src/node/CustomWidgetBlobService.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;;AAElC,OAAO,EAAE,iBAAiB,EAA2B,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB;;GAEG;AACH,MAAM,OAAO,uBAAuB;IAMlC;;;OAGG;IACH,YAAY,cAAsB,EAAE,IAAY;QAC9C,MAAM,SAAS,GAAG,SAAS,CAAC;QAC5B,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7F,IAAI,CAAC,eAAe,GAAG,iBAAiB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,UAAU,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IAEO,eAAe,CAAC,IAAY;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,YAAoB,EAAE,OAAe;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC/E,OAAO,IAAI,CAAC,eAAe,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE;YAC3F,eAAe,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,0BAA0B,EAAE;SAC3F,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CACd,YAAoB,EACpB,IAA6B;QAE7B,OAAO,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,YAAoB;QACrC,OAAO,IAAI,CAAC,eAAe,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAClF,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,YAAoB;;;YAClC,KAAyB,
|
|
1
|
+
{"version":3,"file":"CustomWidgetBlobService.js","sourceRoot":"","sources":["../../../src/node/CustomWidgetBlobService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { BlobServiceClient, BlockBlobUploadResponse } from \"@azure/storage-blob\";\nimport { buildBlobConfigPath, buildBlobDataPath } from \"../paths\";\nimport mime from \"mime\";\n\nexport type Config = Record<string, unknown>;\n\n/**\n * A service wrapping ContainerClient class to simplify blob handling\n */\nexport class CustomWidgetBlobService {\n readonly containerClient;\n readonly name;\n readonly pathWidget;\n readonly pathConfig;\n\n /**\n * @param blobStorageUrl - blob storage SAS URL\n * @param name - name of the custom widget to be taken care of\n */\n constructor(blobStorageUrl: string, name: string) {\n const container = \"content\";\n const blobServiceClient = new BlobServiceClient(blobStorageUrl.replace(`/${container}`, \"\"));\n this.containerClient = blobServiceClient.getContainerClient(container);\n this.name = name;\n this.pathWidget = buildBlobDataPath(name);\n this.pathConfig = buildBlobConfigPath(name);\n }\n\n private extractFileName(path: string): string | undefined {\n return path.split(\"/\").pop();\n }\n\n async blobUpload(absolutePath: string, content: Buffer): Promise<BlockBlobUploadResponse> {\n const fileName = this.extractFileName(absolutePath);\n if (!fileName) throw new Error(\"a fileName was not found in the absolutePath\");\n return this.containerClient.getBlockBlobClient(absolutePath).upload(content, content.length, {\n blobHTTPHeaders: { blobContentType: mime.getType(fileName) || \"application/octet-stream\" },\n });\n }\n\n async jsonUpload(\n absolutePath: string,\n json: Record<string, unknown>\n ): Promise<BlockBlobUploadResponse> {\n return this.blobUpload(absolutePath, Buffer.from(JSON.stringify(json)));\n }\n\n async blobDownload(absolutePath: string): Promise<Buffer> {\n return this.containerClient.getBlockBlobClient(absolutePath).downloadToBuffer();\n }\n\n async dirDelete(absolutePath: string): Promise<void> {\n for await (const blob of await this.containerClient.listBlobsFlat({ prefix: absolutePath })) {\n await this.containerClient.deleteBlob(blob.name);\n }\n }\n\n async uploadWidgetDataFile(file: string, content: Buffer): Promise<BlockBlobUploadResponse> {\n return this.blobUpload(this.pathWidget + file, content);\n }\n\n async cleanDataDir(): Promise<void> {\n return this.dirDelete(this.pathWidget);\n }\n\n async getConfig(): Promise<Config> {\n const buffer = await this.blobDownload(this.pathConfig);\n return JSON.parse(buffer.toString());\n }\n\n async uploadConfig(config: Config): Promise<BlockBlobUploadResponse> {\n return this.jsonUpload(this.pathConfig, config);\n }\n}\n\nexport default CustomWidgetBlobService;\n"]}
|
|
@@ -11,13 +11,13 @@ import readdir from "./readdir";
|
|
|
11
11
|
* @param serviceInformation - service information for deployment
|
|
12
12
|
* @param name - name of the widget to be deployed
|
|
13
13
|
* @param fallbackConfigPath - local path to the config file (by default "./static/config.msapim.json")
|
|
14
|
-
* @param
|
|
14
|
+
* @param config - optional config object
|
|
15
15
|
*/
|
|
16
|
-
async function deploy(serviceInformation, name, fallbackConfigPath = "./static/" + APIM_CONFIG_FILE_NAME, rootLocal = "./dist/") {
|
|
16
|
+
async function deploy(serviceInformation, name, fallbackConfigPath = "./static/" + APIM_CONFIG_FILE_NAME, { rootLocal = "./dist/", interactiveBrowserCredentialOptions = { redirectUri: "http://localhost:1337" }, } = {}) {
|
|
17
17
|
console.log("\n\n");
|
|
18
18
|
console.log("Starting deploy process of custom widget: " + name);
|
|
19
19
|
console.log("Please, sign in to your Azure account when prompted\n");
|
|
20
|
-
const blobStorageUrl = await getStorageSasUrl(serviceInformation);
|
|
20
|
+
const blobStorageUrl = await getStorageSasUrl(serviceInformation, interactiveBrowserCredentialOptions);
|
|
21
21
|
const customWidgetBlobService = new CustomWidgetBlobService(blobStorageUrl, name);
|
|
22
22
|
let config;
|
|
23
23
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../../src/node/deploy.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,uBAAmC,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../../src/node/deploy.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,uBAAmC,MAAM,2BAA2B,CAAC;AAE5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAClD,OAAO,OAAO,MAAM,WAAW,CAAC;AA0BhC;;;;;;;GAOG;AACH,KAAK,UAAU,MAAM,CACnB,kBAAsC,EACtC,IAAY,EACZ,kBAAkB,GAAG,WAAW,GAAG,qBAAqB,EACxD,EACE,SAAS,GAAG,SAAS,EACrB,mCAAmC,GAAG,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAC9D,EAAE;IAEpB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpB,OAAO,CAAC,GAAG,CAAC,4CAA4C,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;IAErE,MAAM,cAAc,GAAG,MAAM,gBAAgB,CAC3C,kBAAkB,EAClB,mCAAmC,CACpC,CAAC;IACF,MAAM,uBAAuB,GAAG,IAAI,uBAAuB,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAElF,IAAI,MAA0B,CAAC;IAC/B,IAAI;QACF,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,MAAM,GAAG,MAAM,uBAAuB,CAAC,SAAS,EAAE,CAAC;KACpD;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;KAClC;IACD,IAAI,CAAC,MAAM,EAAE;QACX,OAAO,CAAC,GAAG,CAAC,sCAAsC,GAAG,kBAAkB,CAAC,CAAC;QACzE,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;KACrE;IACD,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;KACrD;IAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAEpC,MAAM,KAAK,GAAG,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IAErC,OAAO,CAAC,GAAG,CAAC,0CAA0C,GAAG,SAAS,GAAG,YAAY,CAAC,CAAC;IAEnF,MAAM,uBAAuB,CAAC,YAAY,EAAE,CAAC;IAE7C,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACrB,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,uBAAuB;aACpC,oBAAoB,CAAC,IAAI,EAAE,OAAO,CAAC;aACnC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC,CAAC;QACrD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,4BAA4B,CAAC,CAAC;IAEzD,MAAM,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;IAC/B,MAAM,uBAAuB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AACzC,CAAC;AAED,eAAe,MAAM,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport CustomWidgetBlobService, { Config } from \"./CustomWidgetBlobService\";\nimport { InteractiveBrowserCredentialNodeOptions } from \"@azure/identity\";\nimport { APIM_CONFIG_FILE_NAME } from \"../paths\";\nimport fs from \"fs\";\nimport getStorageSasUrl from \"./getStorageSasUrl\";\nimport readdir from \"./readdir\";\n\n/**\n * resourceId - resource ID of API Management service \"subscriptions/[subscription-id]/resourceGroups/[resource-group-name]/providers/Microsoft.ApiManagement/service/[service-name]\"\n * managementApiEndpoint - URL with protocol (e.g. https://management.azure.com)\n * apiVersion - optional to override default (e.g. \"2019-01-01\")\n * tokenOverride - optional, provides token to use for auth, instead of 'az login' approach\n */\nexport type ServiceInformation = {\n resourceId: string;\n managementApiEndpoint: string;\n apiVersion?: string;\n tokenOverride?: string;\n};\n\n/**\n * Optional options object for configuring the deployment function.\n *\n * @param rootLocal - optional, root of the local folder with compiled project to be exported (by default \"./dist\")\n * @param interactiveBrowserCredentialOptions - options for InteractiveBrowserCredential for Node or InBrowser from \\@azure/identity\n */\nexport type DeployConfig = {\n rootLocal?: string;\n interactiveBrowserCredentialOptions?: InteractiveBrowserCredentialNodeOptions;\n};\n\n/**\n * Deploys everything from /dist folder to the API Management DevPortals' blob storage.\n *\n * @param serviceInformation - service information for deployment\n * @param name - name of the widget to be deployed\n * @param fallbackConfigPath - local path to the config file (by default \"./static/config.msapim.json\")\n * @param config - optional config object\n */\nasync function deploy(\n serviceInformation: ServiceInformation,\n name: string,\n fallbackConfigPath = \"./static/\" + APIM_CONFIG_FILE_NAME,\n {\n rootLocal = \"./dist/\",\n interactiveBrowserCredentialOptions = { redirectUri: \"http://localhost:1337\" },\n }: DeployConfig = {}\n): Promise<void> {\n console.log(\"\\n\\n\");\n console.log(\"Starting deploy process of custom widget: \" + name);\n console.log(\"Please, sign in to your Azure account when prompted\\n\");\n\n const blobStorageUrl = await getStorageSasUrl(\n serviceInformation,\n interactiveBrowserCredentialOptions\n );\n const customWidgetBlobService = new CustomWidgetBlobService(blobStorageUrl, name);\n\n let config: Config | undefined;\n try {\n console.log(\"Looking for config file in the Azure blob storage\");\n config = await customWidgetBlobService.getConfig();\n } catch (e) {\n console.log(\"Config not found.\");\n }\n if (!config) {\n console.log(\"Looking for a local config file in: \" + fallbackConfigPath);\n config = JSON.parse(fs.readFileSync(fallbackConfigPath).toString());\n }\n if (!config) {\n throw new Error(\"Config file could not be loaded.\");\n }\n\n console.log(\"Config file loaded\\n\");\n\n const files = readdir(\"\", rootLocal);\n\n console.log(\"Starting upload of data files from the '\" + rootLocal + \"' folder\\n\");\n\n await customWidgetBlobService.cleanDataDir();\n\n const promises: Promise<void>[] = [];\n files.forEach((file) => {\n const content = fs.readFileSync(rootLocal + file);\n const promise = customWidgetBlobService\n .uploadWidgetDataFile(file, content)\n .then(() => console.log(\"Uploaded file: \" + file));\n promises.push(promise);\n });\n await Promise.all(promises);\n\n console.log(files.length + \" files has been uploaded\\n\");\n\n config.deployedOn = new Date();\n await customWidgetBlobService.uploadConfig(config);\n console.log(\"Uploaded updated config\");\n}\n\nexport default deploy;\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
-
import { InteractiveBrowserCredential } from "@azure/identity";
|
|
3
|
+
import { InteractiveBrowserCredential, } from "@azure/identity";
|
|
4
4
|
import { getClient } from "@azure-rest/core-client";
|
|
5
|
-
async function getAccessToken(managementApiEndpoint) {
|
|
6
|
-
const credentials = new InteractiveBrowserCredential();
|
|
5
|
+
async function getAccessToken(managementApiEndpoint, options) {
|
|
6
|
+
const credentials = new InteractiveBrowserCredential(options);
|
|
7
7
|
const scope = `${managementApiEndpoint}/user_impersonation`;
|
|
8
8
|
const { token } = await credentials.getToken(scope);
|
|
9
9
|
return `Bearer ${token}`;
|
|
@@ -13,7 +13,7 @@ async function getAccessToken(managementApiEndpoint) {
|
|
|
13
13
|
*
|
|
14
14
|
* @returns storage SAS URL
|
|
15
15
|
*/
|
|
16
|
-
async function getStorageSasUrl({ managementApiEndpoint, resourceId, apiVersion = "2019-01-01", tokenOverride, }) {
|
|
16
|
+
async function getStorageSasUrl({ managementApiEndpoint, resourceId, apiVersion = "2019-01-01", tokenOverride, }, interactiveBrowserCredentialOptions) {
|
|
17
17
|
var _a;
|
|
18
18
|
const httpClient = getClient(`${managementApiEndpoint}/${resourceId}`, { apiVersion });
|
|
19
19
|
const response = await httpClient
|
|
@@ -22,7 +22,7 @@ async function getStorageSasUrl({ managementApiEndpoint, resourceId, apiVersion
|
|
|
22
22
|
headers: {
|
|
23
23
|
"If-Match": "*",
|
|
24
24
|
"Content-Type": "application/json",
|
|
25
|
-
Authorization: tokenOverride !== null && tokenOverride !== void 0 ? tokenOverride : (await getAccessToken(managementApiEndpoint)),
|
|
25
|
+
Authorization: tokenOverride !== null && tokenOverride !== void 0 ? tokenOverride : (await getAccessToken(managementApiEndpoint, interactiveBrowserCredentialOptions)),
|
|
26
26
|
},
|
|
27
27
|
});
|
|
28
28
|
if (!((_a = response === null || response === void 0 ? void 0 : response.body) === null || _a === void 0 ? void 0 : _a.containerSasUrl))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getStorageSasUrl.js","sourceRoot":"","sources":["../../../src/node/getStorageSasUrl.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,
|
|
1
|
+
{"version":3,"file":"getStorageSasUrl.js","sourceRoot":"","sources":["../../../src/node/getStorageSasUrl.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EACL,4BAA4B,GAE7B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,KAAK,UAAU,cAAc,CAC3B,qBAA6B,EAC7B,OAAqB;IAErB,MAAM,WAAW,GAAG,IAAI,4BAA4B,CAAC,OAAO,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,GAAG,qBAAqB,qBAAqB,CAAC;IAC5D,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,OAAO,UAAU,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,gBAAgB,CAC7B,EACE,qBAAqB,EACrB,UAAU,EACV,UAAU,GAAG,YAAY,EACzB,aAAa,GACM,EACrB,mCAAiD;;IAEjD,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,qBAAqB,IAAI,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;IACvF,MAAM,QAAQ,GAAG,MAAM,UAAU;SAC9B,aAAa,CAAC,uDAAuD,UAAU,EAAE,CAAC,CAAC,OAAO;SAC1F,IAAI,CAAC;QACJ,OAAO,EAAE;YACP,UAAU,EAAE,GAAG;YACf,cAAc,EAAE,kBAAkB;YAClC,aAAa,EACX,aAAa,aAAb,aAAa,cAAb,aAAa,GACb,CAAC,MAAM,cAAc,CAAC,qBAAqB,EAAE,mCAAmC,CAAC,CAAC;SACrF;KACF,CAAC,CAAC;IAEL,IAAI,CAAC,CAAA,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,0CAAE,eAAe,CAAA;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACvF,OAAO,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC;AACvC,CAAC;AAED,eAAe,gBAAgB,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport {\n InteractiveBrowserCredential,\n InteractiveBrowserCredentialNodeOptions as IBCNOptions,\n} from \"@azure/identity\";\nimport { ServiceInformation } from \"./deploy\";\nimport { getClient } from \"@azure-rest/core-client\";\n\nasync function getAccessToken(\n managementApiEndpoint: string,\n options?: IBCNOptions\n): Promise<string> {\n const credentials = new InteractiveBrowserCredential(options);\n const scope = `${managementApiEndpoint}/user_impersonation`;\n const { token } = await credentials.getToken(scope);\n return `Bearer ${token}`;\n}\n\n/**\n * Function to get storage SAS URL.\n *\n * @returns storage SAS URL\n */\nasync function getStorageSasUrl(\n {\n managementApiEndpoint,\n resourceId,\n apiVersion = \"2019-01-01\",\n tokenOverride,\n }: ServiceInformation,\n interactiveBrowserCredentialOptions?: IBCNOptions\n): Promise<string> {\n const httpClient = getClient(`${managementApiEndpoint}/${resourceId}`, { apiVersion });\n const response = await httpClient\n .pathUnchecked(`/portalSettings/mediaContent/listSecrets?apiVersion=${apiVersion}`) // TODO\n .post({\n headers: {\n \"If-Match\": \"*\",\n \"Content-Type\": \"application/json\",\n Authorization:\n tokenOverride ??\n (await getAccessToken(managementApiEndpoint, interactiveBrowserCredentialOptions)),\n },\n });\n\n if (!response?.body?.containerSasUrl) throw new Error(\"Could not get storage SAS URL\");\n return response.body.containerSasUrl;\n}\n\nexport default getStorageSasUrl;\n"]}
|
package/dist-esm/src/utils.js
CHANGED
|
@@ -53,7 +53,7 @@ export function getValuesPure(valuesDefault, urlSearchParams) {
|
|
|
53
53
|
const urlValues = parseWidgetData(urlSearchParams).values;
|
|
54
54
|
Object.keys(values).forEach((key) => {
|
|
55
55
|
const value = urlValues[key];
|
|
56
|
-
if (value != null
|
|
56
|
+
if (value != null)
|
|
57
57
|
values[key] = value; // if value is specified in the URL, replace the default value
|
|
58
58
|
});
|
|
59
59
|
return values;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Key for a search param, from which editor data will be loaded from.\n */\nexport const APIM_EDITOR_DATA_KEY = \"editorData\";\n/**\n * Key for a post message object, it's used to propagate changes from editor to the DevPortal. Used to prevent interference with other applications.\n */\nexport const APIM_ON_CHANGE_MESSAGE_KEY = \"customInputValueChangedMSAPIM\";\n/**\n * Key for a post message object, it's used to request and send secrets - token and user id, from the DevPortal. Used to prevent interference with other applications.\n */\nexport const APIM_ASK_FOR_SECRETS_MESSAGE_KEY = \"askForSecretsMSAPIM\";\n\n/**\n * Base of a values obj\n */\nexport type ValuesCommon = Record<string, unknown>;\n/**\n * All possible runtime environments\n */\nexport type Environment = \"development\" | \"publishing\" | \"runtime\" | \"error\";\n\n/** Information about the widget instance received from the Dev Portal */\nexport interface PortalData {\n // /** web content's origin (URL) of your Dev Portal */\n // origin: string;\n /** current runtime environment */\n environment: Environment;\n /** ID of this particular instance of the widget */\n instanceId: string;\n}\n\n/** JSON object with all the data you'll receive from the Dev Portal */\nexport interface EditorData<Values extends ValuesCommon> extends PortalData {\n /** values you've set in the admin editor window */\n values: Partial<Values>;\n}\n\nfunction parseWidgetData<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): EditorData<Values> {\n try {\n const urlEditorParams: EditorData<Values> = JSON.parse(\n decodeURIComponent(urlSearchParams.get(APIM_EDITOR_DATA_KEY) ?? \"\")\n );\n\n // if (!(\"origin\" in urlEditorParams)) {\n // console.error(\n // \"Could not get 'origin' from the search params of the URL:\\n\" + self.location.href\n // );\n // }\n return urlEditorParams;\n } catch (e) {\n console.error(\n `Could not get '${APIM_EDITOR_DATA_KEY}' from the search params of the URL:\\n` +\n self.location,\n e\n );\n return { values: {}, environment: \"error\", instanceId: \"error\" };\n }\n}\n\nexport function getWidgetDataPure<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): EditorData<Values> {\n return parseWidgetData<Values>(urlSearchParams);\n}\n\n/**\n * Function to get all data related to the widget including technical values not expected to be needed in most cases.\n * Intended mostly for internal use, API might change. Consider using getValues or getEditorValues instead.\n */\nexport function getWidgetData<Values extends ValuesCommon>(): EditorData<Values> {\n return getWidgetDataPure(new URLSearchParams(self.location.search));\n}\n\nexport function getEditorValuesPure<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): Partial<Values> {\n return getWidgetDataPure<Values>(urlSearchParams).values;\n}\n\n/**\n * Function to get values you've set in the admin editor window.\n */\nexport function getEditorValues<Values extends ValuesCommon>(): Partial<Values> {\n return getEditorValuesPure<Values>(new URLSearchParams(self.location.search));\n}\n\nexport function getValuesPure<Values extends ValuesCommon>(\n valuesDefault: Values,\n urlSearchParams: URLSearchParams\n): Values {\n const values = { ...valuesDefault }; // set Obj to contain all possible values and prefill default value\n const urlValues = parseWidgetData<Values>(urlSearchParams).values;\n\n Object.keys(values).forEach((key: keyof Values) => {\n const value = urlValues[key];\n if (value != null && value !== \"\") values[key] = value as Values[typeof key]; // if value is specified in the URL, replace the default value\n });\n return values;\n}\n\n/**\n * Function to get values you've set in the admin editor window. Undefined/empty values are replaced with default values.\n *\n * @param valuesDefault - object with your default values to use, just import valuesDefault object from values.ts folder\n */\nexport function getValues<Values extends ValuesCommon>(valuesDefault: Values): Values {\n return getValuesPure(valuesDefault, new URLSearchParams(self.location.search));\n}\n\n/**\n * Type of the onChange function.\n */\nexport type OnChange<Values extends ValuesCommon> = (values: Partial<Values>) => void;\n\n/**\n * The onChange function itself with 'origin' provided as a param.\n *\n * @param origin - web content's origin (URL) of your Dev Portal to send changes to\n * @param instanceId - ID of this particular instance of the widget\n * @param values - values that changed\n */\nexport function onChangeWithOrigin<Values extends ValuesCommon>(\n origin: string,\n instanceId: string,\n values: Values\n): void {\n Object.entries(values).forEach(([key, value]) => {\n self.parent.postMessage({ [APIM_ON_CHANGE_MESSAGE_KEY]: { key, value, instanceId } }, origin);\n });\n}\n\n/**\n * Build onChange function, which you can use, to send changed data from the editor.\n */\nexport function buildOnChange<Values extends ValuesCommon>(): OnChange<Values> {\n const { instanceId } = getWidgetData();\n return (values: Partial<Values>) => onChangeWithOrigin(\"*\", instanceId, values);\n}\n\n/**\n * Possible target modules\n * \"app\" for main application which is embedded in your Dev Portal\n * \"editor\" for form in admin panel\n */\nexport type TargetModule = \"app\" | \"editor\";\n/**\n * Secrets needed for communication with Dev Portal back-end\n */\nexport type Secrets = {\n managementApiUrl: string;\n apiVersion: string;\n userId?: string;\n token?: string;\n};\n\n/**\n * Request secrets - token & userId, from the Dev portal parent window.\n *\n * @param targetModule - is the function invoke from the main \"app\" window or the admin \"editor\"?\n */\nexport async function askForSecrets(targetModule: TargetModule): Promise<Secrets> {\n let receiveSecrets: (e: MessageEvent) => void;\n\n const promise = new Promise<Secrets>((resolve, reject) => {\n const { instanceId, environment }: PortalData = getWidgetData();\n\n receiveSecrets = ({ data }) => {\n if (!(APIM_ASK_FOR_SECRETS_MESSAGE_KEY in data)) return;\n\n const secrets = data[APIM_ASK_FOR_SECRETS_MESSAGE_KEY];\n if (typeof secrets !== \"object\" || !(\"managementApiUrl\" in secrets)) {\n reject(\"Secrets send by Dev Portal are invalid\");\n }\n\n resolve(secrets);\n };\n\n self.addEventListener(\"message\", receiveSecrets);\n\n const message = {\n [APIM_ASK_FOR_SECRETS_MESSAGE_KEY]: {\n instanceId,\n origin: self.location.origin,\n targetModule,\n },\n };\n\n if (targetModule === \"app\" && environment === \"development\") {\n self.parent.parent.postMessage(message, \"*\");\n } else {\n self.parent.postMessage(message, \"*\");\n }\n });\n\n return promise.finally(() => self.removeEventListener(\"message\", receiveSecrets));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Key for a search param, from which editor data will be loaded from.\n */\nexport const APIM_EDITOR_DATA_KEY = \"editorData\";\n/**\n * Key for a post message object, it's used to propagate changes from editor to the DevPortal. Used to prevent interference with other applications.\n */\nexport const APIM_ON_CHANGE_MESSAGE_KEY = \"customInputValueChangedMSAPIM\";\n/**\n * Key for a post message object, it's used to request and send secrets - token and user id, from the DevPortal. Used to prevent interference with other applications.\n */\nexport const APIM_ASK_FOR_SECRETS_MESSAGE_KEY = \"askForSecretsMSAPIM\";\n\n/**\n * Base of a values obj\n */\nexport type ValuesCommon = Record<string, unknown>;\n/**\n * All possible runtime environments\n */\nexport type Environment = \"development\" | \"publishing\" | \"runtime\" | \"error\";\n\n/** Information about the widget instance received from the Dev Portal */\nexport interface PortalData {\n // /** web content's origin (URL) of your Dev Portal */\n // origin: string;\n /** current runtime environment */\n environment: Environment;\n /** ID of this particular instance of the widget */\n instanceId: string;\n}\n\n/** JSON object with all the data you'll receive from the Dev Portal */\nexport interface EditorData<Values extends ValuesCommon> extends PortalData {\n /** values you've set in the admin editor window */\n values: Partial<Values>;\n}\n\nfunction parseWidgetData<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): EditorData<Values> {\n try {\n const urlEditorParams: EditorData<Values> = JSON.parse(\n decodeURIComponent(urlSearchParams.get(APIM_EDITOR_DATA_KEY) ?? \"\")\n );\n\n // if (!(\"origin\" in urlEditorParams)) {\n // console.error(\n // \"Could not get 'origin' from the search params of the URL:\\n\" + self.location.href\n // );\n // }\n return urlEditorParams;\n } catch (e) {\n console.error(\n `Could not get '${APIM_EDITOR_DATA_KEY}' from the search params of the URL:\\n` +\n self.location,\n e\n );\n return { values: {}, environment: \"error\", instanceId: \"error\" };\n }\n}\n\nexport function getWidgetDataPure<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): EditorData<Values> {\n return parseWidgetData<Values>(urlSearchParams);\n}\n\n/**\n * Function to get all data related to the widget including technical values not expected to be needed in most cases.\n * Intended mostly for internal use, API might change. Consider using getValues or getEditorValues instead.\n */\nexport function getWidgetData<Values extends ValuesCommon>(): EditorData<Values> {\n return getWidgetDataPure(new URLSearchParams(self.location.search));\n}\n\nexport function getEditorValuesPure<Values extends ValuesCommon>(\n urlSearchParams: URLSearchParams\n): Partial<Values> {\n return getWidgetDataPure<Values>(urlSearchParams).values;\n}\n\n/**\n * Function to get values you've set in the admin editor window.\n */\nexport function getEditorValues<Values extends ValuesCommon>(): Partial<Values> {\n return getEditorValuesPure<Values>(new URLSearchParams(self.location.search));\n}\n\nexport function getValuesPure<Values extends ValuesCommon>(\n valuesDefault: Values,\n urlSearchParams: URLSearchParams\n): Values {\n const values = { ...valuesDefault }; // set Obj to contain all possible values and prefill default value\n const urlValues = parseWidgetData<Values>(urlSearchParams).values;\n\n Object.keys(values).forEach((key: keyof Values) => {\n const value = urlValues[key];\n if (value != null) values[key] = value as Values[typeof key]; // if value is specified in the URL, replace the default value\n });\n return values;\n}\n\n/**\n * Function to get values you've set in the admin editor window. Undefined/empty values are replaced with default values.\n *\n * @param valuesDefault - object with your default values to use, just import valuesDefault object from values.ts folder\n */\nexport function getValues<Values extends ValuesCommon>(valuesDefault: Values): Values {\n return getValuesPure(valuesDefault, new URLSearchParams(self.location.search));\n}\n\n/**\n * Type of the onChange function.\n */\nexport type OnChange<Values extends ValuesCommon> = (values: Partial<Values>) => void;\n\n/**\n * The onChange function itself with 'origin' provided as a param.\n *\n * @param origin - web content's origin (URL) of your Dev Portal to send changes to\n * @param instanceId - ID of this particular instance of the widget\n * @param values - values that changed\n */\nexport function onChangeWithOrigin<Values extends ValuesCommon>(\n origin: string,\n instanceId: string,\n values: Values\n): void {\n Object.entries(values).forEach(([key, value]) => {\n self.parent.postMessage({ [APIM_ON_CHANGE_MESSAGE_KEY]: { key, value, instanceId } }, origin);\n });\n}\n\n/**\n * Build onChange function, which you can use, to send changed data from the editor.\n */\nexport function buildOnChange<Values extends ValuesCommon>(): OnChange<Values> {\n const { instanceId } = getWidgetData();\n return (values: Partial<Values>) => onChangeWithOrigin(\"*\", instanceId, values);\n}\n\n/**\n * Possible target modules\n * \"app\" for main application which is embedded in your Dev Portal\n * \"editor\" for form in admin panel\n */\nexport type TargetModule = \"app\" | \"editor\";\n/**\n * Secrets needed for communication with Dev Portal back-end and other runtime data\n */\nexport type Secrets = {\n managementApiUrl: string;\n apiVersion: string;\n userId?: string;\n token?: string;\n parentLocation: {\n host: string;\n hostname: string;\n href: string;\n origin: string;\n pathname: string;\n port: string;\n protocol: string;\n search: string;\n };\n};\n\n/**\n * Request secrets - token & userId, from the Dev portal parent window.\n *\n * @param targetModule - is the function invoke from the main \"app\" window or the admin \"editor\"?\n */\nexport async function askForSecrets(targetModule: TargetModule): Promise<Secrets> {\n let receiveSecrets: (e: MessageEvent) => void;\n\n const promise = new Promise<Secrets>((resolve, reject) => {\n const { instanceId, environment }: PortalData = getWidgetData();\n\n receiveSecrets = ({ data }) => {\n if (!(APIM_ASK_FOR_SECRETS_MESSAGE_KEY in data)) return;\n\n const secrets = data[APIM_ASK_FOR_SECRETS_MESSAGE_KEY];\n if (typeof secrets !== \"object\" || !(\"managementApiUrl\" in secrets)) {\n reject(\"Secrets send by Dev Portal are invalid\");\n }\n\n resolve(secrets);\n };\n\n self.addEventListener(\"message\", receiveSecrets);\n\n const message = {\n [APIM_ASK_FOR_SECRETS_MESSAGE_KEY]: {\n instanceId,\n origin: self.location.origin,\n targetModule,\n },\n };\n\n if (targetModule === \"app\" && environment === \"development\") {\n self.parent.parent.postMessage(message, \"*\");\n } else {\n self.parent.postMessage(message, \"*\");\n }\n });\n\n return promise.finally(() => self.removeEventListener(\"message\", receiveSecrets));\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure/api-management-custom-widgets-tools",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.2",
|
|
4
4
|
"author": "Microsoft Corporation",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"sdk-type": "client",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
|
|
14
14
|
},
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": ">=
|
|
16
|
+
"node": ">=14.0.0"
|
|
17
17
|
},
|
|
18
18
|
"keywords": [
|
|
19
19
|
"azure",
|
|
@@ -58,56 +58,51 @@
|
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@azure/dev-tool": "^1.0.0",
|
|
61
|
-
"@azure-tools/test-recorder": "^
|
|
62
|
-
"@microsoft/api-extractor": "7.
|
|
61
|
+
"@azure-tools/test-recorder": "^3.0.0",
|
|
62
|
+
"@microsoft/api-extractor": "^7.31.1",
|
|
63
63
|
"@types/chai": "^4.1.6",
|
|
64
|
-
"@types/mocha": "^
|
|
65
|
-
"@types/mime": "
|
|
66
|
-
"@types/node": "^
|
|
67
|
-
"@types/glob": "^7.1.1",
|
|
68
|
-
"@types/inquirer": "^8.2.1",
|
|
64
|
+
"@types/mocha": "^10.0.0",
|
|
65
|
+
"@types/mime": "^3.0.1",
|
|
66
|
+
"@types/node": "^14.0.0",
|
|
69
67
|
"@types/yargs": "^17.0.10",
|
|
70
68
|
"@types/yargs-parser": "^21.0.0",
|
|
71
69
|
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
|
|
72
70
|
"chai": "^4.2.0",
|
|
73
71
|
"cross-env": "^7.0.2",
|
|
74
|
-
"eslint": "^
|
|
75
|
-
"mocha": "^
|
|
72
|
+
"eslint": "^8.0.0",
|
|
73
|
+
"mocha": "^10.0.0",
|
|
76
74
|
"mocha-junit-reporter": "^2.0.0",
|
|
77
75
|
"prettier": "^2.5.1",
|
|
78
76
|
"nyc": "^15.0.0",
|
|
79
77
|
"rimraf": "^3.0.0",
|
|
80
|
-
"typescript": "~
|
|
78
|
+
"typescript": "~5.0.0",
|
|
81
79
|
"util": "^0.12.1",
|
|
82
|
-
"dotenv": "^
|
|
80
|
+
"dotenv": "^16.0.0",
|
|
83
81
|
"@azure/test-utils": "^1.0.0",
|
|
84
|
-
"@types/mustache": "4.1
|
|
85
|
-
"sinon": "^
|
|
82
|
+
"@types/mustache": "^4.2.1",
|
|
83
|
+
"sinon": "^15.0.0",
|
|
86
84
|
"karma": "^6.2.0",
|
|
87
85
|
"karma-chrome-launcher": "^3.0.0",
|
|
88
86
|
"karma-coverage": "^2.0.0",
|
|
89
|
-
"karma-edge-launcher": "^0.4.2",
|
|
90
87
|
"karma-env-preprocessor": "^0.1.1",
|
|
91
88
|
"karma-firefox-launcher": "^1.1.0",
|
|
92
|
-
"karma-ie-launcher": "^1.0.0",
|
|
93
89
|
"karma-json-preprocessor": "^0.3.3",
|
|
94
90
|
"karma-json-to-file-reporter": "^1.0.1",
|
|
95
91
|
"karma-junit-reporter": "^2.0.1",
|
|
96
92
|
"karma-mocha": "^2.0.1",
|
|
97
93
|
"karma-mocha-reporter": "^2.2.5",
|
|
98
|
-
"@types/sinon": "^
|
|
94
|
+
"@types/sinon": "^10.0.0",
|
|
95
|
+
"ts-node": "^10.0.0"
|
|
99
96
|
},
|
|
100
97
|
"dependencies": {
|
|
101
|
-
"@azure/identity": "^
|
|
98
|
+
"@azure/identity": "^3.3.0",
|
|
102
99
|
"@azure-rest/core-client": "^1.0.0-beta.10",
|
|
103
100
|
"@azure/storage-blob": "^12.9.0",
|
|
104
101
|
"mime": "^3.0.0",
|
|
105
102
|
"mustache": "^4.2.0",
|
|
106
103
|
"prettier": "^2.5.1",
|
|
107
|
-
"glob": "^7.1.2",
|
|
108
104
|
"tslib": "^2.2.0",
|
|
109
|
-
"
|
|
110
|
-
"rollup": "
|
|
111
|
-
"@rollup/plugin-node-resolve": "~13.3.0"
|
|
105
|
+
"rollup": "^2.66.1",
|
|
106
|
+
"@rollup/plugin-node-resolve": "^13.1.3"
|
|
112
107
|
}
|
|
113
108
|
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* @packageDocumentation https://aka.ms/apimdocs/portal/customwidgets
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { InteractiveBrowserCredentialNodeOptions } from '@azure/identity';
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Key for a post message object, it's used to request and send secrets - token and user id, from the DevPortal. Used to prevent interference with other applications.
|
|
7
9
|
*/
|
|
@@ -55,15 +57,26 @@ export declare function buildBlobDataPath(name: string): string;
|
|
|
55
57
|
*/
|
|
56
58
|
export declare function buildOnChange<Values extends ValuesCommon>(): OnChange<Values>;
|
|
57
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Optional options object for configuring the deployment function.
|
|
62
|
+
*
|
|
63
|
+
* @param rootLocal - optional, root of the local folder with compiled project to be exported (by default "./dist")
|
|
64
|
+
* @param interactiveBrowserCredentialOptions - options for InteractiveBrowserCredential for Node or InBrowser from \@azure/identity
|
|
65
|
+
*/
|
|
66
|
+
export declare type DeployConfig = {
|
|
67
|
+
rootLocal?: string;
|
|
68
|
+
interactiveBrowserCredentialOptions?: InteractiveBrowserCredentialNodeOptions;
|
|
69
|
+
};
|
|
70
|
+
|
|
58
71
|
/**
|
|
59
72
|
* Deploys everything from /dist folder to the API Management DevPortals' blob storage.
|
|
60
73
|
*
|
|
61
74
|
* @param serviceInformation - service information for deployment
|
|
62
75
|
* @param name - name of the widget to be deployed
|
|
63
76
|
* @param fallbackConfigPath - local path to the config file (by default "./static/config.msapim.json")
|
|
64
|
-
* @param
|
|
77
|
+
* @param config - optional config object
|
|
65
78
|
*/
|
|
66
|
-
export declare function deployNodeJS(serviceInformation: ServiceInformation, name: string, fallbackConfigPath?: string, rootLocal?:
|
|
79
|
+
export declare function deployNodeJS(serviceInformation: ServiceInformation, name: string, fallbackConfigPath?: string, { rootLocal, interactiveBrowserCredentialOptions, }?: DeployConfig): Promise<void>;
|
|
67
80
|
|
|
68
81
|
/** JSON object with all the data you'll receive from the Dev Portal */
|
|
69
82
|
export declare interface EditorData<Values extends ValuesCommon> extends PortalData {
|
|
@@ -117,13 +130,23 @@ export declare interface PortalData {
|
|
|
117
130
|
}
|
|
118
131
|
|
|
119
132
|
/**
|
|
120
|
-
* Secrets needed for communication with Dev Portal back-end
|
|
133
|
+
* Secrets needed for communication with Dev Portal back-end and other runtime data
|
|
121
134
|
*/
|
|
122
135
|
export declare type Secrets = {
|
|
123
136
|
managementApiUrl: string;
|
|
124
137
|
apiVersion: string;
|
|
125
138
|
userId?: string;
|
|
126
139
|
token?: string;
|
|
140
|
+
parentLocation: {
|
|
141
|
+
host: string;
|
|
142
|
+
hostname: string;
|
|
143
|
+
href: string;
|
|
144
|
+
origin: string;
|
|
145
|
+
pathname: string;
|
|
146
|
+
port: string;
|
|
147
|
+
protocol: string;
|
|
148
|
+
search: string;
|
|
149
|
+
};
|
|
127
150
|
};
|
|
128
151
|
|
|
129
152
|
/**
|