Compare commits
1 Commits
fix/shared
...
fix/action
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f862b4aaae |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hoppscotch-backend",
|
"name": "hoppscotch-backend",
|
||||||
"version": "2023.12.2",
|
"version": "2023.12.0-1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -28,13 +28,6 @@ export const JSON_INVALID = 'json_invalid';
|
|||||||
*/
|
*/
|
||||||
export const AUTH_PROVIDER_NOT_SPECIFIED = 'auth/provider_not_specified';
|
export const AUTH_PROVIDER_NOT_SPECIFIED = 'auth/provider_not_specified';
|
||||||
|
|
||||||
/**
|
|
||||||
* Auth Provider not specified
|
|
||||||
* (Auth)
|
|
||||||
*/
|
|
||||||
export const AUTH_PROVIDER_NOT_CONFIGURED =
|
|
||||||
'auth/provider_not_configured_correctly';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Environment variable "VITE_ALLOWED_AUTH_PROVIDERS" is not present in .env file
|
* Environment variable "VITE_ALLOWED_AUTH_PROVIDERS" is not present in .env file
|
||||||
*/
|
*/
|
||||||
@@ -683,16 +676,9 @@ export const INFRA_CONFIG_RESET_FAILED = 'infra_config/reset_failed' as const;
|
|||||||
*/
|
*/
|
||||||
export const INFRA_CONFIG_INVALID_INPUT = 'infra_config/invalid_input' as const;
|
export const INFRA_CONFIG_INVALID_INPUT = 'infra_config/invalid_input' as const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Infra Config service (auth provider/mailer/audit logs) not configured
|
|
||||||
* (InfraConfigService)
|
|
||||||
*/
|
|
||||||
export const INFRA_CONFIG_SERVICE_NOT_CONFIGURED =
|
|
||||||
'infra_config/service_not_configured' as const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error message for when the database table does not exist
|
* Error message for when the database table does not exist
|
||||||
* (InfraConfigService)
|
* (InfraConfigService)
|
||||||
*/
|
*/
|
||||||
export const DATABASE_TABLE_NOT_EXIST =
|
export const DATABASE_TABLE_NOT_EXIST =
|
||||||
'Database migration not found. Please check the documentation for assistance: https://docs.hoppscotch.io/documentation/self-host/community-edition/install-and-build#running-migrations';
|
'Database migration not performed. Please check the FAQ for assistance: https://docs.hoppscotch.io/support/getting-started/faq';
|
||||||
|
|||||||
@@ -1,33 +1,10 @@
|
|||||||
import { AuthProvider } from 'src/auth/helper';
|
|
||||||
import { AUTH_PROVIDER_NOT_CONFIGURED } from 'src/errors';
|
|
||||||
import { PrismaService } from 'src/prisma/prisma.service';
|
import { PrismaService } from 'src/prisma/prisma.service';
|
||||||
import { InfraConfigEnum } from 'src/types/InfraConfig';
|
|
||||||
import { throwErr } from 'src/utils';
|
|
||||||
|
|
||||||
export enum ServiceStatus {
|
export enum ServiceStatus {
|
||||||
ENABLE = 'ENABLE',
|
ENABLE = 'ENABLE',
|
||||||
DISABLE = 'DISABLE',
|
DISABLE = 'DISABLE',
|
||||||
}
|
}
|
||||||
|
|
||||||
const AuthProviderConfigurations = {
|
|
||||||
[AuthProvider.GOOGLE]: [
|
|
||||||
InfraConfigEnum.GOOGLE_CLIENT_ID,
|
|
||||||
InfraConfigEnum.GOOGLE_CLIENT_SECRET,
|
|
||||||
],
|
|
||||||
[AuthProvider.GITHUB]: [
|
|
||||||
InfraConfigEnum.GITHUB_CLIENT_ID,
|
|
||||||
InfraConfigEnum.GITHUB_CLIENT_SECRET,
|
|
||||||
],
|
|
||||||
[AuthProvider.MICROSOFT]: [
|
|
||||||
InfraConfigEnum.MICROSOFT_CLIENT_ID,
|
|
||||||
InfraConfigEnum.MICROSOFT_CLIENT_SECRET,
|
|
||||||
],
|
|
||||||
[AuthProvider.EMAIL]: [
|
|
||||||
InfraConfigEnum.MAILER_SMTP_URL,
|
|
||||||
InfraConfigEnum.MAILER_ADDRESS_FROM,
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load environment variables from the database and set them in the process
|
* Load environment variables from the database and set them in the process
|
||||||
*
|
*
|
||||||
@@ -65,42 +42,3 @@ export function stopApp() {
|
|||||||
process.kill(process.pid, 'SIGTERM');
|
process.kill(process.pid, 'SIGTERM');
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the configured SSO providers
|
|
||||||
* @returns Array of configured SSO providers
|
|
||||||
*/
|
|
||||||
export function getConfiguredSSOProviders() {
|
|
||||||
const allowedAuthProviders: string[] =
|
|
||||||
process.env.VITE_ALLOWED_AUTH_PROVIDERS.split(',');
|
|
||||||
let configuredAuthProviders: string[] = [];
|
|
||||||
|
|
||||||
const addProviderIfConfigured = (provider) => {
|
|
||||||
const configParameters: string[] = AuthProviderConfigurations[provider];
|
|
||||||
|
|
||||||
const isConfigured = configParameters.every((configParameter) => {
|
|
||||||
return process.env[configParameter];
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isConfigured) configuredAuthProviders.push(provider);
|
|
||||||
};
|
|
||||||
|
|
||||||
allowedAuthProviders.forEach((provider) => addProviderIfConfigured(provider));
|
|
||||||
|
|
||||||
if (configuredAuthProviders.length === 0) {
|
|
||||||
throwErr(AUTH_PROVIDER_NOT_CONFIGURED);
|
|
||||||
} else if (allowedAuthProviders.length !== configuredAuthProviders.length) {
|
|
||||||
const unConfiguredAuthProviders = allowedAuthProviders.filter(
|
|
||||||
(provider) => {
|
|
||||||
return !configuredAuthProviders.includes(provider);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`${unConfiguredAuthProviders.join(
|
|
||||||
',',
|
|
||||||
)} SSO auth provider(s) are not configured properly. Do configure them from Admin Dashboard.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return configuredAuthProviders.join(',');
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -15,13 +15,11 @@ import {
|
|||||||
INFRA_CONFIG_NOT_LISTED,
|
INFRA_CONFIG_NOT_LISTED,
|
||||||
INFRA_CONFIG_RESET_FAILED,
|
INFRA_CONFIG_RESET_FAILED,
|
||||||
INFRA_CONFIG_UPDATE_FAILED,
|
INFRA_CONFIG_UPDATE_FAILED,
|
||||||
INFRA_CONFIG_SERVICE_NOT_CONFIGURED,
|
|
||||||
} from 'src/errors';
|
} from 'src/errors';
|
||||||
import { throwErr, validateSMTPEmail, validateSMTPUrl } from 'src/utils';
|
import { throwErr, validateEmail, validateSMTPUrl } from 'src/utils';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { ServiceStatus, getConfiguredSSOProviders, stopApp } from './helper';
|
import { ServiceStatus, stopApp } from './helper';
|
||||||
import { EnableAndDisableSSOArgs, InfraConfigArgs } from './input-args';
|
import { EnableAndDisableSSOArgs, InfraConfigArgs } from './input-args';
|
||||||
import { AuthProvider } from 'src/auth/helper';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InfraConfigService implements OnModuleInit {
|
export class InfraConfigService implements OnModuleInit {
|
||||||
@@ -71,7 +69,7 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: InfraConfigEnum.VITE_ALLOWED_AUTH_PROVIDERS,
|
name: InfraConfigEnum.VITE_ALLOWED_AUTH_PROVIDERS,
|
||||||
value: getConfiguredSSOProviders(),
|
value: process.env.VITE_ALLOWED_AUTH_PROVIDERS.toLocaleUpperCase(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -126,23 +124,10 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
cast(dbInfraConfig: DBInfraConfig) {
|
cast(dbInfraConfig: DBInfraConfig) {
|
||||||
return <InfraConfig>{
|
return <InfraConfig>{
|
||||||
name: dbInfraConfig.name,
|
name: dbInfraConfig.name,
|
||||||
value: dbInfraConfig.value ?? '',
|
value: dbInfraConfig.value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all the InfraConfigs as map
|
|
||||||
* @returns InfraConfig map
|
|
||||||
*/
|
|
||||||
async getInfraConfigsMap() {
|
|
||||||
const infraConfigs = await this.prisma.infraConfig.findMany();
|
|
||||||
const infraConfigMap: Record<string, string> = {};
|
|
||||||
infraConfigs.forEach((config) => {
|
|
||||||
infraConfigMap[config.name] = config.value;
|
|
||||||
});
|
|
||||||
return infraConfigMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update InfraConfig by name
|
* Update InfraConfig by name
|
||||||
* @param name Name of the InfraConfig
|
* @param name Name of the InfraConfig
|
||||||
@@ -197,32 +182,6 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the service is configured or not
|
|
||||||
* @param service Service can be Auth Provider, Mailer, Audit Log etc.
|
|
||||||
* @param configMap Map of all the infra configs
|
|
||||||
* @returns Either true or false
|
|
||||||
*/
|
|
||||||
isServiceConfigured(
|
|
||||||
service: AuthProvider,
|
|
||||||
configMap: Record<string, string>,
|
|
||||||
) {
|
|
||||||
switch (service) {
|
|
||||||
case AuthProvider.GOOGLE:
|
|
||||||
return configMap.GOOGLE_CLIENT_ID && configMap.GOOGLE_CLIENT_SECRET;
|
|
||||||
case AuthProvider.GITHUB:
|
|
||||||
return configMap.GITHUB_CLIENT_ID && configMap.GITHUB_CLIENT_SECRET;
|
|
||||||
case AuthProvider.MICROSOFT:
|
|
||||||
return (
|
|
||||||
configMap.MICROSOFT_CLIENT_ID && configMap.MICROSOFT_CLIENT_SECRET
|
|
||||||
);
|
|
||||||
case AuthProvider.EMAIL:
|
|
||||||
return configMap.MAILER_SMTP_URL && configMap.MAILER_ADDRESS_FROM;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable or Disable SSO for login/signup
|
* Enable or Disable SSO for login/signup
|
||||||
* @param provider Auth Provider to enable or disable
|
* @param provider Auth Provider to enable or disable
|
||||||
@@ -236,14 +195,8 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
|
|
||||||
let updatedAuthProviders = allowedAuthProviders;
|
let updatedAuthProviders = allowedAuthProviders;
|
||||||
|
|
||||||
const infraConfigMap = await this.getInfraConfigsMap();
|
|
||||||
|
|
||||||
providerInfo.forEach(({ provider, status }) => {
|
providerInfo.forEach(({ provider, status }) => {
|
||||||
if (status === ServiceStatus.ENABLE) {
|
if (status === ServiceStatus.ENABLE) {
|
||||||
const isConfigured = this.isServiceConfigured(provider, infraConfigMap);
|
|
||||||
if (!isConfigured) {
|
|
||||||
throwErr(INFRA_CONFIG_SERVICE_NOT_CONFIGURED);
|
|
||||||
}
|
|
||||||
updatedAuthProviders.push(provider);
|
updatedAuthProviders.push(provider);
|
||||||
} else if (status === ServiceStatus.DISABLE) {
|
} else if (status === ServiceStatus.DISABLE) {
|
||||||
updatedAuthProviders = updatedAuthProviders.filter(
|
updatedAuthProviders = updatedAuthProviders.filter(
|
||||||
@@ -333,9 +286,6 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the values of the InfraConfigs
|
|
||||||
*/
|
|
||||||
validateEnvValues(
|
validateEnvValues(
|
||||||
infraConfigs: {
|
infraConfigs: {
|
||||||
name: InfraConfigEnumForClient | InfraConfigEnum;
|
name: InfraConfigEnumForClient | InfraConfigEnum;
|
||||||
@@ -349,27 +299,9 @@ export class InfraConfigService implements OnModuleInit {
|
|||||||
if (!isValidUrl) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
if (!isValidUrl) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
||||||
break;
|
break;
|
||||||
case InfraConfigEnumForClient.MAILER_ADDRESS_FROM:
|
case InfraConfigEnumForClient.MAILER_ADDRESS_FROM:
|
||||||
const isValidEmail = validateSMTPEmail(infraConfigs[i].value);
|
const isValidEmail = validateEmail(infraConfigs[i].value);
|
||||||
if (!isValidEmail) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
if (!isValidEmail) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
||||||
break;
|
break;
|
||||||
case InfraConfigEnumForClient.GOOGLE_CLIENT_ID:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
case InfraConfigEnumForClient.GOOGLE_CLIENT_SECRET:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
case InfraConfigEnumForClient.GITHUB_CLIENT_ID:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
case InfraConfigEnumForClient.GITHUB_CLIENT_SECRET:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
case InfraConfigEnumForClient.MICROSOFT_CLIENT_ID:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
case InfraConfigEnumForClient.MICROSOFT_CLIENT_SECRET:
|
|
||||||
if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ async function bootstrap() {
|
|||||||
console.log(`Port: ${configService.get('PORT')}`);
|
console.log(`Port: ${configService.get('PORT')}`);
|
||||||
|
|
||||||
checkEnvironmentAuthProvider(
|
checkEnvironmentAuthProvider(
|
||||||
configService.get('INFRA.VITE_ALLOWED_AUTH_PROVIDERS') ??
|
configService.get('VITE_ALLOWED_AUTH_PROVIDERS'),
|
||||||
configService.get('VITE_ALLOWED_AUTH_PROVIDERS'),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
|
|||||||
@@ -131,28 +131,6 @@ export const validateEmail = (email: string) => {
|
|||||||
).test(email);
|
).test(email);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Regular expressions for supported address object formats by nodemailer
|
|
||||||
// check out for more info https://nodemailer.com/message/addresses
|
|
||||||
const emailRegex1 = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
|
||||||
const emailRegex2 =
|
|
||||||
/^[\w\s]* <([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})>$/;
|
|
||||||
const emailRegex3 =
|
|
||||||
/^"[\w\s]+" <([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})>$/;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks to see if the SMTP email is valid or not
|
|
||||||
* @param email
|
|
||||||
* @returns A Boolean depending on the format of the email
|
|
||||||
*/
|
|
||||||
export const validateSMTPEmail = (email: string) => {
|
|
||||||
// Check if the input matches any of the formats
|
|
||||||
return (
|
|
||||||
emailRegex1.test(email) ||
|
|
||||||
emailRegex2.test(email) ||
|
|
||||||
emailRegex3.test(email)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see if the URL is valid or not
|
* Checks to see if the URL is valid or not
|
||||||
* @param url The URL to validate
|
* @param url The URL to validate
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/cli",
|
"name": "@hoppscotch/cli",
|
||||||
"version": "0.5.1",
|
"version": "0.5.0",
|
||||||
"description": "A CLI to run Hoppscotch test scripts in CI environments.",
|
"description": "A CLI to run Hoppscotch test scripts in CI environments.",
|
||||||
"homepage": "https://hoppscotch.io",
|
"homepage": "https://hoppscotch.io",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
|||||||
@@ -118,15 +118,6 @@ describe("Test 'hopp test <file> --env <file>' command:", () => {
|
|||||||
const { error } = await runCLI(args);
|
const { error } = await runCLI(args);
|
||||||
expect(error).toBeNull();
|
expect(error).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Correctly resolves environment variables referenced in the request body", async () => {
|
|
||||||
const COLL_PATH = getTestJsonFilePath("req-body-env-vars-coll.json");
|
|
||||||
const ENVS_PATH = getTestJsonFilePath("req-body-env-vars-envs.json");
|
|
||||||
const args = `test ${COLL_PATH} --env ${ENVS_PATH}`;
|
|
||||||
|
|
||||||
const { error } = await runCLI(args);
|
|
||||||
expect(error).toBeNull();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Test 'hopp test <file> --delay <delay_in_ms>' command:", () => {
|
describe("Test 'hopp test <file> --delay <delay_in_ms>' command:", () => {
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"v": 2,
|
|
||||||
"name": "Test environment variables in request body",
|
|
||||||
"folders": [],
|
|
||||||
"requests": [
|
|
||||||
{
|
|
||||||
"v": "1",
|
|
||||||
"name": "test-request",
|
|
||||||
"endpoint": "https://echo.hoppscotch.io",
|
|
||||||
"method": "POST",
|
|
||||||
"headers": [],
|
|
||||||
"params": [],
|
|
||||||
"auth": {
|
|
||||||
"authType": "none",
|
|
||||||
"authActive": true
|
|
||||||
},
|
|
||||||
"body": {
|
|
||||||
"contentType": "application/json",
|
|
||||||
"body": "{\n \"firstName\": \"<<firstName>>\",\n \"lastName\": \"<<lastName>>\",\n \"greetText\": \"<<salutation>>, <<fullName>>\",\n \"fullName\": \"<<fullName>>\",\n \"id\": \"<<id>>\"\n}"
|
|
||||||
},
|
|
||||||
"preRequestScript": "",
|
|
||||||
"testScript": "pw.test(\"Status code is 200\", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test(\"Successfully resolves environments recursively\", ()=> {\n pw.expect(pw.env.getResolve(\"recursiveVarX\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"recursiveVarY\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"salutation\")).toBe(\"Hello\")\n});\n\npw.test(\"Successfully resolves environments referenced in the request body\", () => {\n const expectedId = \"7\"\n const expectedFirstName = \"John\"\n const expectedLastName = \"Doe\"\n const expectedFullName = `${expectedFirstName} ${expectedLastName}`\n const expectedGreetText = `Hello, ${expectedFullName}`\n\n pw.expect(pw.env.getResolve(\"recursiveVarX\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"recursiveVarY\")).toBe(\"Hello\")\n pw.expect(pw.env.getResolve(\"salutation\")).toBe(\"Hello\")\n\n const { id, firstName, lastName, fullName, greetText } = JSON.parse(pw.response.body.data)\n\n pw.expect(id).toBe(expectedId)\n pw.expect(expectedFirstName).toBe(firstName)\n pw.expect(expectedLastName).toBe(lastName)\n pw.expect(fullName).toBe(expectedFullName)\n pw.expect(greetText).toBe(expectedGreetText)\n});"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"auth": {
|
|
||||||
"authType": "none",
|
|
||||||
"authActive": true
|
|
||||||
},
|
|
||||||
"headers": []
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Response body sample",
|
|
||||||
"variables": [
|
|
||||||
{
|
|
||||||
"key": "firstName",
|
|
||||||
"value": "John"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "lastName",
|
|
||||||
"value": "Doe"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "id",
|
|
||||||
"value": "7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "fullName",
|
|
||||||
"value": "<<firstName>> <<lastName>>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "recursiveVarX",
|
|
||||||
"value": "<<recursiveVarY>>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "recursiveVarY",
|
|
||||||
"value": "<<salutation>>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "salutation",
|
|
||||||
"value": "Hello"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "greetText",
|
|
||||||
"value": "<<salutation>> <<fullName>>"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -22,10 +22,12 @@ export const trimAnsi = (target: string) => {
|
|||||||
|
|
||||||
export const getErrorCode = (out: string) => {
|
export const getErrorCode = (out: string) => {
|
||||||
const ansiTrimmedStr = trimAnsi(out);
|
const ansiTrimmedStr = trimAnsi(out);
|
||||||
|
|
||||||
return ansiTrimmedStr.split(" ")[0];
|
return ansiTrimmedStr.split(" ")[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTestJsonFilePath = (file: string) => {
|
export const getTestJsonFilePath = (file: string) => {
|
||||||
const filePath = resolve(__dirname, `../../src/__tests__/samples/${file}`);
|
const filePath = `${process.cwd()}/src/__tests__/samples/${file}`;
|
||||||
|
|
||||||
return filePath;
|
return filePath;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ export async function parseEnvsData(path: string) {
|
|||||||
envPairs.push({ key, value });
|
envPairs.push({ key, value });
|
||||||
}
|
}
|
||||||
} else if (HoppEnvExportObjectResult.success) {
|
} else if (HoppEnvExportObjectResult.success) {
|
||||||
envPairs.push(...HoppEnvExportObjectResult.data.variables);
|
const { key, value } = HoppEnvExportObjectResult.data.variables[0];
|
||||||
|
envPairs.push({ key, value });
|
||||||
}
|
}
|
||||||
|
|
||||||
return <HoppEnvs>{ global: [], selected: envPairs };
|
return <HoppEnvs>{ global: [], selected: envPairs };
|
||||||
|
|||||||
@@ -121,7 +121,7 @@
|
|||||||
"generate_token": "Generate Token",
|
"generate_token": "Generate Token",
|
||||||
"graphql_headers": "Authorization Headers are sent as part of the payload to connection_init",
|
"graphql_headers": "Authorization Headers are sent as part of the payload to connection_init",
|
||||||
"include_in_url": "Include in URL",
|
"include_in_url": "Include in URL",
|
||||||
"inherited_from": "Inherited {auth} from parent collection {collection} ",
|
"inherited_from": "Inherited from {auth} from Parent Collection {collection} ",
|
||||||
"learn": "Learn how",
|
"learn": "Learn how",
|
||||||
"oauth": {
|
"oauth": {
|
||||||
"redirect_auth_server_returned_error": "Auth Server returned an error state",
|
"redirect_auth_server_returned_error": "Auth Server returned an error state",
|
||||||
@@ -295,7 +295,6 @@
|
|||||||
"incorrect_email": "Incorrect email",
|
"incorrect_email": "Incorrect email",
|
||||||
"invalid_link": "Invalid link",
|
"invalid_link": "Invalid link",
|
||||||
"invalid_link_description": "The link you clicked is invalid or expired.",
|
"invalid_link_description": "The link you clicked is invalid or expired.",
|
||||||
"invalid_embed_link": "The embed does not exist or is invalid.",
|
|
||||||
"json_parsing_failed": "Invalid JSON",
|
"json_parsing_failed": "Invalid JSON",
|
||||||
"json_prettify_invalid_body": "Couldn't prettify an invalid body, solve json syntax errors and try again",
|
"json_prettify_invalid_body": "Couldn't prettify an invalid body, solve json syntax errors and try again",
|
||||||
"network_error": "There seems to be a network error. Please try again.",
|
"network_error": "There seems to be a network error. Please try again.",
|
||||||
@@ -314,12 +313,10 @@
|
|||||||
"export": {
|
"export": {
|
||||||
"as_json": "Export as JSON",
|
"as_json": "Export as JSON",
|
||||||
"create_secret_gist": "Create secret Gist",
|
"create_secret_gist": "Create secret Gist",
|
||||||
"create_secret_gist_tooltip_text": "Export as secret Gist",
|
|
||||||
"failed": "Something went wrong while exporting",
|
"failed": "Something went wrong while exporting",
|
||||||
"secret_gist_success": "Successfully exported as secret Gist",
|
"gist_created": "Gist created",
|
||||||
"require_github": "Login with GitHub to create secret gist",
|
"require_github": "Login with GitHub to create secret gist",
|
||||||
"title": "Export",
|
"title": "Export"
|
||||||
"success": "Successfully exported"
|
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"all": "All",
|
"all": "All",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/common",
|
"name": "@hoppscotch/common",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2023.12.2",
|
"version": "2023.12.0-1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
||||||
"test": "vitest --run",
|
"test": "vitest --run",
|
||||||
|
|||||||
@@ -9,10 +9,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { HoppCollection } from "@hoppscotch/data"
|
|
||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
import { PropType, computed, ref } from "vue"
|
|
||||||
|
|
||||||
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
||||||
import { UrlSource } from "~/helpers/import-export/import/import-sources/UrlSource"
|
import { UrlSource } from "~/helpers/import-export/import/import-sources/UrlSource"
|
||||||
|
|
||||||
@@ -27,9 +24,11 @@ import {
|
|||||||
} from "~/helpers/import-export/import/importers"
|
} from "~/helpers/import-export/import/importers"
|
||||||
|
|
||||||
import { defineStep } from "~/composables/step-components"
|
import { defineStep } from "~/composables/step-components"
|
||||||
|
import { PropType, computed, ref } from "vue"
|
||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
|
import { HoppCollection } from "@hoppscotch/data"
|
||||||
import { appendRESTCollections, restCollections$ } from "~/newstore/collections"
|
import { appendRESTCollections, restCollections$ } from "~/newstore/collections"
|
||||||
import MyCollectionImport from "~/components/importExport/ImportExportSteps/MyCollectionImport.vue"
|
import MyCollectionImport from "~/components/importExport/ImportExportSteps/MyCollectionImport.vue"
|
||||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||||
@@ -49,7 +48,7 @@ import { getTeamCollectionJSON } from "~/helpers/backend/helpers"
|
|||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
|
||||||
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
||||||
import { gistExporter } from "~/helpers/import-export/export/gist"
|
import { collectionsGistExporter } from "~/helpers/import-export/export/gistExport"
|
||||||
import { myCollectionsExporter } from "~/helpers/import-export/export/myCollections"
|
import { myCollectionsExporter } from "~/helpers/import-export/export/myCollections"
|
||||||
import { teamCollectionsExporter } from "~/helpers/import-export/export/teamCollections"
|
import { teamCollectionsExporter } from "~/helpers/import-export/export/teamCollections"
|
||||||
|
|
||||||
@@ -84,8 +83,6 @@ const currentUser = useReadonlyStream(
|
|||||||
platform.auth.getCurrentUser()
|
platform.auth.getCurrentUser()
|
||||||
)
|
)
|
||||||
|
|
||||||
const myCollections = useReadonlyStream(restCollections$, [])
|
|
||||||
|
|
||||||
const showImportFailedError = () => {
|
const showImportFailedError = () => {
|
||||||
toast.error(t("import.failed"))
|
toast.error(t("import.failed"))
|
||||||
}
|
}
|
||||||
@@ -471,13 +468,8 @@ const HoppGistCollectionsExporter: ImporterOrExporter = {
|
|||||||
icon: IconGithub,
|
icon: IconGithub,
|
||||||
disabled: !currentUser.value
|
disabled: !currentUser.value
|
||||||
? true
|
? true
|
||||||
: currentUser.value?.provider !== "github.com",
|
: currentUser.value.provider !== "github.com",
|
||||||
title:
|
title: t("export.create_secret_gist"),
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
currentUser?.value?.provider === "github.com"
|
|
||||||
? "export.create_secret_gist_tooltip_text"
|
|
||||||
: "export.require_github",
|
|
||||||
applicableTo: ["personal-workspace", "team-workspace"],
|
applicableTo: ["personal-workspace", "team-workspace"],
|
||||||
isLoading: isHoppGistCollectionExporterInProgress,
|
isLoading: isHoppGistCollectionExporterInProgress,
|
||||||
},
|
},
|
||||||
@@ -494,27 +486,13 @@ const HoppGistCollectionsExporter: ImporterOrExporter = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (E.isRight(collectionJSON)) {
|
if (E.isRight(collectionJSON)) {
|
||||||
if (!JSON.parse(collectionJSON.right).length) {
|
collectionsGistExporter(collectionJSON.right, accessToken)
|
||||||
isHoppGistCollectionExporterInProgress.value = false
|
|
||||||
return toast.error(t("error.no_collections_to_export"))
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await gistExporter(collectionJSON.right, accessToken)
|
|
||||||
|
|
||||||
if (E.isLeft(res)) {
|
|
||||||
toast.error(t("export.failed"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
toast.success(t("export.secret_gist_success"))
|
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
type: "HOPP_EXPORT_COLLECTION",
|
type: "HOPP_EXPORT_COLLECTION",
|
||||||
exporter: "gist",
|
exporter: "gist",
|
||||||
platform: "rest",
|
platform: "rest",
|
||||||
})
|
})
|
||||||
|
|
||||||
platform.io.openExternalLink(res.right)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isHoppGistCollectionExporterInProgress.value = false
|
isHoppGistCollectionExporterInProgress.value = false
|
||||||
@@ -582,6 +560,8 @@ const selectedTeamID = computed(() => {
|
|||||||
: undefined
|
: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const myCollections = useReadonlyStream(restCollections$, [])
|
||||||
|
|
||||||
const getCollectionJSON = async () => {
|
const getCollectionJSON = async () => {
|
||||||
if (
|
if (
|
||||||
props.collectionsType.type === "team-collections" &&
|
props.collectionsType.type === "team-collections" &&
|
||||||
|
|||||||
@@ -9,16 +9,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { HoppCollection } from "@hoppscotch/data"
|
|
||||||
import * as E from "fp-ts/Either"
|
|
||||||
import { ref } from "vue"
|
|
||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
|
import { HoppCollection } from "@hoppscotch/data"
|
||||||
import { ImporterOrExporter } from "~/components/importExport/types"
|
import { ImporterOrExporter } from "~/components/importExport/types"
|
||||||
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
||||||
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
||||||
|
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
|
||||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||||
import IconUser from "~icons/lucide/user"
|
import IconUser from "~icons/lucide/user"
|
||||||
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
||||||
@@ -31,7 +30,7 @@ import {
|
|||||||
} from "~/newstore/collections"
|
} from "~/newstore/collections"
|
||||||
import { hoppGqlCollectionsImporter } from "~/helpers/import-export/import/hoppGql"
|
import { hoppGqlCollectionsImporter } from "~/helpers/import-export/import/hoppGql"
|
||||||
import { gqlCollectionsExporter } from "~/helpers/import-export/export/gqlCollections"
|
import { gqlCollectionsExporter } from "~/helpers/import-export/export/gqlCollections"
|
||||||
import { gistExporter } from "~/helpers/import-export/export/gist"
|
import { gqlCollectionsGistExporter } from "~/helpers/import-export/export/gqlCollectionsGistExporter"
|
||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { hoppGQLImporter } from "~/helpers/import-export/import/hopp"
|
import { hoppGQLImporter } from "~/helpers/import-export/import/hopp"
|
||||||
|
|
||||||
@@ -43,10 +42,6 @@ const currentUser = useReadonlyStream(
|
|||||||
platform.auth.getCurrentUser()
|
platform.auth.getCurrentUser()
|
||||||
)
|
)
|
||||||
|
|
||||||
const gqlCollections = useReadonlyStream(graphqlCollections$, [])
|
|
||||||
|
|
||||||
const isGqlCollectionGistExportInProgress = ref(false)
|
|
||||||
|
|
||||||
const GqlCollectionsHoppImporter: ImporterOrExporter = {
|
const GqlCollectionsHoppImporter: ImporterOrExporter = {
|
||||||
metadata: {
|
metadata: {
|
||||||
id: "import.from_json",
|
id: "import.from_json",
|
||||||
@@ -124,6 +119,8 @@ const GqlCollectionsGistImporter: ImporterOrExporter = {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const gqlCollections = useReadonlyStream(graphqlCollections$, [])
|
||||||
|
|
||||||
const GqlCollectionsHoppExporter: ImporterOrExporter = {
|
const GqlCollectionsHoppExporter: ImporterOrExporter = {
|
||||||
metadata: {
|
metadata: {
|
||||||
id: "export.as_json",
|
id: "export.as_json",
|
||||||
@@ -162,35 +159,29 @@ const GqlCollectionsGistExporter: ImporterOrExporter = {
|
|||||||
metadata: {
|
metadata: {
|
||||||
id: "export.as_gist",
|
id: "export.as_gist",
|
||||||
name: "export.create_secret_gist",
|
name: "export.create_secret_gist",
|
||||||
title:
|
title: !currentUser
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
? "export.require_github"
|
||||||
// @ts-ignore
|
: // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
currentUser?.value?.provider === "github.com"
|
// @ts-ignore
|
||||||
? "export.create_secret_gist_tooltip_text"
|
currentUser.provider !== "github.com"
|
||||||
: "export.require_github",
|
? `export.require_github`
|
||||||
|
: "export.create_secret_gist",
|
||||||
icon: IconUser,
|
icon: IconUser,
|
||||||
disabled: !currentUser.value
|
disabled: !currentUser.value
|
||||||
? true
|
? true
|
||||||
: currentUser.value?.provider !== "github.com",
|
: currentUser.value.provider !== "github.com",
|
||||||
applicableTo: ["personal-workspace"],
|
applicableTo: ["personal-workspace"],
|
||||||
isLoading: isGqlCollectionGistExportInProgress,
|
|
||||||
},
|
},
|
||||||
action: async () => {
|
action: async () => {
|
||||||
if (!gqlCollections.value.length) {
|
|
||||||
return toast.error(t("error.no_collections_to_export"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentUser.value) {
|
if (!currentUser.value) {
|
||||||
toast.error(t("profile.no_permission"))
|
toast.error(t("profile.no_permission"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isGqlCollectionGistExportInProgress.value = true
|
|
||||||
|
|
||||||
const accessToken = currentUser.value?.accessToken
|
const accessToken = currentUser.value?.accessToken
|
||||||
|
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
const res = await gistExporter(
|
const res = await gqlCollectionsGistExporter(
|
||||||
JSON.stringify(gqlCollections.value),
|
JSON.stringify(gqlCollections.value),
|
||||||
accessToken
|
accessToken
|
||||||
)
|
)
|
||||||
@@ -200,7 +191,7 @@ const GqlCollectionsGistExporter: ImporterOrExporter = {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.success(t("export.secret_gist_success"))
|
toast.success(t("export.success"))
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
type: "HOPP_EXPORT_COLLECTION",
|
type: "HOPP_EXPORT_COLLECTION",
|
||||||
@@ -210,8 +201,6 @@ const GqlCollectionsGistExporter: ImporterOrExporter = {
|
|||||||
|
|
||||||
platform.io.openExternalLink(res.right)
|
platform.io.openExternalLink(res.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
isGqlCollectionGistExportInProgress.value = false
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,11 +70,7 @@
|
|||||||
v-model:option-tab="selectedOptionTab"
|
v-model:option-tab="selectedOptionTab"
|
||||||
:properties="properties"
|
:properties="properties"
|
||||||
/>
|
/>
|
||||||
<HttpResponse
|
<HttpResponse :document="tab.document" :is-embed="true" />
|
||||||
v-if="tab.document.response"
|
|
||||||
:document="tab.document"
|
|
||||||
:is-embed="true"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -92,19 +88,18 @@ import { runRESTRequest$ } from "~/helpers/RequestRunner"
|
|||||||
import { HoppTab } from "~/services/tab"
|
import { HoppTab } from "~/services/tab"
|
||||||
import { HoppRESTDocument } from "~/helpers/rest/document"
|
import { HoppRESTDocument } from "~/helpers/rest/document"
|
||||||
import IconSave from "~icons/lucide/save"
|
import IconSave from "~icons/lucide/save"
|
||||||
import { RESTOptionTabs } from "../http/RequestOptions.vue"
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelTab: HoppTab<HoppRESTDocument>
|
modelTab: HoppTab<HoppRESTDocument>
|
||||||
properties: RESTOptionTabs[]
|
properties: string[]
|
||||||
sharedRequestID: string
|
sharedRequestID: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const tab = useModel(props, "modelTab")
|
const tab = useModel(props, "modelTab")
|
||||||
|
|
||||||
const selectedOptionTab = ref<RESTOptionTabs>(props.properties[0])
|
const selectedOptionTab = ref(props.properties[0])
|
||||||
|
|
||||||
const requestCancelFunc: Ref<(() => void) | null> = ref(null)
|
const requestCancelFunc: Ref<(() => void) | null> = ref(null)
|
||||||
|
|
||||||
|
|||||||
@@ -9,17 +9,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Environment } from "@hoppscotch/data"
|
|
||||||
import * as E from "fp-ts/Either"
|
|
||||||
import { ref } from "vue"
|
|
||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
|
import { Environment } from "@hoppscotch/data"
|
||||||
import { ImporterOrExporter } from "~/components/importExport/types"
|
import { ImporterOrExporter } from "~/components/importExport/types"
|
||||||
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
||||||
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
||||||
import { hoppEnvImporter } from "~/helpers/import-export/import/hoppEnv"
|
import { hoppEnvImporter } from "~/helpers/import-export/import/hoppEnv"
|
||||||
|
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
import {
|
import {
|
||||||
appendEnvironments,
|
appendEnvironments,
|
||||||
addGlobalEnvVariable,
|
addGlobalEnvVariable,
|
||||||
@@ -41,7 +39,7 @@ import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
|||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { useReadonlyStream } from "~/composables/stream"
|
import { useReadonlyStream } from "~/composables/stream"
|
||||||
import { environmentsExporter } from "~/helpers/import-export/export/environments"
|
import { environmentsExporter } from "~/helpers/import-export/export/environments"
|
||||||
import { gistExporter } from "~/helpers/import-export/export/gist"
|
import { environmentsGistExporter } from "~/helpers/import-export/export/environmentsGistExport"
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
@@ -60,8 +58,6 @@ const currentUser = useReadonlyStream(
|
|||||||
platform.auth.getCurrentUser()
|
platform.auth.getCurrentUser()
|
||||||
)
|
)
|
||||||
|
|
||||||
const isEnvironmentGistExportInProgress = ref(false)
|
|
||||||
|
|
||||||
const isTeamEnvironment = computed(() => {
|
const isTeamEnvironment = computed(() => {
|
||||||
return props.environmentType === "TEAM_ENV"
|
return props.environmentType === "TEAM_ENV"
|
||||||
})
|
})
|
||||||
@@ -266,44 +262,35 @@ const HoppEnvironmentsGistExporter: ImporterOrExporter = {
|
|||||||
title:
|
title:
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
currentUser?.value?.provider === "github.com"
|
currentUser?.provider === "github.com"
|
||||||
? "export.create_secret_gist_tooltip_text"
|
? "export.create_secret_gist"
|
||||||
: "export.require_github",
|
: "export.require_github",
|
||||||
icon: IconUser,
|
icon: IconUser,
|
||||||
disabled: !currentUser.value
|
disabled: !currentUser.value
|
||||||
? true
|
? true
|
||||||
: currentUser.value?.provider !== "github.com",
|
: currentUser.value.provider !== "github.com",
|
||||||
applicableTo: ["personal-workspace", "team-workspace"],
|
applicableTo: ["personal-workspace", "team-workspace"],
|
||||||
isLoading: isEnvironmentGistExportInProgress,
|
|
||||||
},
|
},
|
||||||
action: async () => {
|
action: async () => {
|
||||||
if (!environmentJson.value.length) {
|
|
||||||
return toast.error(t("error.no_environments_to_export"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentUser.value) {
|
if (!currentUser.value) {
|
||||||
toast.error(t("profile.no_permission"))
|
toast.error(t("profile.no_permission"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isEnvironmentGistExportInProgress.value = true
|
|
||||||
|
|
||||||
const accessToken = currentUser.value?.accessToken
|
const accessToken = currentUser.value?.accessToken
|
||||||
|
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
const res = await gistExporter(
|
const res = await environmentsGistExporter(
|
||||||
JSON.stringify(environmentJson.value),
|
JSON.stringify(environmentJson.value),
|
||||||
accessToken,
|
accessToken
|
||||||
"hoppscotch-environment.json"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (E.isLeft(res)) {
|
if (E.isLeft(res)) {
|
||||||
toast.error(t("export.failed"))
|
toast.error(t("export.failed"))
|
||||||
isEnvironmentGistExportInProgress.value = false
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.success(t("export.secret_gist_success"))
|
toast.success(t("export.success"))
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
type: "HOPP_EXPORT_ENVIRONMENT",
|
type: "HOPP_EXPORT_ENVIRONMENT",
|
||||||
@@ -312,8 +299,6 @@ const HoppEnvironmentsGistExporter: ImporterOrExporter = {
|
|||||||
|
|
||||||
platform.io.openExternalLink(res.right)
|
platform.io.openExternalLink(res.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
isEnvironmentGistExportInProgress.value = false
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,10 +140,7 @@ const runQuery = async (
|
|||||||
const runVariables = clone(request.value.variables)
|
const runVariables = clone(request.value.variables)
|
||||||
const runAuth =
|
const runAuth =
|
||||||
request.value.auth.authType === "inherit" && request.value.auth.authActive
|
request.value.auth.authType === "inherit" && request.value.auth.authActive
|
||||||
? clone(
|
? clone(tabs.currentActiveTab.value.document.inheritedProperties?.auth)
|
||||||
tabs.currentActiveTab.value.document.inheritedProperties?.auth
|
|
||||||
.inheritedAuth
|
|
||||||
)
|
|
||||||
: clone(request.value.auth)
|
: clone(request.value.auth)
|
||||||
|
|
||||||
const inheritedHeaders =
|
const inheritedHeaders =
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ import IconClock from "~icons/lucide/clock"
|
|||||||
import IconCopy from "~icons/lucide/copy"
|
import IconCopy from "~icons/lucide/copy"
|
||||||
import IconBox from "~icons/lucide/box"
|
import IconBox from "~icons/lucide/box"
|
||||||
import { computed, nextTick, reactive, ref } from "vue"
|
import { computed, nextTick, reactive, ref } from "vue"
|
||||||
import { GraphQLField, GraphQLType, getNamedType } from "graphql"
|
import { GraphQLField, GraphQLType } from "graphql"
|
||||||
import { refAutoReset } from "@vueuse/core"
|
import { refAutoReset } from "@vueuse/core"
|
||||||
import { useCodemirror } from "@composables/codemirror"
|
import { useCodemirror } from "@composables/codemirror"
|
||||||
import { copyToClipboard } from "@helpers/utils/clipboard"
|
import { copyToClipboard } from "@helpers/utils/clipboard"
|
||||||
@@ -260,6 +260,12 @@ function getFilteredGraphqlTypes(filterText: string, types: GraphQLType[]) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveRootType(type: GraphQLType) {
|
||||||
|
let t: any = type
|
||||||
|
while (t.ofType) t = t.ofType
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
const downloadSchemaIcon = refAutoReset<typeof IconDownload | typeof IconCheck>(
|
const downloadSchemaIcon = refAutoReset<typeof IconDownload | typeof IconCheck>(
|
||||||
@@ -325,7 +331,7 @@ const handleJumpToType = async (type: GraphQLType) => {
|
|||||||
selectedGqlTab.value = "types"
|
selectedGqlTab.value = "types"
|
||||||
await nextTick()
|
await nextTick()
|
||||||
|
|
||||||
const rootTypeName = getNamedType(type).name
|
const rootTypeName = resolveRootType(type).name
|
||||||
const target = document.getElementById(`type_${rootTypeName}`)
|
const target = document.getElementById(`type_${rootTypeName}`)
|
||||||
if (target) {
|
if (target) {
|
||||||
target.scrollIntoView({ block: "center", behavior: "smooth" })
|
target.scrollIntoView({ block: "center", behavior: "smooth" })
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { GraphQLScalarType, GraphQLType, getNamedType } from "graphql"
|
import { GraphQLScalarType, GraphQLType } from "graphql"
|
||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -21,9 +21,15 @@ const emit = defineEmits<{
|
|||||||
|
|
||||||
const typeString = computed(() => `${props.gqlType}`)
|
const typeString = computed(() => `${props.gqlType}`)
|
||||||
const isScalar = computed(() => {
|
const isScalar = computed(() => {
|
||||||
return getNamedType(props.gqlType) instanceof GraphQLScalarType
|
return resolveRootType(props.gqlType) instanceof GraphQLScalarType
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function resolveRootType(type: GraphQLType) {
|
||||||
|
let t = type as any
|
||||||
|
while (t.ofType !== null) t = t.ofType
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
function jumpToType() {
|
function jumpToType() {
|
||||||
if (isScalar.value) return
|
if (isScalar.value) return
|
||||||
emit("jump-to-type", props.gqlType)
|
emit("jump-to-type", props.gqlType)
|
||||||
|
|||||||
@@ -99,7 +99,6 @@ useCodemirror(
|
|||||||
linter,
|
linter,
|
||||||
completer,
|
completer,
|
||||||
environmentHighlights: false,
|
environmentHighlights: false,
|
||||||
contextMenuEnabled: false,
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ import { useReadonlyStream, useStreamSubscriber } from "@composables/stream"
|
|||||||
import { useToast } from "@composables/toast"
|
import { useToast } from "@composables/toast"
|
||||||
import { useVModel } from "@vueuse/core"
|
import { useVModel } from "@vueuse/core"
|
||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
import { Ref, computed, ref, onUnmounted } from "vue"
|
import { Ref, computed, onBeforeUnmount, ref } from "vue"
|
||||||
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
||||||
import { runMutation } from "~/helpers/backend/GQLClient"
|
import { runMutation } from "~/helpers/backend/GQLClient"
|
||||||
import { UpdateRequestDocument } from "~/helpers/backend/graphql"
|
import { UpdateRequestDocument } from "~/helpers/backend/graphql"
|
||||||
@@ -322,10 +322,6 @@ const userHistories = computed(() => {
|
|||||||
return history.value.map((history) => history.request.endpoint).slice(0, 10)
|
return history.value.map((history) => history.request.endpoint).slice(0, 10)
|
||||||
})
|
})
|
||||||
|
|
||||||
const inspectionService = useService(InspectionService)
|
|
||||||
|
|
||||||
const tabs = useService(RESTTabService)
|
|
||||||
|
|
||||||
const newSendRequest = async () => {
|
const newSendRequest = async () => {
|
||||||
if (newEndpoint.value === "" || /^\s+$/.test(newEndpoint.value)) {
|
if (newEndpoint.value === "" || /^\s+$/.test(newEndpoint.value)) {
|
||||||
toast.error(`${t("empty.endpoint")}`)
|
toast.error(`${t("empty.endpoint")}`)
|
||||||
@@ -426,17 +422,6 @@ function isCURL(curl: string) {
|
|||||||
return curl.includes("curl ")
|
return curl.includes("curl ")
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentTabID = tabs.currentTabID.value
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
//check if current tab id exist in the current tab id lists
|
|
||||||
const isCurrentTabRemoved = !tabs
|
|
||||||
.getActiveTabs()
|
|
||||||
.value.some((tab) => tab.id === currentTabID)
|
|
||||||
|
|
||||||
if (isCurrentTabRemoved) cancelRequest()
|
|
||||||
})
|
|
||||||
|
|
||||||
const cancelRequest = () => {
|
const cancelRequest = () => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
requestCancelFunc.value?.()
|
requestCancelFunc.value?.()
|
||||||
@@ -568,6 +553,10 @@ const saveRequest = () => {
|
|||||||
|
|
||||||
const request = ref<HoppRESTRequest | null>(null)
|
const request = ref<HoppRESTRequest | null>(null)
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (loading.value) cancelRequest()
|
||||||
|
})
|
||||||
|
|
||||||
defineActionHandler("request.send-cancel", () => {
|
defineActionHandler("request.send-cancel", () => {
|
||||||
if (!loading.value) newSendRequest()
|
if (!loading.value) newSendRequest()
|
||||||
else cancelRequest()
|
else cancelRequest()
|
||||||
@@ -618,5 +607,8 @@ const isCustomMethod = computed(() => {
|
|||||||
|
|
||||||
const COLUMN_LAYOUT = useSetting("COLUMN_LAYOUT")
|
const COLUMN_LAYOUT = useSetting("COLUMN_LAYOUT")
|
||||||
|
|
||||||
|
const inspectionService = useService(InspectionService)
|
||||||
|
|
||||||
|
const tabs = useService(RESTTabService)
|
||||||
const tabResults = inspectionService.getResultViewFor(tabs.currentTabID.value)
|
const tabResults = inspectionService.getResultViewFor(tabs.currentTabID.value)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
render-inactive-tabs
|
render-inactive-tabs
|
||||||
>
|
>
|
||||||
<HoppSmartTab
|
<HoppSmartTab
|
||||||
v-if="properties ? properties.includes('params') : true"
|
v-if="properties ? properties.includes('parameters') : true"
|
||||||
:id="'params'"
|
:id="'params'"
|
||||||
:label="`${t('tab.parameters')}`"
|
:label="`${t('tab.parameters')}`"
|
||||||
:info="`${newActiveParamsCount$}`"
|
:info="`${newActiveParamsCount$}`"
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<HttpParameters v-model="request.params" />
|
<HttpParameters v-model="request.params" />
|
||||||
</HoppSmartTab>
|
</HoppSmartTab>
|
||||||
<HoppSmartTab
|
<HoppSmartTab
|
||||||
v-if="properties ? properties.includes('bodyParams') : true"
|
v-if="properties ? properties.includes('body') : true"
|
||||||
:id="'bodyParams'"
|
:id="'bodyParams'"
|
||||||
:label="`${t('tab.body')}`"
|
:label="`${t('tab.body')}`"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ useCodemirror(
|
|||||||
linter,
|
linter,
|
||||||
completer,
|
completer,
|
||||||
environmentHighlights: false,
|
environmentHighlights: false,
|
||||||
contextMenuEnabled: false,
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ const widgets: Widget[] = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
type Tabs = "params" | "bodyParams" | "headers" | "authorization"
|
type Tabs = "parameters" | "body" | "headers" | "authorization"
|
||||||
|
|
||||||
type EmbedOption = {
|
type EmbedOption = {
|
||||||
selectedTab: Tabs
|
selectedTab: Tabs
|
||||||
@@ -116,15 +116,15 @@ type EmbedOption = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const embedOption = ref<EmbedOption>({
|
const embedOption = ref<EmbedOption>({
|
||||||
selectedTab: "params",
|
selectedTab: "parameters",
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
value: "params",
|
value: "parameters",
|
||||||
label: t("tab.parameters"),
|
label: t("tab.parameters"),
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "bodyParams",
|
value: "body",
|
||||||
label: t("tab.body"),
|
label: t("tab.body"),
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -225,10 +225,10 @@ const props = defineProps({
|
|||||||
embedOptions: {
|
embedOptions: {
|
||||||
type: Object as PropType<EmbedOption>,
|
type: Object as PropType<EmbedOption>,
|
||||||
default: () => ({
|
default: () => ({
|
||||||
selectedTab: "params",
|
selectedTab: "parameters",
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
value: "params",
|
value: "parameters",
|
||||||
label: "shared_requests.parameters",
|
label: "shared_requests.parameters",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
@@ -290,7 +290,7 @@ const widgets: Widget[] = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
type EmbedTabs = "params" | "bodyParams" | "headers" | "authorization"
|
type EmbedTabs = "parameters" | "body" | "headers" | "authorization"
|
||||||
|
|
||||||
type EmbedOption = {
|
type EmbedOption = {
|
||||||
selectedTab: EmbedTabs
|
selectedTab: EmbedTabs
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ import { useI18n } from "~/composables/i18n"
|
|||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
type EmbedTabs = "params" | "bodyParams" | "headers" | "authorization"
|
type EmbedTabs = "parameters" | "body" | "headers" | "authorization"
|
||||||
|
|
||||||
type EmbedOption = {
|
type EmbedOption = {
|
||||||
selectedTab: EmbedTabs
|
selectedTab: EmbedTabs
|
||||||
@@ -93,15 +93,15 @@ const props = defineProps({
|
|||||||
embedOptions: {
|
embedOptions: {
|
||||||
type: Object as PropType<EmbedOption>,
|
type: Object as PropType<EmbedOption>,
|
||||||
default: () => ({
|
default: () => ({
|
||||||
selectedTab: "params",
|
selectedTab: "parameters",
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
value: "params",
|
value: "parameters",
|
||||||
label: "shared_requests.parameters",
|
label: "shared_requests.parameters",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "bodyParams",
|
value: "body",
|
||||||
label: "shared_requests.body",
|
label: "shared_requests.body",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div v-if="loading" class="flex flex-col items-center justify-center p-4">
|
<div v-if="loading" class="flex flex-col items-center justify-center">
|
||||||
<HoppSmartSpinner class="mb-4" />
|
<HoppSmartSpinner class="mb-4" />
|
||||||
<span class="text-secondaryLight">{{ t("state.loading") }}</span>
|
<span class="text-secondaryLight">{{ t("state.loading") }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -136,15 +136,15 @@ const shareRequestCreatingLoading = ref(false)
|
|||||||
const requestToShare = ref<HoppRESTRequest | null>(null)
|
const requestToShare = ref<HoppRESTRequest | null>(null)
|
||||||
|
|
||||||
const embedOptions = ref<EmbedOption>({
|
const embedOptions = ref<EmbedOption>({
|
||||||
selectedTab: "params",
|
selectedTab: "parameters",
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
value: "params",
|
value: "parameters",
|
||||||
label: t("tab.parameters"),
|
label: t("tab.parameters"),
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "bodyParams",
|
value: "body",
|
||||||
label: t("tab.body"),
|
label: t("tab.body"),
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
@@ -208,7 +208,7 @@ const currentUser = useReadonlyStream(
|
|||||||
|
|
||||||
const step = ref(1)
|
const step = ref(1)
|
||||||
|
|
||||||
type EmbedTabs = "params" | "bodyParams" | "headers" | "authorization"
|
type EmbedTabs = "parameters" | "body" | "headers" | "authorization"
|
||||||
|
|
||||||
type EmbedOption = {
|
type EmbedOption = {
|
||||||
selectedTab: EmbedTabs
|
selectedTab: EmbedTabs
|
||||||
@@ -249,15 +249,7 @@ const loading = computed(
|
|||||||
|
|
||||||
onLoggedIn(() => {
|
onLoggedIn(() => {
|
||||||
try {
|
try {
|
||||||
// wait for a bit to let the auth token to be set
|
adapter.initialize()
|
||||||
// because in some race conditions, the token is not set this fixes that
|
|
||||||
const initLoadTimeout = setTimeout(() => {
|
|
||||||
adapter.initialize()
|
|
||||||
}, 10)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearTimeout(initLoadTimeout)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
@@ -321,15 +313,15 @@ const displayCustomizeRequestModal = (
|
|||||||
info: t("shared_requests.button_info"),
|
info: t("shared_requests.button_info"),
|
||||||
}
|
}
|
||||||
embedOptions.value = {
|
embedOptions.value = {
|
||||||
selectedTab: "params",
|
selectedTab: "parameters",
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
value: "params",
|
value: "parameters",
|
||||||
label: t("tab.parameters"),
|
label: t("tab.parameters"),
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "bodyParams",
|
value: "body",
|
||||||
label: t("tab.body"),
|
label: t("tab.body"),
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
@@ -459,7 +451,7 @@ const getErrorMessage = (err: GQLError<string>) => {
|
|||||||
}
|
}
|
||||||
switch (err.error) {
|
switch (err.error) {
|
||||||
case "shortcode/not_found":
|
case "shortcode/not_found":
|
||||||
return t("shared_requests.not_found")
|
return t("shared_request.not_found")
|
||||||
default:
|
default:
|
||||||
return t("error.something_went_wrong")
|
return t("error.something_went_wrong")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ import { computed } from "vue"
|
|||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
|
|
||||||
type Tabs = "params" | "bodyParams" | "headers" | "authorization"
|
type Tabs = "parameters" | "body" | "headers" | "authorization"
|
||||||
|
|
||||||
type EmbedOption = {
|
type EmbedOption = {
|
||||||
selectedTab: Tabs
|
selectedTab: Tabs
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
v-if="currentSuggestionIndex === index"
|
v-if="currentSuggestionIndex === index"
|
||||||
class="hidden items-center text-secondary md:flex"
|
class="hidden items-center text-secondary md:flex"
|
||||||
>
|
>
|
||||||
<kbd class="shortcut-key">Enter</kbd>
|
<kbd class="shortcut-key">TAB</kbd>
|
||||||
<span class="ml-2 truncate">to select</span>
|
<span class="ml-2 truncate">to select</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -79,7 +79,6 @@ const props = withDefaults(
|
|||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
autoCompleteSource?: string[]
|
autoCompleteSource?: string[]
|
||||||
inspectionResults?: InspectorResult[] | undefined
|
inspectionResults?: InspectorResult[] | undefined
|
||||||
contextMenuEnabled?: boolean
|
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
modelValue: "",
|
modelValue: "",
|
||||||
@@ -92,7 +91,6 @@ const props = withDefaults(
|
|||||||
autoCompleteSource: undefined,
|
autoCompleteSource: undefined,
|
||||||
inspectionResult: undefined,
|
inspectionResult: undefined,
|
||||||
inspectionResults: undefined,
|
inspectionResults: undefined,
|
||||||
contextMenuEnabled: true,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -169,41 +167,36 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
const handleKeystroke = (ev: KeyboardEvent) => {
|
const handleKeystroke = (ev: KeyboardEvent) => {
|
||||||
if (!props.autoCompleteSource) return
|
if (["ArrowDown", "ArrowUp", "Enter", "Tab", "Escape"].includes(ev.key)) {
|
||||||
|
|
||||||
if (["ArrowDown", "ArrowUp", "Enter", "Escape"].includes(ev.key)) {
|
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (["Escape", "Tab", "Shift"].includes(ev.key)) {
|
if (ev.shiftKey) {
|
||||||
showSuggestionPopover.value = false
|
showSuggestionPopover.value = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev.key === "Enter") {
|
showSuggestionPopover.value = true
|
||||||
if (suggestions.value.length > 0 && currentSuggestionIndex.value > -1) {
|
|
||||||
updateModelValue(suggestions.value[currentSuggestionIndex.value])
|
|
||||||
currentSuggestionIndex.value = -1
|
|
||||||
|
|
||||||
//used to set codemirror cursor at the end of the line after selecting a suggestion
|
if (
|
||||||
nextTick(() => {
|
["Enter", "Tab"].includes(ev.key) &&
|
||||||
view.value?.dispatch({
|
suggestions.value.length > 0 &&
|
||||||
selection: EditorSelection.create([
|
currentSuggestionIndex.value > -1
|
||||||
EditorSelection.range(
|
) {
|
||||||
props.modelValue.length,
|
updateModelValue(suggestions.value[currentSuggestionIndex.value])
|
||||||
props.modelValue.length
|
currentSuggestionIndex.value = -1
|
||||||
),
|
|
||||||
]),
|
//used to set codemirror cursor at the end of the line after selecting a suggestion
|
||||||
})
|
nextTick(() => {
|
||||||
|
view.value?.dispatch({
|
||||||
|
selection: EditorSelection.create([
|
||||||
|
EditorSelection.range(
|
||||||
|
props.modelValue.length,
|
||||||
|
props.modelValue.length
|
||||||
|
),
|
||||||
|
]),
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
|
|
||||||
if (showSuggestionPopover.value) {
|
|
||||||
showSuggestionPopover.value = false
|
|
||||||
} else {
|
|
||||||
emit("enter", ev)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showSuggestionPopover.value = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev.key === "ArrowDown") {
|
if (ev.key === "ArrowDown") {
|
||||||
@@ -228,6 +221,15 @@ const handleKeystroke = (ev: KeyboardEvent) => {
|
|||||||
emit("keyup", ev)
|
emit("keyup", ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ev.key === "Enter") {
|
||||||
|
emit("enter", ev)
|
||||||
|
showSuggestionPopover.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.key === "Escape") {
|
||||||
|
showSuggestionPopover.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// used to scroll to the first suggestion when left arrow is pressed
|
// used to scroll to the first suggestion when left arrow is pressed
|
||||||
if (ev.key === "ArrowLeft") {
|
if (ev.key === "ArrowLeft") {
|
||||||
if (suggestions.value.length > 0) {
|
if (suggestions.value.length > 0) {
|
||||||
@@ -357,11 +359,8 @@ const initView = (el: any) => {
|
|||||||
handleTextSelection()
|
handleTextSelection()
|
||||||
}, 140)
|
}, 140)
|
||||||
|
|
||||||
// Only add event listeners if context menu is enabled in the component
|
el.addEventListener("mouseup", debounceFn)
|
||||||
if (props.contextMenuEnabled) {
|
el.addEventListener("keyup", debounceFn)
|
||||||
el.addEventListener("mouseup", debounceFn)
|
|
||||||
el.addEventListener("keyup", debounceFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
const extensions: Extension = [
|
const extensions: Extension = [
|
||||||
EditorView.contentAttributes.of({ "aria-label": props.placeholder }),
|
EditorView.contentAttributes.of({ "aria-label": props.placeholder }),
|
||||||
@@ -397,7 +396,7 @@ const initView = (el: any) => {
|
|||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
},
|
},
|
||||||
scroll(event) {
|
scroll(event) {
|
||||||
if (event.target && props.contextMenuEnabled) {
|
if (event.target) {
|
||||||
handleTextSelection()
|
handleTextSelection()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -406,6 +405,7 @@ const initView = (el: any) => {
|
|||||||
class {
|
class {
|
||||||
update(update: ViewUpdate) {
|
update(update: ViewUpdate) {
|
||||||
if (props.readonly) return
|
if (props.readonly) return
|
||||||
|
|
||||||
if (update.docChanged) {
|
if (update.docChanged) {
|
||||||
const prevValue = clone(cachedValue.value)
|
const prevValue = clone(cachedValue.value)
|
||||||
|
|
||||||
@@ -436,17 +436,6 @@ const initView = (el: any) => {
|
|||||||
clipboardEv = null
|
clipboardEv = null
|
||||||
pastedValue = null
|
pastedValue = null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.contextMenuEnabled) {
|
|
||||||
// close the context menu if text is being updated in the editor
|
|
||||||
invokeAction("contextmenu.open", {
|
|
||||||
position: {
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
},
|
|
||||||
text: null,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,8 +124,6 @@
|
|||||||
E.isRight(pendingInvites.data) &&
|
E.isRight(pendingInvites.data) &&
|
||||||
pendingInvites.data.right.team?.teamInvitations.length === 0
|
pendingInvites.data.right.team?.teamInvitations.length === 0
|
||||||
"
|
"
|
||||||
:src="`/images/states/${colorMode.value}/add_group.svg`"
|
|
||||||
:alt="t('empty.pending_invites')"
|
|
||||||
:text="t('empty.pending_invites')"
|
:text="t('empty.pending_invites')"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
v-if="props.showCount && props.teamMembers.length > maxMembersSoftLimit"
|
v-if="props.showCount && props.teamMembers.length > maxMembersSoftLimit"
|
||||||
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
||||||
:title="remainingSlicedMembers"
|
:title="remainingSlicedMembers"
|
||||||
class="text-[8px] z-10 inline-flex h-5 w-5 cursor-pointer items-center justify-center rounded-full bg-dividerDark text-secondaryDark ring-2 ring-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-primaryDark"
|
class="font- text-8px z-10 inline-flex h-5 w-5 cursor-pointer items-center justify-center rounded-full bg-dividerDark text-secondaryDark ring-2 ring-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-primaryDark"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="handleClick()"
|
@click="handleClick()"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
</HoppSmartPlaceholder>
|
</HoppSmartPlaceholder>
|
||||||
<div v-else-if="!loading" class="flex flex-col">
|
<div v-else-if="!loading" class="flex flex-col">
|
||||||
<div
|
<div
|
||||||
class="sticky top-0 z-10 mb-2 flex items-center justify-between bg-popover py-2 pl-2"
|
class="sticky -top-2 top-0 z-10 mb-2 flex items-center justify-between bg-popover py-2 pl-2"
|
||||||
>
|
>
|
||||||
<div class="flex items-center px-2 font-semibold text-secondaryLight">
|
<div class="flex items-center px-2 font-semibold text-secondaryLight">
|
||||||
{{ t("team.title") }}
|
{{ t("team.title") }}
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ type CodeMirrorOptions = {
|
|||||||
|
|
||||||
additionalExts?: Extension[]
|
additionalExts?: Extension[]
|
||||||
|
|
||||||
contextMenuEnabled?: boolean
|
|
||||||
|
|
||||||
// callback on editor update
|
// callback on editor update
|
||||||
onUpdate?: (view: ViewUpdate) => void
|
onUpdate?: (view: ViewUpdate) => void
|
||||||
}
|
}
|
||||||
@@ -210,9 +208,6 @@ export function useCodemirror(
|
|||||||
): { cursor: Ref<{ line: number; ch: number }> } {
|
): { cursor: Ref<{ line: number; ch: number }> } {
|
||||||
const { subscribeToStream } = useStreamSubscriber()
|
const { subscribeToStream } = useStreamSubscriber()
|
||||||
|
|
||||||
// Set default value for contextMenuEnabled if not provided
|
|
||||||
options.contextMenuEnabled = options.contextMenuEnabled ?? true
|
|
||||||
|
|
||||||
const additionalExts = new Compartment()
|
const additionalExts = new Compartment()
|
||||||
const language = new Compartment()
|
const language = new Compartment()
|
||||||
const lineWrapping = new Compartment()
|
const lineWrapping = new Compartment()
|
||||||
@@ -277,11 +272,8 @@ export function useCodemirror(
|
|||||||
handleTextSelection()
|
handleTextSelection()
|
||||||
}, 140)
|
}, 140)
|
||||||
|
|
||||||
// Only add event listeners if context menu is enabled in the editor
|
el.addEventListener("mouseup", debounceFn)
|
||||||
if (options.contextMenuEnabled) {
|
el.addEventListener("keyup", debounceFn)
|
||||||
el.addEventListener("mouseup", debounceFn)
|
|
||||||
el.addEventListener("keyup", debounceFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.onUpdate) {
|
if (options.onUpdate) {
|
||||||
options.onUpdate(update)
|
options.onUpdate(update)
|
||||||
@@ -320,7 +312,7 @@ export function useCodemirror(
|
|||||||
),
|
),
|
||||||
EditorView.domEventHandlers({
|
EditorView.domEventHandlers({
|
||||||
scroll(event) {
|
scroll(event) {
|
||||||
if (event.target && options.contextMenuEnabled) {
|
if (event.target) {
|
||||||
handleTextSelection()
|
handleTextSelection()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -154,9 +154,6 @@ export function runRESTRequest$(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (E.isRight(runResult)) {
|
if (E.isRight(runResult)) {
|
||||||
// set the response in the tab so that multiple tabs can run request simultaneously
|
|
||||||
tab.value.document.response = res
|
|
||||||
|
|
||||||
tab.value.document.testResults = translateToSandboxTestResults(
|
tab.value.document.testResults = translateToSandboxTestResults(
|
||||||
runResult.right
|
runResult.right
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,24 +1,13 @@
|
|||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
import { flow } from "fp-ts/function"
|
import { flow } from "fp-ts/function"
|
||||||
|
|
||||||
type SafeParseJSON = {
|
|
||||||
(str: string, convertToArray: true): O.Option<Array<unknown>>
|
|
||||||
(str: string, convertToArray?: false): O.Option<Record<string, unknown>>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks and Parses JSON string
|
* Checks and Parses JSON string
|
||||||
* @param str Raw JSON data to be parsed
|
* @param str Raw JSON data to be parsed
|
||||||
* @returns Option type with some(JSON data) or none
|
* @returns Option type with some(JSON data) or none
|
||||||
*/
|
*/
|
||||||
export const safeParseJSON: SafeParseJSON = (str, convertToArray = false) =>
|
export const safeParseJSON = (str: string): O.Option<object> =>
|
||||||
O.tryCatch(() => {
|
O.tryCatch(() => JSON.parse(str))
|
||||||
const data = JSON.parse(str)
|
|
||||||
if (convertToArray) {
|
|
||||||
return Array.isArray(data) ? data : [data]
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if given string is a JSON string
|
* Checks if given string is a JSON string
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const getDefaultGQLRequest = (): HoppGQLRequest => ({
|
|||||||
}`,
|
}`,
|
||||||
query: DEFAULT_QUERY,
|
query: DEFAULT_QUERY,
|
||||||
auth: {
|
auth: {
|
||||||
authType: "none",
|
authType: "inherit",
|
||||||
authActive: true,
|
authActive: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import { createGist } from "~/helpers/gist"
|
||||||
|
|
||||||
|
export const environmentsGistExporter = async (
|
||||||
|
environmentsJSON: string,
|
||||||
|
accessToken: string
|
||||||
|
) => {
|
||||||
|
const res = await createGist(
|
||||||
|
environmentsJSON,
|
||||||
|
"hoppscotch-collections.json",
|
||||||
|
accessToken
|
||||||
|
)()
|
||||||
|
|
||||||
|
if (E.isLeft(res)) {
|
||||||
|
return E.left(res.left)
|
||||||
|
}
|
||||||
|
return E.right(res.right.data.html_url as string)
|
||||||
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import * as E from "fp-ts/Either"
|
|
||||||
import { createGist } from "~/helpers/gist"
|
|
||||||
|
|
||||||
export const gistExporter = async (
|
|
||||||
JSONFileContents: string,
|
|
||||||
accessToken: string,
|
|
||||||
fileName = "hoppscotch-collections.json"
|
|
||||||
) => {
|
|
||||||
if (!accessToken) {
|
|
||||||
return E.left("Invalid User")
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await createGist(JSONFileContents, fileName, accessToken)()
|
|
||||||
|
|
||||||
if (E.isLeft(res)) {
|
|
||||||
return E.left(res.left)
|
|
||||||
}
|
|
||||||
return E.right(res.right.data.html_url as string)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { createGist } from "~/helpers/gist"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
|
||||||
|
export const collectionsGistExporter = async (
|
||||||
|
collectionJSON: string,
|
||||||
|
accessToken: string
|
||||||
|
) => {
|
||||||
|
if (!accessToken) {
|
||||||
|
return E.left("Invalid User")
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await createGist(
|
||||||
|
collectionJSON,
|
||||||
|
"hoppscotch-collections.json",
|
||||||
|
accessToken
|
||||||
|
)()
|
||||||
|
|
||||||
|
if (E.isLeft(res)) {
|
||||||
|
return E.left(res.left)
|
||||||
|
}
|
||||||
|
return E.right(true)
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import { createGist } from "~/helpers/gist"
|
||||||
|
|
||||||
|
export const gqlCollectionsGistExporter = async (
|
||||||
|
gqlCollectionsJSON: string,
|
||||||
|
accessToken: string
|
||||||
|
) => {
|
||||||
|
const res = await createGist(
|
||||||
|
gqlCollectionsJSON,
|
||||||
|
"hoppscotch-collections.json",
|
||||||
|
accessToken
|
||||||
|
)()
|
||||||
|
|
||||||
|
if (E.isLeft(res)) {
|
||||||
|
return E.left(res.left)
|
||||||
|
}
|
||||||
|
return E.right(res.right.data.html_url as string)
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ const hoppEnvSchema = z.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const hoppEnvImporter = (content: string) => {
|
export const hoppEnvImporter = (content: string) => {
|
||||||
const parsedContent = safeParseJSON(content, true)
|
const parsedContent = safeParseJSON(content)
|
||||||
|
|
||||||
// parse json from the environments string
|
// parse json from the environments string
|
||||||
if (O.isNone(parsedContent)) {
|
if (O.isNone(parsedContent)) {
|
||||||
|
|||||||
@@ -549,19 +549,13 @@ const convertPathToHoppReqs = (
|
|||||||
),
|
),
|
||||||
|
|
||||||
// Construct request object
|
// Construct request object
|
||||||
RA.map(({ method, info }) => {
|
RA.map(({ method, info }) =>
|
||||||
const openAPIUrl = parseOpenAPIUrl(doc)
|
makeRESTRequest({
|
||||||
const openAPIPath = replaceOpenApiPathTemplating(pathName)
|
|
||||||
|
|
||||||
const endpoint =
|
|
||||||
openAPIUrl.endsWith("/") && openAPIPath.startsWith("/")
|
|
||||||
? openAPIUrl + openAPIPath.slice(1)
|
|
||||||
: openAPIUrl + openAPIPath
|
|
||||||
|
|
||||||
return makeRESTRequest({
|
|
||||||
name: info.operationId ?? info.summary ?? "Untitled Request",
|
name: info.operationId ?? info.summary ?? "Untitled Request",
|
||||||
method: method.toUpperCase(),
|
method: method.toUpperCase(),
|
||||||
endpoint,
|
endpoint: `${parseOpenAPIUrl(doc)}${replaceOpenApiPathTemplating(
|
||||||
|
pathName
|
||||||
|
)}`,
|
||||||
|
|
||||||
// We don't need to worry about reference types as the Dereferencing pass should remove them
|
// We don't need to worry about reference types as the Dereferencing pass should remove them
|
||||||
params: parseOpenAPIParams(
|
params: parseOpenAPIParams(
|
||||||
@@ -578,7 +572,7 @@ const convertPathToHoppReqs = (
|
|||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
})
|
})
|
||||||
}),
|
),
|
||||||
|
|
||||||
// Disable Readonly
|
// Disable Readonly
|
||||||
RA.toArray
|
RA.toArray
|
||||||
|
|||||||
@@ -156,7 +156,6 @@ export default class ShortcodeListAdapter {
|
|||||||
const [shortcodeCreated$, shortcodeCreatedSub] = runAuthOnlyGQLSubscription(
|
const [shortcodeCreated$, shortcodeCreatedSub] = runAuthOnlyGQLSubscription(
|
||||||
{
|
{
|
||||||
query: ShortcodeCreatedDocument,
|
query: ShortcodeCreatedDocument,
|
||||||
variables: {},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -173,7 +172,6 @@ export default class ShortcodeListAdapter {
|
|||||||
const [shortcodeRevoked$, shortcodeRevokedSub] = runAuthOnlyGQLSubscription(
|
const [shortcodeRevoked$, shortcodeRevokedSub] = runAuthOnlyGQLSubscription(
|
||||||
{
|
{
|
||||||
query: ShortcodeDeletedDocument,
|
query: ShortcodeDeletedDocument,
|
||||||
variables: {},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -190,7 +188,6 @@ export default class ShortcodeListAdapter {
|
|||||||
const [shortcodeUpdated$, shortcodeUpdatedSub] = runAuthOnlyGQLSubscription(
|
const [shortcodeUpdated$, shortcodeUpdatedSub] = runAuthOnlyGQLSubscription(
|
||||||
{
|
{
|
||||||
query: ShortcodeUpdatedDocument,
|
query: ShortcodeUpdatedDocument,
|
||||||
variables: {},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1034,11 +1034,6 @@ export default class NewTeamCollectionAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to obtain the inherited auth and headers for a given folder path, used for both REST and GraphQL team collections
|
|
||||||
* @param folderPath the path of the folder to cascade the auth from
|
|
||||||
* @returns the inherited auth and headers for the given folder path
|
|
||||||
*/
|
|
||||||
public cascadeParentCollectionForHeaderAuth(folderPath: string) {
|
public cascadeParentCollectionForHeaderAuth(folderPath: string) {
|
||||||
let auth: HoppInheritedProperty["auth"] = {
|
let auth: HoppInheritedProperty["auth"] = {
|
||||||
parentID: folderPath ?? "",
|
parentID: folderPath ?? "",
|
||||||
@@ -1085,7 +1080,7 @@ export default class NewTeamCollectionAdapter {
|
|||||||
authType: "inherit",
|
authType: "inherit",
|
||||||
authActive: true,
|
authActive: true,
|
||||||
}
|
}
|
||||||
auth.parentID = path.slice(0, i + 1).join("/")
|
auth.parentID = [...path.slice(0, i + 1)].join("/")
|
||||||
auth.parentName = parentFolder.title
|
auth.parentName = parentFolder.title
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1094,12 +1089,9 @@ export default class NewTeamCollectionAdapter {
|
|||||||
const parentFolderAuth = data.auth
|
const parentFolderAuth = data.auth
|
||||||
const parentFolderHeaders = data.headers
|
const parentFolderHeaders = data.headers
|
||||||
|
|
||||||
if (
|
if (parentFolderAuth?.authType === "inherit" && path.length === 1) {
|
||||||
parentFolderAuth?.authType === "inherit" &&
|
|
||||||
path.slice(0, i + 1).length === 1
|
|
||||||
) {
|
|
||||||
auth = {
|
auth = {
|
||||||
parentID: path.slice(0, i + 1).join("/"),
|
parentID: [...path.slice(0, i + 1)].join("/"),
|
||||||
parentName: parentFolder.title,
|
parentName: parentFolder.title,
|
||||||
inheritedAuth: auth.inheritedAuth,
|
inheritedAuth: auth.inheritedAuth,
|
||||||
}
|
}
|
||||||
@@ -1107,7 +1099,7 @@ export default class NewTeamCollectionAdapter {
|
|||||||
|
|
||||||
if (parentFolderAuth?.authType !== "inherit") {
|
if (parentFolderAuth?.authType !== "inherit") {
|
||||||
auth = {
|
auth = {
|
||||||
parentID: path.slice(0, i + 1).join("/"),
|
parentID: [...path.slice(0, i + 1)].join("/"),
|
||||||
parentName: parentFolder.title,
|
parentName: parentFolder.title,
|
||||||
inheritedAuth: parentFolderAuth,
|
inheritedAuth: parentFolderAuth,
|
||||||
}
|
}
|
||||||
@@ -1120,7 +1112,7 @@ export default class NewTeamCollectionAdapter {
|
|||||||
const index = headers.findIndex(
|
const index = headers.findIndex(
|
||||||
(h) => h.inheritedHeader?.key === header.key
|
(h) => h.inheritedHeader?.key === header.key
|
||||||
)
|
)
|
||||||
const currentPath = path.slice(0, i + 1).join("/")
|
const currentPath = [...path.slice(0, i + 1)].join("/")
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
// Replace the existing header with the same key
|
// Replace the existing header with the same key
|
||||||
headers[index] = {
|
headers[index] = {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
HoppRESTRequest,
|
HoppRESTRequest,
|
||||||
HoppCollection,
|
HoppCollection,
|
||||||
makeCollection,
|
makeCollection,
|
||||||
HoppGQLAuth,
|
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
||||||
import { cloneDeep } from "lodash-es"
|
import { cloneDeep } from "lodash-es"
|
||||||
@@ -12,9 +11,6 @@ import { resolveSaveContextOnRequestReorder } from "~/helpers/collection/request
|
|||||||
import { getService } from "~/modules/dioc"
|
import { getService } from "~/modules/dioc"
|
||||||
import { RESTTabService } from "~/services/tab/rest"
|
import { RESTTabService } from "~/services/tab/rest"
|
||||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
import { HoppRESTAuth } from "@hoppscotch/data"
|
|
||||||
import { HoppRESTHeaders } from "@hoppscotch/data"
|
|
||||||
import { HoppGQLHeader } from "~/helpers/graphql"
|
|
||||||
|
|
||||||
const defaultRESTCollectionState = {
|
const defaultRESTCollectionState = {
|
||||||
state: [
|
state: [
|
||||||
@@ -67,12 +63,6 @@ export function navigateToFolderWithIndexPath(
|
|||||||
return target !== undefined ? target : null
|
return target !== undefined ? target : null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to obtain the inherited auth and headers for a given folder path, used for both REST and GraphQL personal collections
|
|
||||||
* @param folderPath the path of the folder to cascade the auth from
|
|
||||||
* @param type the type of collection
|
|
||||||
* @returns the inherited auth and headers for the given folder path
|
|
||||||
*/
|
|
||||||
export function cascadeParentCollectionForHeaderAuth(
|
export function cascadeParentCollectionForHeaderAuth(
|
||||||
folderPath: string | undefined,
|
folderPath: string | undefined,
|
||||||
type: "rest" | "graphql"
|
type: "rest" | "graphql"
|
||||||
@@ -113,16 +103,10 @@ export function cascadeParentCollectionForHeaderAuth(
|
|||||||
return { auth, headers }
|
return { auth, headers }
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentFolderAuth = parentFolder.auth as HoppRESTAuth | HoppGQLAuth
|
const parentFolderAuth = parentFolder.auth
|
||||||
const parentFolderHeaders = parentFolder.headers as
|
const parentFolderHeaders = parentFolder.headers
|
||||||
| HoppRESTHeaders
|
|
||||||
| HoppGQLHeader[]
|
|
||||||
|
|
||||||
// check if the parent folder has authType 'inherit' and if it is the root folder
|
// check if the parent folder has authType 'inherit' and if it is the root folder
|
||||||
if (
|
if (parentFolderAuth?.authType === "inherit" && path.length === 1) {
|
||||||
parentFolderAuth?.authType === "inherit" &&
|
|
||||||
[...path.slice(0, i + 1)].length === 1
|
|
||||||
) {
|
|
||||||
auth = {
|
auth = {
|
||||||
parentID: [...path.slice(0, i + 1)].join("/"),
|
parentID: [...path.slice(0, i + 1)].join("/"),
|
||||||
parentName: parentFolder.name,
|
parentName: parentFolder.name,
|
||||||
|
|||||||
@@ -1,27 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col justify-center">
|
<div class="flex flex-col flex-1 w-full">
|
||||||
<div
|
|
||||||
v-if="sharedRequestDetails.loading"
|
|
||||||
class="flex justify-center items-center py-5"
|
|
||||||
>
|
|
||||||
<HoppSmartSpinner />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-else-if="E.isLeft(sharedRequestDetails.data) || invalidLink"
|
|
||||||
class="flex flex-1 flex-col items-center justify-center p-8"
|
|
||||||
>
|
|
||||||
<icon-lucide-alert-triangle class="svg-icons mb-2 opacity-75" />
|
|
||||||
<h1 class="heading text-center">
|
|
||||||
{{ t("error.invalid_link") }}
|
|
||||||
</h1>
|
|
||||||
<p class="mt-2 text-center">
|
|
||||||
{{ t("error.invalid_embed_link") }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Embeds
|
<Embeds
|
||||||
v-else-if="tab"
|
v-if="tab"
|
||||||
v-model:modelTab="tab"
|
v-model:modelTab="tab"
|
||||||
:properties="properties"
|
:properties="properties"
|
||||||
:shared-request-i-d="sharedRequestID"
|
:shared-request-i-d="sharedRequestID"
|
||||||
@@ -48,9 +28,6 @@ import {
|
|||||||
import { HoppTab } from "~/services/tab"
|
import { HoppTab } from "~/services/tab"
|
||||||
import { HoppRESTDocument } from "~/helpers/rest/document"
|
import { HoppRESTDocument } from "~/helpers/rest/document"
|
||||||
import { applySetting } from "~/newstore/settings"
|
import { applySetting } from "~/newstore/settings"
|
||||||
import { useI18n } from "~/composables/i18n"
|
|
||||||
|
|
||||||
const t = useI18n()
|
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
|||||||
@@ -244,13 +244,9 @@ export class PersistenceService extends Service {
|
|||||||
private setupSettingsPersistence() {
|
private setupSettingsPersistence() {
|
||||||
const settingsKey = "settings"
|
const settingsKey = "settings"
|
||||||
let settingsData = JSON.parse(
|
let settingsData = JSON.parse(
|
||||||
window.localStorage.getItem(settingsKey) ?? "null"
|
window.localStorage.getItem(settingsKey) || "{}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!settingsData) {
|
|
||||||
settingsData = getDefaultSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate data read from localStorage
|
// Validate data read from localStorage
|
||||||
const result = SETTINGS_SCHEMA.safeParse(settingsData)
|
const result = SETTINGS_SCHEMA.safeParse(settingsData)
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const SettingsDefSchema = z.object({
|
|||||||
httpUser: z.boolean(),
|
httpUser: z.boolean(),
|
||||||
httpPassword: z.boolean(),
|
httpPassword: z.boolean(),
|
||||||
bearerToken: z.boolean(),
|
bearerToken: z.boolean(),
|
||||||
oauth2Token: z.optional(z.boolean()),
|
oauth2Token: z.boolean(),
|
||||||
}),
|
}),
|
||||||
THEME_COLOR: ThemeColorSchema,
|
THEME_COLOR: ThemeColorSchema,
|
||||||
BG_COLOR: BgColorSchema,
|
BG_COLOR: BgColorSchema,
|
||||||
@@ -103,10 +103,13 @@ export const LOCAL_STATE_SCHEMA = z.union([
|
|||||||
.strict(),
|
.strict(),
|
||||||
])
|
])
|
||||||
|
|
||||||
export const SETTINGS_SCHEMA = SettingsDefSchema.extend({
|
export const SETTINGS_SCHEMA = z.union([
|
||||||
EXTENSIONS_ENABLED: z.optional(z.boolean()),
|
z.object({}).strict(),
|
||||||
PROXY_ENABLED: z.optional(z.boolean()),
|
SettingsDefSchema.extend({
|
||||||
})
|
EXTENSIONS_ENABLED: z.optional(z.boolean()),
|
||||||
|
PROXY_ENABLED: z.optional(z.boolean()),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
export const REST_HISTORY_ENTRY_SCHEMA = z
|
export const REST_HISTORY_ENTRY_SCHEMA = z
|
||||||
.object({
|
.object({
|
||||||
@@ -205,7 +208,7 @@ export const MQTT_REQUEST_SCHEMA = z.nullable(
|
|||||||
z
|
z
|
||||||
.object({
|
.object({
|
||||||
endpoint: z.string(),
|
endpoint: z.string(),
|
||||||
clientID: z.optional(z.string()),
|
clientID: z.string(),
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/selfhost-desktop",
|
"name": "@hoppscotch/selfhost-desktop",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2023.12.2",
|
"version": "2023.12.0-1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:vite": "vite",
|
"dev:vite": "vite",
|
||||||
@@ -76,6 +76,8 @@
|
|||||||
"vite-plugin-pwa": "^0.13.1",
|
"vite-plugin-pwa": "^0.13.1",
|
||||||
"vite-plugin-static-copy": "^0.12.0",
|
"vite-plugin-static-copy": "^0.12.0",
|
||||||
"vite-plugin-vue-layouts": "^0.7.0",
|
"vite-plugin-vue-layouts": "^0.7.0",
|
||||||
"vue-tsc": "^1.0.11"
|
"vite-plugin-windicss": "^1.8.8",
|
||||||
|
"vue-tsc": "^1.0.11",
|
||||||
|
"windicss": "^3.5.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "hoppscotch-desktop"
|
name = "hoppscotch-desktop"
|
||||||
version = "23.12.2"
|
version = "23.12.0-1"
|
||||||
description = "A Tauri App"
|
description = "A Tauri App"
|
||||||
authors = ["you"]
|
authors = ["you"]
|
||||||
license = ""
|
license = ""
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "Hoppscotch",
|
"productName": "Hoppscotch",
|
||||||
"version": "23.12.2"
|
"version": "23.12.0-1"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import VueI18n from "@intlify/vite-plugin-vue-i18n"
|
|||||||
import Components from "unplugin-vue-components/vite"
|
import Components from "unplugin-vue-components/vite"
|
||||||
import Icons from "unplugin-icons/vite"
|
import Icons from "unplugin-icons/vite"
|
||||||
import Inspect from "vite-plugin-inspect"
|
import Inspect from "vite-plugin-inspect"
|
||||||
|
import WindiCSS from "vite-plugin-windicss"
|
||||||
import { VitePWA } from "vite-plugin-pwa"
|
import { VitePWA } from "vite-plugin-pwa"
|
||||||
import Pages from "vite-plugin-pages"
|
import Pages from "vite-plugin-pages"
|
||||||
import Layouts from "vite-plugin-vue-layouts"
|
import Layouts from "vite-plugin-vue-layouts"
|
||||||
@@ -104,6 +105,9 @@ export default defineConfig({
|
|||||||
compositionOnly: true,
|
compositionOnly: true,
|
||||||
include: [path.resolve(__dirname, "locales")],
|
include: [path.resolve(__dirname, "locales")],
|
||||||
}),
|
}),
|
||||||
|
WindiCSS({
|
||||||
|
root: path.resolve(__dirname, "../hoppscotch-common"),
|
||||||
|
}),
|
||||||
Components({
|
Components({
|
||||||
dts: "../hoppscotch-common/src/components.d.ts",
|
dts: "../hoppscotch-common/src/components.d.ts",
|
||||||
dirs: [
|
dirs: [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/selfhost-web",
|
"name": "@hoppscotch/selfhost-web",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2023.12.2",
|
"version": "2023.12.0-1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:vite": "vite",
|
"dev:vite": "vite",
|
||||||
|
|||||||
@@ -114,7 +114,6 @@ async function setInitialUser() {
|
|||||||
} else {
|
} else {
|
||||||
setUser(null)
|
setUser(null)
|
||||||
isGettingInitialUser.value = false
|
isGettingInitialUser.value = false
|
||||||
await logout()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -147,26 +146,22 @@ async function setInitialUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function refreshToken() {
|
async function refreshToken() {
|
||||||
try {
|
const res = await axios.get(
|
||||||
const res = await axios.get(
|
`${import.meta.env.VITE_BACKEND_API_URL}/auth/refresh`,
|
||||||
`${import.meta.env.VITE_BACKEND_API_URL}/auth/refresh`,
|
{
|
||||||
{
|
withCredentials: true,
|
||||||
withCredentials: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const isSuccessful = res.status === 200
|
|
||||||
|
|
||||||
if (isSuccessful) {
|
|
||||||
authEvents$.next({
|
|
||||||
event: "token_refresh",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return isSuccessful
|
const isSuccessful = res.status === 200
|
||||||
} catch (error) {
|
|
||||||
return false
|
if (isSuccessful) {
|
||||||
|
authEvents$.next({
|
||||||
|
event: "token_refresh",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isSuccessful
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendMagicLink(email: string) {
|
async function sendMagicLink(email: string) {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
## **Built with**
|
## **Built with**
|
||||||
|
|
||||||
- [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML)
|
- [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML)
|
||||||
- [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS), [SCSS](https://sass-lang.com), [Tailwind CSS](https://tailwindcss.com)
|
- [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS), [SCSS](https://sass-lang.com), [Windi CSS](https://windicss.org)
|
||||||
- [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
|
- [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
|
||||||
- [TypeScript](https://www.typescriptlang.org)
|
- [TypeScript](https://www.typescriptlang.org)
|
||||||
- [Vue](https://vuejs.org)
|
- [Vue](https://vuejs.org)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "hoppscotch-sh-admin",
|
"name": "hoppscotch-sh-admin",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2023.12.2",
|
"version": "2023.12.0-1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
||||||
|
|||||||
59
packages/hoppscotch-sh-admin/src/components.d.ts
vendored
59
packages/hoppscotch-sh-admin/src/components.d.ts
vendored
@@ -1,9 +1,9 @@
|
|||||||
// generated by unplugin-vue-components
|
// generated by unplugin-vue-components
|
||||||
// We suggest you to commit this file into source control
|
// We suggest you to commit this file into source control
|
||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
import '@vue/runtime-core'
|
import '@vue/runtime-core';
|
||||||
|
|
||||||
export {}
|
export {};
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
declare module '@vue/runtime-core' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
@@ -13,6 +13,8 @@ declare module '@vue/runtime-core' {
|
|||||||
AppModal: typeof import('./components/app/Modal.vue')['default']
|
AppModal: typeof import('./components/app/Modal.vue')['default']
|
||||||
AppSidebar: typeof import('./components/app/Sidebar.vue')['default']
|
AppSidebar: typeof import('./components/app/Sidebar.vue')['default']
|
||||||
AppToast: typeof import('./components/app/Toast.vue')['default']
|
AppToast: typeof import('./components/app/Toast.vue')['default']
|
||||||
|
ButtonPrimary: typeof import('./../../hoppscotch-ui/src/components/button/Primary.vue')['default']
|
||||||
|
ButtonSecondary: typeof import('./../../hoppscotch-ui/src/components/button/Secondary.vue')['default']
|
||||||
DashboardMetricsCard: typeof import('./components/dashboard/MetricsCard.vue')['default']
|
DashboardMetricsCard: typeof import('./components/dashboard/MetricsCard.vue')['default']
|
||||||
HoppButtonPrimary: typeof import('@hoppscotch/ui')['HoppButtonPrimary']
|
HoppButtonPrimary: typeof import('@hoppscotch/ui')['HoppButtonPrimary']
|
||||||
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary']
|
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary']
|
||||||
@@ -21,7 +23,6 @@ declare module '@vue/runtime-core' {
|
|||||||
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal']
|
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal']
|
||||||
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput']
|
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput']
|
||||||
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
|
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
|
||||||
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink']
|
|
||||||
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
|
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
|
||||||
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture']
|
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture']
|
||||||
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
|
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
|
||||||
@@ -29,13 +30,42 @@ declare module '@vue/runtime-core' {
|
|||||||
HoppSmartTable: typeof import('@hoppscotch/ui')['HoppSmartTable']
|
HoppSmartTable: typeof import('@hoppscotch/ui')['HoppSmartTable']
|
||||||
HoppSmartTabs: typeof import('@hoppscotch/ui')['HoppSmartTabs']
|
HoppSmartTabs: typeof import('@hoppscotch/ui')['HoppSmartTabs']
|
||||||
HoppSmartToggle: typeof import('@hoppscotch/ui')['HoppSmartToggle']
|
HoppSmartToggle: typeof import('@hoppscotch/ui')['HoppSmartToggle']
|
||||||
|
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
||||||
IconLucideChevronDown: typeof import('~icons/lucide/chevron-down')['default']
|
IconLucideChevronDown: typeof import('~icons/lucide/chevron-down')['default']
|
||||||
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
||||||
|
IconLucideUser: typeof import('~icons/lucide/user')['default']
|
||||||
SettingsAuthProvider: typeof import('./components/settings/AuthProvider.vue')['default']
|
SettingsAuthProvider: typeof import('./components/settings/AuthProvider.vue')['default']
|
||||||
SettingsConfigurations: typeof import('./components/settings/Configurations.vue')['default']
|
SettingsConfigurations: typeof import('./components/settings/Configurations.vue')['default']
|
||||||
SettingsReset: typeof import('./components/settings/Reset.vue')['default']
|
SettingsReset: typeof import('./components/settings/Reset.vue')['default']
|
||||||
SettingsServerRestart: typeof import('./components/settings/ServerRestart.vue')['default']
|
SettingsServerRestart: typeof import('./components/settings/ServerRestart.vue')['default']
|
||||||
SettingsSmtpConfiguration: typeof import('./components/settings/SmtpConfiguration.vue')['default']
|
SettingsSmtpConfiguration: typeof import('./components/settings/SmtpConfiguration.vue')['default']
|
||||||
|
SmartAnchor: typeof import('./../../hoppscotch-ui/src/components/smart/Anchor.vue')['default']
|
||||||
|
SmartAutoComplete: typeof import('./../../hoppscotch-ui/src/components/smart/AutoComplete.vue')['default']
|
||||||
|
SmartCheckbox: typeof import('./../../hoppscotch-ui/src/components/smart/Checkbox.vue')['default']
|
||||||
|
SmartConfirmModal: typeof import('./../../hoppscotch-ui/src/components/smart/ConfirmModal.vue')['default']
|
||||||
|
SmartExpand: typeof import('./../../hoppscotch-ui/src/components/smart/Expand.vue')['default']
|
||||||
|
SmartFileChip: typeof import('./../../hoppscotch-ui/src/components/smart/FileChip.vue')['default']
|
||||||
|
SmartInput: typeof import('./../../hoppscotch-ui/src/components/smart/Input.vue')['default']
|
||||||
|
SmartIntersection: typeof import('./../../hoppscotch-ui/src/components/smart/Intersection.vue')['default']
|
||||||
|
SmartItem: typeof import('./../../hoppscotch-ui/src/components/smart/Item.vue')['default']
|
||||||
|
SmartLink: typeof import('./../../hoppscotch-ui/src/components/smart/Link.vue')['default']
|
||||||
|
SmartModal: typeof import('./../../hoppscotch-ui/src/components/smart/Modal.vue')['default']
|
||||||
|
SmartPicture: typeof import('./../../hoppscotch-ui/src/components/smart/Picture.vue')['default']
|
||||||
|
SmartPlaceholder: typeof import('./../../hoppscotch-ui/src/components/smart/Placeholder.vue')['default']
|
||||||
|
SmartProgressRing: typeof import('./../../hoppscotch-ui/src/components/smart/ProgressRing.vue')['default']
|
||||||
|
SmartRadio: typeof import('./../../hoppscotch-ui/src/components/smart/Radio.vue')['default']
|
||||||
|
SmartRadioGroup: typeof import('./../../hoppscotch-ui/src/components/smart/RadioGroup.vue')['default']
|
||||||
|
SmartSelectWrapper: typeof import('./../../hoppscotch-ui/src/components/smart/SelectWrapper.vue')['default']
|
||||||
|
SmartSlideOver: typeof import('./../../hoppscotch-ui/src/components/smart/SlideOver.vue')['default']
|
||||||
|
SmartSpinner: typeof import('./../../hoppscotch-ui/src/components/smart/Spinner.vue')['default']
|
||||||
|
SmartTab: typeof import('./../../hoppscotch-ui/src/components/smart/Tab.vue')['default']
|
||||||
|
SmartTable: typeof import('./../../hoppscotch-ui/src/components/smart/Table.vue')['default']
|
||||||
|
SmartTabs: typeof import('./../../hoppscotch-ui/src/components/smart/Tabs.vue')['default']
|
||||||
|
SmartToggle: typeof import('./../../hoppscotch-ui/src/components/smart/Toggle.vue')['default']
|
||||||
|
SmartTree: typeof import('./../../hoppscotch-ui/src/components/smart/Tree.vue')['default']
|
||||||
|
SmartTreeBranch: typeof import('./../../hoppscotch-ui/src/components/smart/TreeBranch.vue')['default']
|
||||||
|
SmartWindow: typeof import('./../../hoppscotch-ui/src/components/smart/Window.vue')['default']
|
||||||
|
SmartWindows: typeof import('./../../hoppscotch-ui/src/components/smart/Windows.vue')['default']
|
||||||
TeamsAdd: typeof import('./components/teams/Add.vue')['default']
|
TeamsAdd: typeof import('./components/teams/Add.vue')['default']
|
||||||
TeamsDetails: typeof import('./components/teams/Details.vue')['default']
|
TeamsDetails: typeof import('./components/teams/Details.vue')['default']
|
||||||
TeamsInvite: typeof import('./components/teams/Invite.vue')['default']
|
TeamsInvite: typeof import('./components/teams/Invite.vue')['default']
|
||||||
@@ -46,6 +76,27 @@ declare module '@vue/runtime-core' {
|
|||||||
UsersDetails: typeof import('./components/users/Details.vue')['default']
|
UsersDetails: typeof import('./components/users/Details.vue')['default']
|
||||||
UsersInviteModal: typeof import('./components/users/InviteModal.vue')['default']
|
UsersInviteModal: typeof import('./components/users/InviteModal.vue')['default']
|
||||||
UsersSharedRequests: typeof import('./components/users/SharedRequests.vue')['default']
|
UsersSharedRequests: typeof import('./components/users/SharedRequests.vue')['default']
|
||||||
|
AppHeader: typeof import('./components/app/Header.vue')['default'];
|
||||||
|
AppLogin: typeof import('./components/app/Login.vue')['default'];
|
||||||
|
AppLogout: typeof import('./components/app/Logout.vue')['default'];
|
||||||
|
AppModal: typeof import('./components/app/Modal.vue')['default'];
|
||||||
|
AppSidebar: typeof import('./components/app/Sidebar.vue')['default'];
|
||||||
|
AppToast: typeof import('./components/app/Toast.vue')['default'];
|
||||||
|
DashboardMetricsCard: typeof import('./components/dashboard/MetricsCard.vue')['default'];
|
||||||
|
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary'];
|
||||||
|
HoppSmartAnchor: typeof import('@hoppscotch/ui')['HoppSmartAnchor'];
|
||||||
|
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal'];
|
||||||
|
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput'];
|
||||||
|
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem'];
|
||||||
|
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture'];
|
||||||
|
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner'];
|
||||||
|
IconLucideInbox: typeof import('~icons/lucide/inbox')['default'];
|
||||||
|
TeamsAdd: typeof import('./components/teams/Add.vue')['default'];
|
||||||
|
TeamsDetails: typeof import('./components/teams/Details.vue')['default'];
|
||||||
|
TeamsInvite: typeof import('./components/teams/Invite.vue')['default'];
|
||||||
|
TeamsMembers: typeof import('./components/teams/Members.vue')['default'];
|
||||||
|
TeamsPendingInvites: typeof import('./components/teams/PendingInvites.vue')['default'];
|
||||||
|
Tippy: typeof import('vue-tippy')['Tippy'];
|
||||||
|
UsersInviteModal: typeof import('./components/users/InviteModal.vue')['default'];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
:class="isOpen ? '' : '-translate-x-full ease-in'"
|
:class="isOpen ? '' : '-translate-x-full ease-in'"
|
||||||
class="sidebar-container transform !md:translate-x-0 ease-out"
|
class="sidebar-container transform !md:translate-x-0 ease-out"
|
||||||
>
|
>
|
||||||
<div :class="isExpanded ? 'w-56' : 'w-full'">
|
<div :class="isExpanded ? 'w-80' : 'w-full'">
|
||||||
<div class="flex items-center justify-start px-4 my-4">
|
<div class="flex items-center justify-start px-4 my-4">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<HoppSmartLink class="flex items-center space-x-4" to="/dashboard">
|
<HoppSmartLink class="flex items-center space-x-4" to="/dashboard">
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
</HoppSmartLink>
|
</HoppSmartLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="my-5">
|
<nav class="my-5">
|
||||||
<HoppSmartLink
|
<HoppSmartLink
|
||||||
v-for="(navigation, index) in primaryNavigations"
|
v-for="(navigation, index) in primaryNavigations"
|
||||||
@@ -38,32 +39,19 @@
|
|||||||
:to="navigation.to"
|
:to="navigation.to"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
:exact="navigation.exact"
|
:exact="navigation.exact"
|
||||||
|
class="nav-link"
|
||||||
:class="
|
:class="
|
||||||
!isExpanded
|
!isExpanded
|
||||||
? 'flex items-center justify-center'
|
? 'flex items-center justify-center'
|
||||||
: 'flex items-center'
|
: 'flex items-center'
|
||||||
"
|
"
|
||||||
@click="setActiveTab(navigation.label)"
|
|
||||||
>
|
>
|
||||||
<div
|
<div v-if="navigation.icon">
|
||||||
class="flex p-5 w-full font-bold"
|
<component :is="navigation.icon" class="svg-icons" />
|
||||||
:class="
|
|
||||||
activeTab === navigation.label
|
|
||||||
? 'bg-primaryDark text-secondaryDark border-l-2 border-l-emerald-600'
|
|
||||||
: 'bg-primary hover:bg-primaryLight hover:text-secondaryDark focus-visible:text-secondaryDark focus-visible:bg-primaryLight focus-visible:outline-none'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-if="navigation.icon"
|
|
||||||
class="svg-icons"
|
|
||||||
:class="isExpanded ? 'mr-3' : 'mx-auto'"
|
|
||||||
>
|
|
||||||
<component :is="navigation.icon" />
|
|
||||||
</div>
|
|
||||||
<span v-if="isExpanded" class="nav-title">
|
|
||||||
{{ navigation.label }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
<span v-if="isExpanded" class="nav-title">
|
||||||
|
{{ navigation.label }}
|
||||||
|
</span>
|
||||||
</HoppSmartLink>
|
</HoppSmartLink>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@@ -72,27 +60,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, type Component } from 'vue';
|
import { HoppSmartLink } from '@hoppscotch/ui';
|
||||||
|
|
||||||
import { useI18n } from '~/composables/i18n';
|
|
||||||
import { useSidebar } from '~/composables/useSidebar';
|
import { useSidebar } from '~/composables/useSidebar';
|
||||||
import IconDashboard from '~icons/lucide/layout-dashboard';
|
import IconDashboard from '~icons/lucide/layout-dashboard';
|
||||||
import IconSettings from '~icons/lucide/settings';
|
|
||||||
import IconUser from '~icons/lucide/user';
|
import IconUser from '~icons/lucide/user';
|
||||||
import IconUsers from '~icons/lucide/users';
|
import IconUsers from '~icons/lucide/users';
|
||||||
|
import IconSettings from '~icons/lucide/settings';
|
||||||
|
import { useI18n } from '~/composables/i18n';
|
||||||
|
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
|
|
||||||
const { isOpen, isExpanded } = useSidebar();
|
const { isOpen, isExpanded } = useSidebar();
|
||||||
|
|
||||||
type NavigationItem = {
|
const primaryNavigations = [
|
||||||
label: string;
|
|
||||||
icon: Component;
|
|
||||||
to: string;
|
|
||||||
exact: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
const primaryNavigations: NavigationItem[] = [
|
|
||||||
{
|
{
|
||||||
label: t('metrics.dashboard'),
|
label: t('metrics.dashboard'),
|
||||||
icon: IconDashboard,
|
icon: IconDashboard,
|
||||||
@@ -118,12 +98,6 @@ const primaryNavigations: NavigationItem[] = [
|
|||||||
exact: true,
|
exact: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const activeTab = ref('Dashboard');
|
|
||||||
|
|
||||||
const setActiveTab = (tab: string) => {
|
|
||||||
activeTab.value = tab;
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -132,4 +106,54 @@ const setActiveTab = (tab: string) => {
|
|||||||
@apply transition duration-300;
|
@apply transition duration-300;
|
||||||
@apply flex overflow-y-auto bg-primary border-r border-divider;
|
@apply flex overflow-y-auto bg-primary border-r border-divider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
@apply relative;
|
||||||
|
@apply p-4;
|
||||||
|
@apply flex flex-1;
|
||||||
|
@apply items-center;
|
||||||
|
@apply space-x-4;
|
||||||
|
@apply hover:bg-primaryDark hover:text-secondaryDark;
|
||||||
|
@apply focus-visible:text-secondaryDark;
|
||||||
|
@apply after:absolute;
|
||||||
|
@apply after:inset-x-0;
|
||||||
|
@apply after:md:inset-x-auto;
|
||||||
|
@apply after:md:inset-y-0;
|
||||||
|
@apply after:bottom-0;
|
||||||
|
@apply after:md:bottom-auto;
|
||||||
|
@apply after:md:left-0;
|
||||||
|
@apply after:z-10;
|
||||||
|
@apply after:h-0.5;
|
||||||
|
@apply after:md:h-full;
|
||||||
|
@apply after:w-full;
|
||||||
|
@apply after:md:w-0.5;
|
||||||
|
@apply after:content-[''];
|
||||||
|
@apply focus:after:bg-divider;
|
||||||
|
|
||||||
|
.svg-icons {
|
||||||
|
@apply opacity-75;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.router-link-active {
|
||||||
|
@apply text-secondaryDark;
|
||||||
|
@apply bg-primaryLight;
|
||||||
|
@apply hover:text-secondaryDark;
|
||||||
|
@apply after:bg-accent;
|
||||||
|
|
||||||
|
.svg-icons {
|
||||||
|
@apply opacity-100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.exact-active-link {
|
||||||
|
@apply text-secondaryDark;
|
||||||
|
@apply bg-primaryLight;
|
||||||
|
@apply hover:text-secondaryDark;
|
||||||
|
@apply after:bg-accent;
|
||||||
|
|
||||||
|
.svg-icons {
|
||||||
|
@apply opacity-100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
114
pnpm-lock.yaml
generated
114
pnpm-lock.yaml
generated
@@ -1063,9 +1063,15 @@ importers:
|
|||||||
vite-plugin-vue-layouts:
|
vite-plugin-vue-layouts:
|
||||||
specifier: ^0.7.0
|
specifier: ^0.7.0
|
||||||
version: 0.7.0(vite@4.5.0)(vue-router@4.2.5)(vue@3.3.9)
|
version: 0.7.0(vite@4.5.0)(vue-router@4.2.5)(vue@3.3.9)
|
||||||
|
vite-plugin-windicss:
|
||||||
|
specifier: ^1.8.8
|
||||||
|
version: 1.9.1(vite@4.5.0)
|
||||||
vue-tsc:
|
vue-tsc:
|
||||||
specifier: ^1.0.11
|
specifier: ^1.0.11
|
||||||
version: 1.8.8(typescript@4.9.5)
|
version: 1.8.8(typescript@4.9.5)
|
||||||
|
windicss:
|
||||||
|
specifier: ^3.5.6
|
||||||
|
version: 3.5.6
|
||||||
|
|
||||||
packages/hoppscotch-selfhost-web:
|
packages/hoppscotch-selfhost-web:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4231,7 +4237,7 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vue: 3.3.9
|
vue: 3.3.9
|
||||||
dependencies:
|
dependencies:
|
||||||
vue: 3.3.9(typescript@5.3.2)
|
vue: 3.3.9(typescript@4.9.5)
|
||||||
|
|
||||||
/@codemirror/autocomplete@6.11.1(@codemirror/language@6.9.3)(@codemirror/state@6.3.3)(@codemirror/view@6.22.3)(@lezer/common@1.0.3):
|
/@codemirror/autocomplete@6.11.1(@codemirror/language@6.9.3)(@codemirror/state@6.3.3)(@codemirror/view@6.22.3)(@lezer/common@1.0.3):
|
||||||
resolution: {integrity: sha512-L5UInv8Ffd6BPw0P3EF7JLYAMeEbclY7+6Q11REt8vhih8RuLreKtPy/xk8wPxs4EQgYqzI7cdgpiYwWlbS/ow==}
|
resolution: {integrity: sha512-L5UInv8Ffd6BPw0P3EF7JLYAMeEbclY7+6Q11REt8vhih8RuLreKtPy/xk8wPxs4EQgYqzI7cdgpiYwWlbS/ow==}
|
||||||
@@ -7053,7 +7059,7 @@ packages:
|
|||||||
lodash-es: 4.17.21
|
lodash-es: 4.17.21
|
||||||
path: 0.12.7
|
path: 0.12.7
|
||||||
vite-plugin-eslint: 1.8.1(eslint@8.55.0)(vite@3.2.4)
|
vite-plugin-eslint: 1.8.1(eslint@8.55.0)(vite@3.2.4)
|
||||||
vue: 3.3.9(typescript@4.9.3)
|
vue: 3.3.9(typescript@4.9.5)
|
||||||
vuedraggable-es: 4.1.1(vue@3.3.9)
|
vuedraggable-es: 4.1.1(vue@3.3.9)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
@@ -7092,7 +7098,7 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vue: 3.3.9
|
vue: 3.3.9
|
||||||
dependencies:
|
dependencies:
|
||||||
vue: 3.3.9(typescript@5.3.2)
|
vue: 3.3.9(typescript@4.9.5)
|
||||||
|
|
||||||
/@humanwhocodes/config-array@0.11.10:
|
/@humanwhocodes/config-array@0.11.10:
|
||||||
resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==}
|
resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==}
|
||||||
@@ -7394,7 +7400,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@intlify/bundle-utils': 7.4.0(vue-i18n@9.2.2)
|
'@intlify/bundle-utils': 7.4.0(vue-i18n@9.2.2)
|
||||||
'@intlify/shared': 9.4.1
|
'@intlify/shared': 9.4.1
|
||||||
'@rollup/pluginutils': 5.0.3(rollup@2.79.1)
|
'@rollup/pluginutils': 5.0.3(rollup@3.29.4)
|
||||||
'@vue/compiler-sfc': 3.3.10
|
'@vue/compiler-sfc': 3.3.10
|
||||||
debug: 4.3.4(supports-color@9.2.2)
|
debug: 4.3.4(supports-color@9.2.2)
|
||||||
fast-glob: 3.3.1
|
fast-glob: 3.3.1
|
||||||
@@ -8987,6 +8993,7 @@ packages:
|
|||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
rollup: 2.79.1
|
rollup: 2.79.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@rollup/pluginutils@5.0.3(rollup@3.29.4):
|
/@rollup/pluginutils@5.0.3(rollup@3.29.4):
|
||||||
resolution: {integrity: sha512-hfllNN4a80rwNQ9QCxhxuHCGHMAvabXqxNdaChUSSadMre7t4iEUI6fFAhBOn/eIYTgYVhBv7vCLsAJ4u3lf3g==}
|
resolution: {integrity: sha512-hfllNN4a80rwNQ9QCxhxuHCGHMAvabXqxNdaChUSSadMre7t4iEUI6fFAhBOn/eIYTgYVhBv7vCLsAJ4u3lf3g==}
|
||||||
@@ -9001,7 +9008,6 @@ packages:
|
|||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
rollup: 3.29.4
|
rollup: 3.29.4
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@rollup/pluginutils@5.1.0(rollup@2.79.1):
|
/@rollup/pluginutils@5.1.0(rollup@2.79.1):
|
||||||
resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
|
resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
|
||||||
@@ -10619,7 +10625,7 @@ packages:
|
|||||||
regenerator-runtime: 0.13.11
|
regenerator-runtime: 0.13.11
|
||||||
systemjs: 6.14.2
|
systemjs: 6.14.2
|
||||||
terser: 5.24.0
|
terser: 5.24.0
|
||||||
vite: 3.2.4(@types/node@18.18.8)(sass@1.58.0)(terser@5.24.0)
|
vite: 3.2.4(@types/node@17.0.27)(terser@5.24.0)
|
||||||
|
|
||||||
/@vitejs/plugin-legacy@2.3.0(terser@5.24.0)(vite@4.5.0):
|
/@vitejs/plugin-legacy@2.3.0(terser@5.24.0)(vite@4.5.0):
|
||||||
resolution: {integrity: sha512-Bh62i0gzQvvT8AeAAb78nOnqSYXypkRmQmOTImdPZ39meHR9e2une3AIFmVo4s1SDmcmJ6qj18Sa/lRc/14KaA==}
|
resolution: {integrity: sha512-Bh62i0gzQvvT8AeAAb78nOnqSYXypkRmQmOTImdPZ39meHR9e2une3AIFmVo4s1SDmcmJ6qj18Sa/lRc/14KaA==}
|
||||||
@@ -11137,7 +11143,7 @@ packages:
|
|||||||
'@types/web-bluetooth': 0.0.14
|
'@types/web-bluetooth': 0.0.14
|
||||||
'@vueuse/metadata': 8.7.5
|
'@vueuse/metadata': 8.7.5
|
||||||
'@vueuse/shared': 8.7.5(vue@3.3.9)
|
'@vueuse/shared': 8.7.5(vue@3.3.9)
|
||||||
vue: 3.3.9(typescript@5.3.2)
|
vue: 3.3.9(typescript@4.9.5)
|
||||||
vue-demi: 0.14.6(vue@3.3.9)
|
vue-demi: 0.14.6(vue@3.3.9)
|
||||||
|
|
||||||
/@vueuse/core@9.12.0(vue@3.3.9):
|
/@vueuse/core@9.12.0(vue@3.3.9):
|
||||||
@@ -11196,7 +11202,7 @@ packages:
|
|||||||
vue:
|
vue:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
vue: 3.3.9(typescript@5.3.2)
|
vue: 3.3.9(typescript@4.9.5)
|
||||||
vue-demi: 0.14.6(vue@3.3.9)
|
vue-demi: 0.14.6(vue@3.3.9)
|
||||||
|
|
||||||
/@vueuse/shared@9.12.0(vue@3.3.9):
|
/@vueuse/shared@9.12.0(vue@3.3.9):
|
||||||
@@ -11416,6 +11422,30 @@ packages:
|
|||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@windicss/config@1.9.1:
|
||||||
|
resolution: {integrity: sha512-MjutTiS9XIteriwkH9D+que+bILbpulekYzjJGQDg3Sb2H87aOcO30f7N11ZiHF5OYoZn4yJz4lDbB3A6IuXfQ==}
|
||||||
|
dependencies:
|
||||||
|
debug: 4.3.4(supports-color@9.2.2)
|
||||||
|
jiti: 1.19.3
|
||||||
|
windicss: 3.5.6
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@windicss/plugin-utils@1.9.1:
|
||||||
|
resolution: {integrity: sha512-sz/Z2sxUZIkJ2nVeTmtYTtXhWxe/yTTkM5nqU6eKhP0n6waipTCJJdLvWoZcgzQBbBCL/JLRQd/9BYsBqKuLDQ==}
|
||||||
|
dependencies:
|
||||||
|
'@antfu/utils': 0.7.6
|
||||||
|
'@windicss/config': 1.9.1
|
||||||
|
debug: 4.3.4(supports-color@9.2.2)
|
||||||
|
fast-glob: 3.3.1
|
||||||
|
magic-string: 0.30.4
|
||||||
|
micromatch: 4.0.5
|
||||||
|
windicss: 3.5.6
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@xtuc/ieee754@1.2.0:
|
/@xtuc/ieee754@1.2.0:
|
||||||
resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
|
resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -13584,7 +13614,7 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
rxjs: 7.8.1
|
rxjs: 7.8.1
|
||||||
vue: 3.3.9(typescript@5.3.2)
|
vue: 3.3.9(typescript@4.9.5)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/dir-glob@3.0.1:
|
/dir-glob@3.0.1:
|
||||||
@@ -24132,7 +24162,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
unplugin: 1.5.1
|
unplugin: 1.5.1
|
||||||
vite: 4.5.0(@types/node@17.0.27)(sass@1.69.5)(terser@5.24.0)
|
vite: 4.5.0(@types/node@18.18.8)(sass@1.69.5)(terser@5.24.0)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/unplugin-icons@0.14.9(@vue/compiler-sfc@3.2.45)(vite@3.2.4):
|
/unplugin-icons@0.14.9(@vue/compiler-sfc@3.2.45)(vite@3.2.4):
|
||||||
@@ -24742,7 +24772,7 @@ packages:
|
|||||||
'@types/eslint': 8.44.3
|
'@types/eslint': 8.44.3
|
||||||
eslint: 8.55.0
|
eslint: 8.55.0
|
||||||
rollup: 2.79.1
|
rollup: 2.79.1
|
||||||
vite: 3.2.4(@types/node@18.18.8)(sass@1.58.0)(terser@5.24.0)
|
vite: 3.2.4(@types/node@17.0.27)(terser@5.24.0)
|
||||||
|
|
||||||
/vite-plugin-eslint@1.8.1(eslint@8.55.0)(vite@4.5.0):
|
/vite-plugin-eslint@1.8.1(eslint@8.55.0)(vite@4.5.0):
|
||||||
resolution: {integrity: sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==}
|
resolution: {integrity: sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==}
|
||||||
@@ -24773,7 +24803,7 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: '>=2.0.0'
|
vite: '>=2.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 4.5.0(@types/node@17.0.27)(sass@1.69.5)(terser@5.24.0)
|
vite: 4.5.0(@types/node@18.18.8)(sass@1.69.5)(terser@5.24.0)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vite-plugin-inspect@0.7.38(rollup@2.79.1)(vite@4.5.0):
|
/vite-plugin-inspect@0.7.38(rollup@2.79.1)(vite@4.5.0):
|
||||||
@@ -25036,6 +25066,54 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/vite-plugin-windicss@1.9.1(vite@4.5.0):
|
||||||
|
resolution: {integrity: sha512-CWm1b/tXVCJTbEGn4oB8B7Gev9xDuY9k4E/KiJqDuLYspBUFQyZKPF2mSZ3DfNdojsfqgzxu9ervqvlb9jJ7fw==}
|
||||||
|
peerDependencies:
|
||||||
|
vite: ^2.0.1 || ^3.0.0 || ^4.0.0
|
||||||
|
dependencies:
|
||||||
|
'@windicss/plugin-utils': 1.9.1
|
||||||
|
debug: 4.3.4(supports-color@9.2.2)
|
||||||
|
kolorist: 1.8.0
|
||||||
|
vite: 4.5.0(@types/node@18.18.8)(sass@1.69.5)(terser@5.24.0)
|
||||||
|
windicss: 3.5.6
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/vite@3.2.4(@types/node@17.0.27)(terser@5.24.0):
|
||||||
|
resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==}
|
||||||
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
'@types/node': '>= 14'
|
||||||
|
less: '*'
|
||||||
|
sass: '*'
|
||||||
|
stylus: '*'
|
||||||
|
sugarss: '*'
|
||||||
|
terser: ^5.4.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/node':
|
||||||
|
optional: true
|
||||||
|
less:
|
||||||
|
optional: true
|
||||||
|
sass:
|
||||||
|
optional: true
|
||||||
|
stylus:
|
||||||
|
optional: true
|
||||||
|
sugarss:
|
||||||
|
optional: true
|
||||||
|
terser:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 17.0.27
|
||||||
|
esbuild: 0.15.15
|
||||||
|
postcss: 8.4.32
|
||||||
|
resolve: 1.22.4
|
||||||
|
rollup: 2.79.1
|
||||||
|
terser: 5.24.0
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents: 2.3.3
|
||||||
|
|
||||||
/vite@3.2.4(@types/node@18.18.8)(sass@1.58.0)(terser@5.24.0):
|
/vite@3.2.4(@types/node@18.18.8)(sass@1.58.0)(terser@5.24.0):
|
||||||
resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==}
|
resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
@@ -25458,7 +25536,7 @@ packages:
|
|||||||
'@vue/composition-api':
|
'@vue/composition-api':
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
vue: 3.3.9(typescript@5.3.2)
|
vue: 3.3.9(typescript@4.9.5)
|
||||||
|
|
||||||
/vue-eslint-parser@9.3.1(eslint@8.47.0):
|
/vue-eslint-parser@9.3.1(eslint@8.47.0):
|
||||||
resolution: {integrity: sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==}
|
resolution: {integrity: sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==}
|
||||||
@@ -25542,7 +25620,7 @@ packages:
|
|||||||
vue: 3.3.9
|
vue: 3.3.9
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/devtools-api': 6.5.1
|
'@vue/devtools-api': 6.5.1
|
||||||
vue: 3.3.9(typescript@5.3.2)
|
vue: 3.3.9(typescript@4.9.5)
|
||||||
|
|
||||||
/vue-template-compiler@2.7.14:
|
/vue-template-compiler@2.7.14:
|
||||||
resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==}
|
resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==}
|
||||||
@@ -25654,7 +25732,7 @@ packages:
|
|||||||
vue: 3.3.9
|
vue: 3.3.9
|
||||||
dependencies:
|
dependencies:
|
||||||
sortablejs: 1.14.0
|
sortablejs: 1.14.0
|
||||||
vue: 3.3.9(typescript@5.3.2)
|
vue: 3.3.9(typescript@4.9.5)
|
||||||
|
|
||||||
/w3c-hr-time@1.0.2:
|
/w3c-hr-time@1.0.2:
|
||||||
resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
|
resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
|
||||||
@@ -25925,6 +26003,12 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
string-width: 4.2.3
|
string-width: 4.2.3
|
||||||
|
|
||||||
|
/windicss@3.5.6:
|
||||||
|
resolution: {integrity: sha512-P1mzPEjgFMZLX0ZqfFht4fhV/FX8DTG7ERG1fBLiWvd34pTLVReS5CVsewKn9PApSgXnVfPWwvq+qUsRwpnwFA==}
|
||||||
|
engines: {node: '>= 12'}
|
||||||
|
hasBin: true
|
||||||
|
dev: true
|
||||||
|
|
||||||
/windows-release@4.0.0:
|
/windows-release@4.0.0:
|
||||||
resolution: {integrity: sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==}
|
resolution: {integrity: sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:18-alpine3.19 as base_builder
|
FROM node:18-alpine3.16 as base_builder
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user