@azure/api-management-custom-widgets-scaffolder 1.0.0-beta.2 → 1.0.0-beta.4
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/bin/execute.js +67 -38
- package/bin/templates/_shared/deploy.js.mustache +2 -1
- package/bin/templates/react/package.json.mustache +1 -1
- package/bin/templates/react/src/providers.tsx +10 -0
- package/bin/templates/typescript/package.json.mustache +1 -1
- package/bin/templates/vue/package.json.mustache +1 -1
- package/dist/index.js +21 -16
- package/dist/index.js.map +1 -1
- package/dist-esm/src/bin/execute-configs.js +25 -1
- package/dist-esm/src/bin/execute-configs.js.map +1 -1
- package/dist-esm/src/bin/execute.js +10 -10
- package/dist-esm/src/bin/execute.js.map +1 -1
- package/dist-esm/src/generateProject.browser.js.map +1 -1
- package/dist-esm/src/generateProject.js +11 -1
- package/dist-esm/src/generateProject.js.map +1 -1
- package/dist-esm/src/getTemplates.js +6 -9
- package/dist-esm/src/getTemplates.js.map +1 -1
- package/dist-esm/src/index.js.map +1 -1
- package/dist-esm/src/scaffolding.js +2 -1
- package/dist-esm/src/scaffolding.js.map +1 -1
- package/package.json +21 -21
- package/types/latest/api-management-custom-widgets-scaffolder.d.ts +5 -0
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/bin/execute.js
CHANGED
|
@@ -12,14 +12,7 @@ var chalk = require('chalk');
|
|
|
12
12
|
var glob = require('glob');
|
|
13
13
|
var mustache = require('mustache');
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
var inquirer__default = /*#__PURE__*/_interopDefaultLegacy(inquirer);
|
|
18
|
-
var Parser__default = /*#__PURE__*/_interopDefaultLegacy(Parser);
|
|
19
|
-
var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
|
|
20
|
-
var glob__default = /*#__PURE__*/_interopDefaultLegacy(glob);
|
|
21
|
-
var mustache__default = /*#__PURE__*/_interopDefaultLegacy(mustache);
|
|
22
|
-
|
|
15
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
23
16
|
// Copyright (c) Microsoft Corporation.
|
|
24
17
|
// Licensed under the MIT license.
|
|
25
18
|
/**
|
|
@@ -34,10 +27,11 @@ const OVERRIDE_DEFAULT_PORT = 3000;
|
|
|
34
27
|
const TECHNOLOGIES = ["typescript", "react", "vue"];
|
|
35
28
|
/**
|
|
36
29
|
* Converts user defined name of a custom widget to a unique ID, which is in context of Dev Portal known as "name".
|
|
30
|
+
* Prefix "cw-" to avoid conflicts with existing widgets.
|
|
37
31
|
*
|
|
38
32
|
* @param displayName - User defined name of the custom widget.
|
|
39
33
|
*/
|
|
40
|
-
const displayNameToName = (displayName) => encodeURIComponent(displayName
|
|
34
|
+
const displayNameToName = (displayName) => encodeURIComponent(("cw-" + displayName)
|
|
41
35
|
.normalize("NFD")
|
|
42
36
|
.toLowerCase()
|
|
43
37
|
.replace(/[\u0300-\u036f]/g, "")
|
|
@@ -50,6 +44,7 @@ const displayNameToName = (displayName) => encodeURIComponent(displayName
|
|
|
50
44
|
const widgetFolderName = (name) => `azure-api-management-widget-${name}`;
|
|
51
45
|
|
|
52
46
|
// Copyright (c) Microsoft Corporation.
|
|
47
|
+
// Licensed under the MIT license.
|
|
53
48
|
const fieldIdToName = {
|
|
54
49
|
displayName: "Widget display name",
|
|
55
50
|
technology: "Technology",
|
|
@@ -58,6 +53,8 @@ const fieldIdToName = {
|
|
|
58
53
|
managementApiEndpoint: "Management API hostname",
|
|
59
54
|
apiVersion: "Management API version",
|
|
60
55
|
openUrl: "Developer portal URL",
|
|
56
|
+
configAdvancedTenantId: "Tenant ID",
|
|
57
|
+
configAdvancedRedirectUri: "Redirect URI",
|
|
61
58
|
};
|
|
62
59
|
const prefixUrlProtocol = (value) => /https?:\/\//.test(value) ? value : `https://${value}`;
|
|
63
60
|
const validateRequired = (name, msg = `The “${name}” parameter is required.`) => (input) => (input != null && input !== "") || msg;
|
|
@@ -103,8 +100,16 @@ const validateMiscConfig = {
|
|
|
103
100
|
return true;
|
|
104
101
|
return validateUrl(fieldIdToName.openUrl)(input);
|
|
105
102
|
},
|
|
103
|
+
configAdvancedTenantId: () => {
|
|
104
|
+
return true;
|
|
105
|
+
},
|
|
106
|
+
configAdvancedRedirectUri: (input) => {
|
|
107
|
+
if (!input)
|
|
108
|
+
return true;
|
|
109
|
+
return validateUrl(fieldIdToName.openUrl)(input);
|
|
110
|
+
},
|
|
106
111
|
};
|
|
107
|
-
const promptWidgetConfig = (partial) =>
|
|
112
|
+
const promptWidgetConfig = (partial) => inquirer.prompt([
|
|
108
113
|
{
|
|
109
114
|
name: "displayName",
|
|
110
115
|
type: "input",
|
|
@@ -122,7 +127,7 @@ const promptWidgetConfig = (partial) => inquirer__default["default"].prompt([
|
|
|
122
127
|
],
|
|
123
128
|
},
|
|
124
129
|
], partial);
|
|
125
|
-
const
|
|
130
|
+
const promptServiceInformation = (partial) => inquirer.prompt([
|
|
126
131
|
{
|
|
127
132
|
name: "resourceId",
|
|
128
133
|
type: "input",
|
|
@@ -150,7 +155,7 @@ const promptDeployConfig = (partial) => inquirer__default["default"].prompt([
|
|
|
150
155
|
message: fieldIdToName.apiVersion + " (optional; e.g., 2021-08-01)",
|
|
151
156
|
},
|
|
152
157
|
], partial);
|
|
153
|
-
const promptMiscConfig = (partial) =>
|
|
158
|
+
const promptMiscConfig = (partial) => inquirer.prompt([
|
|
154
159
|
{
|
|
155
160
|
name: "openUrl",
|
|
156
161
|
type: "input",
|
|
@@ -159,6 +164,20 @@ const promptMiscConfig = (partial) => inquirer__default["default"].prompt([
|
|
|
159
164
|
transformer: prefixUrlProtocol,
|
|
160
165
|
validate: validateMiscConfig.openUrl,
|
|
161
166
|
},
|
|
167
|
+
{
|
|
168
|
+
name: "configAdvancedTenantId",
|
|
169
|
+
type: "input",
|
|
170
|
+
message: fieldIdToName.configAdvancedTenantId +
|
|
171
|
+
" to be used in Azure Identity InteractiveBrowserCredential class (optional)",
|
|
172
|
+
validate: validateMiscConfig.openUrl,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: "configAdvancedRedirectUri",
|
|
176
|
+
type: "input",
|
|
177
|
+
message: fieldIdToName.configAdvancedRedirectUri +
|
|
178
|
+
" to be used in Azure Identity InteractiveBrowserCredential class (optional; default is http://localhost:1337)",
|
|
179
|
+
validate: validateMiscConfig.openUrl,
|
|
180
|
+
},
|
|
162
181
|
], partial);
|
|
163
182
|
|
|
164
183
|
class YError extends Error {
|
|
@@ -733,7 +752,7 @@ const REQUIRE_DIRECTORY_ERROR = 'loading a directory of commands is not supporte
|
|
|
733
752
|
|
|
734
753
|
let __dirname$1;
|
|
735
754
|
try {
|
|
736
|
-
__dirname$1 = url.fileURLToPath((typeof document === 'undefined' ?
|
|
755
|
+
__dirname$1 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('execute.js', document.baseURI).href)));
|
|
737
756
|
} catch (e) {
|
|
738
757
|
__dirname$1 = process.cwd();
|
|
739
758
|
}
|
|
@@ -755,7 +774,7 @@ const mainFilename = __dirname$1.substring(0, __dirname$1.lastIndexOf('node_modu
|
|
|
755
774
|
},
|
|
756
775
|
getProcessArgvBin,
|
|
757
776
|
mainFilename: mainFilename || process.cwd(),
|
|
758
|
-
Parser
|
|
777
|
+
Parser,
|
|
759
778
|
path: {
|
|
760
779
|
basename: path.basename,
|
|
761
780
|
dirname: path.dirname,
|
|
@@ -789,6 +808,7 @@ const mainFilename = __dirname$1.substring(0, __dirname$1.lastIndexOf('node_modu
|
|
|
789
808
|
});
|
|
790
809
|
|
|
791
810
|
// Copyright (c) Microsoft Corporation.
|
|
811
|
+
// Licensed under the MIT license.
|
|
792
812
|
const extractConfigFromArgs = (argv, validateConfig, red) => {
|
|
793
813
|
const configPartial = {};
|
|
794
814
|
let missing = false;
|
|
@@ -814,7 +834,7 @@ const extractConfigFromArgs = (argv, validateConfig, red) => {
|
|
|
814
834
|
return { configPartial, missing };
|
|
815
835
|
};
|
|
816
836
|
const buildGetConfig = (gray, red) => {
|
|
817
|
-
const argv =
|
|
837
|
+
const argv = Parser(hideBin(process.argv));
|
|
818
838
|
return async (promptForConfig, validateConfig) => {
|
|
819
839
|
const { configPartial, missing } = extractConfigFromArgs(argv, validateConfig, red);
|
|
820
840
|
if (missing || !Object.values(configPartial).length) {
|
|
@@ -829,23 +849,22 @@ const buildGetConfig = (gray, red) => {
|
|
|
829
849
|
};
|
|
830
850
|
|
|
831
851
|
// Copyright (c) Microsoft Corporation.
|
|
852
|
+
// Licensed under the MIT license.
|
|
832
853
|
async function getTemplates(template) {
|
|
833
854
|
const sharedFiles = await getFiles(path.join(__dirname, "templates", "_shared", "**", "**", "*.*"));
|
|
834
855
|
const templateFiles = await getFiles(path.join(__dirname, "templates", template, "**", "**", "*.*"));
|
|
835
856
|
return [...sharedFiles, ...templateFiles];
|
|
836
857
|
}
|
|
837
858
|
async function getFiles(path) {
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
resolve(matches);
|
|
844
|
-
});
|
|
845
|
-
});
|
|
859
|
+
// Starting from glob v8 `\` is only used as an escape character, and never as a path separator in glob patterns.
|
|
860
|
+
// Glob pattern paths must use forward-slashes as path separators.
|
|
861
|
+
// See https://github.com/isaacs/node-glob/blob/af57da21c7722bb6edb687ccd4ad3b99d3e7a333/changelog.md#80
|
|
862
|
+
const normalizedPath = path.replace(/\\/g, "/");
|
|
863
|
+
return glob.glob(normalizedPath, { dot: true });
|
|
846
864
|
}
|
|
847
865
|
|
|
848
866
|
// Copyright (c) Microsoft Corporation.
|
|
867
|
+
// Licensed under the MIT license.
|
|
849
868
|
const templateSuffix = ".mustache";
|
|
850
869
|
/**
|
|
851
870
|
* Generates a scaffold project of Custom widget for API Managements' Dev Portal.
|
|
@@ -855,7 +874,7 @@ const templateSuffix = ".mustache";
|
|
|
855
874
|
* @param options - JSON object with other data, which will not be stored in the DevPortal.
|
|
856
875
|
*/
|
|
857
876
|
async function generateProject(widgetConfig, deploymentConfig, options = {}) {
|
|
858
|
-
const { openUrl } = options;
|
|
877
|
+
const { openUrl, configAdvancedTenantId, configAdvancedRedirectUri } = options;
|
|
859
878
|
const openUrlParsed = openUrl ? new URL(openUrl) : null;
|
|
860
879
|
if (openUrlParsed) {
|
|
861
880
|
openUrlParsed.searchParams.append(OVERRIDE_PORT_KEY, String(OVERRIDE_DEFAULT_PORT));
|
|
@@ -865,16 +884,26 @@ async function generateProject(widgetConfig, deploymentConfig, options = {}) {
|
|
|
865
884
|
port: OVERRIDE_DEFAULT_PORT,
|
|
866
885
|
open: openUrlParsed ? openUrlParsed.toString() : true,
|
|
867
886
|
};
|
|
887
|
+
const configAdditional = {
|
|
888
|
+
interactiveBrowserCredentialOptions: { redirectUri: "http://localhost:1337" },
|
|
889
|
+
};
|
|
890
|
+
if (configAdvancedTenantId) {
|
|
891
|
+
configAdditional.interactiveBrowserCredentialOptions.tenantId = configAdvancedTenantId;
|
|
892
|
+
}
|
|
893
|
+
if (configAdvancedRedirectUri) {
|
|
894
|
+
configAdditional.interactiveBrowserCredentialOptions.redirectUri = configAdvancedRedirectUri;
|
|
895
|
+
}
|
|
868
896
|
const renderTemplate = async (file) => {
|
|
869
897
|
const isTemplate = file.endsWith(templateSuffix);
|
|
870
898
|
const encoding = file.endsWith(".ttf") ? "binary" : "utf8";
|
|
871
899
|
let fileData = await fs.promises.readFile(file, { encoding });
|
|
872
900
|
if (isTemplate) {
|
|
873
|
-
fileData =
|
|
901
|
+
fileData = mustache.render(fileData, {
|
|
874
902
|
name,
|
|
875
903
|
displayName: widgetConfig.displayName,
|
|
876
904
|
config: JSON.stringify(Object.assign(Object.assign({}, widgetConfig), { name }), null, "\t"),
|
|
877
905
|
configDeploy: JSON.stringify(deploymentConfig, null, "\t"),
|
|
906
|
+
configAdditional: JSON.stringify(configAdditional, null, "\t"),
|
|
878
907
|
serverSettings: JSON.stringify(serverSettings, null, "\t"),
|
|
879
908
|
});
|
|
880
909
|
}
|
|
@@ -899,33 +928,33 @@ async function generateProject(widgetConfig, deploymentConfig, options = {}) {
|
|
|
899
928
|
}
|
|
900
929
|
|
|
901
930
|
const log = console.log;
|
|
902
|
-
const white = (msg) => log(
|
|
903
|
-
const green = (msg) => log(
|
|
904
|
-
const red = (msg) => log(
|
|
905
|
-
const gray = (msg) => log(
|
|
931
|
+
const white = (msg) => log(chalk.white(msg));
|
|
932
|
+
const green = (msg) => log(chalk.green(msg));
|
|
933
|
+
const red = (msg) => log(chalk.red(msg));
|
|
934
|
+
const gray = (msg) => log(chalk.gray(msg));
|
|
906
935
|
async function main() {
|
|
907
936
|
green("\nThis tool generates code scaffold for custom widgets in the Azure API Management’s developer portal. Learn more at https://aka.ms/apimdocs/portal/customwidgets.\n");
|
|
908
937
|
const getConfig = buildGetConfig(gray, red);
|
|
909
938
|
white("Specify the custom widget configuration.");
|
|
910
939
|
const widgetConfig = await getConfig(promptWidgetConfig, validateWidgetConfig);
|
|
911
940
|
white("Specify the Azure API Management service configuration.");
|
|
912
|
-
const
|
|
941
|
+
const serviceInformation = await getConfig(promptServiceInformation, validateDeployConfig);
|
|
913
942
|
white("Specify other options");
|
|
914
943
|
const miscConfig = await getConfig(promptMiscConfig, validateMiscConfig);
|
|
915
|
-
if (
|
|
916
|
-
|
|
944
|
+
if (serviceInformation.resourceId[0] === "/") {
|
|
945
|
+
serviceInformation.resourceId = serviceInformation.resourceId.slice(1);
|
|
917
946
|
}
|
|
918
|
-
if (
|
|
919
|
-
|
|
947
|
+
if (serviceInformation.resourceId.slice(-1) === "/") {
|
|
948
|
+
serviceInformation.resourceId = serviceInformation.resourceId.slice(0, -1);
|
|
920
949
|
}
|
|
921
|
-
if (
|
|
922
|
-
delete
|
|
950
|
+
if (serviceInformation.apiVersion === "") {
|
|
951
|
+
delete serviceInformation.apiVersion;
|
|
923
952
|
}
|
|
924
|
-
|
|
953
|
+
serviceInformation.managementApiEndpoint = prefixUrlProtocol(serviceInformation.managementApiEndpoint);
|
|
925
954
|
miscConfig.openUrl = miscConfig.openUrl
|
|
926
955
|
? prefixUrlProtocol(miscConfig.openUrl)
|
|
927
956
|
: miscConfig.openUrl;
|
|
928
|
-
return generateProject(widgetConfig,
|
|
957
|
+
return generateProject(widgetConfig, serviceInformation, miscConfig)
|
|
929
958
|
.then(() => green("\nThe custom widget’s code scaffold has been successfully generated.\n"))
|
|
930
959
|
.catch(console.error);
|
|
931
960
|
}
|
|
@@ -3,5 +3,6 @@ const {deployNodeJS} = require("@azure/api-management-custom-widgets-tools")
|
|
|
3
3
|
const serviceInformation = {{&configDeploy}}
|
|
4
4
|
const name = "{{name}}"
|
|
5
5
|
const fallbackConfigPath = "./static/config.msapim.json"
|
|
6
|
+
const config = {{&configAdditional}}
|
|
6
7
|
|
|
7
|
-
deployNodeJS(serviceInformation, name, fallbackConfigPath)
|
|
8
|
+
deployNodeJS(serviceInformation, name, fallbackConfigPath, config)
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"deploy": "npm run build && node deploy.js"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@azure/api-management-custom-widgets-tools": "^1.0.0-beta.
|
|
13
|
+
"@azure/api-management-custom-widgets-tools": "^1.0.0-beta.2",
|
|
14
14
|
"react": "^18.2.0",
|
|
15
15
|
"react-dom": "^18.2.0"
|
|
16
16
|
},
|
|
@@ -20,6 +20,16 @@ export const SecretsContext = React.createContext<Secrets>({
|
|
|
20
20
|
userId: "",
|
|
21
21
|
apiVersion: "",
|
|
22
22
|
managementApiUrl: "",
|
|
23
|
+
parentLocation: {
|
|
24
|
+
host: "",
|
|
25
|
+
hostname: "",
|
|
26
|
+
href: "",
|
|
27
|
+
origin: "",
|
|
28
|
+
pathname: "",
|
|
29
|
+
port: "",
|
|
30
|
+
protocol: "",
|
|
31
|
+
search: "",
|
|
32
|
+
},
|
|
23
33
|
})
|
|
24
34
|
export const SecretsProvider: React.FC<{children?: React.ReactNode; targetModule: TargetModule}> = (
|
|
25
35
|
{children, targetModule},
|
package/dist/index.js
CHANGED
|
@@ -7,11 +7,6 @@ var fs = require('fs');
|
|
|
7
7
|
var glob = require('glob');
|
|
8
8
|
var mustache = require('mustache');
|
|
9
9
|
|
|
10
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
11
|
-
|
|
12
|
-
var glob__default = /*#__PURE__*/_interopDefaultLegacy(glob);
|
|
13
|
-
var mustache__default = /*#__PURE__*/_interopDefaultLegacy(mustache);
|
|
14
|
-
|
|
15
10
|
// Copyright (c) Microsoft Corporation.
|
|
16
11
|
// Licensed under the MIT license.
|
|
17
12
|
/**
|
|
@@ -26,10 +21,11 @@ const OVERRIDE_DEFAULT_PORT = 3000;
|
|
|
26
21
|
const TECHNOLOGIES = ["typescript", "react", "vue"];
|
|
27
22
|
/**
|
|
28
23
|
* Converts user defined name of a custom widget to a unique ID, which is in context of Dev Portal known as "name".
|
|
24
|
+
* Prefix "cw-" to avoid conflicts with existing widgets.
|
|
29
25
|
*
|
|
30
26
|
* @param displayName - User defined name of the custom widget.
|
|
31
27
|
*/
|
|
32
|
-
const displayNameToName = (displayName) => encodeURIComponent(displayName
|
|
28
|
+
const displayNameToName = (displayName) => encodeURIComponent(("cw-" + displayName)
|
|
33
29
|
.normalize("NFD")
|
|
34
30
|
.toLowerCase()
|
|
35
31
|
.replace(/[\u0300-\u036f]/g, "")
|
|
@@ -42,23 +38,22 @@ const displayNameToName = (displayName) => encodeURIComponent(displayName
|
|
|
42
38
|
const widgetFolderName = (name) => `azure-api-management-widget-${name}`;
|
|
43
39
|
|
|
44
40
|
// Copyright (c) Microsoft Corporation.
|
|
41
|
+
// Licensed under the MIT license.
|
|
45
42
|
async function getTemplates(template) {
|
|
46
43
|
const sharedFiles = await getFiles(path.join(__dirname, "templates", "_shared", "**", "**", "*.*"));
|
|
47
44
|
const templateFiles = await getFiles(path.join(__dirname, "templates", template, "**", "**", "*.*"));
|
|
48
45
|
return [...sharedFiles, ...templateFiles];
|
|
49
46
|
}
|
|
50
47
|
async function getFiles(path) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
resolve(matches);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
48
|
+
// Starting from glob v8 `\` is only used as an escape character, and never as a path separator in glob patterns.
|
|
49
|
+
// Glob pattern paths must use forward-slashes as path separators.
|
|
50
|
+
// See https://github.com/isaacs/node-glob/blob/af57da21c7722bb6edb687ccd4ad3b99d3e7a333/changelog.md#80
|
|
51
|
+
const normalizedPath = path.replace(/\\/g, "/");
|
|
52
|
+
return glob.glob(normalizedPath, { dot: true });
|
|
59
53
|
}
|
|
60
54
|
|
|
61
55
|
// Copyright (c) Microsoft Corporation.
|
|
56
|
+
// Licensed under the MIT license.
|
|
62
57
|
const templateSuffix = ".mustache";
|
|
63
58
|
/**
|
|
64
59
|
* Generates a scaffold project of Custom widget for API Managements' Dev Portal.
|
|
@@ -68,7 +63,7 @@ const templateSuffix = ".mustache";
|
|
|
68
63
|
* @param options - JSON object with other data, which will not be stored in the DevPortal.
|
|
69
64
|
*/
|
|
70
65
|
async function generateProject(widgetConfig, deploymentConfig, options = {}) {
|
|
71
|
-
const { openUrl } = options;
|
|
66
|
+
const { openUrl, configAdvancedTenantId, configAdvancedRedirectUri } = options;
|
|
72
67
|
const openUrlParsed = openUrl ? new URL(openUrl) : null;
|
|
73
68
|
if (openUrlParsed) {
|
|
74
69
|
openUrlParsed.searchParams.append(OVERRIDE_PORT_KEY, String(OVERRIDE_DEFAULT_PORT));
|
|
@@ -78,16 +73,26 @@ async function generateProject(widgetConfig, deploymentConfig, options = {}) {
|
|
|
78
73
|
port: OVERRIDE_DEFAULT_PORT,
|
|
79
74
|
open: openUrlParsed ? openUrlParsed.toString() : true,
|
|
80
75
|
};
|
|
76
|
+
const configAdditional = {
|
|
77
|
+
interactiveBrowserCredentialOptions: { redirectUri: "http://localhost:1337" },
|
|
78
|
+
};
|
|
79
|
+
if (configAdvancedTenantId) {
|
|
80
|
+
configAdditional.interactiveBrowserCredentialOptions.tenantId = configAdvancedTenantId;
|
|
81
|
+
}
|
|
82
|
+
if (configAdvancedRedirectUri) {
|
|
83
|
+
configAdditional.interactiveBrowserCredentialOptions.redirectUri = configAdvancedRedirectUri;
|
|
84
|
+
}
|
|
81
85
|
const renderTemplate = async (file) => {
|
|
82
86
|
const isTemplate = file.endsWith(templateSuffix);
|
|
83
87
|
const encoding = file.endsWith(".ttf") ? "binary" : "utf8";
|
|
84
88
|
let fileData = await fs.promises.readFile(file, { encoding });
|
|
85
89
|
if (isTemplate) {
|
|
86
|
-
fileData =
|
|
90
|
+
fileData = mustache.render(fileData, {
|
|
87
91
|
name,
|
|
88
92
|
displayName: widgetConfig.displayName,
|
|
89
93
|
config: JSON.stringify(Object.assign(Object.assign({}, widgetConfig), { name }), null, "\t"),
|
|
90
94
|
configDeploy: JSON.stringify(deploymentConfig, null, "\t"),
|
|
95
|
+
configAdditional: JSON.stringify(configAdditional, null, "\t"),
|
|
91
96
|
serverSettings: JSON.stringify(serverSettings, null, "\t"),
|
|
92
97
|
});
|
|
93
98
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/scaffolding.ts","../src/getTemplates.ts","../src/generateProject.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Unique identifier under which is specified which port to use for injecting locally hosted custom widget to a running DevPortal instance.\n */\nexport const OVERRIDE_PORT_KEY = \"MS_APIM_CW_localhost_port\";\n/**\n * Default port for running local dev server on.\n */\nexport const OVERRIDE_DEFAULT_PORT = 3000;\n\n/** All supported technologies to scaffold a widget in. */\nexport type ScaffoldTech = \"typescript\" | \"react\" | \"vue\";\n\n/** List of all supported technologies to scaffold a widget in. */\nexport const TECHNOLOGIES: ScaffoldTech[] = [\"typescript\", \"react\", \"vue\"];\n\n/** Main data which DevPortal needs for every custom widget. */\nexport interface WidgetConfig {\n /** Name of the custom widget which is displayed in DevPortal. */\n displayName: string;\n /** Technology to use to scaffold the widget. */\n technology: ScaffoldTech;\n /** Optional URL for a custom icon, which will be displayed in DevPortal widget list. */\n iconUrl?: string;\n}\n\n/** Data needed for deployment. */\nexport interface DeploymentConfig {\n /** Management API endpoint to use (e.g. management.azure.com). */\n managementApiEndpoint: string;\n /** resourceId of your APIM service, must be in this format: subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.ApiManagement/service/<service-name> */\n resourceId: string;\n /** optional override which API version to use during deployment */\n apiVersion?: string;\n}\n\n/** Miscellaneous data for scaffolding of a custom widget which will not be stored in DevPortal. */\nexport interface Options {\n /** The URL to open after development server of the widget is started (URL of your Developer Portal). If you don't want to use this feature, set it to `false`. If you want to open just the widget page, set it to `true`. */\n openUrl?: string;\n}\n\nexport type Configs = WidgetConfig | DeploymentConfig | Options;\n\n/**\n * Converts user defined name of a custom widget to a unique ID, which is in context of Dev Portal known as \"name\".\n *\n * @param displayName - User defined name of the custom widget.\n */\nexport const displayNameToName = (displayName: string): string =>\n encodeURIComponent(\n displayName\n .normalize(\"NFD\")\n .toLowerCase()\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9-]/g, \"-\")\n );\n\n/**\n * Returns name of the folder for widget project.\n *\n * @param name - name of the widget\n */\nexport const widgetFolderName = (name: string): string => `azure-api-management-widget-${name}`;\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { ScaffoldTech } from \"./scaffolding\";\nimport glob from \"glob\";\nimport { join as pathJoin } from \"path\";\n\nexport async function getTemplates(template: ScaffoldTech): Promise<string[]> {\n const sharedFiles = await getFiles(\n pathJoin(__dirname, \"templates\", \"_shared\", \"**\", \"**\", \"*.*\")\n );\n const templateFiles = await getFiles(\n pathJoin(__dirname, \"templates\", template, \"**\", \"**\", \"*.*\")\n );\n return [...sharedFiles, ...templateFiles];\n}\n\nasync function getFiles(path: string): Promise<string[]> {\n return new Promise((resolve, reject) => {\n glob(path, { dot: true }, (error, matches) => {\n if (error) {\n reject(error);\n }\n resolve(matches);\n });\n });\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport {\n DeploymentConfig,\n OVERRIDE_DEFAULT_PORT,\n OVERRIDE_PORT_KEY,\n Options,\n WidgetConfig,\n displayNameToName,\n widgetFolderName,\n} from \"./scaffolding\";\nimport { join as joinPath, parse as parsePath } from \"path\";\nimport { promises as fs } from \"fs\";\nimport { getTemplates } from \"./getTemplates\";\nimport mustache from \"mustache\";\n\nconst templateSuffix = \".mustache\";\n\n/**\n * Generates a scaffold project of Custom widget for API Managements' Dev Portal.\n *\n * @param widgetConfig - JSON object with data required by DevPortal to handle a widget integration.\n * @param deploymentConfig - JSON object with data for deployment.\n * @param options - JSON object with other data, which will not be stored in the DevPortal.\n */\nexport async function generateProject(\n widgetConfig: WidgetConfig,\n deploymentConfig: DeploymentConfig,\n options: Options = {}\n): Promise<void> {\n const { openUrl } = options;\n const openUrlParsed = openUrl ? new URL(openUrl) : null;\n if (openUrlParsed) {\n openUrlParsed.searchParams.append(OVERRIDE_PORT_KEY, String(OVERRIDE_DEFAULT_PORT));\n }\n\n const name = displayNameToName(widgetConfig.displayName);\n const serverSettings = {\n port: OVERRIDE_DEFAULT_PORT,\n open: openUrlParsed ? openUrlParsed.toString() : true,\n };\n\n const renderTemplate = async (file: string): Promise<void> => {\n const isTemplate = file.endsWith(templateSuffix);\n const encoding = file.endsWith(\".ttf\") ? \"binary\" : \"utf8\";\n let fileData = await fs.readFile(file, { encoding });\n if (isTemplate) {\n fileData = mustache.render(fileData, {\n name,\n displayName: widgetConfig.displayName,\n config: JSON.stringify({ ...widgetConfig, name }, null, \"\\t\"),\n configDeploy: JSON.stringify(deploymentConfig, null, \"\\t\"),\n serverSettings: JSON.stringify(serverSettings, null, \"\\t\"),\n });\n }\n\n let relativePath = file;\n if (__dirname.includes(\"\\\\\")) {\n relativePath = relativePath.replace(/\\//g, \"\\\\\");\n }\n relativePath = relativePath\n .replace(joinPath(__dirname, \"templates\", \"_shared\"), \"\")\n .replace(joinPath(__dirname, \"templates\", widgetConfig.technology), \"\")\n .replace(templateSuffix, \"\");\n const newFilePath = joinPath(process.cwd(), widgetFolderName(name), relativePath);\n const dir = parsePath(newFilePath).dir;\n\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(newFilePath, fileData, { encoding });\n };\n\n const templates = await getTemplates(widgetConfig.technology);\n for (const file of Object.values(templates)) {\n await renderTemplate(file);\n }\n\n return;\n}\n"],"names":["pathJoin","glob","fs","mustache","joinPath","parsePath"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/scaffolding.ts","../src/getTemplates.ts","../src/generateProject.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Unique identifier under which is specified which port to use for injecting locally hosted custom widget to a running DevPortal instance.\n */\nexport const OVERRIDE_PORT_KEY = \"MS_APIM_CW_localhost_port\";\n/**\n * Default port for running local dev server on.\n */\nexport const OVERRIDE_DEFAULT_PORT = 3000;\n\n/** All supported technologies to scaffold a widget in. */\nexport type ScaffoldTech = \"typescript\" | \"react\" | \"vue\";\n\n/** List of all supported technologies to scaffold a widget in. */\nexport const TECHNOLOGIES: ScaffoldTech[] = [\"typescript\", \"react\", \"vue\"];\n\n/** Main data which DevPortal needs for every custom widget. */\nexport interface WidgetConfig {\n /** Name of the custom widget which is displayed in DevPortal. */\n displayName: string;\n /** Technology to use to scaffold the widget. */\n technology: ScaffoldTech;\n /** Optional URL for a custom icon, which will be displayed in DevPortal widget list. */\n iconUrl?: string;\n}\n\n/** Data needed for deployment. */\nexport interface ServiceInformation {\n /** Management API endpoint to use (e.g. management.azure.com). */\n managementApiEndpoint: string;\n /** resourceId of your APIM service, must be in this format: subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.ApiManagement/service/<service-name> */\n resourceId: string;\n /** optional override which API version to use during deployment */\n apiVersion?: string;\n}\n\n/** Miscellaneous data for scaffolding of a custom widget which will not be stored in DevPortal. */\nexport interface Options {\n /** The URL to open after development server of the widget is started (URL of your Developer Portal). If you don't want to use this feature, set it to `false`. If you want to open just the widget page, set it to `true`. */\n openUrl?: string;\n /** advance configuration option for the deploy function - tenant ID for InteractiveBrowserCredentialNodeOptions */\n configAdvancedTenantId?: string;\n /** advance configuration option for the deploy function - redirect URI for InteractiveBrowserCredentialNodeOptions */\n configAdvancedRedirectUri?: string;\n}\n\nexport type Configs = WidgetConfig | ServiceInformation | Options;\n\n/**\n * Converts user defined name of a custom widget to a unique ID, which is in context of Dev Portal known as \"name\".\n * Prefix \"cw-\" to avoid conflicts with existing widgets.\n *\n * @param displayName - User defined name of the custom widget.\n */\nexport const displayNameToName = (displayName: string): string =>\n encodeURIComponent(\n (\"cw-\" + displayName)\n .normalize(\"NFD\")\n .toLowerCase()\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9-]/g, \"-\")\n );\n\n/**\n * Returns name of the folder for widget project.\n *\n * @param name - name of the widget\n */\nexport const widgetFolderName = (name: string): string => `azure-api-management-widget-${name}`;\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { ScaffoldTech } from \"./scaffolding\";\nimport { glob } from \"glob\";\nimport { join as pathJoin } from \"path\";\n\nexport async function getTemplates(template: ScaffoldTech): Promise<string[]> {\n const sharedFiles = await getFiles(\n pathJoin(__dirname, \"templates\", \"_shared\", \"**\", \"**\", \"*.*\")\n );\n const templateFiles = await getFiles(\n pathJoin(__dirname, \"templates\", template, \"**\", \"**\", \"*.*\")\n );\n return [...sharedFiles, ...templateFiles];\n}\n\nasync function getFiles(path: string): Promise<string[]> {\n // Starting from glob v8 `\\` is only used as an escape character, and never as a path separator in glob patterns.\n // Glob pattern paths must use forward-slashes as path separators.\n // See https://github.com/isaacs/node-glob/blob/af57da21c7722bb6edb687ccd4ad3b99d3e7a333/changelog.md#80\n const normalizedPath = path.replace(/\\\\/g, \"/\");\n return glob(normalizedPath, { dot: true });\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport {\n ServiceInformation,\n OVERRIDE_DEFAULT_PORT,\n OVERRIDE_PORT_KEY,\n Options,\n WidgetConfig,\n displayNameToName,\n widgetFolderName,\n} from \"./scaffolding\";\nimport { join as joinPath, parse as parsePath } from \"path\";\nimport { promises as fs } from \"fs\";\nimport { getTemplates } from \"./getTemplates\";\nimport mustache from \"mustache\";\n\nconst templateSuffix = \".mustache\";\n\n/**\n * Generates a scaffold project of Custom widget for API Managements' Dev Portal.\n *\n * @param widgetConfig - JSON object with data required by DevPortal to handle a widget integration.\n * @param deploymentConfig - JSON object with data for deployment.\n * @param options - JSON object with other data, which will not be stored in the DevPortal.\n */\nexport async function generateProject(\n widgetConfig: WidgetConfig,\n deploymentConfig: ServiceInformation,\n options: Options = {}\n): Promise<void> {\n const { openUrl, configAdvancedTenantId, configAdvancedRedirectUri } = options;\n const openUrlParsed = openUrl ? new URL(openUrl) : null;\n if (openUrlParsed) {\n openUrlParsed.searchParams.append(OVERRIDE_PORT_KEY, String(OVERRIDE_DEFAULT_PORT));\n }\n\n const name = displayNameToName(widgetConfig.displayName);\n const serverSettings = {\n port: OVERRIDE_DEFAULT_PORT,\n open: openUrlParsed ? openUrlParsed.toString() : true,\n };\n\n const configAdditional = {\n interactiveBrowserCredentialOptions: { redirectUri: \"http://localhost:1337\" } as {\n redirectUri: string;\n tenantId?: string;\n },\n };\n if (configAdvancedTenantId) {\n configAdditional.interactiveBrowserCredentialOptions.tenantId = configAdvancedTenantId;\n }\n if (configAdvancedRedirectUri) {\n configAdditional.interactiveBrowserCredentialOptions.redirectUri = configAdvancedRedirectUri;\n }\n\n const renderTemplate = async (file: string): Promise<void> => {\n const isTemplate = file.endsWith(templateSuffix);\n const encoding = file.endsWith(\".ttf\") ? \"binary\" : \"utf8\";\n let fileData = await fs.readFile(file, { encoding });\n if (isTemplate) {\n fileData = mustache.render(fileData, {\n name,\n displayName: widgetConfig.displayName,\n config: JSON.stringify({ ...widgetConfig, name }, null, \"\\t\"),\n configDeploy: JSON.stringify(deploymentConfig, null, \"\\t\"),\n configAdditional: JSON.stringify(configAdditional, null, \"\\t\"),\n serverSettings: JSON.stringify(serverSettings, null, \"\\t\"),\n });\n }\n\n let relativePath = file;\n if (__dirname.includes(\"\\\\\")) {\n relativePath = relativePath.replace(/\\//g, \"\\\\\");\n }\n relativePath = relativePath\n .replace(joinPath(__dirname, \"templates\", \"_shared\"), \"\")\n .replace(joinPath(__dirname, \"templates\", widgetConfig.technology), \"\")\n .replace(templateSuffix, \"\");\n const newFilePath = joinPath(process.cwd(), widgetFolderName(name), relativePath);\n const dir = parsePath(newFilePath).dir;\n\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(newFilePath, fileData, { encoding });\n };\n\n const templates = await getTemplates(widgetConfig.technology);\n for (const file of Object.values(templates)) {\n await renderTemplate(file);\n }\n\n return;\n}\n"],"names":["pathJoin","glob","fs","joinPath","parsePath"],"mappings":"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"}
|
|
@@ -10,6 +10,8 @@ export const fieldIdToName = {
|
|
|
10
10
|
managementApiEndpoint: "Management API hostname",
|
|
11
11
|
apiVersion: "Management API version",
|
|
12
12
|
openUrl: "Developer portal URL",
|
|
13
|
+
configAdvancedTenantId: "Tenant ID",
|
|
14
|
+
configAdvancedRedirectUri: "Redirect URI",
|
|
13
15
|
};
|
|
14
16
|
export const prefixUrlProtocol = (value) => /https?:\/\//.test(value) ? value : `https://${value}`;
|
|
15
17
|
const validateRequired = (name, msg = `The “${name}” parameter is required.`) => (input) => (input != null && input !== "") || msg;
|
|
@@ -55,6 +57,14 @@ export const validateMiscConfig = {
|
|
|
55
57
|
return true;
|
|
56
58
|
return validateUrl(fieldIdToName.openUrl)(input);
|
|
57
59
|
},
|
|
60
|
+
configAdvancedTenantId: () => {
|
|
61
|
+
return true;
|
|
62
|
+
},
|
|
63
|
+
configAdvancedRedirectUri: (input) => {
|
|
64
|
+
if (!input)
|
|
65
|
+
return true;
|
|
66
|
+
return validateUrl(fieldIdToName.openUrl)(input);
|
|
67
|
+
},
|
|
58
68
|
};
|
|
59
69
|
export const promptWidgetConfig = (partial) => inquirer.prompt([
|
|
60
70
|
{
|
|
@@ -74,7 +84,7 @@ export const promptWidgetConfig = (partial) => inquirer.prompt([
|
|
|
74
84
|
],
|
|
75
85
|
},
|
|
76
86
|
], partial);
|
|
77
|
-
export const
|
|
87
|
+
export const promptServiceInformation = (partial) => inquirer.prompt([
|
|
78
88
|
{
|
|
79
89
|
name: "resourceId",
|
|
80
90
|
type: "input",
|
|
@@ -111,5 +121,19 @@ export const promptMiscConfig = (partial) => inquirer.prompt([
|
|
|
111
121
|
transformer: prefixUrlProtocol,
|
|
112
122
|
validate: validateMiscConfig.openUrl,
|
|
113
123
|
},
|
|
124
|
+
{
|
|
125
|
+
name: "configAdvancedTenantId",
|
|
126
|
+
type: "input",
|
|
127
|
+
message: fieldIdToName.configAdvancedTenantId +
|
|
128
|
+
" to be used in Azure Identity InteractiveBrowserCredential class (optional)",
|
|
129
|
+
validate: validateMiscConfig.openUrl,
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "configAdvancedRedirectUri",
|
|
133
|
+
type: "input",
|
|
134
|
+
message: fieldIdToName.configAdvancedRedirectUri +
|
|
135
|
+
" to be used in Azure Identity InteractiveBrowserCredential class (optional; default is http://localhost:1337)",
|
|
136
|
+
validate: validateMiscConfig.openUrl,
|
|
137
|
+
},
|
|
114
138
|
], partial);
|
|
115
139
|
//# sourceMappingURL=execute-configs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute-configs.js","sourceRoot":"","sources":["../../../src/bin/execute-configs.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { Configs, DeploymentConfig, Options, TECHNOLOGIES, WidgetConfig } from \"../scaffolding\";\n\nimport inquirer from \"inquirer\";\n\nexport const fieldIdToName: Record<\n keyof (WidgetConfig & DeploymentConfig & Options) | string,\n string\n> = {\n displayName: \"Widget display name\",\n technology: \"Technology\",\n iconUrl: \"iconUrl\",\n\n resourceId:\n \"Azure API Management resource ID (following format: subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.ApiManagement/service/<api-management service-name>)\",\n managementApiEndpoint: \"Management API hostname\",\n apiVersion: \"Management API version\",\n\n openUrl: \"Developer portal URL\",\n};\n\nexport const prefixUrlProtocol = (value: string): string =>\n /https?:\\/\\//.test(value) ? value : `https://${value}`;\n\nconst validateRequired =\n (name: string, msg: string = `The “${name}” parameter is required.`) =>\n (input: unknown) =>\n (input != null && input !== \"\") || msg;\n\nconst validateUrl =\n (\n name: string,\n msg = (input: string) =>\n `Provided “${name}” parameter value (“${prefixUrlProtocol(\n input\n )}”) isn’t a valid URL. Use the correct URL format, e.g., https://contoso.com.`\n ) =>\n (input: string) => {\n try {\n new URL(prefixUrlProtocol(input));\n return true;\n } catch (e) {\n return msg(prefixUrlProtocol(input));\n }\n };\n\nexport type ReplaceTypesPreserveOptional<T extends Record<any, any>, V> = {\n [Key in keyof T]: T[Key] extends undefined ? V | undefined : V;\n};\n\nexport type ValidateFnc = (input: string) => boolean | string;\nexport type Validate<C extends Configs> = ReplaceTypesPreserveOptional<C, ValidateFnc>;\n\nexport const validateWidgetConfig: Validate<WidgetConfig> = {\n displayName: validateRequired(fieldIdToName.displayName),\n technology: (input) => {\n const required = validateRequired(fieldIdToName.technology)(input);\n if (required !== true) return required;\n\n if (TECHNOLOGIES.includes(input as any)) {\n return true;\n } else {\n return (\n \"Provided “technology” parameter value isn’t correct. Use one of the following: \" +\n TECHNOLOGIES.join(\", \")\n );\n }\n },\n};\n\nexport const validateDeployConfig: Validate<DeploymentConfig> = {\n resourceId: (input) => {\n const required = validateRequired(fieldIdToName.resourceId)(input);\n if (required !== true) return required;\n\n const regex =\n /^\\/?subscriptions\\/[^/]+\\/resourceGroups\\/[^/]+\\/providers\\/Microsoft\\.ApiManagement\\/service\\/[^/]+\\/?$/;\n return input === \"test\" || regex.test(input)\n ? true\n : \"Resource ID needs to be a valid Azure resource ID. For example, subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/contoso-group/providers/Microsoft.ApiManagement/service/contoso-apis.\";\n },\n managementApiEndpoint: (input) => validateRequired(fieldIdToName.managementApiEndpoint)(input),\n};\n\nexport const validateMiscConfig: Validate<Options> = {\n openUrl: (input) => {\n if (!input) return true;\n return validateUrl(fieldIdToName.openUrl)(input);\n },\n};\n\nexport const promptWidgetConfig = (partial: Partial<WidgetConfig>): Promise<WidgetConfig> =>\n inquirer.prompt(\n [\n {\n name: \"displayName\",\n type: \"input\",\n message: fieldIdToName.displayName,\n validate: validateWidgetConfig.displayName,\n },\n {\n name: \"technology\",\n type: \"list\",\n message: fieldIdToName.technology,\n choices: [\n { name: \"React\", value: \"react\" },\n { name: \"Vue\", value: \"vue\" },\n { name: \"TypeScript\", value: \"typescript\" },\n ],\n },\n ],\n partial\n );\n\nexport const promptDeployConfig = (partial: Partial<DeploymentConfig>): Promise<DeploymentConfig> =>\n inquirer.prompt(\n [\n {\n name: \"resourceId\",\n type: \"input\",\n message: fieldIdToName.resourceId,\n validate: validateDeployConfig.resourceId,\n },\n {\n name: \"managementApiEndpoint\",\n type: \"list\",\n message: fieldIdToName.managementApiEndpoint,\n choices: [\n {\n name: \"management.azure.com (if you're not sure what to select, use this option)\",\n value: \"management.azure.com\",\n },\n { name: \"management.usgovcloudapi.net\", value: \"management.usgovcloudapi.net\" },\n { name: \"management.chinacloudapi.cn\", value: \"management.chinacloudapi.cn\" },\n ],\n transformer: prefixUrlProtocol,\n validate: validateDeployConfig.managementApiEndpoint,\n },\n {\n name: \"apiVersion\",\n type: \"input\",\n message: fieldIdToName.apiVersion + \" (optional; e.g., 2021-08-01)\",\n },\n ],\n partial\n );\n\nexport const promptMiscConfig = (partial: Partial<Options>): Promise<Options> =>\n inquirer.prompt(\n [\n {\n name: \"openUrl\",\n type: \"input\",\n message:\n fieldIdToName.openUrl +\n \" for widget development and testing (optional; e.g., https://contoso.developer.azure-api.net/ or http://localhost:8080)\",\n transformer: prefixUrlProtocol,\n validate: validateMiscConfig.openUrl,\n },\n ],\n partial\n );\n"]}
|
|
1
|
+
{"version":3,"file":"execute-configs.js","sourceRoot":"","sources":["../../../src/bin/execute-configs.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { Configs, ServiceInformation, Options, TECHNOLOGIES, WidgetConfig } from \"../scaffolding\";\n\nimport inquirer from \"inquirer\";\n\nexport const fieldIdToName: Record<\n keyof (WidgetConfig & ServiceInformation & Options) | string,\n string\n> = {\n displayName: \"Widget display name\",\n technology: \"Technology\",\n iconUrl: \"iconUrl\",\n\n resourceId:\n \"Azure API Management resource ID (following format: subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.ApiManagement/service/<api-management service-name>)\",\n managementApiEndpoint: \"Management API hostname\",\n apiVersion: \"Management API version\",\n\n openUrl: \"Developer portal URL\",\n configAdvancedTenantId: \"Tenant ID\",\n configAdvancedRedirectUri: \"Redirect URI\",\n};\n\nexport const prefixUrlProtocol = (value: string): string =>\n /https?:\\/\\//.test(value) ? value : `https://${value}`;\n\nconst validateRequired =\n (name: string, msg: string = `The “${name}” parameter is required.`) =>\n (input: unknown) =>\n (input != null && input !== \"\") || msg;\n\nconst validateUrl =\n (\n name: string,\n msg = (input: string) =>\n `Provided “${name}” parameter value (“${prefixUrlProtocol(\n input\n )}”) isn’t a valid URL. Use the correct URL format, e.g., https://contoso.com.`\n ) =>\n (input: string) => {\n try {\n new URL(prefixUrlProtocol(input));\n return true;\n } catch (e) {\n return msg(prefixUrlProtocol(input));\n }\n };\n\nexport type ReplaceTypesPreserveOptional<T extends Record<any, any>, V> = {\n [Key in keyof T]: T[Key] extends undefined ? V | undefined : V;\n};\n\nexport type ValidateFnc = (input: string) => boolean | string;\nexport type Validate<C extends Configs> = ReplaceTypesPreserveOptional<C, ValidateFnc>;\n\nexport const validateWidgetConfig: Validate<WidgetConfig> = {\n displayName: validateRequired(fieldIdToName.displayName),\n technology: (input) => {\n const required = validateRequired(fieldIdToName.technology)(input);\n if (required !== true) return required;\n\n if (TECHNOLOGIES.includes(input as any)) {\n return true;\n } else {\n return (\n \"Provided “technology” parameter value isn’t correct. Use one of the following: \" +\n TECHNOLOGIES.join(\", \")\n );\n }\n },\n};\n\nexport const validateDeployConfig: Validate<ServiceInformation> = {\n resourceId: (input) => {\n const required = validateRequired(fieldIdToName.resourceId)(input);\n if (required !== true) return required;\n\n const regex =\n /^\\/?subscriptions\\/[^/]+\\/resourceGroups\\/[^/]+\\/providers\\/Microsoft\\.ApiManagement\\/service\\/[^/]+\\/?$/;\n return input === \"test\" || regex.test(input)\n ? true\n : \"Resource ID needs to be a valid Azure resource ID. For example, subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/contoso-group/providers/Microsoft.ApiManagement/service/contoso-apis.\";\n },\n managementApiEndpoint: (input) => validateRequired(fieldIdToName.managementApiEndpoint)(input),\n};\n\nexport const validateMiscConfig: Validate<Options> = {\n openUrl: (input) => {\n if (!input) return true;\n return validateUrl(fieldIdToName.openUrl)(input);\n },\n configAdvancedTenantId: () => {\n return true;\n },\n configAdvancedRedirectUri: (input) => {\n if (!input) return true;\n return validateUrl(fieldIdToName.openUrl)(input);\n },\n};\n\nexport const promptWidgetConfig = (partial: Partial<WidgetConfig>): Promise<WidgetConfig> =>\n inquirer.prompt(\n [\n {\n name: \"displayName\",\n type: \"input\",\n message: fieldIdToName.displayName,\n validate: validateWidgetConfig.displayName,\n },\n {\n name: \"technology\",\n type: \"list\",\n message: fieldIdToName.technology,\n choices: [\n { name: \"React\", value: \"react\" },\n { name: \"Vue\", value: \"vue\" },\n { name: \"TypeScript\", value: \"typescript\" },\n ],\n },\n ],\n partial\n );\n\nexport const promptServiceInformation = (\n partial: Partial<ServiceInformation>\n): Promise<ServiceInformation> =>\n inquirer.prompt(\n [\n {\n name: \"resourceId\",\n type: \"input\",\n message: fieldIdToName.resourceId,\n validate: validateDeployConfig.resourceId,\n },\n {\n name: \"managementApiEndpoint\",\n type: \"list\",\n message: fieldIdToName.managementApiEndpoint,\n choices: [\n {\n name: \"management.azure.com (if you're not sure what to select, use this option)\",\n value: \"management.azure.com\",\n },\n { name: \"management.usgovcloudapi.net\", value: \"management.usgovcloudapi.net\" },\n { name: \"management.chinacloudapi.cn\", value: \"management.chinacloudapi.cn\" },\n ],\n transformer: prefixUrlProtocol,\n validate: validateDeployConfig.managementApiEndpoint,\n },\n {\n name: \"apiVersion\",\n type: \"input\",\n message: fieldIdToName.apiVersion + \" (optional; e.g., 2021-08-01)\",\n },\n ],\n partial\n );\n\nexport const promptMiscConfig = (partial: Partial<Options>): Promise<Options> =>\n inquirer.prompt(\n [\n {\n name: \"openUrl\",\n type: \"input\",\n message:\n fieldIdToName.openUrl +\n \" for widget development and testing (optional; e.g., https://contoso.developer.azure-api.net/ or http://localhost:8080)\",\n transformer: prefixUrlProtocol,\n validate: validateMiscConfig.openUrl,\n },\n {\n name: \"configAdvancedTenantId\",\n type: \"input\",\n message:\n fieldIdToName.configAdvancedTenantId +\n \" to be used in Azure Identity InteractiveBrowserCredential class (optional)\",\n validate: validateMiscConfig.openUrl,\n },\n {\n name: \"configAdvancedRedirectUri\",\n type: \"input\",\n message:\n fieldIdToName.configAdvancedRedirectUri +\n \" to be used in Azure Identity InteractiveBrowserCredential class (optional; default is http://localhost:1337)\",\n validate: validateMiscConfig.openUrl,\n },\n ],\n partial\n );\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright (c) Microsoft Corporation.
|
|
3
3
|
// Licensed under the MIT license.
|
|
4
4
|
import { buildGetConfig } from "./execute-helpers";
|
|
5
|
-
import { prefixUrlProtocol,
|
|
5
|
+
import { prefixUrlProtocol, promptServiceInformation, promptMiscConfig, promptWidgetConfig, validateDeployConfig, validateMiscConfig, validateWidgetConfig, } from "./execute-configs";
|
|
6
6
|
import chalk from "chalk";
|
|
7
7
|
import { generateProject } from "../generateProject";
|
|
8
8
|
const log = console.log;
|
|
@@ -16,23 +16,23 @@ async function main() {
|
|
|
16
16
|
white("Specify the custom widget configuration.");
|
|
17
17
|
const widgetConfig = await getConfig(promptWidgetConfig, validateWidgetConfig);
|
|
18
18
|
white("Specify the Azure API Management service configuration.");
|
|
19
|
-
const
|
|
19
|
+
const serviceInformation = await getConfig(promptServiceInformation, validateDeployConfig);
|
|
20
20
|
white("Specify other options");
|
|
21
21
|
const miscConfig = await getConfig(promptMiscConfig, validateMiscConfig);
|
|
22
|
-
if (
|
|
23
|
-
|
|
22
|
+
if (serviceInformation.resourceId[0] === "/") {
|
|
23
|
+
serviceInformation.resourceId = serviceInformation.resourceId.slice(1);
|
|
24
24
|
}
|
|
25
|
-
if (
|
|
26
|
-
|
|
25
|
+
if (serviceInformation.resourceId.slice(-1) === "/") {
|
|
26
|
+
serviceInformation.resourceId = serviceInformation.resourceId.slice(0, -1);
|
|
27
27
|
}
|
|
28
|
-
if (
|
|
29
|
-
delete
|
|
28
|
+
if (serviceInformation.apiVersion === "") {
|
|
29
|
+
delete serviceInformation.apiVersion;
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
serviceInformation.managementApiEndpoint = prefixUrlProtocol(serviceInformation.managementApiEndpoint);
|
|
32
32
|
miscConfig.openUrl = miscConfig.openUrl
|
|
33
33
|
? prefixUrlProtocol(miscConfig.openUrl)
|
|
34
34
|
: miscConfig.openUrl;
|
|
35
|
-
return generateProject(widgetConfig,
|
|
35
|
+
return generateProject(widgetConfig, serviceInformation, miscConfig)
|
|
36
36
|
.then(() => green("\nThe custom widget’s code scaffold has been successfully generated.\n"))
|
|
37
37
|
.catch(console.error);
|
|
38
38
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/bin/execute.ts"],"names":[],"mappings":";AAEA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAO,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EACL,iBAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/bin/execute.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\n// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { Log, buildGetConfig } from \"./execute-helpers\";\nimport {\n prefixUrlProtocol,\n promptServiceInformation,\n promptMiscConfig,\n promptWidgetConfig,\n validateDeployConfig,\n validateMiscConfig,\n validateWidgetConfig,\n} from \"./execute-configs\";\n\nimport chalk from \"chalk\";\nimport { generateProject } from \"../generateProject\";\n\nconst log = console.log;\nconst white: Log = (msg) => log(chalk.white(msg));\nconst green: Log = (msg) => log(chalk.green(msg));\nconst red: Log = (msg) => log(chalk.red(msg));\nconst gray: Log = (msg) => log(chalk.gray(msg));\n\nasync function main(): Promise<void> {\n green(\n \"\\nThis tool generates code scaffold for custom widgets in the Azure API Management’s developer portal. Learn more at https://aka.ms/apimdocs/portal/customwidgets.\\n\"\n );\n\n const getConfig = buildGetConfig(gray, red);\n\n white(\"Specify the custom widget configuration.\");\n const widgetConfig = await getConfig(promptWidgetConfig, validateWidgetConfig);\n white(\"Specify the Azure API Management service configuration.\");\n const serviceInformation = await getConfig(promptServiceInformation, validateDeployConfig);\n white(\"Specify other options\");\n const miscConfig = await getConfig(promptMiscConfig, validateMiscConfig);\n\n if (serviceInformation.resourceId[0] === \"/\") {\n serviceInformation.resourceId = serviceInformation.resourceId.slice(1);\n }\n if (serviceInformation.resourceId.slice(-1) === \"/\") {\n serviceInformation.resourceId = serviceInformation.resourceId.slice(0, -1);\n }\n if (serviceInformation.apiVersion === \"\") {\n delete serviceInformation.apiVersion;\n }\n\n serviceInformation.managementApiEndpoint = prefixUrlProtocol(\n serviceInformation.managementApiEndpoint\n );\n\n miscConfig.openUrl = miscConfig.openUrl\n ? prefixUrlProtocol(miscConfig.openUrl)\n : miscConfig.openUrl;\n\n return generateProject(widgetConfig, serviceInformation, miscConfig)\n .then(() => green(\"\\nThe custom widget’s code scaffold has been successfully generated.\\n\"))\n .catch(console.error);\n}\n\nmain()\n .then(() => process.exit(0))\n .catch((err) => {\n console.error(err);\n process.exit(1);\n });\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateProject.browser.js","sourceRoot":"","sources":["../../src/generateProject.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAIlC,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,aAA2B,EAC3B,
|
|
1
|
+
{"version":3,"file":"generateProject.browser.js","sourceRoot":"","sources":["../../src/generateProject.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAIlC,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,aAA2B,EAC3B,aAAiC,EACjC,cAAuB,EAAE;IAEzB,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;AACtC,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { ServiceInformation, Options, WidgetConfig } from \"./scaffolding\";\n\nexport async function generateProject(\n _widgetConfig: WidgetConfig,\n _deployConfig: ServiceInformation,\n _miscConfig: Options = {}\n): Promise<void> {\n throw new Error(\"Only for Node.js\");\n}\n"]}
|
|
@@ -14,7 +14,7 @@ const templateSuffix = ".mustache";
|
|
|
14
14
|
* @param options - JSON object with other data, which will not be stored in the DevPortal.
|
|
15
15
|
*/
|
|
16
16
|
export async function generateProject(widgetConfig, deploymentConfig, options = {}) {
|
|
17
|
-
const { openUrl } = options;
|
|
17
|
+
const { openUrl, configAdvancedTenantId, configAdvancedRedirectUri } = options;
|
|
18
18
|
const openUrlParsed = openUrl ? new URL(openUrl) : null;
|
|
19
19
|
if (openUrlParsed) {
|
|
20
20
|
openUrlParsed.searchParams.append(OVERRIDE_PORT_KEY, String(OVERRIDE_DEFAULT_PORT));
|
|
@@ -24,6 +24,15 @@ export async function generateProject(widgetConfig, deploymentConfig, options =
|
|
|
24
24
|
port: OVERRIDE_DEFAULT_PORT,
|
|
25
25
|
open: openUrlParsed ? openUrlParsed.toString() : true,
|
|
26
26
|
};
|
|
27
|
+
const configAdditional = {
|
|
28
|
+
interactiveBrowserCredentialOptions: { redirectUri: "http://localhost:1337" },
|
|
29
|
+
};
|
|
30
|
+
if (configAdvancedTenantId) {
|
|
31
|
+
configAdditional.interactiveBrowserCredentialOptions.tenantId = configAdvancedTenantId;
|
|
32
|
+
}
|
|
33
|
+
if (configAdvancedRedirectUri) {
|
|
34
|
+
configAdditional.interactiveBrowserCredentialOptions.redirectUri = configAdvancedRedirectUri;
|
|
35
|
+
}
|
|
27
36
|
const renderTemplate = async (file) => {
|
|
28
37
|
const isTemplate = file.endsWith(templateSuffix);
|
|
29
38
|
const encoding = file.endsWith(".ttf") ? "binary" : "utf8";
|
|
@@ -34,6 +43,7 @@ export async function generateProject(widgetConfig, deploymentConfig, options =
|
|
|
34
43
|
displayName: widgetConfig.displayName,
|
|
35
44
|
config: JSON.stringify(Object.assign(Object.assign({}, widgetConfig), { name }), null, "\t"),
|
|
36
45
|
configDeploy: JSON.stringify(deploymentConfig, null, "\t"),
|
|
46
|
+
configAdditional: JSON.stringify(configAdditional, null, "\t"),
|
|
37
47
|
serverSettings: JSON.stringify(serverSettings, null, "\t"),
|
|
38
48
|
});
|
|
39
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateProject.js","sourceRoot":"","sources":["../../src/generateProject.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAEL,qBAAqB,EACrB,iBAAiB,EAGjB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC5D,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,MAAM,cAAc,GAAG,WAAW,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,YAA0B,EAC1B,
|
|
1
|
+
{"version":3,"file":"generateProject.js","sourceRoot":"","sources":["../../src/generateProject.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAEL,qBAAqB,EACrB,iBAAiB,EAGjB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC5D,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,MAAM,cAAc,GAAG,WAAW,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,YAA0B,EAC1B,gBAAoC,EACpC,UAAmB,EAAE;IAErB,MAAM,EAAE,OAAO,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,GAAG,OAAO,CAAC;IAC/E,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,IAAI,aAAa,EAAE;QACjB,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC;KACrF;IAED,MAAM,IAAI,GAAG,iBAAiB,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IACzD,MAAM,cAAc,GAAG;QACrB,IAAI,EAAE,qBAAqB;QAC3B,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI;KACtD,CAAC;IAEF,MAAM,gBAAgB,GAAG;QACvB,mCAAmC,EAAE,EAAE,WAAW,EAAE,uBAAuB,EAG1E;KACF,CAAC;IACF,IAAI,sBAAsB,EAAE;QAC1B,gBAAgB,CAAC,mCAAmC,CAAC,QAAQ,GAAG,sBAAsB,CAAC;KACxF;IACD,IAAI,yBAAyB,EAAE;QAC7B,gBAAgB,CAAC,mCAAmC,CAAC,WAAW,GAAG,yBAAyB,CAAC;KAC9F;IAED,MAAM,cAAc,GAAG,KAAK,EAAE,IAAY,EAAiB,EAAE;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3D,IAAI,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrD,IAAI,UAAU,EAAE;YACd,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE;gBACnC,IAAI;gBACJ,WAAW,EAAE,YAAY,CAAC,WAAW;gBACrC,MAAM,EAAE,IAAI,CAAC,SAAS,iCAAM,YAAY,KAAE,IAAI,KAAI,IAAI,EAAE,IAAI,CAAC;gBAC7D,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,CAAC;gBAC1D,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,CAAC;gBAC9D,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC;aAC3D,CAAC,CAAC;SACJ;QAED,IAAI,YAAY,GAAG,IAAI,CAAC;QACxB,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAC5B,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;SAClD;QACD,YAAY,GAAG,YAAY;aACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC;aACxD,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,WAAW,EAAE,YAAY,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC;aACtE,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QAC/B,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;QAClF,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC;QAEvC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IAC9D,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE;QAC3C,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;KAC5B;IAED,OAAO;AACT,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport {\n ServiceInformation,\n OVERRIDE_DEFAULT_PORT,\n OVERRIDE_PORT_KEY,\n Options,\n WidgetConfig,\n displayNameToName,\n widgetFolderName,\n} from \"./scaffolding\";\nimport { join as joinPath, parse as parsePath } from \"path\";\nimport { promises as fs } from \"fs\";\nimport { getTemplates } from \"./getTemplates\";\nimport mustache from \"mustache\";\n\nconst templateSuffix = \".mustache\";\n\n/**\n * Generates a scaffold project of Custom widget for API Managements' Dev Portal.\n *\n * @param widgetConfig - JSON object with data required by DevPortal to handle a widget integration.\n * @param deploymentConfig - JSON object with data for deployment.\n * @param options - JSON object with other data, which will not be stored in the DevPortal.\n */\nexport async function generateProject(\n widgetConfig: WidgetConfig,\n deploymentConfig: ServiceInformation,\n options: Options = {}\n): Promise<void> {\n const { openUrl, configAdvancedTenantId, configAdvancedRedirectUri } = options;\n const openUrlParsed = openUrl ? new URL(openUrl) : null;\n if (openUrlParsed) {\n openUrlParsed.searchParams.append(OVERRIDE_PORT_KEY, String(OVERRIDE_DEFAULT_PORT));\n }\n\n const name = displayNameToName(widgetConfig.displayName);\n const serverSettings = {\n port: OVERRIDE_DEFAULT_PORT,\n open: openUrlParsed ? openUrlParsed.toString() : true,\n };\n\n const configAdditional = {\n interactiveBrowserCredentialOptions: { redirectUri: \"http://localhost:1337\" } as {\n redirectUri: string;\n tenantId?: string;\n },\n };\n if (configAdvancedTenantId) {\n configAdditional.interactiveBrowserCredentialOptions.tenantId = configAdvancedTenantId;\n }\n if (configAdvancedRedirectUri) {\n configAdditional.interactiveBrowserCredentialOptions.redirectUri = configAdvancedRedirectUri;\n }\n\n const renderTemplate = async (file: string): Promise<void> => {\n const isTemplate = file.endsWith(templateSuffix);\n const encoding = file.endsWith(\".ttf\") ? \"binary\" : \"utf8\";\n let fileData = await fs.readFile(file, { encoding });\n if (isTemplate) {\n fileData = mustache.render(fileData, {\n name,\n displayName: widgetConfig.displayName,\n config: JSON.stringify({ ...widgetConfig, name }, null, \"\\t\"),\n configDeploy: JSON.stringify(deploymentConfig, null, \"\\t\"),\n configAdditional: JSON.stringify(configAdditional, null, \"\\t\"),\n serverSettings: JSON.stringify(serverSettings, null, \"\\t\"),\n });\n }\n\n let relativePath = file;\n if (__dirname.includes(\"\\\\\")) {\n relativePath = relativePath.replace(/\\//g, \"\\\\\");\n }\n relativePath = relativePath\n .replace(joinPath(__dirname, \"templates\", \"_shared\"), \"\")\n .replace(joinPath(__dirname, \"templates\", widgetConfig.technology), \"\")\n .replace(templateSuffix, \"\");\n const newFilePath = joinPath(process.cwd(), widgetFolderName(name), relativePath);\n const dir = parsePath(newFilePath).dir;\n\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(newFilePath, fileData, { encoding });\n };\n\n const templates = await getTemplates(widgetConfig.technology);\n for (const file of Object.values(templates)) {\n await renderTemplate(file);\n }\n\n return;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
-
import glob from "glob";
|
|
3
|
+
import { glob } from "glob";
|
|
4
4
|
import { join as pathJoin } from "path";
|
|
5
5
|
export async function getTemplates(template) {
|
|
6
6
|
const sharedFiles = await getFiles(pathJoin(__dirname, "templates", "_shared", "**", "**", "*.*"));
|
|
@@ -8,13 +8,10 @@ export async function getTemplates(template) {
|
|
|
8
8
|
return [...sharedFiles, ...templateFiles];
|
|
9
9
|
}
|
|
10
10
|
async function getFiles(path) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
resolve(matches);
|
|
17
|
-
});
|
|
18
|
-
});
|
|
11
|
+
// Starting from glob v8 `\` is only used as an escape character, and never as a path separator in glob patterns.
|
|
12
|
+
// Glob pattern paths must use forward-slashes as path separators.
|
|
13
|
+
// See https://github.com/isaacs/node-glob/blob/af57da21c7722bb6edb687ccd4ad3b99d3e7a333/changelog.md#80
|
|
14
|
+
const normalizedPath = path.replace(/\\/g, "/");
|
|
15
|
+
return glob(normalizedPath, { dot: true });
|
|
19
16
|
}
|
|
20
17
|
//# sourceMappingURL=getTemplates.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTemplates.js","sourceRoot":"","sources":["../../src/getTemplates.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"getTemplates.js","sourceRoot":"","sources":["../../src/getTemplates.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,MAAM,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAsB;IACvD,MAAM,WAAW,GAAG,MAAM,QAAQ,CAChC,QAAQ,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAC/D,CAAC;IACF,MAAM,aAAa,GAAG,MAAM,QAAQ,CAClC,QAAQ,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAC9D,CAAC;IACF,OAAO,CAAC,GAAG,WAAW,EAAE,GAAG,aAAa,CAAC,CAAC;AAC5C,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,IAAY;IAClC,iHAAiH;IACjH,kEAAkE;IAClE,wGAAwG;IACxG,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { ScaffoldTech } from \"./scaffolding\";\nimport { glob } from \"glob\";\nimport { join as pathJoin } from \"path\";\n\nexport async function getTemplates(template: ScaffoldTech): Promise<string[]> {\n const sharedFiles = await getFiles(\n pathJoin(__dirname, \"templates\", \"_shared\", \"**\", \"**\", \"*.*\")\n );\n const templateFiles = await getFiles(\n pathJoin(__dirname, \"templates\", template, \"**\", \"**\", \"*.*\")\n );\n return [...sharedFiles, ...templateFiles];\n}\n\nasync function getFiles(path: string): Promise<string[]> {\n // Starting from glob v8 `\\` is only used as an escape character, and never as a path separator in glob patterns.\n // Glob pattern paths must use forward-slashes as path separators.\n // See https://github.com/isaacs/node-glob/blob/af57da21c7722bb6edb687ccd4ad3b99d3e7a333/changelog.md#80\n const normalizedPath = path.replace(/\\\\/g, \"/\");\n return glob(normalizedPath, { dot: true });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AAEH,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,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 OVERRIDE_PORT_KEY,\n OVERRIDE_DEFAULT_PORT,\n TECHNOLOGIES,\n displayNameToName,\n widgetFolderName,\n} from \"./scaffolding\";\nexport { generateProject } from \"./generateProject\";\nexport type {\n WidgetConfig as CustomWidgetCommonConfig,\n DeploymentConfig,\n Options,\n ScaffoldTech,\n} from \"./scaffolding\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AAEH,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,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 OVERRIDE_PORT_KEY,\n OVERRIDE_DEFAULT_PORT,\n TECHNOLOGIES,\n displayNameToName,\n widgetFolderName,\n} from \"./scaffolding\";\nexport { generateProject } from \"./generateProject\";\nexport type {\n WidgetConfig as CustomWidgetCommonConfig,\n ServiceInformation as DeploymentConfig,\n Options,\n ScaffoldTech,\n} from \"./scaffolding\";\n"]}
|
|
@@ -12,10 +12,11 @@ export const OVERRIDE_DEFAULT_PORT = 3000;
|
|
|
12
12
|
export const TECHNOLOGIES = ["typescript", "react", "vue"];
|
|
13
13
|
/**
|
|
14
14
|
* Converts user defined name of a custom widget to a unique ID, which is in context of Dev Portal known as "name".
|
|
15
|
+
* Prefix "cw-" to avoid conflicts with existing widgets.
|
|
15
16
|
*
|
|
16
17
|
* @param displayName - User defined name of the custom widget.
|
|
17
18
|
*/
|
|
18
|
-
export const displayNameToName = (displayName) => encodeURIComponent(displayName
|
|
19
|
+
export const displayNameToName = (displayName) => encodeURIComponent(("cw-" + displayName)
|
|
19
20
|
.normalize("NFD")
|
|
20
21
|
.toLowerCase()
|
|
21
22
|
.replace(/[\u0300-\u036f]/g, "")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffolding.js","sourceRoot":"","sources":["../../src/scaffolding.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,2BAA2B,CAAC;AAC7D;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAK1C,kEAAkE;AAClE,MAAM,CAAC,MAAM,YAAY,GAAmB,CAAC,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffolding.js","sourceRoot":"","sources":["../../src/scaffolding.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,2BAA2B,CAAC;AAC7D;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAK1C,kEAAkE;AAClE,MAAM,CAAC,MAAM,YAAY,GAAmB,CAAC,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAkC3E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,WAAmB,EAAU,EAAE,CAC/D,kBAAkB,CAChB,CAAC,KAAK,GAAG,WAAW,CAAC;KAClB,SAAS,CAAC,KAAK,CAAC;KAChB,WAAW,EAAE;KACb,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;KAC/B,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAC/B,CAAC;AAEJ;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,+BAA+B,IAAI,EAAE,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Unique identifier under which is specified which port to use for injecting locally hosted custom widget to a running DevPortal instance.\n */\nexport const OVERRIDE_PORT_KEY = \"MS_APIM_CW_localhost_port\";\n/**\n * Default port for running local dev server on.\n */\nexport const OVERRIDE_DEFAULT_PORT = 3000;\n\n/** All supported technologies to scaffold a widget in. */\nexport type ScaffoldTech = \"typescript\" | \"react\" | \"vue\";\n\n/** List of all supported technologies to scaffold a widget in. */\nexport const TECHNOLOGIES: ScaffoldTech[] = [\"typescript\", \"react\", \"vue\"];\n\n/** Main data which DevPortal needs for every custom widget. */\nexport interface WidgetConfig {\n /** Name of the custom widget which is displayed in DevPortal. */\n displayName: string;\n /** Technology to use to scaffold the widget. */\n technology: ScaffoldTech;\n /** Optional URL for a custom icon, which will be displayed in DevPortal widget list. */\n iconUrl?: string;\n}\n\n/** Data needed for deployment. */\nexport interface ServiceInformation {\n /** Management API endpoint to use (e.g. management.azure.com). */\n managementApiEndpoint: string;\n /** resourceId of your APIM service, must be in this format: subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.ApiManagement/service/<service-name> */\n resourceId: string;\n /** optional override which API version to use during deployment */\n apiVersion?: string;\n}\n\n/** Miscellaneous data for scaffolding of a custom widget which will not be stored in DevPortal. */\nexport interface Options {\n /** The URL to open after development server of the widget is started (URL of your Developer Portal). If you don't want to use this feature, set it to `false`. If you want to open just the widget page, set it to `true`. */\n openUrl?: string;\n /** advance configuration option for the deploy function - tenant ID for InteractiveBrowserCredentialNodeOptions */\n configAdvancedTenantId?: string;\n /** advance configuration option for the deploy function - redirect URI for InteractiveBrowserCredentialNodeOptions */\n configAdvancedRedirectUri?: string;\n}\n\nexport type Configs = WidgetConfig | ServiceInformation | Options;\n\n/**\n * Converts user defined name of a custom widget to a unique ID, which is in context of Dev Portal known as \"name\".\n * Prefix \"cw-\" to avoid conflicts with existing widgets.\n *\n * @param displayName - User defined name of the custom widget.\n */\nexport const displayNameToName = (displayName: string): string =>\n encodeURIComponent(\n (\"cw-\" + displayName)\n .normalize(\"NFD\")\n .toLowerCase()\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9-]/g, \"-\")\n );\n\n/**\n * Returns name of the folder for widget project.\n *\n * @param name - name of the widget\n */\nexport const widgetFolderName = (name: string): string => `azure-api-management-widget-${name}`;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure/api-management-custom-widgets-scaffolder",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.4",
|
|
4
4
|
"author": "Microsoft Corporation",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"sdk-type": "client",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"create-apimanagement-widget": "bin/execute.js"
|
|
17
17
|
},
|
|
18
18
|
"engines": {
|
|
19
|
-
"node": ">=
|
|
19
|
+
"node": ">=18.0.0"
|
|
20
20
|
},
|
|
21
21
|
"keywords": [
|
|
22
22
|
"azure",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"build:browser": "tsc -p . && dev-tool run bundle --browser-test=false",
|
|
42
42
|
"build:node": "tsc -p . && dev-tool run bundle",
|
|
43
43
|
"build:test": "echo skip",
|
|
44
|
-
"bundle:bin": "rollup -c rollup.config.bin.
|
|
44
|
+
"bundle:bin": "rollup -c rollup.config.bin.mjs",
|
|
45
45
|
"build:samples": "echo skip",
|
|
46
46
|
"build": "npm run clean && tsc -p . && dev-tool run bundle --browser-test=false && npm run bundle:bin && api-extractor run --local",
|
|
47
47
|
"check-format": "prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore --ignore-path ./.prettierignore \"src/templates/**\" \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"extract-api": "tsc -p . && api-extractor run --local",
|
|
50
50
|
"format": "prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore --ignore-path ./.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
|
|
51
51
|
"integration-test:browser": "echo skip",
|
|
52
|
-
"integration-test:node": "dev-tool run test:node-ts-input --
|
|
52
|
+
"integration-test:node": "dev-tool run test:node-ts-input --no-test-proxy=true",
|
|
53
53
|
"integration-test": "npm run integration-test:node && npm run integration-test:browser",
|
|
54
54
|
"lint:fix": "eslint package.json api-extractor.json src test --ext .ts --fix --fix-type [problem,suggestion] --ignore-pattern src/templates",
|
|
55
55
|
"lint": "eslint package.json api-extractor.json src test --ext .ts --ignore-pattern src/templates",
|
|
@@ -63,42 +63,42 @@
|
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@azure/dev-tool": "^1.0.0",
|
|
66
|
-
"@microsoft/api-extractor": "7.
|
|
66
|
+
"@microsoft/api-extractor": "^7.31.1",
|
|
67
67
|
"@types/chai": "^4.1.6",
|
|
68
|
-
"@types/mocha": "^
|
|
69
|
-
"@types/node": "^
|
|
70
|
-
"@types/glob": "^7.1.1",
|
|
68
|
+
"@types/mocha": "^10.0.0",
|
|
69
|
+
"@types/node": "^18.0.0",
|
|
71
70
|
"@types/inquirer": "^8.2.1",
|
|
72
71
|
"@types/yargs": "^17.0.10",
|
|
73
72
|
"@types/yargs-parser": "^21.0.0",
|
|
74
73
|
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
|
|
75
74
|
"chai": "^4.2.0",
|
|
76
75
|
"cross-env": "^7.0.2",
|
|
77
|
-
"eslint": "^
|
|
78
|
-
"
|
|
79
|
-
"mocha
|
|
76
|
+
"eslint": "^8.0.0",
|
|
77
|
+
"magic-string": "~0.27.0",
|
|
78
|
+
"mocha": "^10.0.0",
|
|
80
79
|
"prettier": "^2.5.1",
|
|
81
|
-
"
|
|
80
|
+
"c8": "^8.0.0",
|
|
82
81
|
"rimraf": "^3.0.0",
|
|
83
|
-
"
|
|
82
|
+
"ts-node": "^10.0.0",
|
|
83
|
+
"typescript": "~5.2.0",
|
|
84
84
|
"util": "^0.12.1",
|
|
85
|
-
"dotenv": "^
|
|
85
|
+
"dotenv": "^16.0.0",
|
|
86
86
|
"@azure/test-utils": "^1.0.0",
|
|
87
|
-
"@types/mustache": "4.1
|
|
88
|
-
"sinon": "^
|
|
89
|
-
"@types/sinon": "^
|
|
87
|
+
"@types/mustache": "^4.2.1",
|
|
88
|
+
"sinon": "^17.0.0",
|
|
89
|
+
"@types/sinon": "^17.0.0"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
92
|
"mustache": "^4.2.0",
|
|
93
93
|
"prettier": "^2.5.1",
|
|
94
|
-
"glob": "^
|
|
94
|
+
"glob": "^9.0.0",
|
|
95
95
|
"tslib": "^2.2.0",
|
|
96
|
-
"typescript": "~
|
|
96
|
+
"typescript": "~5.2.0",
|
|
97
97
|
"chalk": "^4.1.2",
|
|
98
98
|
"inquirer": "^8.2.4",
|
|
99
99
|
"yargs": "^17.0.1",
|
|
100
100
|
"yargs-parser": "^21.0.1",
|
|
101
|
-
"rollup": "
|
|
102
|
-
"@rollup/plugin-node-resolve": "
|
|
101
|
+
"rollup": "^4.0.0",
|
|
102
|
+
"@rollup/plugin-node-resolve": "^15.0.0"
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -24,6 +24,7 @@ export declare interface DeploymentConfig {
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Converts user defined name of a custom widget to a unique ID, which is in context of Dev Portal known as "name".
|
|
27
|
+
* Prefix "cw-" to avoid conflicts with existing widgets.
|
|
27
28
|
*
|
|
28
29
|
* @param displayName - User defined name of the custom widget.
|
|
29
30
|
*/
|
|
@@ -42,6 +43,10 @@ export declare function generateProject(widgetConfig: CustomWidgetCommonConfig,
|
|
|
42
43
|
export declare interface Options {
|
|
43
44
|
/** The URL to open after development server of the widget is started (URL of your Developer Portal). If you don't want to use this feature, set it to `false`. If you want to open just the widget page, set it to `true`. */
|
|
44
45
|
openUrl?: string;
|
|
46
|
+
/** advance configuration option for the deploy function - tenant ID for InteractiveBrowserCredentialNodeOptions */
|
|
47
|
+
configAdvancedTenantId?: string;
|
|
48
|
+
/** advance configuration option for the deploy function - redirect URI for InteractiveBrowserCredentialNodeOptions */
|
|
49
|
+
configAdvancedRedirectUri?: string;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
/**
|