Extensions: lint fixes
This commit is contained in:
Родитель
9f17feb6dd
Коммит
758b5be86e
|
@ -6,6 +6,7 @@ module.exports = {
|
|||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:prettier/recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:react/recommended',
|
||||
],
|
||||
|
@ -41,6 +42,7 @@ module.exports = {
|
|||
'@typescript-eslint/interface-name-prefix': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
|
||||
'@typescript-eslint/no-var-requires': 0,
|
||||
'@typescript-eslint/no-use-before-define': 'warn',
|
||||
'@typescript-eslint/prefer-optional-chain': 'error',
|
||||
|
||||
|
@ -110,7 +112,7 @@ module.exports = {
|
|||
'react/no-danger': 'error',
|
||||
'react/no-deprecated': 'warn',
|
||||
'react/prop-types': 'off',
|
||||
'react/no-unknown-property': 'error',
|
||||
'react/no-unknown-property': ['error', { 'ignore': ['css'] }],
|
||||
'react/jsx-boolean-value': ['error', 'never'],
|
||||
'react/jsx-filename-extension': ['error', { extensions: ['.jsx', '.tsx'] }],
|
||||
// https://github.com/yannickcr/eslint-plugin-react/blob/HEAD/docs/rules/jsx-sort-props.md
|
||||
|
|
|
@ -18,20 +18,20 @@ module.exports = {
|
|||
} else {
|
||||
done(null, false, { message: 'Incorrect password' });
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
// define this BEFORE turning on the middleware...
|
||||
composer.addWebRoute('get', '/login', (req, res) => {
|
||||
res.send(
|
||||
'LOGIN REQUIRED <form method="post" action="/login/submit"><input name="username" placeholder="username" value="admin" /><input name="password" type="password" value="secret" /><button type="submit">Login</button></form>'
|
||||
'LOGIN REQUIRED <form method="post" action="/login/submit"><input name="username" placeholder="username" value="admin" /><input name="password" type="password" value="secret" /><button type="submit">Login</button></form>',
|
||||
);
|
||||
});
|
||||
|
||||
composer.addWebRoute(
|
||||
'post',
|
||||
'/login/submit',
|
||||
composer.passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' })
|
||||
composer.passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' }),
|
||||
);
|
||||
|
||||
composer.addAllowedUrl('/login/submit');
|
||||
|
|
|
@ -79,7 +79,7 @@ const CreateActionContent = () => {
|
|||
<Summary>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Select this option when you want to provision new Azure resources and publish a bot. A subscription to'
|
||||
'Select this option when you want to provision new Azure resources and publish a bot. A subscription to',
|
||||
)}
|
||||
</Text>
|
||||
|
||||
|
@ -138,14 +138,14 @@ const ImportActionContent = () => {
|
|||
<p>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Select this option if you have access to existing Azure resources and their associated values.'
|
||||
'Select this option if you have access to existing Azure resources and their associated values.',
|
||||
)}
|
||||
</Text>
|
||||
</p>
|
||||
<p>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Copy and paste the JSON file containing the values of your existing Azure resources, from the Azure portal. This file includes values for some or all of the following:'
|
||||
'Copy and paste the JSON file containing the values of your existing Azure resources, from the Azure portal. This file includes values for some or all of the following:',
|
||||
)}
|
||||
</Text>
|
||||
</p>
|
||||
|
@ -190,7 +190,7 @@ const GenerateActionContent = () => {
|
|||
<Summary>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Select this option to request your Azure admin to provision resources on your behalf, for example, when you don’t have proper permissions to use Azure or you want to generate resources from a sovereign cloud.'
|
||||
'Select this option to request your Azure admin to provision resources on your behalf, for example, when you don’t have proper permissions to use Azure or you want to generate resources from a sovereign cloud.',
|
||||
)}
|
||||
</Text>
|
||||
</Summary>
|
||||
|
@ -200,7 +200,7 @@ const GenerateActionContent = () => {
|
|||
<InstructionDetails>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Add resources you need for the bot and generate a resource request to share with your Azure admin.'
|
||||
'Add resources you need for the bot and generate a resource request to share with your Azure admin.',
|
||||
)}
|
||||
</Text>
|
||||
</InstructionDetails>
|
||||
|
@ -210,7 +210,7 @@ const GenerateActionContent = () => {
|
|||
<InstructionDetails>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Once you get the resource details from your Azure admin, use them to import existing resources.'
|
||||
'Once you get the resource details from your Azure admin, use them to import existing resources.',
|
||||
)}
|
||||
</Text>
|
||||
</InstructionDetails>
|
||||
|
|
|
@ -86,8 +86,8 @@ export const ResourceGroupPicker = ({
|
|||
if (debouncedNewName && !debouncedNewName.match(/^[-\w._()]+$/)) {
|
||||
setNewNameErrorMessage(
|
||||
formatMessage(
|
||||
'Resource group names only allow alphanumeric characters, periods, underscores, hyphens and parenthesis and cannot end in a period.'
|
||||
)
|
||||
'Resource group names only allow alphanumeric characters, periods, underscores, hyphens and parenthesis and cannot end in a period.',
|
||||
),
|
||||
);
|
||||
} else if (alreadyExists) {
|
||||
setNewNameErrorMessage(formatMessage('A resource with this name already exists.'));
|
||||
|
|
|
@ -53,7 +53,7 @@ export const getSubscriptions = async (token: string): Promise<Array<Subscriptio
|
|||
let message = JSON.stringify(err, Object.getOwnPropertyNames(err));
|
||||
if (err?.code === 12 && err?.message?.match(/Bearer/gi)) {
|
||||
message = formatMessage(
|
||||
'There was an authentication problem retrieving subscriptions. Verify your login session has not expired and you have permission to list subscriptions in this account.'
|
||||
'There was an authentication problem retrieving subscriptions. Verify your login session has not expired and you have permission to list subscriptions in this account.',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ export const getResourceGroups = async (token: string, subscriptionId: string):
|
|||
export const getResources = async (
|
||||
token: string,
|
||||
subscriptionId: string,
|
||||
resourceGroupName: string
|
||||
resourceGroupName: string,
|
||||
): Promise<Array<GenericResource>> => {
|
||||
try {
|
||||
if (!subscriptionId) {
|
||||
|
@ -143,7 +143,7 @@ export const getDeployLocations = async (token: string, subscriptionId: string)
|
|||
`https://management.azure.com/subscriptions/${subscriptionId}/locations?api-version=2019-10-01`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
}
|
||||
},
|
||||
);
|
||||
return result.data.value;
|
||||
} catch (error) {
|
||||
|
@ -159,7 +159,7 @@ export const getDeployLocations = async (token: string, subscriptionId: string)
|
|||
export const getSupportedRegionsByType = async (
|
||||
token: string,
|
||||
subscriptionId: string,
|
||||
resourceType: AzureResourceProviderType
|
||||
resourceType: AzureResourceProviderType,
|
||||
): Promise<Array<string>> => {
|
||||
try {
|
||||
if (!subscriptionId) {
|
||||
|
@ -207,7 +207,7 @@ export const getSupportedRegionsByType = async (
|
|||
export const CheckBotNameAvailability = async (
|
||||
token: string,
|
||||
botName: string,
|
||||
subscriptionId: string
|
||||
subscriptionId: string,
|
||||
): Promise<CheckNameAvailabilityResponseBody> => {
|
||||
try {
|
||||
if (!botName) {
|
||||
|
@ -265,7 +265,7 @@ export const CheckBotNameAvailability = async (
|
|||
export const CheckWebAppNameAvailability = async (
|
||||
token: string,
|
||||
webAppName: string,
|
||||
subscriptionId: string
|
||||
subscriptionId: string,
|
||||
): Promise<ResourceNameAvailability> => {
|
||||
try {
|
||||
if (!webAppName) {
|
||||
|
@ -292,7 +292,7 @@ export const CheckWebAppNameAvailability = async (
|
|||
const webSiteManagementClient = new WebSiteManagementClient(credentials, subscriptionId);
|
||||
const getCheckNameAvailabilityResult = await webSiteManagementClient.checkNameAvailability(
|
||||
webAppName,
|
||||
'Microsoft.Web/sites'
|
||||
'Microsoft.Web/sites',
|
||||
);
|
||||
if (getCheckNameAvailabilityResult._response.status >= 300) {
|
||||
logger({
|
||||
|
@ -326,7 +326,7 @@ export const CheckCognitiveResourceSku = async (
|
|||
location: string,
|
||||
sku: string,
|
||||
kind: string,
|
||||
type: string
|
||||
type: string,
|
||||
): Promise<boolean> => {
|
||||
try {
|
||||
if (!subscriptionId) {
|
||||
|
|
|
@ -205,13 +205,13 @@ const DialogTitle = {
|
|||
{children}
|
||||
</a>
|
||||
),
|
||||
}
|
||||
},
|
||||
),
|
||||
},
|
||||
REVIEW: {
|
||||
title: formatMessage('Review resources to be created'),
|
||||
subText: formatMessage(
|
||||
'The following resources will be created and provisioned for your bot. Once provisioned, they will be available in the Azure portal.'
|
||||
'The following resources will be created and provisioned for your bot. Once provisioned, they will be available in the Azure portal.',
|
||||
),
|
||||
},
|
||||
CONFIG_RESOURCES: {
|
||||
|
@ -403,7 +403,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
|
||||
const preferredAppServiceOS = useMemo(getPreferredAppServiceOS, [currentProjectId, projectCollection]);
|
||||
const [formData, setFormData] = useState<ProvisionFormData>(
|
||||
getDefaultFormData(currentConfig, { ...extensionState, appServiceOperatingSystem: preferredAppServiceOS })
|
||||
getDefaultFormData(currentConfig, { ...extensionState, appServiceOperatingSystem: preferredAppServiceOS }),
|
||||
);
|
||||
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
@ -454,7 +454,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
'Provisoning Command:\n' +
|
||||
'{command}\n\n' +
|
||||
'Detailed instructions:\nhttps://aka.ms/how-to-complete-provision-handoff',
|
||||
{ command: provisionComposer }
|
||||
{ command: provisionComposer },
|
||||
);
|
||||
|
||||
setHandoffInstructions(instructions);
|
||||
|
@ -539,8 +539,8 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
if (data.length === 0) {
|
||||
setSubscriptionsErrorMessage(
|
||||
formatMessage(
|
||||
'Your subscription list is empty, please add your subscription, or login with another account.'
|
||||
)
|
||||
'Your subscription list is empty, please add your subscription, or login with another account.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -614,7 +614,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
}
|
||||
}, 500);
|
||||
},
|
||||
[publishType, formData.subscriptionId, currentUser]
|
||||
[publishType, formData.subscriptionId, currentUser],
|
||||
);
|
||||
|
||||
const newHostName = useCallback(
|
||||
|
@ -623,7 +623,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
// debounce name check
|
||||
checkNameAvailability(newName);
|
||||
},
|
||||
[checkNameAvailability]
|
||||
[checkNameAvailability],
|
||||
);
|
||||
|
||||
const updateCurrentLocation = useCallback(
|
||||
|
@ -639,7 +639,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
}
|
||||
}
|
||||
},
|
||||
[deployLocations, luisLocations]
|
||||
[deployLocations, luisLocations],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -693,7 +693,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
|
||||
setPageAndTitle(PageTypes.AddResources);
|
||||
},
|
||||
[extensionResourceOptions]
|
||||
[extensionResourceOptions],
|
||||
);
|
||||
|
||||
const onSubmit = useCallback(
|
||||
|
@ -710,7 +710,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
clearAll();
|
||||
closeDialog();
|
||||
},
|
||||
[currentUser]
|
||||
[currentUser],
|
||||
);
|
||||
|
||||
const onSave = useCallback(() => {
|
||||
|
@ -723,17 +723,17 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
const isSignedOut = await logOut();
|
||||
if (isSignedOut) {
|
||||
addNotification(
|
||||
getLogoutNotificationSettings(formatMessage('You have successfully signed out of Azure'), 'info')
|
||||
getLogoutNotificationSettings(formatMessage('You have successfully signed out of Azure'), 'info'),
|
||||
);
|
||||
closeDialog();
|
||||
} else {
|
||||
addNotification(
|
||||
getLogoutNotificationSettings(
|
||||
formatMessage(
|
||||
'There was an error attempting to sign out of Azure. To complete sign out, you may need to restart Composer.'
|
||||
'There was an error attempting to sign out of Azure. To complete sign out, you may need to restart Composer.',
|
||||
),
|
||||
'error'
|
||||
)
|
||||
'error',
|
||||
),
|
||||
);
|
||||
}
|
||||
}, [addNotification]);
|
||||
|
@ -748,13 +748,13 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
const confirmed = await OpenConfirmModal(
|
||||
formatMessage('Sign out of Azure'),
|
||||
formatMessage(
|
||||
'By signing out of Azure, your new publishing profile will be canceled and this dialog will close. Do you want to continue?'
|
||||
'By signing out of Azure, your new publishing profile will be canceled and this dialog will close. Do you want to continue?',
|
||||
),
|
||||
{
|
||||
onRenderContent: (subtitle: string) => <div>{subtitle}</div>,
|
||||
confirmText: formatMessage('Sign out'),
|
||||
cancelText: formatMessage('Cancel'),
|
||||
}
|
||||
},
|
||||
);
|
||||
if (confirmed) {
|
||||
await signoutAndNotify();
|
||||
|
@ -765,7 +765,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
</div>
|
||||
);
|
||||
},
|
||||
[signoutAndNotify]
|
||||
[signoutAndNotify],
|
||||
);
|
||||
|
||||
const isNextDisabled = useMemo(() => {
|
||||
|
@ -777,7 +777,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
!formData.region ||
|
||||
subscriptionsErrorMessage ||
|
||||
errorResourceGroupName ||
|
||||
errorHostName !== ''
|
||||
errorHostName !== '',
|
||||
);
|
||||
}, [
|
||||
formData.subscriptionId,
|
||||
|
@ -867,8 +867,8 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
</ConfigureResourcesPropertyLabel>
|
||||
{renderPropertyInfoIcon(
|
||||
formatMessage(
|
||||
'A custom resource group name that you choose or create. Resource groups allow you to group Azure resources for access and management.'
|
||||
)
|
||||
'A custom resource group name that you choose or create. Resource groups allow you to group Azure resources for access and management.',
|
||||
),
|
||||
)}
|
||||
</Stack>
|
||||
<ResourceGroupPicker
|
||||
|
@ -892,7 +892,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
{formatMessage('Operating System')}
|
||||
</ConfigureResourcesPropertyLabel>
|
||||
{renderPropertyInfoIcon(
|
||||
formatMessage('Select the operating system that will host your application service.')
|
||||
formatMessage('Select the operating system that will host your application service.'),
|
||||
)}
|
||||
</Stack>
|
||||
<ChoiceGroup
|
||||
|
@ -1282,7 +1282,7 @@ export const AzureProvisionDialog: React.FC = () => {
|
|||
<Fragment>
|
||||
<ProvisionHandoff
|
||||
developerInstructions={formatMessage(
|
||||
'If Azure resources and subscription are managed by others, use the following information to request creation of the resources that you need to build and run your bot.'
|
||||
'If Azure resources and subscription are managed by others, use the following information to request creation of the resources that you need to build and run your bot.',
|
||||
)}
|
||||
handoffInstructions={handoffInstructions}
|
||||
hidden={!showHandoff}
|
||||
|
|
|
@ -91,7 +91,7 @@ const isUsingAdaptiveRuntimeKey = (runtimeKey?: string): boolean =>
|
|||
* @default { isUsingAdaptiveRuntime: false, runtimeLanguage: 'dotnet', runtimeType: 'webapp'}
|
||||
*/
|
||||
export const parseRuntimeKey = (
|
||||
runtimeKey?: string
|
||||
runtimeKey?: string,
|
||||
): { isUsingAdaptiveRuntime: boolean; runtimeLanguage?: string; runtimeType?: string } => {
|
||||
const isAdaptive = isUsingAdaptiveRuntimeKey(runtimeKey);
|
||||
|
||||
|
|
|
@ -60,14 +60,14 @@ export class AzureResourceMananger {
|
|||
if (!config.name) {
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.CREATE_RESOURCEGROUP_ERROR,
|
||||
'You should provide a valid resource group name.'
|
||||
'You should provide a valid resource group name.',
|
||||
);
|
||||
}
|
||||
// Create a new resource group
|
||||
if (!config.location) {
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.CREATE_RESOURCEGROUP_ERROR,
|
||||
'You should provide a valid resource group name.'
|
||||
'You should provide a valid resource group name.',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ export class AzureResourceMananger {
|
|||
});
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.CREATE_RESOURCEGROUP_ERROR,
|
||||
resourceGroupGetResult._response.bodyAsText
|
||||
resourceGroupGetResult._response.bodyAsText,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ export class AzureResourceMananger {
|
|||
if (resourceGroupResult._response.status >= 300) {
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.CREATE_RESOURCEGROUP_ERROR,
|
||||
resourceGroupResult._response.bodyAsText
|
||||
resourceGroupResult._response.bodyAsText,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ export class AzureResourceMananger {
|
|||
* @param config
|
||||
*/
|
||||
public async deployLuisAuthoringResource(
|
||||
config: LuisAuthoringResourceConfig
|
||||
config: LuisAuthoringResourceConfig,
|
||||
): Promise<{ authoringKey: string; authoringEndpoint: string; location: string }> {
|
||||
try {
|
||||
this.logger({
|
||||
|
@ -150,7 +150,7 @@ export class AzureResourceMananger {
|
|||
const cognitiveServicesManagementClient = new CognitiveServicesManagementClient(
|
||||
this.creds,
|
||||
this.subscriptionId,
|
||||
this.options
|
||||
this.options,
|
||||
);
|
||||
// check location is validated
|
||||
let authoringLocation = config.location;
|
||||
|
@ -166,7 +166,7 @@ export class AzureResourceMananger {
|
|||
name: config.sku ?? 'F0',
|
||||
},
|
||||
location: authoringLocation,
|
||||
}
|
||||
},
|
||||
);
|
||||
if (deployResult._response.status >= 300) {
|
||||
this.logger({
|
||||
|
@ -175,7 +175,7 @@ export class AzureResourceMananger {
|
|||
});
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.CREATE_LUIS_AUTHORING_RESOURCE_ERROR,
|
||||
deployResult._response.bodyAsText
|
||||
deployResult._response.bodyAsText,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ export class AzureResourceMananger {
|
|||
* @param config
|
||||
*/
|
||||
public async deployLuisResource(
|
||||
config: LuisResourceConfig
|
||||
config: LuisResourceConfig,
|
||||
): Promise<{ endpoint: string; endpointKey: string; location: string }> {
|
||||
try {
|
||||
this.logger({
|
||||
|
@ -208,7 +208,7 @@ export class AzureResourceMananger {
|
|||
const cognitiveServicesManagementClient = new CognitiveServicesManagementClient(
|
||||
this.creds,
|
||||
this.subscriptionId,
|
||||
this.options
|
||||
this.options,
|
||||
);
|
||||
// check luis publish location is validated
|
||||
let authoringLocation = config.location;
|
||||
|
@ -224,7 +224,7 @@ export class AzureResourceMananger {
|
|||
name: config.sku ?? 'S0',
|
||||
},
|
||||
location: authoringLocation,
|
||||
}
|
||||
},
|
||||
);
|
||||
if (deployResult._response.status >= 300) {
|
||||
this.logger({
|
||||
|
@ -281,7 +281,7 @@ export class AzureResourceMananger {
|
|||
replicaCount: 1,
|
||||
partitionCount: 1,
|
||||
hostingMode: 'default',
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (searchServiceDeployResult._response.status >= 300) {
|
||||
|
@ -307,7 +307,7 @@ export class AzureResourceMananger {
|
|||
family: 'S',
|
||||
capacity: 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (servicePlanResult._response.status >= 300) {
|
||||
|
@ -322,7 +322,7 @@ export class AzureResourceMananger {
|
|||
const applicationInsightsManagementClient = new ApplicationInsightsManagementClient(
|
||||
this.creds,
|
||||
this.subscriptionId,
|
||||
this.options
|
||||
this.options,
|
||||
);
|
||||
const appinsightsName = config.resourceGroupName;
|
||||
const appinsightsDeployResult = await applicationInsightsManagementClient.components.createOrUpdate(
|
||||
|
@ -332,7 +332,7 @@ export class AzureResourceMananger {
|
|||
location: config.location,
|
||||
applicationType: 'web',
|
||||
kind: 'web',
|
||||
}
|
||||
},
|
||||
);
|
||||
if (appinsightsDeployResult._response.status >= 300 || appinsightsDeployResult.provisioningState != 'Succeeded') {
|
||||
this.logger({
|
||||
|
@ -348,7 +348,7 @@ export class AzureResourceMananger {
|
|||
).primaryKey;
|
||||
const appInsightsComponent = await applicationInsightsManagementClient.components.get(
|
||||
config.resourceGroupName,
|
||||
appinsightsName
|
||||
appinsightsName,
|
||||
);
|
||||
const userAppInsightsKey = appInsightsComponent.instrumentationKey;
|
||||
const userAppInsightsName = appinsightsName;
|
||||
|
@ -415,7 +415,7 @@ export class AzureResourceMananger {
|
|||
],
|
||||
},
|
||||
enabled: true,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (webAppResult._response.status >= 300) {
|
||||
|
@ -430,7 +430,7 @@ export class AzureResourceMananger {
|
|||
const cognitiveServicesManagementClient = new CognitiveServicesManagementClient(
|
||||
this.creds,
|
||||
this.subscriptionId,
|
||||
this.options
|
||||
this.options,
|
||||
);
|
||||
const deployResult = await cognitiveServicesManagementClient.accounts.create(
|
||||
config.resourceGroupName,
|
||||
|
@ -446,7 +446,7 @@ export class AzureResourceMananger {
|
|||
qnaRuntimeEndpoint: `https://${webAppResult.hostNames?.[0]}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
if (deployResult._response.status >= 300) {
|
||||
this.logger({
|
||||
|
@ -459,7 +459,7 @@ export class AzureResourceMananger {
|
|||
const endpoint = webAppResult.hostNames?.[0];
|
||||
const keys = await cognitiveServicesManagementClient.accounts.listKeys(
|
||||
config.resourceGroupName,
|
||||
qnaMakerServiceName
|
||||
qnaMakerServiceName,
|
||||
);
|
||||
const subscriptionKey = keys?.key1 ?? '';
|
||||
return {
|
||||
|
@ -480,7 +480,7 @@ export class AzureResourceMananger {
|
|||
* @param config
|
||||
*/
|
||||
public async deployAppInsightsResource(
|
||||
config: ApplicationInsightsConfig
|
||||
config: ApplicationInsightsConfig,
|
||||
): Promise<{ instrumentationKey: string; connectionString: string }> {
|
||||
try {
|
||||
this.logger({
|
||||
|
@ -490,7 +490,7 @@ export class AzureResourceMananger {
|
|||
const applicationInsightsManagementClient = new ApplicationInsightsManagementClient(
|
||||
this.creds,
|
||||
this.subscriptionId,
|
||||
this.options
|
||||
this.options,
|
||||
);
|
||||
const deployResult = await applicationInsightsManagementClient.components.createOrUpdate(
|
||||
config.resourceGroupName,
|
||||
|
@ -499,7 +499,7 @@ export class AzureResourceMananger {
|
|||
location: config.location,
|
||||
applicationType: config.applicationType ?? 'web',
|
||||
kind: 'web',
|
||||
}
|
||||
},
|
||||
);
|
||||
if (deployResult._response.status >= 300 || deployResult.provisioningState != 'Succeeded') {
|
||||
this.logger({
|
||||
|
@ -551,7 +551,7 @@ export class AzureResourceMananger {
|
|||
appinsightsApiKeyResponse = await appinsightsClient.aPIKeys.create(
|
||||
config.resourceGroupName,
|
||||
config.name,
|
||||
apiKeyOptions
|
||||
apiKeyOptions,
|
||||
);
|
||||
|
||||
const appinsightsApiKey = appinsightsApiKeyResponse.apiKey;
|
||||
|
@ -583,7 +583,7 @@ export class AzureResourceMananger {
|
|||
this.logger({
|
||||
status: BotProjectDeployLoggerType.PROVISION_ERROR,
|
||||
message: `! Something went wrong while trying to link Application Insights settings to Bot Service Result: ${JSON.stringify(
|
||||
botUpdateResult
|
||||
botUpdateResult,
|
||||
)}`,
|
||||
});
|
||||
throw err;
|
||||
|
@ -632,7 +632,7 @@ export class AzureResourceMananger {
|
|||
failoverPriority: 0,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (dbAccountDeployResult._response.status >= 300 || dbAccountDeployResult.provisioningState != 'Succeeded') {
|
||||
|
@ -653,7 +653,7 @@ export class AzureResourceMananger {
|
|||
id: config.databaseName,
|
||||
},
|
||||
options: {},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (dbDeployResult._response.status >= 300) {
|
||||
|
@ -697,7 +697,7 @@ export class AzureResourceMananger {
|
|||
},
|
||||
},
|
||||
options: {},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (containerCreateResult._response.status >= 300) {
|
||||
|
@ -710,7 +710,7 @@ export class AzureResourceMananger {
|
|||
|
||||
const authKeyResult = await cosmosDBManagementClient.databaseAccounts.listKeys(
|
||||
config.resourceGroupName,
|
||||
config.name
|
||||
config.name,
|
||||
);
|
||||
if (authKeyResult._response.status >= 300) {
|
||||
this.logger({
|
||||
|
@ -744,7 +744,7 @@ export class AzureResourceMananger {
|
|||
* @param config
|
||||
*/
|
||||
public async deployBlobStorageResource(
|
||||
config: BlobStorageConfig
|
||||
config: BlobStorageConfig,
|
||||
): Promise<{ name: string; connectionString: string; container: string }> {
|
||||
try {
|
||||
this.logger({
|
||||
|
@ -770,7 +770,7 @@ export class AzureResourceMananger {
|
|||
|
||||
const accountKeysResult = await storageManagementClient.storageAccounts.listKeys(
|
||||
config.resourceGroupName,
|
||||
config.name
|
||||
config.name,
|
||||
);
|
||||
const connectionString = accountKeysResult?.keys?.[0].value ?? '';
|
||||
|
||||
|
@ -813,7 +813,7 @@ export class AzureResourceMananger {
|
|||
family: 'S',
|
||||
capacity: 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (servicePlanResult._response.status >= 300) {
|
||||
|
@ -916,7 +916,7 @@ export class AzureResourceMananger {
|
|||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (azureFunctionsResult._response.status >= 300) {
|
||||
|
@ -926,7 +926,7 @@ export class AzureResourceMananger {
|
|||
});
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.CREATE_FUNCTIONS_RESOURCE_ERROR,
|
||||
azureFunctionsResult._response.bodyAsText
|
||||
azureFunctionsResult._response.bodyAsText,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ export class BackgroundProcessManager {
|
|||
projectId: string,
|
||||
processName: string,
|
||||
initialMessage?: string,
|
||||
comment?: string
|
||||
comment?: string,
|
||||
): string {
|
||||
const id = uuid();
|
||||
this.processes[id] = {
|
||||
|
|
|
@ -51,7 +51,7 @@ export class BotProjectDeploy {
|
|||
environment: string,
|
||||
hostname?: string,
|
||||
luisResource?: string,
|
||||
absSettings?: any
|
||||
absSettings?: any,
|
||||
) {
|
||||
try {
|
||||
this.logger(absSettings);
|
||||
|
@ -100,7 +100,7 @@ export class BotProjectDeploy {
|
|||
settings.luis,
|
||||
luisResource,
|
||||
this.projPath,
|
||||
this.logger
|
||||
this.logger,
|
||||
);
|
||||
|
||||
const qnaConfig = await project.builder.getQnaConfig();
|
||||
|
@ -127,14 +127,14 @@ export class BotProjectDeploy {
|
|||
path.join(pathToArtifacts, 'manifests'),
|
||||
project.fileStorage,
|
||||
path.join(pathToArtifacts, 'wwwroot', 'manifests'),
|
||||
project.fileStorage
|
||||
project.fileStorage,
|
||||
);
|
||||
// Update skill endpoint url in skill manifest.
|
||||
await this.updateSkillSettings(
|
||||
profileName,
|
||||
hostname,
|
||||
settings.MicrosoftAppId,
|
||||
path.join(pathToArtifacts, 'wwwroot', 'manifests')
|
||||
path.join(pathToArtifacts, 'wwwroot', 'manifests'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ export class BotProjectDeploy {
|
|||
hostname,
|
||||
absSettings.subscriptionId,
|
||||
absSettings.resourceGroup,
|
||||
linuxFxVersion
|
||||
linuxFxVersion,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ export class BotProjectDeploy {
|
|||
name: string,
|
||||
env: string,
|
||||
hostname?: string,
|
||||
scmHostDomain?: string
|
||||
scmHostDomain?: string,
|
||||
) {
|
||||
this.logger({
|
||||
status: BotProjectDeployLoggerType.DEPLOY_INFO,
|
||||
|
@ -351,7 +351,7 @@ export class BotProjectDeploy {
|
|||
const errorMessage = JSON.stringify(err, Object.getOwnPropertyNames(err));
|
||||
throw createCustomizeError(
|
||||
AzurePublishErrors.DEPLOY_ZIP_ERROR,
|
||||
`There was a problem publishing bot assets (zip deploy). ${errorMessage}`
|
||||
`There was a problem publishing bot assets (zip deploy). ${errorMessage}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -370,7 +370,7 @@ export class BotProjectDeploy {
|
|||
hostname: string,
|
||||
subscriptionId: string,
|
||||
resourceGroup: string,
|
||||
linuxFxVersion: string
|
||||
linuxFxVersion: string,
|
||||
) {
|
||||
try {
|
||||
const updateEndpoint = this.buildUpdateEndpoint(hostname, name, env, subscriptionId, resourceGroup);
|
||||
|
@ -379,7 +379,7 @@ export class BotProjectDeploy {
|
|||
{
|
||||
properties: { linuxFxVersion: linuxFxVersion },
|
||||
},
|
||||
{ headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' } }
|
||||
{ headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' } },
|
||||
);
|
||||
|
||||
if (response.status === 200) {
|
||||
|
@ -392,7 +392,7 @@ export class BotProjectDeploy {
|
|||
const errorMessage = JSON.stringify(err, Object.getOwnPropertyNames(err));
|
||||
throw createCustomizeError(
|
||||
AzurePublishErrors.DEPLOY_ZIP_ERROR,
|
||||
`There was a problem updating the bot's settings. ${errorMessage}`
|
||||
`There was a problem updating the bot's settings. ${errorMessage}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +402,7 @@ export class BotProjectDeploy {
|
|||
name: string,
|
||||
env: string,
|
||||
subscriptionId: string,
|
||||
resourceGroupName: string
|
||||
resourceGroupName: string,
|
||||
) => {
|
||||
const hostnameResult = hostname ? hostname : name + (env ? '-' + env : '');
|
||||
return `https://management.azure.com/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.Web/sites/${hostnameResult}/config/web?api-version=2022-03-01`;
|
||||
|
@ -553,7 +553,7 @@ export class BotProjectDeploy {
|
|||
private async getTenantId(accessToken: string, subId: string) {
|
||||
if (!accessToken) {
|
||||
throw new Error(
|
||||
'Error: Missing access token. Please provide a non-expired Azure access token. Tokens can be obtained by running az account get-access-token'
|
||||
'Error: Missing access token. Please provide a non-expired Azure access token. Tokens can be obtained by running az account get-access-token',
|
||||
);
|
||||
}
|
||||
if (!subId) {
|
||||
|
|
|
@ -167,7 +167,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
profileName: string,
|
||||
jobId: string,
|
||||
resourcekey: string,
|
||||
customizeConfiguration: DeployResources
|
||||
customizeConfiguration: DeployResources,
|
||||
) => {
|
||||
const { accessToken, name, environment, hostname, luisResource, abs } = customizeConfiguration;
|
||||
|
||||
|
@ -251,7 +251,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
profileName,
|
||||
jobId,
|
||||
resourcekey,
|
||||
customizeConfiguration
|
||||
customizeConfiguration,
|
||||
);
|
||||
} catch (err) {
|
||||
this.logger('%O', err);
|
||||
|
@ -259,7 +259,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
await this.updateHistory(
|
||||
project.id,
|
||||
profileName,
|
||||
publishResultFromStatus(BackgroundProcessManager.getStatus(jobId)).result
|
||||
publishResultFromStatus(BackgroundProcessManager.getStatus(jobId)).result,
|
||||
);
|
||||
BackgroundProcessManager.removeProcess(jobId);
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
project.id,
|
||||
profileName,
|
||||
'Accepted for publishing...',
|
||||
metadata.comment
|
||||
metadata.comment,
|
||||
);
|
||||
|
||||
// resource key to map to one provision resource
|
||||
|
@ -420,8 +420,8 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
throw new Error(
|
||||
formatMessage(
|
||||
'There was a problem publishing {projectName}/{profileName}. The profile has not been provisioned yet.',
|
||||
{ projectName: project.name, profileName }
|
||||
)
|
||||
{ projectName: project.name, profileName },
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -440,8 +440,8 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
throw new Error(
|
||||
formatMessage(
|
||||
'There was a problem publishing {projectName}/{profileName}. These required resources have not been provisioned: {missingResourcesText}',
|
||||
{ projectName: project.name, profileName, missingResourcesText }
|
||||
)
|
||||
{ projectName: project.name, profileName, missingResourcesText },
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -522,7 +522,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
processName: string,
|
||||
project: IBotProject,
|
||||
user,
|
||||
jobId = ''
|
||||
jobId = '',
|
||||
): Promise<ProcessStatus> => {
|
||||
const botId = project.id;
|
||||
// get status by Job ID first.
|
||||
|
@ -554,7 +554,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
const hasLuContent = luResources.some((luResource) => luResource.content?.trim() !== '');
|
||||
|
||||
const hasLuisRecognizers = recognizers.some(
|
||||
(recognizer) => recognizer.content?.$kind === SDKKinds.LuisRecognizer
|
||||
(recognizer) => recognizer.content?.$kind === SDKKinds.LuisRecognizer,
|
||||
);
|
||||
|
||||
const requiresLUIS = hasLuContent && hasLuisRecognizers;
|
||||
|
@ -673,7 +673,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
return !!profile?.hostname;
|
||||
default:
|
||||
throw new Error(
|
||||
formatMessage('Azure resource type {resourceKey} is not handled.', { resourceKey: resource.key })
|
||||
formatMessage('Azure resource type {resourceKey} is not handled.', { resourceKey: resource.key }),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -55,7 +55,7 @@ export class KeyVaultApi {
|
|||
vaultName: string,
|
||||
email: string,
|
||||
objectId: string,
|
||||
tenantId: string
|
||||
tenantId: string,
|
||||
) {
|
||||
const keyVaultManagementClient = new KeyVaultManagementClient(this.creds, this.subscriptionId);
|
||||
const setResult = await keyVaultManagementClient.vaults.update(resourceGroupName, vaultName, {
|
||||
|
@ -129,7 +129,7 @@ export class KeyVaultApi {
|
|||
properties: {
|
||||
MicrosoftAppPassword: `@Microsoft.KeyVault(SecretUri=${secretUri})`,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
if (updateResult._response.status >= 300) {
|
||||
this.logger({
|
||||
|
@ -149,7 +149,7 @@ export class KeyVaultApi {
|
|||
properties: {
|
||||
MicrosoftAppPassword: secretValue,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
if (updateResult._response.status >= 300) {
|
||||
this.logger({
|
||||
|
|
|
@ -24,7 +24,7 @@ type Resources = {
|
|||
qnaResources: Resource[];
|
||||
};
|
||||
|
||||
export type BuildSettingType<T = {}> = {
|
||||
export type BuildSettingType<T = NonNullable<unknown>> = {
|
||||
[K in keyof T]: T[K];
|
||||
} & {
|
||||
luis: ILuisConfig;
|
||||
|
@ -87,7 +87,7 @@ export async function publishLuisToPrediction(
|
|||
luisSettings: ILuisConfig,
|
||||
luisResource: string,
|
||||
path: string,
|
||||
logger
|
||||
logger,
|
||||
) {
|
||||
let {
|
||||
// eslint-disable-next-line prefer-const
|
||||
|
@ -153,7 +153,7 @@ export async function publishLuisToPrediction(
|
|||
const error = JSON.parse(err.error);
|
||||
if (error?.error?.message && error?.error?.message.indexOf('access token expiry') > 0) {
|
||||
throw new Error(
|
||||
`Type: ${error?.error?.code}, Message: ${error?.error?.message}, run az account get-access-token, then replace the accessToken in your configuration`
|
||||
`Type: ${error?.error?.code}, Message: ${error?.error?.message}, run az account get-access-token, then replace the accessToken in your configuration`,
|
||||
);
|
||||
} else {
|
||||
throw err;
|
||||
|
@ -200,7 +200,7 @@ export async function publishLuisToPrediction(
|
|||
const error = JSON.parse(err.error);
|
||||
if (error?.error?.message && error?.error?.message.indexOf('access token expiry') > 0) {
|
||||
throw new Error(
|
||||
`Type: ${error?.error?.code}, Message: ${error?.error?.message}, run az account get-access-token, then replace the accessToken in your configuration`
|
||||
`Type: ${error?.error?.code}, Message: ${error?.error?.message}, run az account get-access-token, then replace the accessToken in your configuration`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ export async function publishLuisToPrediction(
|
|||
throw Error(
|
||||
`Failed to bind luis prediction resource to luis applications. Please check if your luisResource is set to luis prediction service name in your publish profile.
|
||||
${luisDebugInfo}.
|
||||
${luisError}`
|
||||
${luisError}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { BotProjectProvision, ProvisionConfig } from './provision';
|
||||
|
||||
const mockConfig = ({
|
||||
const mockConfig = {
|
||||
logger: console.log,
|
||||
accessToken: 'accessToken',
|
||||
graphToken: 'graphToken',
|
||||
|
@ -18,7 +18,7 @@ const mockConfig = ({
|
|||
name: 'profileName',
|
||||
type: 'azurepublish',
|
||||
subscription: 'test',
|
||||
} as unknown) as ProvisionConfig;
|
||||
} as unknown as ProvisionConfig;
|
||||
|
||||
const azProvision = new BotProjectProvision(mockConfig);
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ export class BotProjectProvision {
|
|||
logErrorMsg('App create', err.message);
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.CREATE_APP_REGISTRATION,
|
||||
'App create failed! Please file an issue on Github.'
|
||||
'App create failed! Please file an issue on Github.',
|
||||
);
|
||||
} else {
|
||||
await this.sleep(3000);
|
||||
|
@ -170,7 +170,7 @@ export class BotProjectProvision {
|
|||
logErrorMsg('Add application password', err.message);
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.CREATE_APP_REGISTRATION,
|
||||
'Add application password failed! Please file an issue on Github.'
|
||||
'Add application password failed! Please file an issue on Github.',
|
||||
);
|
||||
} else {
|
||||
await this.sleep(3000);
|
||||
|
@ -199,13 +199,13 @@ export class BotProjectProvision {
|
|||
if (!this.accessToken) {
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.GET_TENANTID,
|
||||
'Error: Missing access token. Please provide a non-expired Azure access token. Tokens can be obtained by running az account get-access-token'
|
||||
'Error: Missing access token. Please provide a non-expired Azure access token. Tokens can be obtained by running az account get-access-token',
|
||||
);
|
||||
}
|
||||
if (!this.subscriptionId) {
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.GET_TENANTID,
|
||||
`Error: Missing subscription Id. Please provide a valid Azure subscription id.`
|
||||
`Error: Missing subscription Id. Please provide a valid Azure subscription id.`,
|
||||
);
|
||||
}
|
||||
try {
|
||||
|
@ -222,7 +222,7 @@ export class BotProjectProvision {
|
|||
} catch (err) {
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.GET_TENANTID,
|
||||
`Get Tenant Id Failed, details: ${this.getErrorMesssage(err)}`
|
||||
`Get Tenant Id Failed, details: ${this.getErrorMesssage(err)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export async function copyDir(
|
|||
srcStorage: IFileStorage,
|
||||
dstDir: string,
|
||||
dstStorage: IFileStorage,
|
||||
pathsToExclude?: Set<string>
|
||||
pathsToExclude?: Set<string>,
|
||||
) {
|
||||
if (!(await srcStorage.exists(srcDir)) || !(await srcStorage.stat(srcDir)).isDir) {
|
||||
throw new Error(`No such dir ${srcDir}}`);
|
||||
|
|
|
@ -35,7 +35,7 @@ export const getSubscriptions = async (token: string): Promise<Array<Subscriptio
|
|||
let message = JSON.stringify(err, Object.getOwnPropertyNames(err));
|
||||
if (err?.code === 12 && err?.message?.match(/Bearer/gi)) {
|
||||
message = formatMessage(
|
||||
'There was an authentication problem retrieving subscriptions. Verify your login session has not expired and you have permission to list subscriptions in this account.'
|
||||
'There was an authentication problem retrieving subscriptions. Verify your login session has not expired and you have permission to list subscriptions in this account.',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ export const getDeployLocations = async (token: string, subscriptionId: string)
|
|||
`https://management.azure.com/subscriptions/${subscriptionId}/locations?api-version=2019-10-01`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
}
|
||||
},
|
||||
);
|
||||
return result.data.value;
|
||||
} catch (error) {
|
||||
|
@ -98,7 +98,7 @@ export const getDeployLocations = async (token: string, subscriptionId: string)
|
|||
export const checkWebAppNameAvailability = async (
|
||||
token: string,
|
||||
webAppName: string,
|
||||
subscriptionId: string
|
||||
subscriptionId: string,
|
||||
): Promise<ResourceNameAvailability> => {
|
||||
try {
|
||||
if (!webAppName) {
|
||||
|
@ -125,7 +125,7 @@ export const checkWebAppNameAvailability = async (
|
|||
const webSiteManagementClient = new WebSiteManagementClient(credentials, subscriptionId);
|
||||
const getCheckNameAvailabilityResult = await webSiteManagementClient.checkNameAvailability(
|
||||
webAppName,
|
||||
'Microsoft.Web/sites'
|
||||
'Microsoft.Web/sites',
|
||||
);
|
||||
if (getCheckNameAvailabilityResult._response.status >= 300) {
|
||||
logger({
|
||||
|
|
|
@ -30,7 +30,7 @@ const Root = styled.div<RootStyleProps>(
|
|||
grid-template-columns: 1fr;
|
||||
grid-auto-rows: auto;
|
||||
}
|
||||
`
|
||||
`,
|
||||
);
|
||||
|
||||
export const AzureProvisionWizard = () => {
|
||||
|
|
|
@ -73,7 +73,7 @@ export const CreateResourcesWizard = React.memo((props: Props) => {
|
|||
{children}
|
||||
</a>
|
||||
),
|
||||
}
|
||||
},
|
||||
),
|
||||
onRenderContent: () => (
|
||||
<ChooseResourcesStep enabledResources={enabledResources} onChangeSelection={setEnabledResources} />
|
||||
|
@ -84,7 +84,7 @@ export const CreateResourcesWizard = React.memo((props: Props) => {
|
|||
id: 'review-resources',
|
||||
title: formatMessage('Review resources to be created'),
|
||||
subTitle: formatMessage(
|
||||
'The following resources will be created and provisioned for your bot. Once provisioned, they will be available in the Azure portal.'
|
||||
'The following resources will be created and provisioned for your bot. Once provisioned, they will be available in the Azure portal.',
|
||||
),
|
||||
onRenderContent: () => <ReviewResourcesStep />,
|
||||
navigationState: { nextText: formatMessage('Done') },
|
||||
|
|
|
@ -62,7 +62,7 @@ export const HandOffToAdminWizard = React.memo((props: Props) => {
|
|||
{children}
|
||||
</a>
|
||||
),
|
||||
}
|
||||
},
|
||||
),
|
||||
onRenderContent: () => (
|
||||
<ChooseResourcesStep enabledResources={resources} onChangeSelection={setEnabledHandOffResources} />
|
||||
|
@ -85,7 +85,7 @@ export const HandOffToAdminWizard = React.memo((props: Props) => {
|
|||
{showHandOff && (
|
||||
<ProvisionHandoff
|
||||
developerInstructions={formatMessage(
|
||||
'If Azure resources and subscription are managed by others, use the following information to request creation of the resources that you need to build and run your bot.'
|
||||
'If Azure resources and subscription are managed by others, use the following information to request creation of the resources that you need to build and run your bot.',
|
||||
)}
|
||||
handoffInstructions={handOffInstructions}
|
||||
hidden={!showHandOff}
|
||||
|
|
|
@ -51,7 +51,7 @@ export const CreateResourceInstructionsStep = () => {
|
|||
<Summary>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Select this option when you want to provision new Azure resources and publish a bot. A subscription to'
|
||||
'Select this option when you want to provision new Azure resources and publish a bot. A subscription to',
|
||||
)}
|
||||
</Text>
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ export const HandOffInstructionsStep = () => {
|
|||
<Summary>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Select this option to request your Azure admin to provision resources on your behalf, for example, when you don’t have proper permissions to use Azure or you want to generate resources from a sovereign cloud.'
|
||||
'Select this option to request your Azure admin to provision resources on your behalf, for example, when you don’t have proper permissions to use Azure or you want to generate resources from a sovereign cloud.',
|
||||
)}
|
||||
</Text>
|
||||
</Summary>
|
||||
|
@ -59,7 +59,7 @@ export const HandOffInstructionsStep = () => {
|
|||
<InstructionDetails>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Add resources you need for the bot and generate a resource request to share with your Azure admin.'
|
||||
'Add resources you need for the bot and generate a resource request to share with your Azure admin.',
|
||||
)}
|
||||
</Text>
|
||||
</InstructionDetails>
|
||||
|
@ -69,7 +69,7 @@ export const HandOffInstructionsStep = () => {
|
|||
<InstructionDetails>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Once you get the resource details from your Azure admin, use them to import existing resources.'
|
||||
'Once you get the resource details from your Azure admin, use them to import existing resources.',
|
||||
)}
|
||||
</Text>
|
||||
</InstructionDetails>
|
||||
|
|
|
@ -36,14 +36,14 @@ export const ImportInstructionsStep = () => {
|
|||
<Summary>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Select this option if you have access to existing Azure resources and their associated values.'
|
||||
'Select this option if you have access to existing Azure resources and their associated values.',
|
||||
)}
|
||||
</Text>
|
||||
</Summary>
|
||||
<Summary>
|
||||
<Text>
|
||||
{formatMessage(
|
||||
'Copy and paste the JSON file containing the values of your existing Azure resources, from the Azure portal. This file includes values for some or all of the following:'
|
||||
'Copy and paste the JSON file containing the values of your existing Azure resources, from the Azure portal. This file includes values for some or all of the following:',
|
||||
)}
|
||||
</Text>
|
||||
</Summary>
|
||||
|
|
|
@ -166,8 +166,8 @@ export const ResourceConfigurationStep = (props: Props) => {
|
|||
</ConfigureResourcesPropertyLabel>
|
||||
{renderPropertyInfoIcon(
|
||||
formatMessage(
|
||||
'A custom resource group name that you choose or create. Resource groups allow you to group Azure resources for access and management.'
|
||||
)
|
||||
'A custom resource group name that you choose or create. Resource groups allow you to group Azure resources for access and management.',
|
||||
),
|
||||
)}
|
||||
</Stack>
|
||||
<ResourceGroupPicker
|
||||
|
@ -193,7 +193,7 @@ export const ResourceConfigurationStep = (props: Props) => {
|
|||
{formatMessage('Operating System')}
|
||||
</ConfigureResourcesPropertyLabel>
|
||||
{renderPropertyInfoIcon(
|
||||
formatMessage('Select the operating system that will host your application service.')
|
||||
formatMessage('Select the operating system that will host your application service.'),
|
||||
)}
|
||||
</Stack>
|
||||
<OperatingSystemChoiceGroup
|
||||
|
|
|
@ -119,7 +119,7 @@ export const ReviewResourcesStep = () => {
|
|||
isPadded: true,
|
||||
},
|
||||
],
|
||||
[]
|
||||
[],
|
||||
);
|
||||
|
||||
const reviewListItems = React.useMemo(() => {
|
||||
|
|
|
@ -51,7 +51,7 @@ export const DeployLocationPicker = React.memo((props: Props) => {
|
|||
placeholder: formatMessage('Select Region'),
|
||||
errorMessage,
|
||||
}),
|
||||
[errorMessage]
|
||||
[errorMessage],
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -59,7 +59,7 @@ export const DeployLocationPicker = React.memo((props: Props) => {
|
|||
isLoading={isLoading}
|
||||
items={sortBy(
|
||||
deployLocations.map((t) => ({ key: t.name, text: t.displayName })),
|
||||
[(location) => location.text]
|
||||
[(location) => location.text],
|
||||
)}
|
||||
onSubmit={(option) => props.onChangeDeployLocation(option.key)}
|
||||
{...{
|
||||
|
|
|
@ -19,14 +19,8 @@ type Props = {
|
|||
} & Omit<SearchableDropdownProps, 'items' | 'onSubmit' | 'creationProps'>;
|
||||
|
||||
export const ResourceGroupPicker = React.memo((props: Props) => {
|
||||
const {
|
||||
onChangeResourceGroup,
|
||||
accessToken,
|
||||
subscriptionId,
|
||||
value,
|
||||
isNewResourceGroup,
|
||||
onValidateResourceGroupName,
|
||||
} = props;
|
||||
const { onChangeResourceGroup, accessToken, subscriptionId, value, isNewResourceGroup, onValidateResourceGroupName } =
|
||||
props;
|
||||
|
||||
const [resourceGroups, setResourceGroups] = useState<ResourceGroup[]>([]);
|
||||
const [errorMessage, setErrorMessage] = useState<string>('');
|
||||
|
@ -42,8 +36,8 @@ export const ResourceGroupPicker = React.memo((props: Props) => {
|
|||
if (debouncedNewName && !debouncedNewName.match(/^[-\w._()]+$/)) {
|
||||
setNewNameErrorMessage(
|
||||
formatMessage(
|
||||
'Resource group names only allow alphanumeric characters, periods, underscores, hyphens and parenthesis and cannot end in a period.'
|
||||
)
|
||||
'Resource group names only allow alphanumeric characters, periods, underscores, hyphens and parenthesis and cannot end in a period.',
|
||||
),
|
||||
);
|
||||
} else if (alreadyExists) {
|
||||
setNewNameErrorMessage(formatMessage('A resource with this name already exists.'));
|
||||
|
@ -83,12 +77,12 @@ export const ResourceGroupPicker = React.memo((props: Props) => {
|
|||
placeholder: formatMessage('Select Resource Group'),
|
||||
errorMessage,
|
||||
}),
|
||||
[errorMessage]
|
||||
[errorMessage],
|
||||
);
|
||||
|
||||
const creationItem = React.useMemo(
|
||||
() => ({ key: 'CREATE_NEW_RESOURCE_GROUP', text: formatMessage('Create new resource group') }),
|
||||
[]
|
||||
[],
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -31,8 +31,8 @@ export const SubscriptionPicker = React.memo((props: Props) => {
|
|||
if (subscriptions.length === 0) {
|
||||
setErrorMessage(
|
||||
formatMessage(
|
||||
'Your subscription list is empty, please add your subscription, or login with another account.'
|
||||
)
|
||||
'Your subscription list is empty, please add your subscription, or login with another account.',
|
||||
),
|
||||
);
|
||||
}
|
||||
setSubscriptions(subscriptions);
|
||||
|
@ -51,7 +51,7 @@ export const SubscriptionPicker = React.memo((props: Props) => {
|
|||
placeholder: formatMessage('Select subscription'),
|
||||
errorMessage,
|
||||
}),
|
||||
[errorMessage]
|
||||
[errorMessage],
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -75,7 +75,7 @@ export const TenantPicker = memo((props: Props) => {
|
|||
setErrorMessage(
|
||||
formatMessage('There was a problem loading Azure directories. {errMessage}', {
|
||||
errMessage: err.message || err.toString(),
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
})();
|
||||
|
@ -101,7 +101,7 @@ export const TenantPicker = memo((props: Props) => {
|
|||
setErrorMessage(
|
||||
formatMessage('There was a problem getting the access token for the current Azure directory. {errMessage}', {
|
||||
errMessage: ex.message || ex.toString(),
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -120,7 +120,7 @@ export const TenantPicker = memo((props: Props) => {
|
|||
placeholder: formatMessage('Select Azure directory'),
|
||||
errorMessage,
|
||||
}),
|
||||
[errorMessage, tenants]
|
||||
[errorMessage, tenants],
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -239,7 +239,7 @@ const getNextIteratorValue = (iterator: number, direction: 'forward' | 'backward
|
|||
const getNextSelectableItem = (
|
||||
items: IContextualMenuItem[],
|
||||
selectedIndex: number,
|
||||
direction: 'forward' | 'backward'
|
||||
direction: 'forward' | 'backward',
|
||||
) => {
|
||||
if (!items.length) {
|
||||
return undefined;
|
||||
|
@ -423,9 +423,10 @@ export const SearchableDropdown = (props: SearchableDropdownProps) => {
|
|||
*/
|
||||
const calloutTarget = rootRef.current?.querySelector('.ms-TextField-wrapper');
|
||||
|
||||
const createNewItem = React.useMemo(() => creationItem ?? { key: 'CREATE_NEW', text: formatMessage('Create New') }, [
|
||||
creationItem,
|
||||
]);
|
||||
const createNewItem = React.useMemo(
|
||||
() => creationItem ?? { key: 'CREATE_NEW', text: formatMessage('Create New') },
|
||||
[creationItem],
|
||||
);
|
||||
|
||||
if (allowCreation) {
|
||||
filteredItems.unshift(createNewItem);
|
||||
|
@ -690,7 +691,7 @@ export const SearchableDropdown = (props: SearchableDropdownProps) => {
|
|||
* utilize it.
|
||||
*/
|
||||
const onRenderTextFieldLabel = () => {
|
||||
if (!textFieldProps || !textFieldProps.label) {
|
||||
if (!textFieldProps?.label) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,5 +58,5 @@ export const SearchableDropdownTextField = React.forwardRef(
|
|||
onKeyDown={interceptKeyDown}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
@ -18,7 +18,7 @@ export const substringSearchStrategy = <T, K extends keyof T>(
|
|||
haystack: T[],
|
||||
needle: string,
|
||||
keyParam?: K,
|
||||
searchFn?: (item: T, query: string) => boolean
|
||||
searchFn?: (item: T, query: string) => boolean,
|
||||
): T[] => {
|
||||
const query = (needle || '').toLocaleLowerCase();
|
||||
|
||||
|
|
|
@ -32,17 +32,17 @@ export const UserPersona = (props: Props) => {
|
|||
const isSignedOut = await logOut();
|
||||
if (isSignedOut) {
|
||||
addNotification(
|
||||
getLogoutNotificationSettings(formatMessage('You have successfully signed out of Azure'), 'info')
|
||||
getLogoutNotificationSettings(formatMessage('You have successfully signed out of Azure'), 'info'),
|
||||
);
|
||||
closeDialog();
|
||||
} else {
|
||||
addNotification(
|
||||
getLogoutNotificationSettings(
|
||||
formatMessage(
|
||||
'There was an error attempting to sign out of Azure. To complete sign out, you may need to restart Composer.'
|
||||
'There was an error attempting to sign out of Azure. To complete sign out, you may need to restart Composer.',
|
||||
),
|
||||
'error'
|
||||
)
|
||||
'error',
|
||||
),
|
||||
);
|
||||
}
|
||||
}, [addNotification]);
|
||||
|
@ -57,13 +57,13 @@ export const UserPersona = (props: Props) => {
|
|||
const confirmed = await OpenConfirmModal(
|
||||
formatMessage('Sign out of Azure'),
|
||||
formatMessage(
|
||||
'By signing out of Azure, your new publishing profile will be canceled and this dialog will close. Do you want to continue?'
|
||||
'By signing out of Azure, your new publishing profile will be canceled and this dialog will close. Do you want to continue?',
|
||||
),
|
||||
{
|
||||
onRenderContent: (subtitle: string) => <div>{subtitle}</div>,
|
||||
confirmText: formatMessage('Sign out'),
|
||||
cancelText: formatMessage('Cancel'),
|
||||
}
|
||||
},
|
||||
);
|
||||
if (confirmed) {
|
||||
await signoutAndNotify();
|
||||
|
@ -75,7 +75,7 @@ export const UserPersona = (props: Props) => {
|
|||
</div>
|
||||
);
|
||||
},
|
||||
[signoutAndNotify, props.onSignOut]
|
||||
[signoutAndNotify, props.onSignOut],
|
||||
);
|
||||
return <Persona {...props} onRenderSecondaryText={props.onRenderSecondaryText || onRenderSecondaryText} />;
|
||||
};
|
||||
|
|
|
@ -45,7 +45,7 @@ export const useHandOffInstructions = () => {
|
|||
'Provisoning Command:\n' +
|
||||
'{command}\n\n' +
|
||||
'Detailed instructions:\nhttps://aka.ms/how-to-complete-provision-handoff',
|
||||
{ command: provisionComposer }
|
||||
{ command: provisionComposer },
|
||||
);
|
||||
}, [resources, subscriptionId, hostName, deployRegion, resourceGroupName]);
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@ const isUsingAdaptiveRuntimeKey = (runtimeKey?: string): boolean =>
|
|||
runtimeKey === 'csharp-azurewebapp-v2' || !!runtimeKey?.startsWith('adaptive-runtime-');
|
||||
|
||||
const parseRuntimeKey = (
|
||||
runtimeKey?: string
|
||||
runtimeKey?: string,
|
||||
): { isUsingAdaptiveRuntime: boolean; runtimeLanguage?: string; runtimeType?: string } => {
|
||||
const isAdaptive = isUsingAdaptiveRuntimeKey(runtimeKey);
|
||||
|
||||
|
|
|
@ -47,10 +47,10 @@ export const useResourceConfiguration = () => {
|
|||
requireUserLogin(publishConfig?.tenantId, { requireGraph: true }); //use tenantId from import config if present
|
||||
}, [isAuthenticated]);
|
||||
|
||||
const hasErrors = React.useMemo(() => isInvalidResourceGroupName || isInvalidHostName, [
|
||||
isInvalidHostName,
|
||||
isInvalidResourceGroupName,
|
||||
]);
|
||||
const hasErrors = React.useMemo(
|
||||
() => isInvalidResourceGroupName || isInvalidHostName,
|
||||
[isInvalidHostName, isInvalidResourceGroupName],
|
||||
);
|
||||
|
||||
const isValidConfiguration = React.useMemo(
|
||||
(): boolean =>
|
||||
|
@ -63,7 +63,7 @@ export const useResourceConfiguration = () => {
|
|||
!luisRegion ||
|
||||
!hostName
|
||||
),
|
||||
[currentTenant, subscriptionId, resourceGroupName, hasErrors, deployLocation, luisRegion, hostName]
|
||||
[currentTenant, subscriptionId, resourceGroupName, hasErrors, deployLocation, luisRegion, hostName],
|
||||
);
|
||||
|
||||
const handleChangeSubscription = React.useCallback((subscriptionId: string) => {
|
||||
|
@ -83,7 +83,7 @@ export const useResourceConfiguration = () => {
|
|||
(isValid: boolean) => {
|
||||
setIsInvalidResourceGroupName(isValid);
|
||||
},
|
||||
[setIsInvalidResourceGroupName]
|
||||
[setIsInvalidResourceGroupName],
|
||||
);
|
||||
|
||||
const handleChangeDeployLocation = React.useCallback((deployLocationId: string) => {
|
||||
|
@ -95,7 +95,7 @@ export const useResourceConfiguration = () => {
|
|||
setLuisRegion(
|
||||
(LuisAuthoringSupportLocation.includes(deployLocation)
|
||||
? deployLocation
|
||||
: LuisAuthoringSupportLocation[0]) as LuisRegion
|
||||
: LuisAuthoringSupportLocation[0]) as LuisRegion,
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
|
|
|
@ -44,7 +44,7 @@ const appInsightsProvisionMethod = (provisionConfig: ProvisionServiceConfig) =>
|
|||
|
||||
const applicationInsightsManagementClient = new ApplicationInsightsManagementClient(
|
||||
tokenCredentials,
|
||||
provisionConfig.subscriptionId
|
||||
provisionConfig.subscriptionId,
|
||||
);
|
||||
|
||||
const botServiceClient = new AzureBotService(tokenCredentials, provisionConfig.subscriptionId);
|
||||
|
@ -57,7 +57,7 @@ const appInsightsProvisionMethod = (provisionConfig: ProvisionServiceConfig) =>
|
|||
location: resourceConfig.location,
|
||||
applicationType: resourceConfig.applicationType ?? 'web',
|
||||
kind: 'web',
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
type ApiKeyOptions = {
|
||||
|
@ -86,7 +86,7 @@ const appInsightsProvisionMethod = (provisionConfig: ProvisionServiceConfig) =>
|
|||
appInsightsClient: ApplicationInsightsManagementClient,
|
||||
botServiceClient: AzureBotService,
|
||||
apiKeyOptions: ApiKeyOptions,
|
||||
config: AppInsightsResourceConfig
|
||||
config: AppInsightsResourceConfig,
|
||||
) => {
|
||||
const appComponents = await appInsightsClient.components.get(config.resourceGroupName, config.name);
|
||||
const appInsightsId = appComponents.appId;
|
||||
|
@ -95,7 +95,7 @@ const appInsightsProvisionMethod = (provisionConfig: ProvisionServiceConfig) =>
|
|||
const appInsightsApiKeyResponse = await appInsightsClient.aPIKeys.create(
|
||||
config.resourceGroupName,
|
||||
config.name,
|
||||
apiKeyOptions
|
||||
apiKeyOptions,
|
||||
);
|
||||
|
||||
const appInsightsApiKey = appInsightsApiKeyResponse.apiKey;
|
||||
|
@ -113,7 +113,7 @@ const appInsightsProvisionMethod = (provisionConfig: ProvisionServiceConfig) =>
|
|||
|
||||
return async (
|
||||
resourceConfig: AppInsightsResourceConfig,
|
||||
workingSet: ProvisionWorkingSet
|
||||
workingSet: ProvisionWorkingSet,
|
||||
): Promise<ProvisionWorkingSet> => {
|
||||
try {
|
||||
const deployResult = await createOrUpdateAppInsightsComponent(resourceConfig);
|
||||
|
@ -124,7 +124,7 @@ const appInsightsProvisionMethod = (provisionConfig: ProvisionServiceConfig) =>
|
|||
applicationInsightsManagementClient,
|
||||
botServiceClient,
|
||||
apiKeyOptions,
|
||||
resourceConfig
|
||||
resourceConfig,
|
||||
);
|
||||
|
||||
const provisionResult = {
|
||||
|
|
|
@ -45,7 +45,7 @@ const postRequestWithRetry = async (requestUri: string, requestOptions: AxiosReq
|
|||
} else if (retryCount == 0) {
|
||||
throw createCustomizeError(
|
||||
ProvisionErrors.CREATE_APP_REGISTRATION,
|
||||
'App create failed! Please file an issue on Github.'
|
||||
'App create failed! Please file an issue on Github.',
|
||||
);
|
||||
} else {
|
||||
await sleep(3000);
|
||||
|
@ -93,7 +93,7 @@ const appRegistrationProvisionMethod = (provisionConfig: ProvisionServiceConfig)
|
|||
|
||||
return async (
|
||||
resourceConfig: AppRegistrationResourceConfig,
|
||||
workingSet: ProvisionWorkingSet
|
||||
workingSet: ProvisionWorkingSet,
|
||||
): Promise<ProvisionWorkingSet> => {
|
||||
const { appName } = resourceConfig;
|
||||
const { appId, id } = await createApp(appName);
|
||||
|
|
|
@ -90,7 +90,7 @@ const azureFunctionsProvisionMethod = (provisionConfig: ProvisionServiceConfig):
|
|||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const hostname = azureFunctionsResult?.hostNames?.[0];
|
||||
|
|
|
@ -65,7 +65,7 @@ const blobStorageProvisionMethod = (provisionConfig: ProvisionServiceConfig): Pr
|
|||
|
||||
const accountKeysResult = await storageManagementClient.storageAccounts.listKeys(
|
||||
config.resourceGroupName,
|
||||
config.name
|
||||
config.name,
|
||||
);
|
||||
const connectionString = accountKeysResult?.keys?.[0]?.value ?? '';
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ const cosmosDbProvisionMethod = (provisionConfig: ProvisionServiceConfig): Provi
|
|||
failoverPriority: 0,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -78,7 +78,7 @@ const cosmosDbProvisionMethod = (provisionConfig: ProvisionServiceConfig): Provi
|
|||
id: config.databaseName,
|
||||
},
|
||||
options: {},
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -115,7 +115,7 @@ const cosmosDbProvisionMethod = (provisionConfig: ProvisionServiceConfig): Provi
|
|||
},
|
||||
},
|
||||
options: {},
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -123,32 +123,31 @@ const cosmosDbProvisionMethod = (provisionConfig: ProvisionServiceConfig): Provi
|
|||
return await cosmosDBManagementClient.databaseAccounts.listKeys(config.resourceGroupName, config.displayName);
|
||||
};
|
||||
|
||||
const provision = () => async (
|
||||
config: CosmosDbConfig,
|
||||
workingSet: ProvisionWorkingSet
|
||||
): Promise<ProvisionWorkingSet> => {
|
||||
try {
|
||||
const { documentEndpoint } = await createDbAccount(config);
|
||||
await createDb(config);
|
||||
await createContainer(config);
|
||||
const { primaryMasterKey } = await getAuthKey(config);
|
||||
const provision =
|
||||
() =>
|
||||
async (config: CosmosDbConfig, workingSet: ProvisionWorkingSet): Promise<ProvisionWorkingSet> => {
|
||||
try {
|
||||
const { documentEndpoint } = await createDbAccount(config);
|
||||
await createDb(config);
|
||||
await createContainer(config);
|
||||
const { primaryMasterKey } = await getAuthKey(config);
|
||||
|
||||
const provisionResult: CosmosDbProvisionResult = {
|
||||
authKey: primaryMasterKey,
|
||||
cosmosDbEndpoint: documentEndpoint,
|
||||
databaseId: config.databaseName,
|
||||
containerId: config.containerName,
|
||||
collectionId: 'botstate-collection',
|
||||
};
|
||||
const provisionResult: CosmosDbProvisionResult = {
|
||||
authKey: primaryMasterKey,
|
||||
cosmosDbEndpoint: documentEndpoint,
|
||||
databaseId: config.databaseName,
|
||||
containerId: config.containerName,
|
||||
collectionId: 'botstate-collection',
|
||||
};
|
||||
|
||||
return {
|
||||
...workingSet,
|
||||
cosmosDb: provisionResult,
|
||||
};
|
||||
} catch (err) {
|
||||
throw createCustomizeError(ProvisionErrors.CREATE_COSMOSDB_ERROR, stringifyError(err));
|
||||
}
|
||||
};
|
||||
return {
|
||||
...workingSet,
|
||||
cosmosDb: provisionResult,
|
||||
};
|
||||
} catch (err) {
|
||||
throw createCustomizeError(ProvisionErrors.CREATE_COSMOSDB_ERROR, stringifyError(err));
|
||||
}
|
||||
};
|
||||
|
||||
return provision();
|
||||
};
|
||||
|
|
|
@ -45,7 +45,7 @@ const luisAuthoringProvisionMethod = (provisionConfig: ProvisionServiceConfig):
|
|||
|
||||
const cognitiveServicesManagementClient = new CognitiveServicesManagementClient(
|
||||
tokenCredentials,
|
||||
provisionConfig.subscriptionId
|
||||
provisionConfig.subscriptionId,
|
||||
);
|
||||
|
||||
return async (config: LuisAuthoringConfig, workingSet: ProvisionWorkingSet): Promise<ProvisionWorkingSet> => {
|
||||
|
@ -65,7 +65,7 @@ const luisAuthoringProvisionMethod = (provisionConfig: ProvisionServiceConfig):
|
|||
name: config.sku ?? 'F0',
|
||||
},
|
||||
location: authoringLocation,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const authoringEndpoint = deployResult.properties?.endpoint ?? '';
|
||||
|
|
|
@ -44,7 +44,7 @@ const luisPredictionProvisionMethod = (provisionConfig: ProvisionServiceConfig):
|
|||
const tokenCredentials = new TokenCredentials(provisionConfig.accessToken);
|
||||
const cognitiveServicesManagementClient = new CognitiveServicesManagementClient(
|
||||
tokenCredentials,
|
||||
provisionConfig.subscriptionId
|
||||
provisionConfig.subscriptionId,
|
||||
);
|
||||
|
||||
return async (config: LuisPredictionConfig, workingSet: ProvisionWorkingSet): Promise<ProvisionWorkingSet> => {
|
||||
|
@ -64,7 +64,7 @@ const luisPredictionProvisionMethod = (provisionConfig: ProvisionServiceConfig):
|
|||
name: config.sku ?? 'S0',
|
||||
},
|
||||
location: authoringLocation,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const endpoint = deployResult.properties?.endpoint ?? '';
|
||||
|
|
|
@ -58,12 +58,12 @@ const qnAProvisionMethod = (provisionConfig: ProvisionServiceConfig): ProvisionM
|
|||
const tokenCredentials = new TokenCredentials(provisionConfig.accessToken);
|
||||
const applicationInsightsManagementClient = new ApplicationInsightsManagementClient(
|
||||
tokenCredentials,
|
||||
provisionConfig.subscriptionId
|
||||
provisionConfig.subscriptionId,
|
||||
);
|
||||
const webSiteManagementClient = new WebSiteManagementClient(tokenCredentials, provisionConfig.subscriptionId);
|
||||
const cognitiveServicesManagementClient = new CognitiveServicesManagementClient(
|
||||
tokenCredentials,
|
||||
provisionConfig.subscriptionId
|
||||
provisionConfig.subscriptionId,
|
||||
);
|
||||
|
||||
const createOrUpdateSearchService = async (config: QnAResourceConfig, qnaMakerSearchName: string) => {
|
||||
|
@ -102,7 +102,7 @@ const qnAProvisionMethod = (provisionConfig: ProvisionServiceConfig): ProvisionM
|
|||
const createOrUpdateQnAAccount = async (
|
||||
config: QnAResourceConfig,
|
||||
qnaMakerServiceName: string,
|
||||
qnaEndpoint: string
|
||||
qnaEndpoint: string,
|
||||
) => {
|
||||
return await cognitiveServicesManagementClient.accounts.create(config.resourceGroupName, qnaMakerServiceName, {
|
||||
kind: 'QnAMaker',
|
||||
|
@ -121,7 +121,7 @@ const qnAProvisionMethod = (provisionConfig: ProvisionServiceConfig): ProvisionM
|
|||
const getSubscriptionKey = async (config: QnAResourceConfig, qnaMakerServiceName: string) => {
|
||||
const keys = await cognitiveServicesManagementClient.accounts.listKeys(
|
||||
config.resourceGroupName,
|
||||
qnaMakerServiceName
|
||||
qnaMakerServiceName,
|
||||
);
|
||||
return keys?.key1 ?? '';
|
||||
};
|
||||
|
@ -132,11 +132,11 @@ const qnAProvisionMethod = (provisionConfig: ProvisionServiceConfig): ProvisionM
|
|||
servicePlanName: string,
|
||||
qnaMakerSearchName: string,
|
||||
azureSearchAdminKey: string,
|
||||
appInsightsName: string
|
||||
appInsightsName: string,
|
||||
) => {
|
||||
const appInsightsComponent = await applicationInsightsManagementClient.components.get(
|
||||
config.resourceGroupName,
|
||||
appInsightsName
|
||||
appInsightsName,
|
||||
);
|
||||
const userAppInsightsKey = appInsightsComponent.instrumentationKey;
|
||||
const userAppInsightsName = appInsightsName;
|
||||
|
@ -236,7 +236,7 @@ const qnAProvisionMethod = (provisionConfig: ProvisionServiceConfig): ProvisionM
|
|||
servicePlanResult.name,
|
||||
qnaMakerSearchName,
|
||||
azureSearchAdminKey,
|
||||
qnaAppInsightsName
|
||||
qnaAppInsightsName,
|
||||
);
|
||||
|
||||
// Create qna account
|
||||
|
|
|
@ -41,7 +41,7 @@ const appServiceProvisionMethod = (provisionConfig: ProvisionServiceConfig) => {
|
|||
|
||||
return async (
|
||||
resourceConfig: ServicePlanResourceConfig,
|
||||
workingSet: ProvisionWorkingSet
|
||||
workingSet: ProvisionWorkingSet,
|
||||
): Promise<ProvisionWorkingSet> => {
|
||||
const operatingSystem = resourceConfig.operatingSystem ? resourceConfig.operatingSystem : 'windows';
|
||||
try {
|
||||
|
@ -60,7 +60,7 @@ const appServiceProvisionMethod = (provisionConfig: ProvisionServiceConfig) => {
|
|||
family: 'S',
|
||||
capacity: 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
return { ...workingSet, appService: { appServicePlanName: appServiceResult.name } };
|
||||
} catch (err) {
|
||||
|
|
|
@ -14,7 +14,7 @@ export type WebAppConfig = ResourceConfig & {
|
|||
location: string;
|
||||
resourceGroupName: string;
|
||||
};
|
||||
export type AppServiceConfig = ResourceDefinition & {};
|
||||
export type AppServiceConfig = ResourceDefinition & NonNullable<unknown>;
|
||||
|
||||
export type BotChannelResult = {
|
||||
botName: string;
|
||||
|
|
|
@ -45,7 +45,7 @@ const webAppProvisionMethod = (provisionConfig: ProvisionServiceConfig) => {
|
|||
|
||||
return async (
|
||||
resourceConfig: WebAppResourceConfig,
|
||||
workingSet: ProvisionWorkingSet
|
||||
workingSet: ProvisionWorkingSet,
|
||||
): Promise<ProvisionWorkingSet> => {
|
||||
const { resourceGroupName, webAppName, operatingSystem, location } = resourceConfig;
|
||||
try {
|
||||
|
|
|
@ -34,7 +34,7 @@ const createAzurePublishPlugin = (): PublishPlugin<ProvisionServiceConfig> => {
|
|||
});
|
||||
}
|
||||
return resources;
|
||||
}, [])
|
||||
}, []),
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -90,7 +90,7 @@ const createAzurePublishPlugin = (): PublishPlugin<ProvisionServiceConfig> => {
|
|||
processName: string,
|
||||
project: IBotProject,
|
||||
_user,
|
||||
jobId = ''
|
||||
jobId = '',
|
||||
): Promise<ProcessStatus> => {
|
||||
let status = processTracker.get(jobId);
|
||||
if (!status) {
|
||||
|
|
|
@ -10,7 +10,7 @@ export type OnProvisionProgress = (status: number, message: string) => void;
|
|||
export type ProvisionMethod = (
|
||||
config: ResourceConfig,
|
||||
workingSet: ProvisionWorkingSet,
|
||||
onProgress?: OnProvisionProgress
|
||||
onProgress?: OnProvisionProgress,
|
||||
) => Promise<ProvisionWorkingSet>;
|
||||
|
||||
export type ResourceProvisionService = {
|
||||
|
|
|
@ -12,9 +12,10 @@ export const handOffToAdminDispatcher = () => {
|
|||
});
|
||||
|
||||
const setRequiredHandOffResources = useRecoilCallback(
|
||||
({ set }: CallbackInterface) => (resources: ResourcesItem[]) => {
|
||||
set(requiredHandOffResourcesState, resources);
|
||||
}
|
||||
({ set }: CallbackInterface) =>
|
||||
(resources: ResourcesItem[]) => {
|
||||
set(requiredHandOffResourcesState, resources);
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
|
@ -21,9 +21,10 @@ export const resourceConfigurationDispatcher = () => {
|
|||
});
|
||||
|
||||
const setResourceGroup = useRecoilCallback(
|
||||
({ set }: CallbackInterface) => (resourceGroupName: string, isNew: boolean) => {
|
||||
set(resourceGroupState, { name: resourceGroupName, isNew });
|
||||
}
|
||||
({ set }: CallbackInterface) =>
|
||||
(resourceGroupName: string, isNew: boolean) => {
|
||||
set(resourceGroupState, { name: resourceGroupName, isNew });
|
||||
},
|
||||
);
|
||||
|
||||
const setDeployLocation = useRecoilCallback(({ set }: CallbackInterface) => (deployLocation: string) => {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { throwNotImplementedError } from '../throwNotImplementedError';
|
|||
|
||||
export const createABSService = (token: string, subscriptionId: string) => {
|
||||
const tokenCredentials = new TokenCredentials(token);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const azureBotService = new AzureBotService(tokenCredentials, subscriptionId);
|
||||
|
||||
const checkNameAvailability = async () => {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { throwNotImplementedError } from '../throwNotImplementedError';
|
|||
|
||||
const createAppInsightsService = (token: string, subscriptionId: string) => {
|
||||
const tokenCredentials = new TokenCredentials(token);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const applicationInsightsManagementClient = new ApplicationInsightsManagementClient(tokenCredentials, subscriptionId);
|
||||
|
||||
const checkNameAvailability = async () => {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { throwNotImplementedError } from '../throwNotImplementedError';
|
|||
|
||||
const createBlobStorageService = (token: string, subscriptionId: string) => {
|
||||
const tokenCredentials = new TokenCredentials(token);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const storageManagementClient = new StorageManagementClient(tokenCredentials, subscriptionId);
|
||||
|
||||
const checkNameAvailability = async () => {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { throwNotImplementedError } from '../throwNotImplementedError';
|
|||
|
||||
export const createCosmosDBService = (token: string, subscriptionId: string) => {
|
||||
const tokenCredentials = new TokenCredentials(token);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const cosmosDBManagementClient = new CosmosDBManagementClient(tokenCredentials, subscriptionId);
|
||||
|
||||
const checkNameAvailability = async () => {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { throwNotImplementedError } from '../throwNotImplementedError';
|
|||
|
||||
const createLuisService = (token: string, subscriptionId: string) => {
|
||||
const tokenCredentials = new TokenCredentials(token);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const cognitiveServicesManagementClient = new CognitiveServicesManagementClient(tokenCredentials, subscriptionId);
|
||||
|
||||
const checkNameAvailability = async () => {
|
||||
|
|
|
@ -8,9 +8,9 @@ import { throwNotImplementedError } from '../throwNotImplementedError';
|
|||
|
||||
const createQNAService = (token: string, subscriptionId: string) => {
|
||||
const tokenCredentials = new TokenCredentials(token);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const searchManagementClient = new SearchManagementClient(tokenCredentials, subscriptionId);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const webSiteManagementClient = new WebSiteManagementClient(tokenCredentials, subscriptionId);
|
||||
|
||||
const checkNameAvailability = async () => {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { throwNotImplementedError } from '../throwNotImplementedError';
|
|||
|
||||
const createWebAppAzureFunctionService = (token: string, subscriptionId: string) => {
|
||||
const tokenCredentials = new TokenCredentials(token);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const webSiteManagementClient = new WebSiteManagementClient(tokenCredentials, subscriptionId);
|
||||
|
||||
const checkNameAvailability = async () => {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { throwNotImplementedError } from '../throwNotImplementedError';
|
|||
|
||||
export const createWebAppService = (token: string, subscriptionId: string) => {
|
||||
const tokenCredentials = new TokenCredentials(token);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const webSiteManagementClient = new WebSiteManagementClient(tokenCredentials, subscriptionId);
|
||||
|
||||
const checkNameAvailability = async () => {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { throwNotImplementedError } from '../throwNotImplementedError';
|
|||
|
||||
const createWebAppServicePlanService = (token: string, subscriptionId: string) => {
|
||||
const tokenCredentials = new TokenCredentials(token);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const webSiteManagementClient = new WebSiteManagementClient(tokenCredentials, subscriptionId);
|
||||
|
||||
const checkNameAvailability = async () => {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { throwNotImplementedError } from './throwNotImplementedError';
|
|||
|
||||
const createResourceGroupService = (token: string, subscriptionId: string) => {
|
||||
const tokenCredentials = new TokenCredentials(token);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error types missmatch
|
||||
const client = new ResourceManagementClient(tokenCredentials, subscriptionId);
|
||||
|
||||
const list = async () => {
|
||||
|
|
|
@ -22,8 +22,8 @@ module.exports = {
|
|||
token: accessToken,
|
||||
profile: profile,
|
||||
});
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// define this BEFORE turning on the middleware...
|
||||
|
@ -45,7 +45,7 @@ module.exports = {
|
|||
console.log('login complete!');
|
||||
// Successful authentication, redirect home.
|
||||
res.redirect('/home');
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
composer.addAllowedUrl('/logout');
|
||||
|
@ -60,7 +60,7 @@ module.exports = {
|
|||
(user, done) => {
|
||||
console.log('DESERIALIZE USER!', user);
|
||||
done(null, JSON.parse(user));
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -110,7 +110,7 @@ class LocalPublisher implements PublishPlugin<PublishConfig> {
|
|||
RuntimeLogServer.sendRuntimeLogToSubscribers(
|
||||
botId,
|
||||
LocalPublisher.runningBots[botId].result.runtimeLog ?? '',
|
||||
LocalPublisher.runningBots[botId].result.runtimeError ?? ''
|
||||
LocalPublisher.runningBots[botId].result.runtimeError ?? '',
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -257,7 +257,7 @@ class LocalPublisher implements PublishPlugin<PublishConfig> {
|
|||
// get port, and stop previous bot if exist
|
||||
try {
|
||||
// if a port (e.g. --port 5000) is configured in the custom runtime command try to parse and set this port
|
||||
if (settings.runtime.command && settings.runtime.command.includes('--port')) {
|
||||
if (settings.runtime?.command?.includes?.('--port')) {
|
||||
try {
|
||||
port = Number(/--port (\d+)/.exec(settings.runtime.command)[1]);
|
||||
} catch (err) {
|
||||
|
@ -340,7 +340,7 @@ class LocalPublisher implements PublishPlugin<PublishConfig> {
|
|||
},
|
||||
(err) => {
|
||||
reject(`Bot on localhost:${port} not working, error message: ${err.message}`);
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
|
@ -387,20 +387,18 @@ class LocalPublisher implements PublishPlugin<PublishConfig> {
|
|||
child: ChildProcess,
|
||||
botId: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
logger: (...args: any[]) => void
|
||||
logger: (...args: any[]) => void,
|
||||
) => {
|
||||
let errOutput = '';
|
||||
child.stdout &&
|
||||
child.stdout.on('data', (data: any) => {
|
||||
const runtimeData = data.toString();
|
||||
this.appendRuntimeLogs(botId, runtimeData);
|
||||
logger('%s', data.toString());
|
||||
});
|
||||
child.stdout?.on?.('data', (data: any) => {
|
||||
const runtimeData = data.toString();
|
||||
this.appendRuntimeLogs(botId, runtimeData);
|
||||
logger('%s', data.toString());
|
||||
});
|
||||
|
||||
child.stderr &&
|
||||
child.stderr.on('data', (err: any) => {
|
||||
errOutput += err.toString();
|
||||
});
|
||||
child.stderr?.on?.('data', (err: any) => {
|
||||
errOutput += err.toString();
|
||||
});
|
||||
|
||||
child.on('exit', (code) => {
|
||||
if (code !== 0) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import express, { Request, Response } from 'express';
|
|||
import WS from 'ws';
|
||||
import { Debugger } from 'debug';
|
||||
|
||||
const { Server: WSServer } = WS
|
||||
const { Server: WSServer } = WS;
|
||||
|
||||
interface WebSocket {
|
||||
close(): void;
|
||||
|
@ -105,7 +105,7 @@ export class RuntimeLogServer {
|
|||
JSON.stringify({
|
||||
standardOutput,
|
||||
standardError,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ class LocalPublisher implements PublishPlugin<PublishConfig> {
|
|||
const profileName = config.name;
|
||||
const botId = project.id;
|
||||
|
||||
if (this.data[botId] && this.data[botId][profileName]) {
|
||||
if (this.data?.[botId]?.[profileName]) {
|
||||
const response = this.data[botId][profileName][this.data[botId][profileName].length - 1];
|
||||
// return latest status
|
||||
return response;
|
||||
|
@ -100,7 +100,7 @@ class LocalPublisher implements PublishPlugin<PublishConfig> {
|
|||
const profileName = config.name;
|
||||
const botId = project.id;
|
||||
const result = [];
|
||||
if (this.data[botId] && this.data[botId][profileName]) {
|
||||
if (this.data?.[botId]?.[profileName]) {
|
||||
this.data[botId][profileName].map((item) => {
|
||||
result.push({
|
||||
...item.result,
|
||||
|
|
|
@ -155,7 +155,7 @@ class MongoStorage implements IFileStorage {
|
|||
resolve(
|
||||
files.map((item) => {
|
||||
return item.path.replace(path, '');
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -270,7 +270,7 @@ class MongoStorage implements IFileStorage {
|
|||
resolve(
|
||||
files.map((item) => {
|
||||
return item.path.replace(path, '');
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,8 +5,8 @@ module.exports = {
|
|||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:prettier/recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'prettier/@typescript-eslint',
|
||||
],
|
||||
plugins: ['import', 'notice', 'security', 'lodash'],
|
||||
env: {
|
||||
|
|
|
@ -78,7 +78,7 @@ export const FeedModal: React.FC<WorkingModalProps> = (props) => {
|
|||
setSelectedItem(undefined);
|
||||
}
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -276,7 +276,7 @@ export const FeedModal: React.FC<WorkingModalProps> = (props) => {
|
|||
if (
|
||||
await confirm(
|
||||
formatMessage('Delete this feed?'),
|
||||
formatMessage('Are you sure you want to remove this feed source?')
|
||||
formatMessage('Are you sure you want to remove this feed source?'),
|
||||
)
|
||||
) {
|
||||
setItems(items.filter((i) => i.key !== selectedItem.key));
|
||||
|
|
|
@ -42,7 +42,7 @@ const ImportDialog: React.FC<ImportDialogProps> = (props) => {
|
|||
<form onSubmit={submit}>
|
||||
<p>
|
||||
{formatMessage(
|
||||
'Install a specific package by pasting the name and version number below. The text must be an exact match in order to find the correct package. You can also add and browse feeds to find packages to add.'
|
||||
'Install a specific package by pasting the name and version number below. The text must be an exact match in order to find the correct package. You can also add and browse feeds to find packages to add.',
|
||||
)}
|
||||
</p>
|
||||
<TextField
|
||||
|
|
|
@ -22,7 +22,11 @@ export class NpmFeed implements IFeed {
|
|||
* @param packageSource package source from where to retrieve packages.
|
||||
* @param data data received in the `objects` field from the http call to the npm registry.
|
||||
*/
|
||||
constructor(private composer: IExtensionRegistration, private packageSource?: IPackageSource, private data?) {}
|
||||
constructor(
|
||||
private composer: IExtensionRegistration,
|
||||
private packageSource?: IPackageSource,
|
||||
private data?,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Gets packages from the npm feed based on the provided query.
|
||||
|
|
|
@ -26,7 +26,10 @@ export class LocalNuGetFeed implements IFeed {
|
|||
* @param composer Composer registration used for logging.
|
||||
* @param url Url of the feed, represented usually by the file path to the NuGet file system feed.
|
||||
*/
|
||||
constructor(private composer: IExtensionRegistration, private url: string) {}
|
||||
constructor(
|
||||
private composer: IExtensionRegistration,
|
||||
private url: string,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Gets packages from local NuGet feed according to query request.
|
||||
|
@ -49,6 +52,7 @@ export class LocalNuGetFeed implements IFeed {
|
|||
// * extract only folders from that list
|
||||
// * pass each one through the getPackageInfo function, which extracts metadata from the package
|
||||
// * return a feed in the form that is used by nuget search API
|
||||
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
||||
const packages = await readdir(url, { withFileTypes: true });
|
||||
|
||||
const feedPromises: Promise<IPackageDefinition>[] = packages
|
||||
|
@ -69,6 +73,7 @@ export class LocalNuGetFeed implements IFeed {
|
|||
|
||||
let versions;
|
||||
try {
|
||||
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
||||
versions = await readdir(packageDir, { withFileTypes: true });
|
||||
versions = versions.filter((f) => f.isDirectory()).map((f) => f.name);
|
||||
if (versions.length === 0) {
|
||||
|
@ -77,13 +82,14 @@ export class LocalNuGetFeed implements IFeed {
|
|||
versions = semverSort.desc(versions);
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`Could not find versions of local package ${packageName} at ${rootDir}. For more info about setting up a local feed, see here: https://docs.microsoft.com/en-us/nuget/hosting-packages/local-feeds. Error: ${err}`
|
||||
`Could not find versions of local package ${packageName} at ${rootDir}. For more info about setting up a local feed, see here: https://docs.microsoft.com/en-us/nuget/hosting-packages/local-feeds. Error: ${err}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Read from the nuspec file in the latest to get other info.
|
||||
try {
|
||||
const pathToNuspec = path.join(packageDir, versions[0], `${packageName}.nuspec`);
|
||||
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
||||
const xml = await readFile(pathToNuspec, 'utf8');
|
||||
const parsed = await parseStringPromise(xml);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ export class NuGetFeed implements IFeed {
|
|||
constructor(
|
||||
private composer: IExtensionRegistration,
|
||||
private packageSource?: IPackageSource,
|
||||
private data?: INuGetSearchResult | INuGetServiceIndex
|
||||
private data?: INuGetSearchResult | INuGetServiceIndex,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
@ -50,7 +50,7 @@ export class NuGetFeed implements IFeed {
|
|||
let serviceIndex: INuGetServiceIndex = this.data as INuGetServiceIndex;
|
||||
|
||||
// If we don't have a service index provided at construction, get it from the url
|
||||
if (!serviceIndex || !serviceIndex.resources) {
|
||||
if (!serviceIndex?.resources) {
|
||||
const httpResponse = await axios.get(this.packageSource.url);
|
||||
serviceIndex = httpResponse?.data;
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
// append user specified query to defaultQuery
|
||||
if (req.query.term) {
|
||||
packageSource.defaultQuery.query = `${packageSource.defaultQuery.query}+${encodeURIComponent(
|
||||
req.query.term
|
||||
req.query.term,
|
||||
)}`;
|
||||
}
|
||||
|
||||
|
@ -261,7 +261,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
false, // verbosity: true = verbose
|
||||
composer.log,
|
||||
composer.log,
|
||||
captureErrors
|
||||
captureErrors,
|
||||
);
|
||||
const dryRunMergeResults = await dryrun.merge();
|
||||
|
||||
|
@ -311,7 +311,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
packageName,
|
||||
version,
|
||||
source,
|
||||
currentProject
|
||||
currentProject,
|
||||
);
|
||||
|
||||
const manifestFile = runtime.identifyManifest(runtimePath, currentProject.name);
|
||||
|
@ -325,7 +325,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
false, // verbosity: true = verbose
|
||||
composer.log,
|
||||
composer.log,
|
||||
captureErrors
|
||||
captureErrors,
|
||||
);
|
||||
|
||||
const dryRunMergeResults = await dryrun.merge();
|
||||
|
@ -353,7 +353,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
false, // verbosity: true = verbose
|
||||
composer.log,
|
||||
composer.log,
|
||||
composer.log
|
||||
composer.log,
|
||||
);
|
||||
|
||||
const mergeResults = await realMerge.merge();
|
||||
|
@ -361,7 +361,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
composer.log(
|
||||
'MERGE RESULTS',
|
||||
path.join(currentProject.dataDir, 'dialogs/imported'),
|
||||
JSON.stringify(mergeResults, null, 2)
|
||||
JSON.stringify(mergeResults, null, 2),
|
||||
);
|
||||
|
||||
const installedComponents = await loadPackageAssets(mergeResults.components.filter(isAdaptiveComponent));
|
||||
|
@ -379,7 +379,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
if (
|
||||
newlyInstalledPlugin &&
|
||||
!currentProject.settings.runtimeSettings?.components?.find(
|
||||
(p: { name: string }) => p.name === newlyInstalledPlugin.name
|
||||
(p: { name: string }) => p.name === newlyInstalledPlugin.name,
|
||||
)
|
||||
) {
|
||||
const newSettings = await currentProject.getEnvSettings();
|
||||
|
@ -464,7 +464,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
false, // verbosity: true = verbose
|
||||
composer.log,
|
||||
composer.log,
|
||||
captureErrors
|
||||
captureErrors,
|
||||
);
|
||||
|
||||
const mergeResults = await merger.merge();
|
||||
|
@ -484,7 +484,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
|
|||
) {
|
||||
const newSettings = await currentProject.getEnvSettings();
|
||||
newSettings.runtimeSettings.components = newSettings.runtimeSettings.components.filter(
|
||||
(p) => p.name !== packageName
|
||||
(p) => p.name !== packageName,
|
||||
);
|
||||
currentProject.updateEnvSettings(newSettings);
|
||||
}
|
||||
|
|
|
@ -148,19 +148,19 @@ const Library: React.FC = () => {
|
|||
recentlyUsedCategory: formatMessage('Recently Used'),
|
||||
installedCategory: formatMessage('Installed'),
|
||||
updateConfirmationPrompt: formatMessage(
|
||||
'Any changes you made to this package will be lost! Are you sure you want to continue?'
|
||||
'Any changes you made to this package will be lost! Are you sure you want to continue?',
|
||||
),
|
||||
updateConfirmationTitle: formatMessage('Update Package'),
|
||||
conflictConfirmationTitle: formatMessage('Conflicting changes detected'),
|
||||
conflictConfirmationPrompt: formatMessage(
|
||||
'This operation will overwrite changes made to previously imported files. Do you want to proceed?'
|
||||
'This operation will overwrite changes made to previously imported files. Do you want to proceed?',
|
||||
),
|
||||
removeConfirmationTitle: formatMessage('Remove Package'),
|
||||
removeConfirmationPrompt: formatMessage(
|
||||
'Any changes you made to this package will be lost! In addition, this may leave your bot in a broken state. Are you sure you want to continue?'
|
||||
'Any changes you made to this package will be lost! In addition, this may leave your bot in a broken state. Are you sure you want to continue?',
|
||||
),
|
||||
requireEject: formatMessage(
|
||||
'To install components, this project must have an ejected runtime. Please navigate to the project settings page, custom runtime section.'
|
||||
'To install components, this project must have an ejected runtime. Please navigate to the project settings page, custom runtime section.',
|
||||
),
|
||||
ejectRuntime: formatMessage('Eject Runtime'),
|
||||
noComponentsInstalled: formatMessage('No packages installed'),
|
||||
|
@ -182,7 +182,7 @@ const Library: React.FC = () => {
|
|||
packageName: string,
|
||||
version: string,
|
||||
isUpdating: boolean,
|
||||
source: string
|
||||
source: string,
|
||||
) => {
|
||||
return httpClient.post(`${API_ROOT}/projects/${projectId}/import`, {
|
||||
package: packageName,
|
||||
|
@ -303,7 +303,7 @@ const Library: React.FC = () => {
|
|||
let availversions;
|
||||
let setversion;
|
||||
|
||||
if (selectedItem.versions && selectedItem.versions.length) {
|
||||
if (selectedItem?.versions?.length) {
|
||||
availversions = selectedItem.versions;
|
||||
} else {
|
||||
availversions = [selectedItem.version];
|
||||
|
@ -501,7 +501,7 @@ const Library: React.FC = () => {
|
|||
} catch (err) {
|
||||
setApplicationLevelError({
|
||||
status: err.response.status,
|
||||
message: err.response && err.response.data.message ? err.response.data.message : err,
|
||||
message: err?.response?.data?.message ?? err,
|
||||
summary: strings.libraryError,
|
||||
});
|
||||
} finally {
|
||||
|
@ -519,7 +519,7 @@ const Library: React.FC = () => {
|
|||
} catch (err) {
|
||||
setApplicationLevelError({
|
||||
status: err.response.status,
|
||||
message: err.response && err.response.data.message ? err.response.data.message : err,
|
||||
message: err?.response?.data?.message ?? err,
|
||||
summary: strings.libraryError,
|
||||
});
|
||||
}
|
||||
|
@ -563,7 +563,7 @@ const Library: React.FC = () => {
|
|||
if (err.response) {
|
||||
setApplicationLevelError({
|
||||
status: err.response.status,
|
||||
message: err.response && err.response.data.message ? err.response.data.message : err,
|
||||
message: err?.response?.data?.message ?? err,
|
||||
summary: strings.importError,
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -113,7 +113,7 @@ export const PVADialog: FC = () => {
|
|||
setBot(bot);
|
||||
}
|
||||
},
|
||||
[bots, env]
|
||||
[bots, env],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -62,7 +62,7 @@ describe('publish()', () => {
|
|||
mockBotProject,
|
||||
{ comment: 'testing' },
|
||||
undefined,
|
||||
mockGetAccessToken
|
||||
mockGetAccessToken,
|
||||
);
|
||||
|
||||
expect(result.status).toBe(202);
|
||||
|
@ -71,7 +71,7 @@ describe('publish()', () => {
|
|||
expect(innerResult.comment).toBe('testing');
|
||||
expect(innerResult.eTag).toBe('W/"version"');
|
||||
expect(innerResult.log).toEqual(
|
||||
mockDiagnostics.map((diag) => `---\n${JSON.stringify(diag, null, 2)}\n---\n`).join('\n')
|
||||
mockDiagnostics.map((diag) => `---\n${JSON.stringify(diag, null, 2)}\n---\n`).join('\n'),
|
||||
);
|
||||
expect(innerResult.id).toBe('operationId');
|
||||
expect(innerResult.action).toEqual(null);
|
||||
|
@ -87,7 +87,7 @@ describe('publish()', () => {
|
|||
mockBotProject,
|
||||
{ comment: 'testing' },
|
||||
undefined,
|
||||
mockGetAccessToken
|
||||
mockGetAccessToken,
|
||||
);
|
||||
|
||||
expect(result.status).toBe(502);
|
||||
|
@ -104,7 +104,7 @@ describe('publish()', () => {
|
|||
mockBotProject,
|
||||
{ comment: 'testing' },
|
||||
undefined,
|
||||
mockGetAccessToken
|
||||
mockGetAccessToken,
|
||||
);
|
||||
|
||||
expect(result.status).toBe(500);
|
||||
|
|
|
@ -23,7 +23,7 @@ export const publish = async (
|
|||
project: IBotProject,
|
||||
metadata: any,
|
||||
_user?: UserIdentity,
|
||||
getAccessToken?
|
||||
getAccessToken?,
|
||||
): Promise<PublishResponse> => {
|
||||
const {
|
||||
// these are provided by Composer
|
||||
|
@ -68,7 +68,7 @@ export const publish = async (
|
|||
resolve();
|
||||
});
|
||||
archive.pipe(botContentWriter);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
const botContent = Buffer.concat(botContentData);
|
||||
|
@ -90,7 +90,7 @@ export const publish = async (
|
|||
},
|
||||
});
|
||||
if (res.status === 202) {
|
||||
const job = await res.json() as PVAPublishJob;
|
||||
const job = (await res.json()) as PVAPublishJob;
|
||||
logger.log('Publish job started: %O', job);
|
||||
|
||||
// transform the PVA job to a publish response
|
||||
|
@ -134,7 +134,7 @@ export const getStatus = async (
|
|||
config: PublishConfig,
|
||||
project: IBotProject,
|
||||
user?: UserIdentity,
|
||||
getAccessToken?
|
||||
getAccessToken?,
|
||||
): Promise<PublishResponse> => {
|
||||
const {
|
||||
// these are provided by Composer
|
||||
|
@ -174,7 +174,7 @@ export const getStatus = async (
|
|||
'If-None-Match': project.eTag || '',
|
||||
},
|
||||
});
|
||||
const job = await res.json() as PVAPublishJob;
|
||||
const job = (await res.json()) as PVAPublishJob;
|
||||
logger.log('Got updated status from publish job: %O', job);
|
||||
|
||||
// transform the PVA job to a publish response
|
||||
|
@ -210,7 +210,7 @@ export const history = async (
|
|||
config: PublishConfig,
|
||||
_project: IBotProject,
|
||||
_user?: UserIdentity,
|
||||
getAccessToken?
|
||||
getAccessToken?,
|
||||
): Promise<PublishResult[]> => {
|
||||
const {
|
||||
// these are specific to the PVA publish profile shape
|
||||
|
@ -232,7 +232,7 @@ export const history = async (
|
|||
method: 'GET',
|
||||
headers: getAuthHeaders(accessToken, tenantId),
|
||||
});
|
||||
const jobs = await res.json() as PVAPublishJob[];
|
||||
const jobs = (await res.json()) as PVAPublishJob[];
|
||||
|
||||
// return the first 20
|
||||
return jobs.map((job) => xformJobToResult(job)).slice(0, 19);
|
||||
|
@ -245,7 +245,7 @@ export const pull = async (
|
|||
config: PublishConfig,
|
||||
_project: IBotProject,
|
||||
_user?: UserIdentity,
|
||||
getAccessToken?
|
||||
getAccessToken?,
|
||||
): Promise<PullResponse> => {
|
||||
const {
|
||||
// these are specific to the PVA publish profile shape
|
||||
|
@ -281,6 +281,7 @@ export const pull = async (
|
|||
const zipDir = join(process.env.COMPOSER_TEMP_DIR as string, 'pva-publish');
|
||||
ensureDirSync(zipDir);
|
||||
const zipPath = join(zipDir, `bot-assets-${Date.now()}.zip`);
|
||||
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
||||
const writeStream = createWriteStream(zipPath);
|
||||
await new Promise((resolve, reject) => {
|
||||
writeStream.once('finish', resolve);
|
||||
|
@ -342,11 +343,7 @@ const ensurePublishProfileHistory = (botProjectId: string, profileName: string)
|
|||
};
|
||||
|
||||
const getOperationIdOfLastJob = (botProjectId: string, profileName: string): string => {
|
||||
if (
|
||||
publishHistory[botProjectId] &&
|
||||
publishHistory[botProjectId][profileName] &&
|
||||
!!publishHistory[botProjectId][profileName].length
|
||||
) {
|
||||
if (publishHistory?.[botProjectId]?.[profileName]?.length) {
|
||||
const mostRecentJob = publishHistory[botProjectId][profileName][0];
|
||||
return mostRecentJob.id || '';
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export async function copyDir(
|
|||
srcStorage: IFileStorage,
|
||||
dstDir: string,
|
||||
dstStorage: IFileStorage,
|
||||
pathsToExclude?: Set<string>
|
||||
pathsToExclude?: Set<string>,
|
||||
) {
|
||||
if (!(await srcStorage.exists(srcDir)) || !(await srcStorage.stat(srcDir)).isDir) {
|
||||
throw new Error(`No such dir ${srcDir}}`);
|
||||
|
|
|
@ -46,7 +46,7 @@ const writeAllLocalFunctionsSettings = async (fullSettings: DialogSetting, port:
|
|||
'luis:endpointKey',
|
||||
fullSettings.luis?.endpointKey || fullSettings.luis?.authoringKey,
|
||||
runtimePath,
|
||||
log
|
||||
log,
|
||||
);
|
||||
await writeLocalFunctionsSetting('qna:endpointKey', fullSettings.qna?.endpointKey, runtimePath, log);
|
||||
let skillHostEndpoint;
|
||||
|
@ -100,7 +100,7 @@ export default async (composer: any): Promise<void> => {
|
|||
version: string,
|
||||
source: string,
|
||||
project: IBotProject,
|
||||
isPreview = false
|
||||
isPreview = false,
|
||||
): Promise<string> => {
|
||||
// run dotnet install on the project
|
||||
const command = `dotnet add ${project.name}.csproj package "${packageName}"${
|
||||
|
@ -122,7 +122,7 @@ export default async (composer: any): Promise<void> => {
|
|||
`dotnet remove ${project.name}.csproj package ${packageName}`,
|
||||
{
|
||||
cwd: path.join(runtimePath),
|
||||
}
|
||||
},
|
||||
);
|
||||
if (installError) {
|
||||
throw new Error(installError);
|
||||
|
@ -139,7 +139,7 @@ export default async (composer: any): Promise<void> => {
|
|||
runtimePath: string,
|
||||
project: IBotProject,
|
||||
settings: DialogSetting,
|
||||
profileName: string
|
||||
profileName: string,
|
||||
): Promise<string> => {
|
||||
composer.log('BUILD FOR DEPLOY TO AZURE!');
|
||||
|
||||
|
@ -189,7 +189,7 @@ export default async (composer: any): Promise<void> => {
|
|||
dstStorage: IFileStorage,
|
||||
srcManifestDir: string,
|
||||
srcStorage: IFileStorage,
|
||||
mode = 'azurewebapp' // set default as azurewebapp
|
||||
mode = 'azurewebapp', // set default as azurewebapp
|
||||
) => {
|
||||
// update manifst into runtime wwwroot
|
||||
if (mode === 'azurewebapp') {
|
||||
|
@ -241,7 +241,7 @@ export default async (composer: any): Promise<void> => {
|
|||
version: string,
|
||||
source: string,
|
||||
project: IBotProject,
|
||||
isPreview = false
|
||||
isPreview = false,
|
||||
): Promise<string> => {
|
||||
// run dotnet install on the project
|
||||
const command = `dotnet add ${project.name}.csproj package "${packageName}"${
|
||||
|
@ -263,7 +263,7 @@ export default async (composer: any): Promise<void> => {
|
|||
`dotnet remove ${project.name}.csproj package ${packageName}`,
|
||||
{
|
||||
cwd: path.join(runtimePath),
|
||||
}
|
||||
},
|
||||
);
|
||||
if (installError) {
|
||||
throw new Error(installError);
|
||||
|
@ -280,7 +280,7 @@ export default async (composer: any): Promise<void> => {
|
|||
runtimePath: string,
|
||||
project: IBotProject,
|
||||
settings: DialogSetting,
|
||||
profileName: string
|
||||
profileName: string,
|
||||
): Promise<string> => {
|
||||
composer.log('BUILD FOR DEPLOY TO AZURE!');
|
||||
|
||||
|
@ -347,14 +347,14 @@ export default async (composer: any): Promise<void> => {
|
|||
version: string,
|
||||
source: string,
|
||||
_project: IBotProject,
|
||||
isPreview = false
|
||||
isPreview = false,
|
||||
): Promise<string> => {
|
||||
// run dotnet install on the project
|
||||
const { stderr: installError, stdout: installOutput } = await execAsync(
|
||||
`npm install --loglevel=error --save ${packageName}${version ? '@' + version : ''}`,
|
||||
{
|
||||
cwd: path.join(runtimePath),
|
||||
}
|
||||
},
|
||||
);
|
||||
if (installError) {
|
||||
throw new Error(installError);
|
||||
|
@ -367,7 +367,7 @@ export default async (composer: any): Promise<void> => {
|
|||
`npm uninstall --loglevel=error --save ${packageName}`,
|
||||
{
|
||||
cwd: path.join(runtimePath),
|
||||
}
|
||||
},
|
||||
);
|
||||
if (installError) {
|
||||
throw new Error(installError);
|
||||
|
@ -381,7 +381,7 @@ export default async (composer: any): Promise<void> => {
|
|||
runtimePath: string,
|
||||
project: IBotProject,
|
||||
settings: DialogSetting,
|
||||
profileName: string
|
||||
profileName: string,
|
||||
): Promise<string> => {
|
||||
// do stuff
|
||||
composer.log(`BUILD THIS JS PROJECT in ${runtimePath}`);
|
||||
|
@ -425,14 +425,14 @@ export default async (composer: any): Promise<void> => {
|
|||
version: string,
|
||||
source: string,
|
||||
_project: IBotProject,
|
||||
isPreview = false
|
||||
isPreview = false,
|
||||
): Promise<string> => {
|
||||
// run dotnet install on the project
|
||||
const { stderr: installError, stdout: installOutput } = await execAsync(
|
||||
`npm install --loglevel=error --save ${packageName}${version ? '@' + version : ''}`,
|
||||
{
|
||||
cwd: path.join(runtimePath),
|
||||
}
|
||||
},
|
||||
);
|
||||
if (installError) {
|
||||
throw new Error(installError);
|
||||
|
@ -445,7 +445,7 @@ export default async (composer: any): Promise<void> => {
|
|||
`npm uninstall --loglevel=error --save ${packageName}`,
|
||||
{
|
||||
cwd: path.join(runtimePath),
|
||||
}
|
||||
},
|
||||
);
|
||||
if (installError) {
|
||||
throw new Error(installError);
|
||||
|
@ -459,7 +459,7 @@ export default async (composer: any): Promise<void> => {
|
|||
runtimePath: string,
|
||||
project: IBotProject,
|
||||
settings: DialogSetting,
|
||||
profileName: string
|
||||
profileName: string,
|
||||
): Promise<string> => {
|
||||
// do stuff
|
||||
composer.log(`BUILD THIS JS PROJECT in ${runtimePath}`);
|
||||
|
|
|
@ -46,8 +46,15 @@ export const textField = css`
|
|||
|
||||
// copied from Fluent
|
||||
export const label = css`
|
||||
font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto,
|
||||
'Helvetica Neue', sans-serif;
|
||||
font-family:
|
||||
'Segoe UI',
|
||||
'Segoe UI Web (West European)',
|
||||
'Segoe UI',
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
Roboto,
|
||||
'Helvetica Neue',
|
||||
sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: rgb(50, 49, 48);
|
||||
|
@ -64,8 +71,15 @@ export const shortTextField = css`
|
|||
`;
|
||||
|
||||
export const output = css`
|
||||
font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto,
|
||||
'Helvetica Neue', sans-serif;
|
||||
font-family:
|
||||
'Segoe UI',
|
||||
'Segoe UI Web (West European)',
|
||||
'Segoe UI',
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
Roboto,
|
||||
'Helvetica Neue',
|
||||
sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
`;
|
||||
|
|
Загрузка…
Ссылка в новой задаче