feat: add auto-create collection option to mock server creation (#5637)
Co-authored-by: Anwarul Islam <anwaarulislaam@gmail.com>
This commit is contained in:
parent
cd82eb212d
commit
008335c715
18 changed files with 1342 additions and 143 deletions
|
|
@ -892,6 +892,13 @@ export const MOCK_SERVER_NOT_FOUND = 'mock_server/not_found';
|
|||
*/
|
||||
export const MOCK_SERVER_INVALID_COLLECTION = 'mock_server/invalid_collection';
|
||||
|
||||
/**
|
||||
* Mock server collection creation failed
|
||||
* (MockServerService)
|
||||
*/
|
||||
export const MOCK_SERVER_COLLECTION_CREATION_FAILED =
|
||||
'mock_server/collection_creation_failed';
|
||||
|
||||
/**
|
||||
* Mock server already exists for this collection
|
||||
* (MockServerService)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,781 @@
|
|||
import { randomUUID } from 'crypto';
|
||||
|
||||
const generateRefId = () => `${Date.now().toString(36)}_${randomUUID()}`;
|
||||
|
||||
export const mockServerCollRequestExample = (
|
||||
collectionName: string = 'Hoppscotch API Mock example',
|
||||
) => {
|
||||
const baseEnv = '<<mockUrl>>';
|
||||
return [
|
||||
{
|
||||
v: 10,
|
||||
name: collectionName,
|
||||
folders: [],
|
||||
requests: [
|
||||
{
|
||||
v: '16',
|
||||
_ref_id: `req_${generateRefId()}`,
|
||||
name: 'addPet',
|
||||
method: 'POST',
|
||||
endpoint: baseEnv + '/v2/pet',
|
||||
params: [],
|
||||
headers: [],
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: 'application/json',
|
||||
body: '{\n\t"id": 1,\n\t"category": {\n\t\t"id": 1,\n\t\t"name": "string"\n\t},\n\t"name": "doggie",\n\t"photoUrls": [\n\t\t"string"\n\t],\n\t"tags": [],\n\t"status": "available"\n}',
|
||||
},
|
||||
preRequestScript: '',
|
||||
testScript: '',
|
||||
requestVariables: [],
|
||||
responses: {
|
||||
'Invalid input': {
|
||||
name: 'Invalid input',
|
||||
status: 'Method Not Allowed',
|
||||
code: 405,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'addPet',
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: 'application/json',
|
||||
body: '{\n\t"id": 1,\n\t"category": {\n\t\t"id": 1,\n\t\t"name": "string"\n\t},\n\t"name": "doggie",\n\t"photoUrls": [\n\t\t"string"\n\t],\n\t"tags": [],\n\t"status": "available"\n}',
|
||||
},
|
||||
endpoint: baseEnv + '/v2/pet',
|
||||
params: [],
|
||||
headers: [],
|
||||
method: 'POST',
|
||||
requestVariables: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
v: '16',
|
||||
_ref_id: `req_${generateRefId()}`,
|
||||
name: 'updatePet',
|
||||
method: 'PUT',
|
||||
endpoint: baseEnv + '/v2/pet',
|
||||
params: [],
|
||||
headers: [],
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: 'application/json',
|
||||
body: '{\n\t"id": 1,\n\t"category": {\n\t\t"id": 1,\n\t\t"name": "string"\n\t},\n\t"name": "doggie",\n\t"photoUrls": [\n\t\t"string"\n\t],\n\t"tags": [],\n\t"status": "available"\n}',
|
||||
},
|
||||
preRequestScript: '',
|
||||
testScript: '',
|
||||
requestVariables: [],
|
||||
responses: {
|
||||
'Invalid ID supplied': {
|
||||
name: 'Invalid ID supplied',
|
||||
status: 'Bad Request',
|
||||
code: 400,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'updatePet',
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: 'application/json',
|
||||
body: '{\n\t"id": 1,\n\t"category": {\n\t\t"id": 1,\n\t\t"name": "string"\n\t},\n\t"name": "doggie",\n\t"photoUrls": [\n\t\t"string"\n\t],\n\t"tags": [],\n\t"status": "available"\n}',
|
||||
},
|
||||
endpoint: baseEnv + '/v2/pet',
|
||||
params: [],
|
||||
headers: [],
|
||||
method: 'PUT',
|
||||
requestVariables: [],
|
||||
},
|
||||
},
|
||||
'Pet not found': {
|
||||
name: 'Pet not found',
|
||||
status: 'Not Found',
|
||||
code: 404,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'updatePet',
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: 'application/json',
|
||||
body: '{\n\t"id": 1,\n\t"category": {\n\t\t"id": 1,\n\t\t"name": "string"\n\t},\n\t"name": "doggie",\n\t"photoUrls": [\n\t\t"string"\n\t],\n\t"tags": [],\n\t"status": "available"\n}',
|
||||
},
|
||||
endpoint: baseEnv + '/v2/pet',
|
||||
params: [],
|
||||
headers: [],
|
||||
method: 'PUT',
|
||||
requestVariables: [],
|
||||
},
|
||||
},
|
||||
'Validation exception': {
|
||||
name: 'Validation exception',
|
||||
status: 'Method Not Allowed',
|
||||
code: 405,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'updatePet',
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: 'application/json',
|
||||
body: '{\n\t"id": 1,\n\t"category": {\n\t\t"id": 1,\n\t\t"name": "string"\n\t},\n\t"name": "doggie",\n\t"photoUrls": [\n\t\t"string"\n\t],\n\t"tags": [],\n\t"status": "available"\n}',
|
||||
},
|
||||
endpoint: baseEnv + '/v2/pet',
|
||||
params: [],
|
||||
headers: [],
|
||||
method: 'PUT',
|
||||
requestVariables: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
v: '16',
|
||||
_ref_id: `req_${generateRefId()}`,
|
||||
name: 'findPetsByStatus',
|
||||
method: 'GET',
|
||||
endpoint: baseEnv + '/v2/pet/findByStatus',
|
||||
params: [
|
||||
{
|
||||
key: 'status',
|
||||
value: '',
|
||||
active: true,
|
||||
description:
|
||||
'Status values that need to be considered for filter',
|
||||
},
|
||||
],
|
||||
headers: [],
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: null,
|
||||
body: null,
|
||||
},
|
||||
preRequestScript: '',
|
||||
testScript: '',
|
||||
requestVariables: [],
|
||||
responses: {
|
||||
'successful operation': {
|
||||
name: 'successful operation',
|
||||
status: 'OK',
|
||||
code: 200,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'findPetsByStatus',
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: null,
|
||||
body: null,
|
||||
},
|
||||
endpoint: 'petstore.swagger.io/v2/pet/findByStatus',
|
||||
params: [
|
||||
{
|
||||
key: 'status',
|
||||
value: '',
|
||||
active: true,
|
||||
description:
|
||||
'Status values that need to be considered for filter',
|
||||
},
|
||||
],
|
||||
headers: [],
|
||||
method: 'GET',
|
||||
requestVariables: [],
|
||||
},
|
||||
},
|
||||
'Invalid status value': {
|
||||
name: 'Invalid status value',
|
||||
status: 'Bad Request',
|
||||
code: 400,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'findPetsByStatus',
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: null,
|
||||
body: null,
|
||||
},
|
||||
endpoint: 'petstore.swagger.io/v2/pet/findByStatus',
|
||||
params: [
|
||||
{
|
||||
key: 'status',
|
||||
value: '',
|
||||
active: true,
|
||||
description:
|
||||
'Status values that need to be considered for filter',
|
||||
},
|
||||
],
|
||||
headers: [],
|
||||
method: 'GET',
|
||||
requestVariables: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
v: '16',
|
||||
_ref_id: `req_${generateRefId()}`,
|
||||
name: 'getPetById',
|
||||
method: 'GET',
|
||||
endpoint: baseEnv + '/v2/pet/<<petId>>',
|
||||
params: [],
|
||||
headers: [],
|
||||
auth: {
|
||||
authType: 'api-key',
|
||||
addTo: 'HEADERS',
|
||||
authActive: true,
|
||||
key: 'api_key',
|
||||
value: '',
|
||||
},
|
||||
body: {
|
||||
contentType: null,
|
||||
body: null,
|
||||
},
|
||||
preRequestScript: '',
|
||||
testScript: '',
|
||||
requestVariables: [
|
||||
{
|
||||
key: 'petId',
|
||||
value: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
'successful operation': {
|
||||
name: 'successful operation',
|
||||
status: 'OK',
|
||||
code: 200,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'getPetById',
|
||||
auth: {
|
||||
authType: 'api-key',
|
||||
addTo: 'HEADERS',
|
||||
authActive: true,
|
||||
key: 'api_key',
|
||||
value: '',
|
||||
},
|
||||
body: {
|
||||
contentType: null,
|
||||
body: null,
|
||||
},
|
||||
endpoint: 'petstore.swagger.io/v2/pet/<<petId>>',
|
||||
params: [],
|
||||
headers: [],
|
||||
method: 'GET',
|
||||
requestVariables: [
|
||||
{
|
||||
key: 'petId',
|
||||
value: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
'Invalid ID supplied': {
|
||||
name: 'Invalid ID supplied',
|
||||
status: 'Bad Request',
|
||||
code: 400,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'getPetById',
|
||||
auth: {
|
||||
authType: 'api-key',
|
||||
addTo: 'HEADERS',
|
||||
authActive: true,
|
||||
key: 'api_key',
|
||||
value: '',
|
||||
},
|
||||
body: {
|
||||
contentType: null,
|
||||
body: null,
|
||||
},
|
||||
endpoint: 'petstore.swagger.io/v2/pet/<<petId>>',
|
||||
params: [],
|
||||
headers: [],
|
||||
method: 'GET',
|
||||
requestVariables: [
|
||||
{
|
||||
key: 'petId',
|
||||
value: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
'Pet not found': {
|
||||
name: 'Pet not found',
|
||||
status: 'Not Found',
|
||||
code: 404,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'getPetById',
|
||||
auth: {
|
||||
authType: 'api-key',
|
||||
addTo: 'HEADERS',
|
||||
authActive: true,
|
||||
key: 'api_key',
|
||||
value: '',
|
||||
},
|
||||
body: {
|
||||
contentType: null,
|
||||
body: null,
|
||||
},
|
||||
endpoint: 'petstore.swagger.io/v2/pet/<<petId>>',
|
||||
params: [],
|
||||
headers: [],
|
||||
method: 'GET',
|
||||
requestVariables: [
|
||||
{
|
||||
key: 'petId',
|
||||
value: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
v: '16',
|
||||
_ref_id: `req_${generateRefId()}`,
|
||||
name: 'updatePetWithForm',
|
||||
method: 'POST',
|
||||
endpoint: baseEnv + '/v2/pet/<<petId>>',
|
||||
params: [],
|
||||
headers: [],
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: 'application/x-www-form-urlencoded',
|
||||
body: 'name: \nstatus: ',
|
||||
},
|
||||
preRequestScript: '',
|
||||
testScript: '',
|
||||
requestVariables: [
|
||||
{
|
||||
key: 'petId',
|
||||
value: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
'Invalid input': {
|
||||
name: 'Invalid input',
|
||||
status: 'Method Not Allowed',
|
||||
code: 405,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'updatePetWithForm',
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: 'application/x-www-form-urlencoded',
|
||||
body: 'name: \nstatus: ',
|
||||
},
|
||||
endpoint: 'petstore.swagger.io/v2/pet/<<petId>>',
|
||||
params: [],
|
||||
headers: [],
|
||||
method: 'POST',
|
||||
requestVariables: [
|
||||
{
|
||||
key: 'petId',
|
||||
value: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
v: '16',
|
||||
_ref_id: `req_${generateRefId()}`,
|
||||
name: 'deletePet',
|
||||
method: 'DELETE',
|
||||
endpoint: baseEnv + '/v2/pet/<<petId>>',
|
||||
params: [],
|
||||
headers: [
|
||||
{
|
||||
key: 'api_key',
|
||||
value: '',
|
||||
active: true,
|
||||
description: '',
|
||||
},
|
||||
],
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: null,
|
||||
body: null,
|
||||
},
|
||||
preRequestScript: '',
|
||||
testScript: '',
|
||||
requestVariables: [
|
||||
{
|
||||
key: 'petId',
|
||||
value: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
'Invalid ID supplied': {
|
||||
name: 'Invalid ID supplied',
|
||||
status: 'Bad Request',
|
||||
code: 400,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'deletePet',
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: null,
|
||||
body: null,
|
||||
},
|
||||
endpoint: 'petstore.swagger.io/v2/pet/<<petId>>',
|
||||
params: [],
|
||||
headers: [
|
||||
{
|
||||
key: 'api_key',
|
||||
value: '',
|
||||
active: true,
|
||||
description: '',
|
||||
},
|
||||
],
|
||||
method: 'DELETE',
|
||||
requestVariables: [
|
||||
{
|
||||
key: 'petId',
|
||||
value: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
'Pet not found': {
|
||||
name: 'Pet not found',
|
||||
status: 'Not Found',
|
||||
code: 404,
|
||||
headers: [
|
||||
{
|
||||
key: 'content-type',
|
||||
value: 'application/json',
|
||||
description: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
body: '',
|
||||
originalRequest: {
|
||||
v: '6',
|
||||
name: 'deletePet',
|
||||
auth: {
|
||||
authType: 'oauth-2',
|
||||
authActive: true,
|
||||
grantTypeInfo: {
|
||||
authEndpoint: baseEnv + '/oauth/authorize',
|
||||
clientID: '',
|
||||
grantType: 'IMPLICIT',
|
||||
scopes: 'write:pets read:pets',
|
||||
token: '',
|
||||
authRequestParams: [],
|
||||
refreshRequestParams: [],
|
||||
},
|
||||
addTo: 'HEADERS',
|
||||
},
|
||||
body: {
|
||||
contentType: null,
|
||||
body: null,
|
||||
},
|
||||
endpoint: 'petstore.swagger.io/v2/pet/<<petId>>',
|
||||
params: [],
|
||||
headers: [
|
||||
{
|
||||
key: 'api_key',
|
||||
value: '',
|
||||
active: true,
|
||||
description: '',
|
||||
},
|
||||
],
|
||||
method: 'DELETE',
|
||||
requestVariables: [
|
||||
{
|
||||
key: 'petId',
|
||||
value: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
data: {
|
||||
auth: {
|
||||
authType: 'inherit',
|
||||
authActive: true,
|
||||
},
|
||||
headers: [],
|
||||
_ref_id: `coll_${generateRefId()}`,
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
|
@ -118,10 +118,25 @@ export class CreateMockServerInput {
|
|||
name: string;
|
||||
|
||||
@Field({
|
||||
nullable: true,
|
||||
description:
|
||||
'ID of the (team or user) collection to associate with the mock server',
|
||||
})
|
||||
collectionID: string;
|
||||
collectionID?: string;
|
||||
|
||||
@Field({
|
||||
nullable: true,
|
||||
description:
|
||||
'Whether to auto-create a collection for the mock server if collectionID is not provided',
|
||||
})
|
||||
autoCreateCollection?: boolean;
|
||||
|
||||
@Field({
|
||||
nullable: true,
|
||||
description:
|
||||
'Whether to auto-create request examples in the collection for the mock server',
|
||||
})
|
||||
autoCreateRequestExample?: boolean;
|
||||
|
||||
@Field(() => WorkspaceType, {
|
||||
description: 'Type of workspace: USER or TEAM',
|
||||
|
|
|
|||
|
|
@ -8,9 +8,18 @@ import { TeamModule } from 'src/team/team.module';
|
|||
import { TeamRequestModule } from 'src/team-request/team-request.module';
|
||||
import { MockServerController } from './mock-server.controller';
|
||||
import { AccessTokenModule } from 'src/access-token/access-token.module';
|
||||
import { TeamCollectionModule } from 'src/team-collection/team-collection.module';
|
||||
import { UserCollectionModule } from 'src/user-collection/user-collection.module';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, TeamModule, TeamRequestModule, AccessTokenModule],
|
||||
imports: [
|
||||
PrismaModule,
|
||||
UserCollectionModule,
|
||||
TeamModule,
|
||||
TeamCollectionModule,
|
||||
TeamRequestModule,
|
||||
AccessTokenModule,
|
||||
],
|
||||
controllers: [MockServerController],
|
||||
providers: [
|
||||
MockServerService,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import { GqlTeamMemberGuard } from 'src/team/guards/gql-team-member.guard';
|
|||
import { RequiresTeamRole } from 'src/team/decorators/requires-team-role.decorator';
|
||||
import { TeamAccessRole } from 'src/team/team.model';
|
||||
import { throwErr } from 'src/utils';
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
import { INVALID_PARAMS } from 'src/errors';
|
||||
|
||||
@Resolver(() => MockServer)
|
||||
export class MockServerResolver {
|
||||
|
|
@ -72,7 +74,7 @@ export class MockServerResolver {
|
|||
})
|
||||
@UseGuards(GqlAuthGuard)
|
||||
async myMockServers(
|
||||
@GqlUser() user: User,
|
||||
@GqlUser() user: AuthUser,
|
||||
@Args() args: OffsetPaginationArgs,
|
||||
): Promise<MockServer[]> {
|
||||
return this.mockServerService.getUserMockServers(user.uid, args);
|
||||
|
|
@ -104,7 +106,7 @@ export class MockServerResolver {
|
|||
})
|
||||
@UseGuards(GqlAuthGuard)
|
||||
async mockServer(
|
||||
@GqlUser() user: User,
|
||||
@GqlUser() user: AuthUser,
|
||||
@Args({
|
||||
name: 'id',
|
||||
type: () => ID,
|
||||
|
|
@ -124,7 +126,7 @@ export class MockServerResolver {
|
|||
})
|
||||
@UseGuards(GqlAuthGuard)
|
||||
async mockServerLogs(
|
||||
@GqlUser() user: User,
|
||||
@GqlUser() user: AuthUser,
|
||||
@Args({
|
||||
name: 'mockServerID',
|
||||
type: () => ID,
|
||||
|
|
@ -151,8 +153,15 @@ export class MockServerResolver {
|
|||
@UseGuards(GqlAuthGuard)
|
||||
async createMockServer(
|
||||
@Args('input') input: CreateMockServerInput,
|
||||
@GqlUser() user: User,
|
||||
@GqlUser() user: AuthUser,
|
||||
): Promise<MockServer> {
|
||||
if (
|
||||
(input.collectionID && input.autoCreateCollection) ||
|
||||
(!input.collectionID && !input.autoCreateCollection)
|
||||
) {
|
||||
throwErr(INVALID_PARAMS);
|
||||
}
|
||||
|
||||
const result = await this.mockServerService.createMockServer(user, input);
|
||||
|
||||
if (E.isLeft(result)) throwErr(result.left);
|
||||
|
|
@ -164,7 +173,7 @@ export class MockServerResolver {
|
|||
})
|
||||
@UseGuards(GqlAuthGuard)
|
||||
async updateMockServer(
|
||||
@GqlUser() user: User,
|
||||
@GqlUser() user: AuthUser,
|
||||
@Args() args: MockServerMutationArgs,
|
||||
@Args('input') input: UpdateMockServerInput,
|
||||
): Promise<MockServer> {
|
||||
|
|
@ -183,7 +192,7 @@ export class MockServerResolver {
|
|||
})
|
||||
@UseGuards(GqlAuthGuard)
|
||||
async deleteMockServer(
|
||||
@GqlUser() user: User,
|
||||
@GqlUser() user: AuthUser,
|
||||
@Args() args: MockServerMutationArgs,
|
||||
): Promise<boolean> {
|
||||
const result = await this.mockServerService.deleteMockServer(
|
||||
|
|
@ -200,7 +209,7 @@ export class MockServerResolver {
|
|||
})
|
||||
@UseGuards(GqlAuthGuard)
|
||||
async deleteMockServerLog(
|
||||
@GqlUser() user: User,
|
||||
@GqlUser() user: AuthUser,
|
||||
@Args({
|
||||
name: 'logID',
|
||||
type: () => ID,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import { MockServerService } from './mock-server.service';
|
|||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { MockServerAnalyticsService } from './mock-server-analytics.service';
|
||||
import { TeamCollectionService } from '../team-collection/team-collection.service';
|
||||
import { UserCollectionService } from '../user-collection/user-collection.service';
|
||||
import { mockDeep, mockReset } from 'jest-mock-extended';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import {
|
||||
|
|
@ -17,9 +19,9 @@ import {
|
|||
UserCollection,
|
||||
TeamCollection,
|
||||
UserRequest,
|
||||
User,
|
||||
} from 'src/generated/prisma/client';
|
||||
import { WorkspaceType } from '../types/WorkspaceTypes';
|
||||
import { User } from '../user/user.model';
|
||||
import {
|
||||
CreateMockServerInput,
|
||||
UpdateMockServerInput,
|
||||
|
|
@ -28,17 +30,23 @@ import {
|
|||
const mockPrisma = mockDeep<PrismaService>();
|
||||
const mockAnalyticsService = mockDeep<MockServerAnalyticsService>();
|
||||
const mockConfigService = mockDeep<ConfigService>();
|
||||
const mockTeamCollectionService = mockDeep<TeamCollectionService>();
|
||||
const mockUserCollectionService = mockDeep<UserCollectionService>();
|
||||
|
||||
const mockServerService = new MockServerService(
|
||||
mockAnalyticsService,
|
||||
mockPrisma,
|
||||
mockConfigService,
|
||||
mockPrisma,
|
||||
mockAnalyticsService,
|
||||
mockTeamCollectionService,
|
||||
mockUserCollectionService,
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
mockReset(mockPrisma);
|
||||
mockReset(mockAnalyticsService);
|
||||
mockReset(mockConfigService);
|
||||
mockReset(mockTeamCollectionService);
|
||||
mockReset(mockUserCollectionService);
|
||||
|
||||
// Default config values
|
||||
mockConfigService.get.mockImplementation((key: string) => {
|
||||
|
|
@ -57,6 +65,7 @@ const user: User = {
|
|||
email: 'test@example.com',
|
||||
photoURL: null,
|
||||
isAdmin: false,
|
||||
refreshToken: null,
|
||||
currentGQLSession: '{}',
|
||||
currentRESTSession: '{}',
|
||||
createdOn: currentTime,
|
||||
|
|
@ -471,6 +480,282 @@ describe('MockServerService', () => {
|
|||
expect(result.left).toBe('mock_server/creation_failed');
|
||||
}
|
||||
});
|
||||
|
||||
describe('auto-create collection', () => {
|
||||
test('should auto-create user collection without request example', async () => {
|
||||
const autoCreateInput: CreateMockServerInput = {
|
||||
name: 'Auto Mock Server',
|
||||
workspaceType: WorkspaceType.USER,
|
||||
workspaceID: undefined,
|
||||
delayInMs: 0,
|
||||
autoCreateCollection: true,
|
||||
autoCreateRequestExample: false,
|
||||
};
|
||||
|
||||
const createdCollection = { ...userCollection, id: 'new-coll-123' };
|
||||
mockUserCollectionService.createUserCollection.mockResolvedValue(
|
||||
E.right(createdCollection as any),
|
||||
);
|
||||
mockPrisma.mockServer.create.mockResolvedValue({
|
||||
...dbMockServer,
|
||||
collectionID: 'new-coll-123',
|
||||
});
|
||||
|
||||
const result = await mockServerService.createMockServer(
|
||||
user,
|
||||
autoCreateInput,
|
||||
);
|
||||
|
||||
expect(E.isRight(result)).toBe(true);
|
||||
expect(mockUserCollectionService.createUserCollection).toHaveBeenCalledWith(
|
||||
user,
|
||||
autoCreateInput.name,
|
||||
null,
|
||||
null,
|
||||
'REST',
|
||||
);
|
||||
expect(mockPrisma.mockServer.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
collectionID: 'new-coll-123',
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('should auto-create user collection with request example', async () => {
|
||||
const autoCreateInput: CreateMockServerInput = {
|
||||
name: 'Auto Mock Server',
|
||||
workspaceType: WorkspaceType.USER,
|
||||
workspaceID: undefined,
|
||||
delayInMs: 0,
|
||||
autoCreateCollection: true,
|
||||
autoCreateRequestExample: true,
|
||||
};
|
||||
|
||||
mockUserCollectionService.importCollectionsFromJSON.mockResolvedValue(
|
||||
E.right({
|
||||
exportedCollection: JSON.stringify([{ id: 'imported-coll-123' }]),
|
||||
} as any),
|
||||
);
|
||||
mockPrisma.mockServer.create.mockResolvedValue({
|
||||
...dbMockServer,
|
||||
collectionID: 'imported-coll-123',
|
||||
});
|
||||
|
||||
const result = await mockServerService.createMockServer(
|
||||
user,
|
||||
autoCreateInput,
|
||||
);
|
||||
|
||||
expect(E.isRight(result)).toBe(true);
|
||||
expect(mockUserCollectionService.importCollectionsFromJSON).toHaveBeenCalled();
|
||||
expect(mockPrisma.mockServer.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
collectionID: 'imported-coll-123',
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('should auto-create team collection without request example', async () => {
|
||||
const autoCreateInput: CreateMockServerInput = {
|
||||
name: 'Team Auto Mock',
|
||||
workspaceType: WorkspaceType.TEAM,
|
||||
workspaceID: 'team123',
|
||||
delayInMs: 0,
|
||||
autoCreateCollection: true,
|
||||
autoCreateRequestExample: false,
|
||||
};
|
||||
|
||||
const createdTeamColl = { ...teamCollection, id: 'new-team-coll-123' };
|
||||
mockPrisma.team.findFirst.mockResolvedValue({ id: 'team123' } as any);
|
||||
mockTeamCollectionService.createCollection.mockResolvedValue(
|
||||
E.right(createdTeamColl as any),
|
||||
);
|
||||
mockPrisma.mockServer.create.mockResolvedValue({
|
||||
...dbMockServer,
|
||||
workspaceType: WorkspaceType.TEAM,
|
||||
workspaceID: 'team123',
|
||||
collectionID: 'new-team-coll-123',
|
||||
});
|
||||
|
||||
const result = await mockServerService.createMockServer(
|
||||
user,
|
||||
autoCreateInput,
|
||||
);
|
||||
|
||||
expect(E.isRight(result)).toBe(true);
|
||||
expect(mockTeamCollectionService.createCollection).toHaveBeenCalledWith(
|
||||
'team123',
|
||||
autoCreateInput.name,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
expect(mockPrisma.mockServer.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
collectionID: 'new-team-coll-123',
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('should auto-create team collection with request example', async () => {
|
||||
const autoCreateInput: CreateMockServerInput = {
|
||||
name: 'Team Auto Mock',
|
||||
workspaceType: WorkspaceType.TEAM,
|
||||
workspaceID: 'team123',
|
||||
delayInMs: 0,
|
||||
autoCreateCollection: true,
|
||||
autoCreateRequestExample: true,
|
||||
};
|
||||
|
||||
mockPrisma.team.findFirst.mockResolvedValue({ id: 'team123' } as any);
|
||||
mockTeamCollectionService.importCollectionsFromJSON.mockResolvedValue(
|
||||
E.right([{ id: 'imported-team-coll-123' }] as any),
|
||||
);
|
||||
mockPrisma.mockServer.create.mockResolvedValue({
|
||||
...dbMockServer,
|
||||
workspaceType: WorkspaceType.TEAM,
|
||||
workspaceID: 'team123',
|
||||
collectionID: 'imported-team-coll-123',
|
||||
});
|
||||
|
||||
const result = await mockServerService.createMockServer(
|
||||
user,
|
||||
autoCreateInput,
|
||||
);
|
||||
|
||||
expect(E.isRight(result)).toBe(true);
|
||||
expect(mockTeamCollectionService.importCollectionsFromJSON).toHaveBeenCalled();
|
||||
expect(mockPrisma.mockServer.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
collectionID: 'imported-team-coll-123',
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('should return error when auto-create user collection fails', async () => {
|
||||
const autoCreateInput: CreateMockServerInput = {
|
||||
name: 'Auto Mock Server',
|
||||
workspaceType: WorkspaceType.USER,
|
||||
workspaceID: undefined,
|
||||
delayInMs: 0,
|
||||
autoCreateCollection: true,
|
||||
autoCreateRequestExample: false,
|
||||
};
|
||||
|
||||
mockUserCollectionService.createUserCollection.mockResolvedValue(
|
||||
E.left('user_collection/creation_failed'),
|
||||
);
|
||||
|
||||
const result = await mockServerService.createMockServer(
|
||||
user,
|
||||
autoCreateInput,
|
||||
);
|
||||
|
||||
expect(E.isLeft(result)).toBe(true);
|
||||
if (E.isLeft(result)) {
|
||||
expect(result.left).toBe('user_collection/creation_failed');
|
||||
}
|
||||
});
|
||||
|
||||
test('should return error when auto-create team collection fails', async () => {
|
||||
const autoCreateInput: CreateMockServerInput = {
|
||||
name: 'Team Auto Mock',
|
||||
workspaceType: WorkspaceType.TEAM,
|
||||
workspaceID: 'team123',
|
||||
delayInMs: 0,
|
||||
autoCreateCollection: true,
|
||||
autoCreateRequestExample: false,
|
||||
};
|
||||
|
||||
mockPrisma.team.findFirst.mockResolvedValue({ id: 'team123' } as any);
|
||||
mockTeamCollectionService.createCollection.mockResolvedValue(
|
||||
E.left('team_coll/short_title'),
|
||||
);
|
||||
|
||||
const result = await mockServerService.createMockServer(
|
||||
user,
|
||||
autoCreateInput,
|
||||
);
|
||||
|
||||
expect(E.isLeft(result)).toBe(true);
|
||||
if (E.isLeft(result)) {
|
||||
expect(result.left).toBe('team_coll/short_title');
|
||||
}
|
||||
});
|
||||
|
||||
test('should rollback collection on mock server creation failure', async () => {
|
||||
const autoCreateInput: CreateMockServerInput = {
|
||||
name: 'Auto Mock Server',
|
||||
workspaceType: WorkspaceType.USER,
|
||||
workspaceID: undefined,
|
||||
delayInMs: 0,
|
||||
autoCreateCollection: true,
|
||||
autoCreateRequestExample: false,
|
||||
};
|
||||
|
||||
const createdCollection = { ...userCollection, id: 'rollback-coll-123' };
|
||||
mockUserCollectionService.createUserCollection.mockResolvedValue(
|
||||
E.right(createdCollection as any),
|
||||
);
|
||||
mockPrisma.mockServer.create.mockRejectedValue(
|
||||
new Error('Database error'),
|
||||
);
|
||||
mockUserCollectionService.deleteUserCollection.mockResolvedValue(
|
||||
E.right(true),
|
||||
);
|
||||
|
||||
const result = await mockServerService.createMockServer(
|
||||
user,
|
||||
autoCreateInput,
|
||||
);
|
||||
|
||||
expect(E.isLeft(result)).toBe(true);
|
||||
expect(mockUserCollectionService.deleteUserCollection).toHaveBeenCalledWith(
|
||||
'rollback-coll-123',
|
||||
user.uid,
|
||||
);
|
||||
});
|
||||
|
||||
test('should rollback team collection on mock server creation failure', async () => {
|
||||
const autoCreateInput: CreateMockServerInput = {
|
||||
name: 'Team Auto Mock',
|
||||
workspaceType: WorkspaceType.TEAM,
|
||||
workspaceID: 'team123',
|
||||
delayInMs: 0,
|
||||
autoCreateCollection: true,
|
||||
autoCreateRequestExample: false,
|
||||
};
|
||||
|
||||
const createdTeamColl = { ...teamCollection, id: 'rollback-team-coll-123' };
|
||||
mockPrisma.team.findFirst.mockResolvedValue({ id: 'team123' } as any);
|
||||
mockTeamCollectionService.createCollection.mockResolvedValue(
|
||||
E.right(createdTeamColl as any),
|
||||
);
|
||||
mockPrisma.mockServer.create.mockRejectedValue(
|
||||
new Error('Database error'),
|
||||
);
|
||||
mockTeamCollectionService.deleteCollection.mockResolvedValue(
|
||||
E.right(true),
|
||||
);
|
||||
|
||||
const result = await mockServerService.createMockServer(
|
||||
user,
|
||||
autoCreateInput,
|
||||
);
|
||||
|
||||
expect(E.isLeft(result)).toBe(true);
|
||||
expect(mockTeamCollectionService.deleteCollection).toHaveBeenCalledWith(
|
||||
'rollback-team-coll-123',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateMockServer', () => {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import {
|
|||
MockServerCollection,
|
||||
MockServerLog,
|
||||
} from './mock-server.model';
|
||||
import { User } from 'src/user/user.model';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import {
|
||||
MOCK_SERVER_NOT_FOUND,
|
||||
|
|
@ -19,6 +18,7 @@ import {
|
|||
MOCK_SERVER_DELETION_FAILED,
|
||||
MOCK_SERVER_LOG_NOT_FOUND,
|
||||
MOCK_SERVER_LOG_DELETION_FAILED,
|
||||
MOCK_SERVER_COLLECTION_CREATION_FAILED,
|
||||
} from 'src/errors';
|
||||
import { randomBytes } from 'crypto';
|
||||
import { WorkspaceType } from 'src/types/WorkspaceTypes';
|
||||
|
|
@ -31,13 +31,20 @@ import { OffsetPaginationArgs } from 'src/types/input-types.args';
|
|||
import { ConfigService } from '@nestjs/config';
|
||||
import { MockServerAnalyticsService } from './mock-server-analytics.service';
|
||||
import { PrismaError } from 'src/prisma/prisma-error-codes';
|
||||
import { TeamCollectionService } from 'src/team-collection/team-collection.service';
|
||||
import { UserCollectionService } from 'src/user-collection/user-collection.service';
|
||||
import { ReqType } from 'src/types/RequestTypes';
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
import { mockServerCollRequestExample } from './constants/mock-server-coll-request-example';
|
||||
|
||||
@Injectable()
|
||||
export class MockServerService {
|
||||
constructor(
|
||||
private readonly mockServerAnalyticsService: MockServerAnalyticsService,
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly configService: ConfigService,
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly mockServerAnalyticsService: MockServerAnalyticsService,
|
||||
private readonly teamCollectionService: TeamCollectionService,
|
||||
private readonly userCollectionService: UserCollectionService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
|
@ -252,7 +259,10 @@ export class MockServerService {
|
|||
/**
|
||||
* Validate workspace access permission and existence
|
||||
*/
|
||||
private async validateWorkspace(user: User, input: CreateMockServerInput) {
|
||||
private async validateWorkspace(
|
||||
user: AuthUser,
|
||||
input: CreateMockServerInput,
|
||||
) {
|
||||
if (input.workspaceType === WorkspaceType.TEAM) {
|
||||
if (!input.workspaceID) return E.left(TEAM_INVALID_ID);
|
||||
|
||||
|
|
@ -271,7 +281,12 @@ export class MockServerService {
|
|||
/**
|
||||
* Validate collection exists and user has access
|
||||
*/
|
||||
private async validateCollection(user: User, input: CreateMockServerInput) {
|
||||
private async validateCollection(
|
||||
user: AuthUser,
|
||||
input: CreateMockServerInput,
|
||||
) {
|
||||
if (!input.collectionID) return E.left(MOCK_SERVER_INVALID_COLLECTION);
|
||||
|
||||
if (input.workspaceType === WorkspaceType.TEAM) {
|
||||
const collection = await this.prisma.teamCollection.findUnique({
|
||||
where: { id: input.collectionID, teamID: input.workspaceID },
|
||||
|
|
@ -291,24 +306,105 @@ export class MockServerService {
|
|||
return E.left(MOCK_SERVER_INVALID_COLLECTION);
|
||||
}
|
||||
|
||||
private async createAutoCollection(
|
||||
user: AuthUser,
|
||||
input: CreateMockServerInput,
|
||||
) {
|
||||
if (input.workspaceType === WorkspaceType.USER) {
|
||||
if (!input.autoCreateRequestExample) {
|
||||
// create only a collection
|
||||
const userColl = await this.userCollectionService.createUserCollection(
|
||||
user,
|
||||
input.name,
|
||||
null,
|
||||
null,
|
||||
ReqType.REST,
|
||||
);
|
||||
|
||||
if (E.isLeft(userColl)) return E.left(userColl.left);
|
||||
return E.right({ id: userColl.right.id });
|
||||
} else {
|
||||
// create collection with a request example
|
||||
const importedUserColl =
|
||||
await this.userCollectionService.importCollectionsFromJSON(
|
||||
JSON.stringify(mockServerCollRequestExample(input.name)),
|
||||
user.uid,
|
||||
null,
|
||||
ReqType.REST,
|
||||
);
|
||||
if (E.isLeft(importedUserColl)) return E.left(importedUserColl.left);
|
||||
if (JSON.parse(importedUserColl.right.exportedCollection).length === 0)
|
||||
return E.left(MOCK_SERVER_COLLECTION_CREATION_FAILED);
|
||||
|
||||
return E.right({
|
||||
id: JSON.parse(importedUserColl.right.exportedCollection)[0].id,
|
||||
});
|
||||
}
|
||||
} else if (input.workspaceType === WorkspaceType.TEAM) {
|
||||
if (!input.workspaceID) return E.left(TEAM_INVALID_ID);
|
||||
|
||||
if (!input.autoCreateRequestExample) {
|
||||
const teamColl = await this.teamCollectionService.createCollection(
|
||||
input.workspaceID,
|
||||
input.name,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
if (E.isLeft(teamColl)) return E.left(teamColl.left);
|
||||
return E.right({ id: teamColl.right.id });
|
||||
} else {
|
||||
const importedTeamColl =
|
||||
await this.teamCollectionService.importCollectionsFromJSON(
|
||||
JSON.stringify(mockServerCollRequestExample(input.name)),
|
||||
input.workspaceID,
|
||||
null,
|
||||
);
|
||||
|
||||
if (E.isLeft(importedTeamColl)) return E.left(importedTeamColl.left);
|
||||
if (importedTeamColl.right.length === 0)
|
||||
return E.left(MOCK_SERVER_COLLECTION_CREATION_FAILED);
|
||||
|
||||
return E.right({
|
||||
id: importedTeamColl.right[0].id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return E.left(MOCK_SERVER_COLLECTION_CREATION_FAILED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new mock server
|
||||
*/
|
||||
async createMockServer(
|
||||
user: User,
|
||||
user: AuthUser,
|
||||
input: CreateMockServerInput,
|
||||
): Promise<E.Either<string, MockServer>> {
|
||||
let collectionID: string | undefined = input.collectionID;
|
||||
try {
|
||||
// Validate workspace type and ID
|
||||
|
||||
const workspaceValidation = await this.validateWorkspace(user, input);
|
||||
if (E.isLeft(workspaceValidation)) {
|
||||
return E.left(workspaceValidation.left);
|
||||
}
|
||||
|
||||
// Validate collection exists and user has access
|
||||
const collectionValidation = await this.validateCollection(user, input);
|
||||
if (E.isLeft(collectionValidation)) {
|
||||
return E.left(collectionValidation.left);
|
||||
if (!input.autoCreateCollection) {
|
||||
// Validate collection exists and user has access
|
||||
const collectionValidation = await this.validateCollection(user, input);
|
||||
if (E.isLeft(collectionValidation)) {
|
||||
return E.left(collectionValidation.left);
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-create collection if needed
|
||||
if (input.autoCreateCollection) {
|
||||
const newCollection = await this.createAutoCollection(user, input);
|
||||
if (E.isLeft(newCollection)) {
|
||||
return E.left(newCollection.left);
|
||||
}
|
||||
collectionID = newCollection.right.id;
|
||||
}
|
||||
|
||||
// Create mock server
|
||||
|
|
@ -318,7 +414,7 @@ export class MockServerService {
|
|||
name: input.name,
|
||||
subdomain,
|
||||
creatorUid: user.uid,
|
||||
collectionID: input.collectionID,
|
||||
collectionID: input.collectionID ?? collectionID,
|
||||
workspaceType: input.workspaceType,
|
||||
workspaceID:
|
||||
input.workspaceType === WorkspaceType.TEAM
|
||||
|
|
@ -335,9 +431,21 @@ export class MockServerService {
|
|||
|
||||
return E.right(this.cast(mockServer));
|
||||
} catch (error) {
|
||||
if (input.autoCreateCollection && collectionID) {
|
||||
if (input.workspaceType === WorkspaceType.USER) {
|
||||
await this.userCollectionService.deleteUserCollection(
|
||||
collectionID,
|
||||
user.uid,
|
||||
);
|
||||
} else if (input.workspaceType === WorkspaceType.TEAM) {
|
||||
await this.teamCollectionService.deleteCollection(collectionID);
|
||||
}
|
||||
}
|
||||
|
||||
if (error.code === PrismaError.UNIQUE_CONSTRAINT_VIOLATION) {
|
||||
return this.createMockServer(user, input); // Retry on subdomain conflict
|
||||
}
|
||||
|
||||
console.error('Error creating mock server:', error);
|
||||
return E.left(MOCK_SERVER_CREATION_FAILED);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { InputType, Field } from '@nestjs/graphql';
|
||||
import { IsOptional, Matches } from 'class-validator';
|
||||
import { WorkspaceType } from 'src/types/WorkspaceTypes';
|
||||
|
||||
@InputType()
|
||||
|
|
@ -13,6 +14,10 @@ export class CreatePublishedDocsArgs {
|
|||
name: 'version',
|
||||
description: 'Version of the published document',
|
||||
})
|
||||
@Matches(/^[a-zA-Z0-9.-]+$/, {
|
||||
message:
|
||||
'Version must only contain alphanumeric characters, dots, and hyphens',
|
||||
})
|
||||
version: string;
|
||||
|
||||
@Field({
|
||||
|
|
@ -62,6 +67,11 @@ export class UpdatePublishedDocsArgs {
|
|||
description: 'Version of the published document',
|
||||
nullable: true,
|
||||
})
|
||||
@IsOptional()
|
||||
@Matches(/^[a-zA-Z0-9.-]+$/, {
|
||||
message:
|
||||
'Version must only contain alphanumeric characters, dots, and hyphens',
|
||||
})
|
||||
version?: string;
|
||||
|
||||
@Field({
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ export class TeamCollectionResolver {
|
|||
parentCollectionID ?? null,
|
||||
);
|
||||
if (E.isLeft(importedCollection)) throwErr(importedCollection.left);
|
||||
return importedCollection.right;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Mutation(() => TeamCollection, {
|
||||
|
|
|
|||
|
|
@ -1397,7 +1397,7 @@ describe('importCollectionsFromJSON', () => {
|
|||
rootTeamCollection.teamID,
|
||||
null,
|
||||
);
|
||||
expect(result).toEqualRight(true);
|
||||
expect(result).toEqualRight([rootTeamCollection]);
|
||||
});
|
||||
|
||||
test('should successfully create new TeamCollections in a child collection and TeamRequests with valid inputs', async () => {
|
||||
|
|
@ -1410,7 +1410,7 @@ describe('importCollectionsFromJSON', () => {
|
|||
rootTeamCollection.teamID,
|
||||
rootTeamCollection.id,
|
||||
);
|
||||
expect(result).toEqualRight(true);
|
||||
expect(result).toEqualRight([rootTeamCollection]);
|
||||
});
|
||||
|
||||
test('should send pubsub message to "team_coll/<teamID>/coll_added" on successful creation from jsonString', async () => {
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ export class TeamCollectionService {
|
|||
),
|
||||
);
|
||||
|
||||
return E.right(true);
|
||||
return E.right(teamCollections);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1083,6 +1083,8 @@
|
|||
"environment_variable_added": "Mock URL added to environment",
|
||||
"environment_variable_updated": "Mock URL updated in environment",
|
||||
"environment_created_with_variable": "Environment created with mock URL",
|
||||
"add_example_request": "Add example request",
|
||||
"add_example_request_hint": "The collection will be created with a sample request that demonstrates how to use the mock server",
|
||||
"create_example_collection": "Create example collection",
|
||||
"create_example_collection_hint": "Create a pet store example collection with sample requests (GET, POST, PUT, DELETE)",
|
||||
"creating_example_collection": "Creating example collection...",
|
||||
|
|
|
|||
|
|
@ -186,24 +186,24 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Create Example Collection Toggle (only when "new collection" is selected) -->
|
||||
<!-- Auto-create Request Example Toggle (only for new collection mode) -->
|
||||
<div
|
||||
v-if="collectionSelectionMode === 'new'"
|
||||
class="flex flex-col space-y-2"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<HoppSmartToggle
|
||||
:on="createExampleCollection"
|
||||
@change="createExampleCollection = !createExampleCollection"
|
||||
:on="autoCreateRequestExample"
|
||||
@change="autoCreateRequestExample = !autoCreateRequestExample"
|
||||
>
|
||||
{{ t("mock_server.create_example_collection") }}
|
||||
{{ t("mock_server.add_example_request") }}
|
||||
</HoppSmartToggle>
|
||||
</div>
|
||||
<div
|
||||
v-if="createExampleCollection"
|
||||
v-if="autoCreateRequestExample"
|
||||
class="w-full text-xs text-secondaryLight"
|
||||
>
|
||||
{{ t("mock_server.create_example_collection_hint") }}
|
||||
{{ t("mock_server.add_example_request_hint") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -276,9 +276,7 @@
|
|||
:loading="loading"
|
||||
:disabled="
|
||||
!mockServerName.trim() ||
|
||||
(!effectiveCollectionID &&
|
||||
collectionSelectionMode === 'existing') ||
|
||||
(collectionSelectionMode === 'new' && !createExampleCollection)
|
||||
(!effectiveCollectionID && collectionSelectionMode === 'existing')
|
||||
"
|
||||
:icon="IconServer"
|
||||
@click="handleCreateMockServer"
|
||||
|
|
@ -300,17 +298,10 @@ import { useReadonlyStream } from "@composables/stream"
|
|||
import { useToast } from "@composables/toast"
|
||||
import { computed, ref, watch } from "vue"
|
||||
import { TippyComponent } from "vue-tippy"
|
||||
import * as E from "fp-ts/Either"
|
||||
import { MockServer } from "~/helpers/backend/graphql"
|
||||
import { showCreateMockServerModal$ } from "~/newstore/mockServers"
|
||||
import { useMockServer } from "~/composables/useMockServer"
|
||||
import MockServerCreatedInfo from "~/components/mockServer/MockServerCreatedInfo.vue"
|
||||
import { useService } from "dioc/vue"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
import {
|
||||
createMockCollectionForTeam,
|
||||
createMockCollectionForPersonal,
|
||||
} from "~/helpers/mockServer/exampleMockCollection"
|
||||
|
||||
// Icons
|
||||
import IconCheck from "~icons/lucide/check"
|
||||
|
|
@ -330,12 +321,6 @@ const {
|
|||
toggleMockServer,
|
||||
} = useMockServer()
|
||||
|
||||
// Services
|
||||
const workspaceService = useService(WorkspaceService)
|
||||
|
||||
// Current workspace
|
||||
const currentWorkspace = computed(() => workspaceService.currentWorkspace.value)
|
||||
|
||||
// Modal state
|
||||
const modalData = useReadonlyStream(showCreateMockServerModal$, {
|
||||
show: false,
|
||||
|
|
@ -350,7 +335,7 @@ const createdServer = ref<MockServer | null>(null)
|
|||
const delayInMsVal = ref<string>("0")
|
||||
const isPublic = ref<boolean>(true)
|
||||
const setInEnvironment = ref<boolean>(true)
|
||||
const createExampleCollection = ref<boolean>(false)
|
||||
const autoCreateRequestExample = ref<boolean>(true)
|
||||
const selectedCollectionID = ref("")
|
||||
const selectedCollectionName = ref("")
|
||||
const tippyActions = ref<TippyComponent | null>(null)
|
||||
|
|
@ -388,6 +373,8 @@ const effectiveCollectionID = computed(() => {
|
|||
// Get collection name
|
||||
const collectionName = computed(() => {
|
||||
if (selectedCollectionName.value) return selectedCollectionName.value
|
||||
// When creating new collection, use the mock server name as collection name
|
||||
if (collectionSelectionMode.value === "new") return mockServerName.value
|
||||
return "Unknown Collection"
|
||||
})
|
||||
|
||||
|
|
@ -402,42 +389,6 @@ const selectCollection = (option: any) => {
|
|||
selectedCollectionName.value = option.label
|
||||
}
|
||||
|
||||
// Function to create an example collection and return its ID and name
|
||||
const createExampleCollectionAndGetID = async (
|
||||
collectionName: string
|
||||
): Promise<{
|
||||
id: string
|
||||
name: string
|
||||
}> => {
|
||||
const workspaceType = currentWorkspace.value.type
|
||||
|
||||
if (workspaceType === "personal") {
|
||||
// For personal workspace
|
||||
const result = await createMockCollectionForPersonal(collectionName)
|
||||
|
||||
if (E.isLeft(result)) {
|
||||
throw new Error(result.left)
|
||||
}
|
||||
|
||||
return result.right
|
||||
} else if (workspaceType === "team" && currentWorkspace.value.teamID) {
|
||||
// For team workspace
|
||||
const teamID = currentWorkspace.value.teamID
|
||||
const result = await createMockCollectionForTeam(teamID, collectionName)
|
||||
|
||||
if (E.isLeft(result)) {
|
||||
throw new Error(result.left)
|
||||
}
|
||||
|
||||
// Wait a bit for the subscription to update
|
||||
await new Promise((resolve) => setTimeout(resolve, 500))
|
||||
|
||||
return result.right
|
||||
}
|
||||
|
||||
throw new Error("Unknown workspace type")
|
||||
}
|
||||
|
||||
// Create new mock server
|
||||
const handleCreateMockServer = async () => {
|
||||
// Validate mock server name first
|
||||
|
|
@ -446,53 +397,28 @@ const handleCreateMockServer = async () => {
|
|||
return
|
||||
}
|
||||
|
||||
// Start loading and show creating message
|
||||
loading.value = true
|
||||
|
||||
// If "new collection" mode is selected, create example collection (if toggle is enabled)
|
||||
let collectionIDToUse = effectiveCollectionID.value
|
||||
|
||||
if (collectionSelectionMode.value === "new") {
|
||||
if (createExampleCollection.value) {
|
||||
try {
|
||||
// Silently create the collection in the background
|
||||
const newCollection = await createExampleCollectionAndGetID(
|
||||
mockServerName.value.trim()
|
||||
)
|
||||
|
||||
// Update the selected collection with the actual created collection's ID and name
|
||||
collectionIDToUse = newCollection.id
|
||||
selectedCollectionID.value = newCollection.id
|
||||
selectedCollectionName.value = newCollection.name
|
||||
} catch (error) {
|
||||
console.error("Failed to create collection:", error)
|
||||
// If collection creation fails, stop the entire process
|
||||
toast.error(t("mock_server.failed_to_create_mock_server"))
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// If new collection mode but example collection is not enabled
|
||||
toast.error(t("mock_server.enable_example_collection_hint"))
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Validate collection ID
|
||||
if (!collectionIDToUse) {
|
||||
// For existing collection mode, validate that a collection is selected
|
||||
if (
|
||||
collectionSelectionMode.value === "existing" &&
|
||||
!effectiveCollectionID.value
|
||||
) {
|
||||
toast.error(t("mock_server.select_collection_error"))
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
// Wait a bit more to ensure collection is fully available in the system
|
||||
await new Promise((resolve) => setTimeout(resolve, 300))
|
||||
// Start loading
|
||||
loading.value = true
|
||||
|
||||
// Determine if we should auto-create a collection
|
||||
const isNewCollectionMode = collectionSelectionMode.value === "new"
|
||||
|
||||
// Now create the mock server
|
||||
const result = await createMockServer({
|
||||
mockServerName: mockServerName.value,
|
||||
collectionID: collectionIDToUse,
|
||||
collectionID: isNewCollectionMode ? undefined : effectiveCollectionID.value,
|
||||
autoCreateCollection: isNewCollectionMode ? true : undefined,
|
||||
autoCreateRequestExample:
|
||||
isNewCollectionMode && autoCreateRequestExample.value ? true : undefined,
|
||||
delayInMs: Number(delayInMsVal.value) || 0,
|
||||
isPublic: isPublic.value,
|
||||
setInEnvironment: setInEnvironment.value,
|
||||
|
|
@ -503,6 +429,12 @@ const handleCreateMockServer = async () => {
|
|||
|
||||
if (result.success && result.server) {
|
||||
createdServer.value = result.server
|
||||
|
||||
// Update the selected collection info from the created server
|
||||
if (result.server.collection) {
|
||||
selectedCollectionID.value = result.server.collection.id
|
||||
selectedCollectionName.value = result.server.collection.title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -539,19 +471,12 @@ watch(show, (newShow) => {
|
|||
loading.value = false
|
||||
delayInMsVal.value = "0"
|
||||
isPublic.value = true
|
||||
autoCreateRequestExample.value = true
|
||||
setInEnvironment.value = true
|
||||
createExampleCollection.value = false
|
||||
selectedCollectionID.value = ""
|
||||
selectedCollectionName.value = ""
|
||||
createdServer.value = null
|
||||
collectionSelectionMode.value = "existing"
|
||||
}
|
||||
})
|
||||
|
||||
// Auto-enable example collection toggle when switching to "new" mode
|
||||
watch(collectionSelectionMode, (newMode) => {
|
||||
if (newMode === "new") {
|
||||
createExampleCollection.value = true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ import {
|
|||
addMockServer,
|
||||
mockServers$,
|
||||
updateMockServer as updateMockServerInStore,
|
||||
loadMockServers,
|
||||
} from "~/newstore/mockServers"
|
||||
import { TeamCollectionsService } from "~/services/team-collection.service"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
export function useMockServer() {
|
||||
const t = useI18n()
|
||||
|
|
@ -62,6 +64,30 @@ export function useMockServer() {
|
|||
: undefined
|
||||
)
|
||||
|
||||
// Function to refetch collections and mock servers
|
||||
const refetchData = async () => {
|
||||
try {
|
||||
// Refetch mock servers
|
||||
await loadMockServers()
|
||||
|
||||
// Refetch collections based on workspace type
|
||||
if (
|
||||
currentWorkspace.value.type === "team" &&
|
||||
currentWorkspace.value.teamID
|
||||
) {
|
||||
// For team workspace, reload team collections by re-initializing with the same team ID
|
||||
teamCollectionsService.changeTeamID(currentWorkspace.value.teamID)
|
||||
} else {
|
||||
// For personal workspace, load REST collections only (mock servers are REST-based)
|
||||
if (platform.sync.collections.loadUserCollections) {
|
||||
await platform.sync.collections.loadUserCollections("REST")
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to refetch data:", error)
|
||||
}
|
||||
}
|
||||
|
||||
// Function to add mock URL to environment
|
||||
const addMockUrlToEnvironment = async (
|
||||
mockUrl: string,
|
||||
|
|
@ -190,7 +216,9 @@ export function useMockServer() {
|
|||
// Create new mock server
|
||||
const createMockServer = async (params: {
|
||||
mockServerName: string
|
||||
collectionID: string
|
||||
collectionID?: string
|
||||
autoCreateCollection?: boolean
|
||||
autoCreateRequestExample?: boolean
|
||||
delayInMs: number
|
||||
isPublic: boolean
|
||||
setInEnvironment: boolean
|
||||
|
|
@ -199,16 +227,24 @@ export function useMockServer() {
|
|||
const {
|
||||
mockServerName,
|
||||
collectionID,
|
||||
autoCreateCollection,
|
||||
autoCreateRequestExample,
|
||||
delayInMs,
|
||||
isPublic,
|
||||
setInEnvironment,
|
||||
collectionName,
|
||||
} = params
|
||||
|
||||
if (!mockServerName.trim() || !collectionID) {
|
||||
if (!collectionID) {
|
||||
toast.error(t("mock_server.select_collection_error"))
|
||||
}
|
||||
if (!mockServerName.trim()) {
|
||||
return { success: false, server: null }
|
||||
}
|
||||
|
||||
// Exactly one of collectionID or autoCreateCollection must be provided (XOR)
|
||||
if (
|
||||
(!collectionID && !autoCreateCollection) ||
|
||||
(collectionID && autoCreateCollection)
|
||||
) {
|
||||
toast.error(t("mock_server.select_collection_error"))
|
||||
return { success: false, server: null }
|
||||
}
|
||||
|
||||
|
|
@ -225,11 +261,13 @@ export function useMockServer() {
|
|||
const result = await pipe(
|
||||
createMockServerMutation(
|
||||
mockServerName.trim(),
|
||||
collectionID,
|
||||
workspaceType,
|
||||
workspaceID,
|
||||
delayInMs,
|
||||
isPublic
|
||||
isPublic,
|
||||
collectionID,
|
||||
autoCreateCollection,
|
||||
autoCreateRequestExample
|
||||
),
|
||||
TE.match(
|
||||
(error) => {
|
||||
|
|
@ -258,6 +296,9 @@ export function useMockServer() {
|
|||
}
|
||||
}
|
||||
|
||||
// Refetch collections and mock servers to get the latest data
|
||||
await refetchData()
|
||||
|
||||
return { success: true, server: result }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,11 +54,13 @@ type DeleteMockServerError =
|
|||
|
||||
export const createMockServer = (
|
||||
name: string,
|
||||
collectionID: string,
|
||||
workspaceType: WorkspaceType = WorkspaceType.User,
|
||||
workspaceID?: string,
|
||||
delayInMs: number = 0,
|
||||
isPublic: boolean = true
|
||||
isPublic: boolean = true,
|
||||
collectionID?: string,
|
||||
autoCreateCollection?: boolean,
|
||||
autoCreateRequestExample?: boolean
|
||||
) =>
|
||||
TE.tryCatch(
|
||||
async () => {
|
||||
|
|
@ -67,6 +69,8 @@ export const createMockServer = (
|
|||
input: {
|
||||
name,
|
||||
collectionID,
|
||||
autoCreateCollection,
|
||||
autoCreateRequestExample,
|
||||
workspaceType,
|
||||
workspaceID,
|
||||
delayInMs,
|
||||
|
|
@ -107,7 +111,7 @@ export const createMockServer = (
|
|||
return {
|
||||
...data,
|
||||
userUid: data.creator?.uid || "", // Legacy field
|
||||
collectionID: data.collection?.id || collectionID, // Legacy field
|
||||
collectionID: data.collection?.id || collectionID || "", // Legacy field - use response collection ID if available
|
||||
} as MockServer
|
||||
},
|
||||
(error) => (error as Error).message as CreateMockServerError
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import * as E from "fp-ts/Either"
|
|||
|
||||
export type CollectionsPlatformDef = {
|
||||
initCollectionsSync: () => void
|
||||
loadUserCollections?: (collectionType: "REST" | "GQL") => Promise<void>
|
||||
importToPersonalWorkspace?: (
|
||||
collections: HoppCollection[],
|
||||
reqType: ReqType
|
||||
|
|
|
|||
|
|
@ -1032,6 +1032,7 @@ import { importToPersonalWorkspace } from "./import"
|
|||
|
||||
export const def: CollectionsPlatformDef = {
|
||||
initCollectionsSync,
|
||||
loadUserCollections,
|
||||
importToPersonalWorkspace,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1032,6 +1032,7 @@ function setupUserRequestDeletedSubscription() {
|
|||
|
||||
export const def: CollectionsPlatformDef = {
|
||||
initCollectionsSync,
|
||||
loadUserCollections,
|
||||
importToPersonalWorkspace,
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue