diff --git a/.vscode/launch.json b/.vscode/launch.json index cec015a76..30dcc9240 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -157,6 +157,26 @@ "./packages/lu/lib/**" ] }, + { + "type": "node", + "request": "launch", + "name": "Dialog merge root-package schema", + "preLaunchTask": "${defaultBuildTask}", + "program": "${workspaceFolder}/packages/dialog/bin/run", + "outputCapture": "std", + "outFiles": [ + "./packages/dialog/lib/**" + ], + "args": [ + "dialog:merge", + "npm/node_modules/root-package/package.json", + "-o", + "oracles/root-package", + "--verbose" + ], + "internalConsoleOptions": "openOnSessionStart", + "cwd": "${workspaceFolder}/packages/dialog/test/commands/dialog/" + }, { "type": "node", "request": "launch", diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 7617b4676..2835b7c6f 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -48,9 +48,7 @@ dependencies: fast-text-encoding: 1.0.3 fetch-mock: 7.7.3 get-stdin: 6.0.0 - get-uri: 3.0.2 glob: 7.1.6 - https-proxy-agent: 2.2.4 intercept-stdout: 0.1.2 is-ci: 2.0.0 json-ptr: 1.3.1 @@ -1009,6 +1007,14 @@ packages: node: '>= 4.0.0' resolution: integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + /agent-base/6.0.2: + dependencies: + debug: 4.1.1 + dev: false + engines: + node: '>= 6.0.0' + resolution: + integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== /ajv/6.12.0: dependencies: fast-deep-equal: 3.1.1 @@ -3391,6 +3397,15 @@ packages: node: '>= 4.5.0' resolution: integrity: sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== + /https-proxy-agent/5.0.0: + dependencies: + agent-base: 6.0.2 + debug: 4.1.1 + dev: false + engines: + node: '>= 6' + resolution: + integrity: sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== /hyperlinker/1.0.0: dev: false engines: @@ -7292,6 +7307,7 @@ packages: '@types/xml2js': 0.4.5 adaptive-expressions: 4.8.0-preview ajv: 6.12.6 + axios: 0.21.1 botbuilder-lg: 4.8.0-preview chai: 4.2.0 chalk: 2.4.2 @@ -7301,6 +7317,7 @@ packages: get-json: 1.0.1 get-uri: 3.0.2 globby: 11.0.0 + https-proxy-agent: 5.0.0 json-ptr: 1.3.1 json-schema-merge-allof: 0.7.0 json-schema-ref-parser: 8.0.0 @@ -7323,7 +7340,7 @@ packages: dev: false name: '@rush-temp/bf-dialog' resolution: - integrity: sha512-f835rOeaw5mMWjEF+Ch/yTnPHAw/8Q16iVrMlPHb27reOi0t1qtOSOuOKpXWUCIr65oCvvzE32JwnPCy8XFG7w== + integrity: sha512-Pe+h+iEst6RqFvAkWH/RzlUSuJlXoXI957ACIv2jtNe73ps02BYaynLquChghKVuXnZ2Ul+oceCyXx+D9dFQog== tarball: 'file:projects/bf-dialog.tgz' version: 0.0.0 'file:projects/bf-dispatcher.tgz': @@ -7480,7 +7497,7 @@ packages: dev: false name: '@rush-temp/bf-luis-cli' resolution: - integrity: sha512-hi+iOx5Yq08FxsCiGuAIZzdB1/4wcaP/qnDaXfBNMsoT1AB/hjHydm0OyRR/QtBwjFAxMzUCafPmHKqD3JdhPw== + integrity: sha512-fg5B1E3kaqUNQDT45ZWxBSAHE/gNVmIAbz2VCKEcK1/xK7DYLvcGlX5bFMC4AaYw7vSnJZ4Q5S3JYugPG6TinQ== tarball: 'file:projects/bf-luis-cli.tgz' version: 0.0.0 'file:projects/bf-orchestrator-cli.tgz': @@ -7594,7 +7611,7 @@ packages: dev: false name: '@rush-temp/bf-qnamaker' resolution: - integrity: sha512-4493Sz8sTpkTWkPegzzpmpFadoboXwalx1Yj9hLwJLuw/csHob4JzWS0Ota83j6lWkfy0NtObDUb7GJrZtN5xg== + integrity: sha512-XZ3HKrN0Wmk+5WLyi9NfLxhOMPTkQN5R0H+Js+0vM2jaq00NmpGinUalQTDvYrJrgaTIsentVSedsEUHyUU/JQ== tarball: 'file:projects/bf-qnamaker.tgz' version: 0.0.0 'file:projects/botframework-cli.tgz': @@ -7684,9 +7701,7 @@ specifiers: fast-text-encoding: ^1.0.3 fetch-mock: ^7.3.9 get-stdin: ^6.0.0 - get-uri: ~3.0.2 glob: ^7.1.3 - https-proxy-agent: ^2.2.1 intercept-stdout: ^0.1.2 is-ci: 2.0.0 json-ptr: ~1.3.0 diff --git a/packages/dialog/package.json b/packages/dialog/package.json index d78f73bfe..1f9cfbb57 100644 --- a/packages/dialog/package.json +++ b/packages/dialog/package.json @@ -45,10 +45,11 @@ "@types/lru-cache": "^5.1.0", "@types/xml2js": "^0.4.4", "ajv": "^6.12.2", + "axios": "~0.21.1", + "https-proxy-agent": "^5.0.0", "chalk": "^2.4.2", "clone": "^2.1.2", "fs-extra": "^8.1.0", - "get-uri": "~3.0.2", "globby": "^11.0.0", "@apidevtools/json-schema-ref-parser": "^9.0.1", "os": "~0.1.1", @@ -80,4 +81,4 @@ "tslint": "^5.18.0", "typescript": "^4.0.3" } -} +} \ No newline at end of file diff --git a/packages/dialog/src/library/getJSON.ts b/packages/dialog/src/library/getJSON.ts new file mode 100644 index 000000000..7363a99a6 --- /dev/null +++ b/packages/dialog/src/library/getJSON.ts @@ -0,0 +1,51 @@ +/*! + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import * as fs from 'fs-extra' +const axios = require('axios') +const url = require('url') +const httpsProxyAgent = require('https-proxy-agent') + +const httpsProxy = function (config) { + const parsed = url.parse(config.url) + const protocol = parsed.protocol + if (protocol !== 'https:') { + return config + } + + /* tslint:disable:no-string-literal */ + const envProxy = process.env['HTTPS_PROXY'] || process.env['https_proxy'] + /* tslint:enable:no-string-literal */ + if (envProxy) { + const parsed = url.parse(envProxy) + const proxyOpt = { + hostname: parsed.hostname, + port: parsed.port + } + + if (parsed.auth) { + (proxyOpt as any).auth = parsed.auth + } + + config.httpsAgent = httpsProxyAgent(proxyOpt) + //Disable direct proxy + config.proxy = false + } + + return config +} +axios.interceptors.request.use(httpsProxy) + +const filePrefix = 'file:///' + +// Get JSON from a URL. +export default async function getJSON(url: string): Promise { + if (url.startsWith(filePrefix)) { + return fs.readJSON(url.substring(filePrefix.length)) + } + + const resp = await axios.get(url); + return resp.data +} diff --git a/packages/dialog/src/library/schemaMerger.ts b/packages/dialog/src/library/schemaMerger.ts index 0934ea1c2..4c016fa9c 100644 --- a/packages/dialog/src/library/schemaMerger.ts +++ b/packages/dialog/src/library/schemaMerger.ts @@ -12,10 +12,10 @@ import * as xp from 'xml2js' import Ajv = require('ajv') import parser from '@apidevtools/json-schema-ref-parser' import {JsonPointer as ptr} from 'json-ptr' +import getJSON from './getJSON' const allof = require('json-schema-merge-allof') const clone = require('clone') -const getUri = require('get-uri') const glob = require('globby') const semverRsort = require('semver/functions/rsort') const util = require('util') @@ -40,16 +40,6 @@ function pathName(path: string | undefined, extension: string): string { return path ? `${path}/${extension}` : extension } -// Get JSON from a URI. -async function getJSON(uri: string): Promise { - const stream = await getUri(uri) - let data = '' - for await (const chunk of stream) { - data += chunk.toString() - } - return JSON.parse(data) -} - // Convert to the right kind of slash. // ppath.normalize did not do this properly on the mac. function normalize(path: string): string { @@ -67,6 +57,11 @@ function forwardSlashes(input: string): string { return input.replace(/\\/g, '/') } +// Consistent sort comparison +function sortFunction(a: any, b: any): number { + return a.localeCompare(b, 'en') +} + // Deep merge of JSON objects function mergeObjects(obj1: any, obj2: any): any { const target = {} @@ -83,7 +78,7 @@ function mergeObjects(obj1: any, obj2: any): any { merger(obj1) merger(obj2) const finalTarget = {} - for (const key of Object.keys(target).sort()) { + for (const key of Object.keys(target).sort(sortFunction)) { finalTarget[key] = target[key] } return finalTarget @@ -649,7 +644,7 @@ export class SchemaMerger { this.validateAndExpandPolicies() const oneOf = Object.keys(this.definitions) .filter(kind => !this.isInterface(kind) && this.definitions[kind].$role) - .sort() + .sort(sortFunction) .map(kind => { return {$ref: `#/definitions/${kind}`} }) @@ -661,7 +656,7 @@ export class SchemaMerger { this.currentFile = this.output + '.schema' this.currentKind = '' const finalDefinitions: any = {} - for (const key of Object.keys(this.definitions).sort()) { + for (const key of Object.keys(this.definitions).sort(sortFunction)) { finalDefinitions[key] = this.definitions[key] } let finalSchema: any = { @@ -778,7 +773,7 @@ export class SchemaMerger { if (!this.failed) { for (const locale of Object.keys(result)) { const uischema = {$schema: this.metaUISchemaId} - for (const key of Object.keys(result[locale]).sort()) { + for (const key of Object.keys(result[locale]).sort(sortFunction)) { uischema[key] = result[locale][key] } this.currentFile = ppath.join(ppath.dirname(this.output), outputName + (locale ? '.' + locale : '') + '.uischema') @@ -1788,7 +1783,7 @@ export class SchemaMerger { for (this.currentKind in this.definitions) { const definition = this.definitions[this.currentKind] if (this.isInterface(this.currentKind) && definition.oneOf) { - definition.oneOf = definition.oneOf.sort((a: any, b: any) => (a.$ref || a.type).localeCompare(b.$ref || b.type)) + definition.oneOf = definition.oneOf.sort((a: any, b: any) => sortFunction(a.$ref ?? a.type, b.$ref ?? b.type)) } } } diff --git a/packages/dialog/src/library/schemaTracker.ts b/packages/dialog/src/library/schemaTracker.ts index 466ba52b2..abca8f5c4 100644 --- a/packages/dialog/src/library/schemaTracker.ts +++ b/packages/dialog/src/library/schemaTracker.ts @@ -5,20 +5,14 @@ import Ajv = require('ajv') import parser from '@apidevtools/json-schema-ref-parser' - -let getUri: any = require('get-uri') +import http from './getJSON' // Get JSON from a URI. async function getJSON(uri: string): Promise { if (uri.indexOf(':') < 2) { uri = `file:///${uri}` } - let stream = await getUri(uri) - let data = '' - for await (let chunk of stream) { - data += chunk.toString() - } - return JSON.parse(data) + return http(uri) } export class SchemaTracker { diff --git a/packages/dialog/test/commands/dialog/merge.test.ts b/packages/dialog/test/commands/dialog/merge.test.ts index a7c98af5b..5020dcbf3 100644 --- a/packages/dialog/test/commands/dialog/merge.test.ts +++ b/packages/dialog/test/commands/dialog/merge.test.ts @@ -148,7 +148,7 @@ describe('dialog:merge', async () => { console.log('Start missing component schema') const [merged, lines] = await merge(['schemas/badSchemas/missingComponent.schema'], 'app.schema') assert(!merged, 'Merge should have failed') - assert(countMatches(/file does not exist/i, lines) === 1, 'No missing component schema') + assert(countMatches(/status code 404/i, lines) === 1, 'No missing component schema') }) it('mismatched component schema', async () => { @@ -495,7 +495,7 @@ describe('dialog:merge', async () => { .persist() const [merged, lines] = await merge(['schemas/*.schema'], 'app.schema') assert(!merged, 'Merging should fail') - assert(countMatches(/internal server error/i, lines) === 1, 'Did not detect server error') + assert(countMatches(/status code 500/i, lines) === 1, 'Did not detect server error') scope.done() nock.cleanAll() }) diff --git a/packages/dialog/test/commands/dialog/npm/packageBase.json b/packages/dialog/test/commands/dialog/npm/packageBase.json new file mode 100644 index 000000000..f8e55f561 --- /dev/null +++ b/packages/dialog/test/commands/dialog/npm/packageBase.json @@ -0,0 +1,87 @@ +{ + "$schema": "https://schemas.botframework.com/schemas/component/v1.0/component.schema", + "$role": [], + "title": "Example schema for packages", + "description": "Example schema for packages.", + "properties": { + "Object": { + "type": "object", + "title": " object", + "description": "This is an object.", + "properties": { + "subObject": { + "type": "string", + "title": "SubObject", + "description": "SubObject property of Object." + } + } + }, + "SimpleArray": { + "type": "array", + "title": " Empty Array", + "description": "This is simple items array.", + "items": true + }, + "Array": { + "type": "array", + "title": " Array", + "description": "This is a complex item array.", + "items": { + "type": "object", + "title": "Array item", + "description": "This is an array item.", + "properties": { + "subArray": { + "type": "integer", + "title": "Integer item", + "description": "Integer item" + } + } + } + }, + "AnyOf": { + "title": " AnyOf", + "description": "This is an anyOf.", + "anyOf": [ + { + "type": "object", + "title": "AnyOf1", + "description": "This is anyOf1 object.", + "properties": { + "anyOf1": { + "type": "object", + "title": "AnyOf1 object", + "description": "This is anyOf1.", + "properties": { + "subAnyOf1": { + "type": "string", + "title": "SubAnyOf1", + "description": "SubAnyOf1 string" + } + } + } + } + }, + { + "type": "object", + "title": "AnyOf2", + "description": "This is anyOf2 object.", + "properties": { + "anyOf2": { + "type": "object", + "title": "AnyOf2 object", + "description": "This is anyOf2.", + "properties": { + "subAnyOf2": { + "type": "string", + "title": "SubAnyOf2", + "description": "SubAnyOf2 string" + } + } + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/packages/dialog/test/commands/dialog/oracles/app.schema b/packages/dialog/test/commands/dialog/oracles/app.schema index 96d665b03..62ae7ab80 100644 --- a/packages/dialog/test/commands/dialog/oracles/app.schema +++ b/packages/dialog/test/commands/dialog/oracles/app.schema @@ -4,96 +4,20 @@ "title": "Component kinds", "description": "These are all of the kinds that can be created by the loader.", "oneOf": [ - { - "$ref": "#/definitions/Recognizer" - }, { "$ref": "#/definitions/policyLevel2" }, { "$ref": "#/definitions/prompt" }, + { + "$ref": "#/definitions/Recognizer" + }, { "$ref": "#/definitions/root" } ], "definitions": { - "INothing": { - "title": "Microsoft Nothing", - "description": "Definition of a union type with no implementations.", - "$role": "interface" - }, - "IRecognizer": { - "$role": "interface", - "$comment": "Has multiple implementations", - "title": "Recognizer", - "description": "Recognizer interface.", - "oneOf": [ - { - "$ref": "#/definitions/Recognizer" - }, - { - "type": "string", - "title": "Reference to IRecognizer", - "description": "Reference to IRecognizer .dialog file." - } - ] - }, - "Recognizer": { - "$role": "implements(IRecognizer)", - "required": [ - "req", - "$kind" - ], - "definitions": { - "insideDef": { - "$role": "expression", - "title": "Inside", - "description": "Something inside." - } - }, - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^\\$": { - "title": "Tooling property", - "description": "Open ended property for tooling." - } - }, - "properties": { - "req": { - "$role": "expression", - "title": "Required", - "description": "Something required." - }, - "opt": { - "type": "string", - "title": "Optional", - "description": "Something optional." - }, - "complex": { - "title": "Complex", - "description": "Complex object.", - "properties": { - "inside": { - "$ref": "#/definitions/Recognizer/definitions/insideDef" - } - } - }, - "$kind": { - "title": "Kind of dialog object", - "description": "Defines the valid properties for the component you are configuring (from a dialog .schema file)", - "type": "string", - "pattern": "^[a-zA-Z][a-zA-Z0-9.]*$", - "const": "Recognizer" - }, - "$designer": { - "title": "Designer information", - "type": "object", - "description": "Extra information for the Bot Framework Composer." - } - } - }, "arrayExpression": { "$role": "expression", "title": "Array or expression", @@ -232,6 +156,11 @@ "user.age > 13" ] }, + "INothing": { + "title": "Microsoft Nothing", + "description": "Definition of a union type with no implementations.", + "$role": "interface" + }, "integerExpression": { "$role": "expression", "title": "Integer or expression", @@ -254,6 +183,22 @@ } ] }, + "IRecognizer": { + "$role": "interface", + "$comment": "Has multiple implementations", + "title": "Recognizer", + "description": "Recognizer interface.", + "oneOf": [ + { + "$ref": "#/definitions/Recognizer" + }, + { + "type": "string", + "title": "Reference to IRecognizer", + "description": "Reference to IRecognizer .dialog file." + } + ] + }, "numberExpression": { "$role": "expression", "title": "Number or expression", @@ -432,6 +377,61 @@ } } }, + "Recognizer": { + "$role": "implements(IRecognizer)", + "required": [ + "req", + "$kind" + ], + "definitions": { + "insideDef": { + "$role": "expression", + "title": "Inside", + "description": "Something inside." + } + }, + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^\\$": { + "title": "Tooling property", + "description": "Open ended property for tooling." + } + }, + "properties": { + "req": { + "$role": "expression", + "title": "Required", + "description": "Something required." + }, + "opt": { + "type": "string", + "title": "Optional", + "description": "Something optional." + }, + "complex": { + "title": "Complex", + "description": "Complex object.", + "properties": { + "inside": { + "$ref": "#/definitions/Recognizer/definitions/insideDef" + } + } + }, + "$kind": { + "title": "Kind of dialog object", + "description": "Defines the valid properties for the component you are configuring (from a dialog .schema file)", + "type": "string", + "pattern": "^[a-zA-Z][a-zA-Z0-9.]*$", + "const": "Recognizer" + }, + "$designer": { + "title": "Designer information", + "type": "object", + "description": "Extra information for the Bot Framework Composer." + } + } + }, "role": { "title": "$role", "description": "Defines the role played in the dialog schema from [expression|interface|implements($kind)|extends($kind)].", diff --git a/packages/dialog/test/commands/dialog/oracles/project3.schema b/packages/dialog/test/commands/dialog/oracles/project3.schema index 4b0a90e51..c544b54f1 100644 --- a/packages/dialog/test/commands/dialog/oracles/project3.schema +++ b/packages/dialog/test/commands/dialog/oracles/project3.schema @@ -33,6 +33,129 @@ } ], "definitions": { + "arrayExpression": { + "$role": "expression", + "title": "Array or expression", + "description": "Array or expression to evaluate.", + "oneOf": [ + { + "type": "array", + "title": "Array", + "description": "Array constant." + }, + { + "$ref": "#/definitions/equalsExpression" + } + ] + }, + "booleanExpression": { + "$role": "expression", + "title": "Boolean or expression", + "description": "Boolean constant or expression to evaluate.", + "oneOf": [ + { + "type": "boolean", + "title": "Boolean", + "description": "Boolean constant.", + "default": false, + "examples": [ + false + ] + }, + { + "$ref": "#/definitions/equalsExpression", + "examples": [ + "=user.isVip" + ] + } + ] + }, + "component": { + "required": [ + "$kind" + ], + "additionalProperties": false, + "patternProperties": { + "^\\$": { + "title": "Tooling property", + "description": "Open ended property for tooling." + } + }, + "properties": { + "$kind": { + "title": "Kind of dialog object", + "description": "Defines the valid properties for the component you are configuring (from a dialog .schema file)", + "type": "string", + "pattern": "^[a-zA-Z][a-zA-Z0-9.]*$" + }, + "$designer": { + "title": "Designer information", + "type": "object", + "description": "Extra information for the Bot Framework Composer." + } + } + }, + "condition": { + "$role": "expression", + "title": "Boolean condition", + "description": "Boolean constant or expression to evaluate.", + "oneOf": [ + { + "$ref": "#/definitions/expression" + }, + { + "type": "boolean", + "title": "Boolean", + "description": "Boolean value.", + "default": true, + "examples": [ + false + ] + } + ] + }, + "equalsExpression": { + "$role": "expression", + "type": "string", + "title": "Expression", + "description": "Expression starting with =.", + "pattern": "^=.*\\S.*", + "examples": [ + "=user.name" + ] + }, + "expression": { + "$role": "expression", + "type": "string", + "title": "Expression", + "description": "Expression to evaluate.", + "pattern": "^.*\\S.*", + "examples": [ + "user.age > 13" + ] + }, + "integerExpression": { + "$role": "expression", + "title": "Integer or expression", + "description": "Integer constant or expression to evaluate.", + "oneOf": [ + { + "type": "integer", + "title": "Integer", + "description": "Integer constant.", + "default": 0, + "examples": [ + 15 + ] + }, + { + "$ref": "#/definitions/equalsExpression", + "examples": [ + "=user.age" + ] + } + ] + }, "Microsoft.AdaptiveDialog": { "$role": "implements(Microsoft.IDialog)", "title": "Adaptive Dialog", @@ -750,129 +873,6 @@ } } }, - "arrayExpression": { - "$role": "expression", - "title": "Array or expression", - "description": "Array or expression to evaluate.", - "oneOf": [ - { - "type": "array", - "title": "Array", - "description": "Array constant." - }, - { - "$ref": "#/definitions/equalsExpression" - } - ] - }, - "booleanExpression": { - "$role": "expression", - "title": "Boolean or expression", - "description": "Boolean constant or expression to evaluate.", - "oneOf": [ - { - "type": "boolean", - "title": "Boolean", - "description": "Boolean constant.", - "default": false, - "examples": [ - false - ] - }, - { - "$ref": "#/definitions/equalsExpression", - "examples": [ - "=user.isVip" - ] - } - ] - }, - "component": { - "required": [ - "$kind" - ], - "additionalProperties": false, - "patternProperties": { - "^\\$": { - "title": "Tooling property", - "description": "Open ended property for tooling." - } - }, - "properties": { - "$kind": { - "title": "Kind of dialog object", - "description": "Defines the valid properties for the component you are configuring (from a dialog .schema file)", - "type": "string", - "pattern": "^[a-zA-Z][a-zA-Z0-9.]*$" - }, - "$designer": { - "title": "Designer information", - "type": "object", - "description": "Extra information for the Bot Framework Composer." - } - } - }, - "condition": { - "$role": "expression", - "title": "Boolean condition", - "description": "Boolean constant or expression to evaluate.", - "oneOf": [ - { - "$ref": "#/definitions/expression" - }, - { - "type": "boolean", - "title": "Boolean", - "description": "Boolean value.", - "default": true, - "examples": [ - false - ] - } - ] - }, - "equalsExpression": { - "$role": "expression", - "type": "string", - "title": "Expression", - "description": "Expression starting with =.", - "pattern": "^=.*\\S.*", - "examples": [ - "=user.name" - ] - }, - "expression": { - "$role": "expression", - "type": "string", - "title": "Expression", - "description": "Expression to evaluate.", - "pattern": "^.*\\S.*", - "examples": [ - "user.age > 13" - ] - }, - "integerExpression": { - "$role": "expression", - "title": "Integer or expression", - "description": "Integer constant or expression to evaluate.", - "oneOf": [ - { - "type": "integer", - "title": "Integer", - "description": "Integer constant.", - "default": 0, - "examples": [ - 15 - ] - }, - { - "$ref": "#/definitions/equalsExpression", - "examples": [ - "=user.age" - ] - } - ] - }, "nuget3.component1": { "$role": [], "title": "Nuget3 schema", diff --git a/packages/dialog/test/commands/dialog/oracles/project5.schema b/packages/dialog/test/commands/dialog/oracles/project5.schema index 4b0a90e51..c544b54f1 100644 --- a/packages/dialog/test/commands/dialog/oracles/project5.schema +++ b/packages/dialog/test/commands/dialog/oracles/project5.schema @@ -33,6 +33,129 @@ } ], "definitions": { + "arrayExpression": { + "$role": "expression", + "title": "Array or expression", + "description": "Array or expression to evaluate.", + "oneOf": [ + { + "type": "array", + "title": "Array", + "description": "Array constant." + }, + { + "$ref": "#/definitions/equalsExpression" + } + ] + }, + "booleanExpression": { + "$role": "expression", + "title": "Boolean or expression", + "description": "Boolean constant or expression to evaluate.", + "oneOf": [ + { + "type": "boolean", + "title": "Boolean", + "description": "Boolean constant.", + "default": false, + "examples": [ + false + ] + }, + { + "$ref": "#/definitions/equalsExpression", + "examples": [ + "=user.isVip" + ] + } + ] + }, + "component": { + "required": [ + "$kind" + ], + "additionalProperties": false, + "patternProperties": { + "^\\$": { + "title": "Tooling property", + "description": "Open ended property for tooling." + } + }, + "properties": { + "$kind": { + "title": "Kind of dialog object", + "description": "Defines the valid properties for the component you are configuring (from a dialog .schema file)", + "type": "string", + "pattern": "^[a-zA-Z][a-zA-Z0-9.]*$" + }, + "$designer": { + "title": "Designer information", + "type": "object", + "description": "Extra information for the Bot Framework Composer." + } + } + }, + "condition": { + "$role": "expression", + "title": "Boolean condition", + "description": "Boolean constant or expression to evaluate.", + "oneOf": [ + { + "$ref": "#/definitions/expression" + }, + { + "type": "boolean", + "title": "Boolean", + "description": "Boolean value.", + "default": true, + "examples": [ + false + ] + } + ] + }, + "equalsExpression": { + "$role": "expression", + "type": "string", + "title": "Expression", + "description": "Expression starting with =.", + "pattern": "^=.*\\S.*", + "examples": [ + "=user.name" + ] + }, + "expression": { + "$role": "expression", + "type": "string", + "title": "Expression", + "description": "Expression to evaluate.", + "pattern": "^.*\\S.*", + "examples": [ + "user.age > 13" + ] + }, + "integerExpression": { + "$role": "expression", + "title": "Integer or expression", + "description": "Integer constant or expression to evaluate.", + "oneOf": [ + { + "type": "integer", + "title": "Integer", + "description": "Integer constant.", + "default": 0, + "examples": [ + 15 + ] + }, + { + "$ref": "#/definitions/equalsExpression", + "examples": [ + "=user.age" + ] + } + ] + }, "Microsoft.AdaptiveDialog": { "$role": "implements(Microsoft.IDialog)", "title": "Adaptive Dialog", @@ -750,129 +873,6 @@ } } }, - "arrayExpression": { - "$role": "expression", - "title": "Array or expression", - "description": "Array or expression to evaluate.", - "oneOf": [ - { - "type": "array", - "title": "Array", - "description": "Array constant." - }, - { - "$ref": "#/definitions/equalsExpression" - } - ] - }, - "booleanExpression": { - "$role": "expression", - "title": "Boolean or expression", - "description": "Boolean constant or expression to evaluate.", - "oneOf": [ - { - "type": "boolean", - "title": "Boolean", - "description": "Boolean constant.", - "default": false, - "examples": [ - false - ] - }, - { - "$ref": "#/definitions/equalsExpression", - "examples": [ - "=user.isVip" - ] - } - ] - }, - "component": { - "required": [ - "$kind" - ], - "additionalProperties": false, - "patternProperties": { - "^\\$": { - "title": "Tooling property", - "description": "Open ended property for tooling." - } - }, - "properties": { - "$kind": { - "title": "Kind of dialog object", - "description": "Defines the valid properties for the component you are configuring (from a dialog .schema file)", - "type": "string", - "pattern": "^[a-zA-Z][a-zA-Z0-9.]*$" - }, - "$designer": { - "title": "Designer information", - "type": "object", - "description": "Extra information for the Bot Framework Composer." - } - } - }, - "condition": { - "$role": "expression", - "title": "Boolean condition", - "description": "Boolean constant or expression to evaluate.", - "oneOf": [ - { - "$ref": "#/definitions/expression" - }, - { - "type": "boolean", - "title": "Boolean", - "description": "Boolean value.", - "default": true, - "examples": [ - false - ] - } - ] - }, - "equalsExpression": { - "$role": "expression", - "type": "string", - "title": "Expression", - "description": "Expression starting with =.", - "pattern": "^=.*\\S.*", - "examples": [ - "=user.name" - ] - }, - "expression": { - "$role": "expression", - "type": "string", - "title": "Expression", - "description": "Expression to evaluate.", - "pattern": "^.*\\S.*", - "examples": [ - "user.age > 13" - ] - }, - "integerExpression": { - "$role": "expression", - "title": "Integer or expression", - "description": "Integer constant or expression to evaluate.", - "oneOf": [ - { - "type": "integer", - "title": "Integer", - "description": "Integer constant.", - "default": 0, - "examples": [ - 15 - ] - }, - { - "$ref": "#/definitions/equalsExpression", - "examples": [ - "=user.age" - ] - } - ] - }, "nuget3.component1": { "$role": [], "title": "Nuget3 schema", diff --git a/packages/lu/package.json b/packages/lu/package.json index a6259fc09..40d25e0c9 100644 --- a/packages/lu/package.json +++ b/packages/lu/package.json @@ -36,7 +36,7 @@ "@types/node-fetch": "~2.5.5", "antlr4": "~4.8.0", "axios": "~0.21.1", - "axios-https-proxy": "^0.1.1", + "https-proxy-agent": "^5.0.0", "chalk": "2.4.1", "console-stream": "^0.1.1", "deep-equal": "^1.0.1", diff --git a/packages/lu/src/parser/lubuild/http-request.ts b/packages/lu/src/parser/lubuild/http-request.ts index f87ef9f05..5f5410960 100644 --- a/packages/lu/src/parser/lubuild/http-request.ts +++ b/packages/lu/src/parser/lubuild/http-request.ts @@ -4,8 +4,9 @@ */ const axios = require('axios') -const axiosHttpsProxy = require('axios-https-proxy') -axios.interceptors.request.use(axiosHttpsProxy) +const httpsProxy = require('../utils/httpsProxy') + +axios.interceptors.request.use(httpsProxy) export default { async get( diff --git a/packages/lu/src/parser/qnabuild/serviceBase.js b/packages/lu/src/parser/qnabuild/serviceBase.js index cd0f3abb2..cc6bed18c 100644 --- a/packages/lu/src/parser/qnabuild/serviceBase.js +++ b/packages/lu/src/parser/qnabuild/serviceBase.js @@ -4,10 +4,12 @@ */ const axios = require('axios') -const axiosHttpsProxy = require('axios-https-proxy') +const httpsProxy = require('../utils/httpsProxy') const os = require('os') const packageJSON = require('./../../../package') -axios.interceptors.request.use(axiosHttpsProxy) + +axios.interceptors.request.use(httpsProxy) + /** * Base class for all services diff --git a/packages/lu/src/parser/utils/httpsProxy.js b/packages/lu/src/parser/utils/httpsProxy.js new file mode 100644 index 000000000..13009a7c8 --- /dev/null +++ b/packages/lu/src/parser/utils/httpsProxy.js @@ -0,0 +1,36 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +const url = require('url') +const httpsProxyAgent = require('https-proxy-agent') + +const httpsProxy = function(config) { + const parsed = url.parse(config.url) + const protocol = parsed.protocol + if (protocol !== 'https:') { + return config + } + + const envProxy = process.env['HTTPS_PROXY'] || process.env['https_proxy'] + if (envProxy) { + const parsed = url.parse(envProxy) + const proxyOpt = { + hostname: parsed.hostname, + port: parsed.port + } + + if (parsed.auth) { + proxyOpt.auth = parsed.auth + } + + config.httpsAgent = httpsProxyAgent(proxyOpt) + //Disable direct proxy + config.proxy = false + } + + return config +} + +module.exports = httpsProxy; \ No newline at end of file