feat: implement environments for selfhosted (#30)
This commit is contained in:
3
packages/hoppscotch-selfhost-web/.gitignore
vendored
3
packages/hoppscotch-selfhost-web/.gitignore
vendored
@@ -25,3 +25,6 @@ dist-ssr
|
||||
|
||||
# Sitemap Generation Artifacts (see vite.config.ts)
|
||||
.sitemap-gen
|
||||
|
||||
# Backend Code generation
|
||||
src/api/generated
|
||||
19
packages/hoppscotch-selfhost-web/gql-codegen.yml
Normal file
19
packages/hoppscotch-selfhost-web/gql-codegen.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
overwrite: true
|
||||
schema:
|
||||
- ${VITE_BACKEND_GQL_URL}
|
||||
generates:
|
||||
src/api/generated/graphql.ts:
|
||||
documents: "src/**/*.graphql"
|
||||
plugins:
|
||||
- add:
|
||||
content: >
|
||||
/* eslint-disable */
|
||||
// Auto-generated file (DO NOT EDIT!!!), refer gql-codegen.yml
|
||||
- typescript
|
||||
- typescript-operations
|
||||
- typed-document-node
|
||||
- typescript-urql-graphcache
|
||||
|
||||
src/helpers/backend/backend-schema.json:
|
||||
plugins:
|
||||
- urql-introspection
|
||||
@@ -16,13 +16,16 @@
|
||||
"do-build-prod": "pnpm run build",
|
||||
"do-lint": "pnpm run prod-lint",
|
||||
"do-typecheck": "pnpm run lint",
|
||||
"do-lintfix": "pnpm run lintfix"
|
||||
"do-lintfix": "pnpm run lintfix",
|
||||
"gql-codegen": "graphql-codegen --require dotenv/config --config gql-codegen.yml dotenv_config_path=\"../../.env\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@hoppscotch/common": "workspace:^",
|
||||
"axios": "^0.21.4",
|
||||
"buffer": "^6.0.3",
|
||||
"firebase": "^9.8.4",
|
||||
"fp-ts": "^2.13.1",
|
||||
"graphql": "^15.8.0",
|
||||
"process": "^0.11.10",
|
||||
"rxjs": "^7.5.5",
|
||||
"stream-browserify": "^3.0.0",
|
||||
@@ -31,6 +34,14 @@
|
||||
"workbox-window": "^6.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/add": "^3.2.0",
|
||||
"@graphql-codegen/cli": "^2.8.0",
|
||||
"@graphql-codegen/typed-document-node": "^2.3.1",
|
||||
"@graphql-codegen/typescript": "^2.7.1",
|
||||
"@graphql-codegen/typescript-operations": "^2.5.1",
|
||||
"@graphql-codegen/typescript-urql-graphcache": "^2.3.1",
|
||||
"@graphql-codegen/urql-introspection": "^2.2.0",
|
||||
"@graphql-typed-document-node/core": "^3.1.1",
|
||||
"@intlify/vite-plugin-vue-i18n": "^6.0.1",
|
||||
"@rushstack/eslint-patch": "^1.1.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.19.0",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
mutation ClearGlobalEnvironments($id: ID!) {
|
||||
clearGlobalEnvironments(id: $id) {
|
||||
id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
mutation CreateUserEnvironment($name: String!, $variables: String!) {
|
||||
createUserEnvironment(name: $name, variables: $variables) {
|
||||
id
|
||||
userUid
|
||||
name
|
||||
variables
|
||||
isGlobal
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
mutation CreateUserGlobalEnvironment($variables: String!) {
|
||||
createUserGlobalEnvironment(variables: $variables) {
|
||||
id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
mutation DeleteUserEnvironment($id: ID!) {
|
||||
deleteUserEnvironment(id: $id)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
mutation UpdateUserEnvironment($id: ID!, $name: String!, $variables: String!) {
|
||||
updateUserEnvironment(id: $id, name: $name, variables: $variables) {
|
||||
id
|
||||
userUid
|
||||
name
|
||||
variables
|
||||
isGlobal
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
mutation CreateUserEnvironment($name: String!, $variables: String!) {
|
||||
createUserEnvironment(name: $name, variables: $variables) {
|
||||
id
|
||||
userUid
|
||||
name
|
||||
variables
|
||||
isGlobal
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
query GetGlobalEnvironments {
|
||||
me {
|
||||
globalEnvironments {
|
||||
id
|
||||
isGlobal
|
||||
name
|
||||
userUid
|
||||
variables
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
query GetUserEnvironments {
|
||||
me {
|
||||
environments {
|
||||
id
|
||||
isGlobal
|
||||
name
|
||||
userUid
|
||||
variables
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
subscription UserEnvironmentCreated {
|
||||
userEnvironmentCreated {
|
||||
id
|
||||
isGlobal
|
||||
name
|
||||
userUid
|
||||
variables
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
subscription UserEnvironmentDeleted {
|
||||
userEnvironmentDeleted {
|
||||
id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
subscription UserEnvironmentUpdated {
|
||||
userEnvironmentUpdated {
|
||||
id
|
||||
userUid
|
||||
name
|
||||
variables
|
||||
isGlobal
|
||||
}
|
||||
}
|
||||
101
packages/hoppscotch-selfhost-web/src/lib/sync/index.ts
Normal file
101
packages/hoppscotch-selfhost-web/src/lib/sync/index.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { Observable } from "rxjs"
|
||||
import DispatchingStore from "@hoppscotch/common/newstore/DispatchingStore"
|
||||
|
||||
export type DispatchersOf<T extends DispatchingStore<any, any>> =
|
||||
T extends DispatchingStore<any, infer U>
|
||||
? U extends Record<infer D, any>
|
||||
? D
|
||||
: never
|
||||
: never
|
||||
|
||||
export type StoreSyncDefinitionOf<T extends DispatchingStore<any, any>> = {
|
||||
[x in DispatchersOf<T>]?: T extends DispatchingStore<any, infer U>
|
||||
? U extends Record<x, any>
|
||||
? U[x] extends (x: any, y: infer Y) => any
|
||||
? (payload: Y) => void
|
||||
: never
|
||||
: never
|
||||
: never
|
||||
}
|
||||
|
||||
let _isRunningDispatchWithoutSyncing = true
|
||||
|
||||
export function runDispatchWithOutSyncing(func: () => void) {
|
||||
_isRunningDispatchWithoutSyncing = false
|
||||
func()
|
||||
_isRunningDispatchWithoutSyncing = true
|
||||
}
|
||||
|
||||
export const getSyncInitFunction = <T extends DispatchingStore<any, any>>(
|
||||
store: T,
|
||||
storeSyncDefinition: StoreSyncDefinitionOf<T>,
|
||||
shouldSyncValue: () => boolean,
|
||||
shouldSyncObservable: Observable<boolean>
|
||||
) => {
|
||||
let startSubscriptions: () => () => void | undefined
|
||||
let stopSubscriptions: () => void | undefined
|
||||
|
||||
let oldSyncStatus = shouldSyncValue()
|
||||
|
||||
// Start and stop the subscriptions according to the sync settings from profile
|
||||
shouldSyncObservable.subscribe((newSyncStatus) => {
|
||||
if (oldSyncStatus === true && newSyncStatus === false) {
|
||||
stopListeningToSubscriptions()
|
||||
} else if (oldSyncStatus === false && newSyncStatus === true) {
|
||||
startListeningToSubscriptions()
|
||||
}
|
||||
|
||||
oldSyncStatus = newSyncStatus
|
||||
})
|
||||
|
||||
function startStoreSync() {
|
||||
store.dispatches$.subscribe((actionParams) => {
|
||||
// typescript cannot understand that the dispatcher can be the index, so casting to any
|
||||
if ((storeSyncDefinition as any)[actionParams.dispatcher]) {
|
||||
const dispatcher = actionParams.dispatcher
|
||||
const payload = actionParams.payload
|
||||
|
||||
const operationMapperFunction = (storeSyncDefinition as any)[dispatcher]
|
||||
|
||||
if (
|
||||
operationMapperFunction &&
|
||||
_isRunningDispatchWithoutSyncing &&
|
||||
shouldSyncValue()
|
||||
) {
|
||||
operationMapperFunction(payload)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function setupSubscriptions(func: () => () => void) {
|
||||
startSubscriptions = func
|
||||
}
|
||||
|
||||
function startListeningToSubscriptions() {
|
||||
if (!startSubscriptions) {
|
||||
console.warn(
|
||||
"We don't have a function to start subscriptions. Please use `setupSubscriptions` to setup the start function."
|
||||
)
|
||||
}
|
||||
|
||||
startSubscriptions()
|
||||
}
|
||||
|
||||
function stopListeningToSubscriptions() {
|
||||
if (!stopSubscriptions) {
|
||||
console.warn(
|
||||
"We don't have a function to unsubscribe. make sure you return the unsubscribe function when using setupSubscriptions"
|
||||
)
|
||||
}
|
||||
|
||||
stopSubscriptions()
|
||||
}
|
||||
|
||||
return {
|
||||
startStoreSync,
|
||||
setupSubscriptions,
|
||||
startListeningToSubscriptions,
|
||||
stopListeningToSubscriptions,
|
||||
}
|
||||
}
|
||||
33
packages/hoppscotch-selfhost-web/src/lib/sync/mapper.ts
Normal file
33
packages/hoppscotch-selfhost-web/src/lib/sync/mapper.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
export const createMapper = () => {
|
||||
const indexBackendIDMap = new Map<number, string | undefined>()
|
||||
const backendIdIndexMap = new Map<string, number | undefined>()
|
||||
|
||||
return {
|
||||
addEntry(localIndex: number, backendId: string) {
|
||||
indexBackendIDMap.set(localIndex, backendId)
|
||||
backendIdIndexMap.set(backendId, localIndex)
|
||||
},
|
||||
getValue() {
|
||||
return indexBackendIDMap
|
||||
},
|
||||
getBackendIdByIndex(localIndex: number) {
|
||||
return indexBackendIDMap.get(localIndex)
|
||||
},
|
||||
getIndexByBackendId(backendId: string) {
|
||||
return backendIdIndexMap.get(backendId)
|
||||
},
|
||||
removeEntry(backendId?: string, index?: number) {
|
||||
if (backendId) {
|
||||
const index = backendIdIndexMap.get(backendId)
|
||||
|
||||
backendIdIndexMap.delete(backendId)
|
||||
index && indexBackendIDMap.delete(index)
|
||||
} else if (index) {
|
||||
const backendId = indexBackendIDMap.get(index)
|
||||
|
||||
indexBackendIDMap.delete(index)
|
||||
backendId && backendIdIndexMap.delete(backendId)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
import { createHoppApp } from "@hoppscotch/common"
|
||||
import { def as authDef } from "./platform/auth"
|
||||
import { def as environmentsDef } from "./platform/environments/environments.platform"
|
||||
|
||||
createHoppApp("#app", {
|
||||
auth: authDef,
|
||||
sync: {
|
||||
environments: environmentsDef,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import {
|
||||
runMutation,
|
||||
runGQLQuery,
|
||||
runGQLSubscription,
|
||||
} from "@hoppscotch/common/helpers/backend/GQLClient"
|
||||
|
||||
import {
|
||||
CreateUserEnvironmentDocument,
|
||||
CreateUserEnvironmentMutation,
|
||||
CreateUserEnvironmentMutationVariables,
|
||||
UpdateUserEnvironmentMutation,
|
||||
UpdateUserEnvironmentMutationVariables,
|
||||
UpdateUserEnvironmentDocument,
|
||||
DeleteUserEnvironmentMutation,
|
||||
DeleteUserEnvironmentMutationVariables,
|
||||
DeleteUserEnvironmentDocument,
|
||||
ClearGlobalEnvironmentsMutation,
|
||||
ClearGlobalEnvironmentsMutationVariables,
|
||||
ClearGlobalEnvironmentsDocument,
|
||||
CreateUserGlobalEnvironmentMutation,
|
||||
CreateUserGlobalEnvironmentMutationVariables,
|
||||
CreateUserGlobalEnvironmentDocument,
|
||||
GetGlobalEnvironmentsDocument,
|
||||
GetGlobalEnvironmentsQueryVariables,
|
||||
GetGlobalEnvironmentsQuery,
|
||||
GetUserEnvironmentsDocument,
|
||||
UserEnvironmentCreatedDocument,
|
||||
UserEnvironmentUpdatedDocument,
|
||||
UserEnvironmentDeletedDocument,
|
||||
} from "./../../api/generated/graphql"
|
||||
|
||||
import { Environment } from "@hoppscotch/data"
|
||||
|
||||
export const createUserEnvironment = (name: string, variables: string) =>
|
||||
runMutation<
|
||||
CreateUserEnvironmentMutation,
|
||||
CreateUserEnvironmentMutationVariables,
|
||||
""
|
||||
>(CreateUserEnvironmentDocument, {
|
||||
name,
|
||||
variables,
|
||||
})()
|
||||
|
||||
export const updateUserEnvironment = (
|
||||
id: string,
|
||||
{ name, variables }: Environment
|
||||
) =>
|
||||
runMutation<
|
||||
UpdateUserEnvironmentMutation,
|
||||
UpdateUserEnvironmentMutationVariables,
|
||||
""
|
||||
>(UpdateUserEnvironmentDocument, {
|
||||
id,
|
||||
name,
|
||||
variables: JSON.stringify(variables),
|
||||
})
|
||||
|
||||
export const deleteUserEnvironment = (id: string) =>
|
||||
runMutation<
|
||||
DeleteUserEnvironmentMutation,
|
||||
DeleteUserEnvironmentMutationVariables,
|
||||
""
|
||||
>(DeleteUserEnvironmentDocument, {
|
||||
id,
|
||||
})
|
||||
|
||||
export const clearGlobalEnvironmentVariables = (id: string) =>
|
||||
runMutation<
|
||||
ClearGlobalEnvironmentsMutation,
|
||||
ClearGlobalEnvironmentsMutationVariables,
|
||||
""
|
||||
>(ClearGlobalEnvironmentsDocument, {
|
||||
id,
|
||||
})()
|
||||
|
||||
export const getUserEnvironments = () =>
|
||||
runGQLQuery({
|
||||
query: GetUserEnvironmentsDocument,
|
||||
})
|
||||
|
||||
export const getGlobalEnvironments = () =>
|
||||
runGQLQuery<
|
||||
GetGlobalEnvironmentsQuery,
|
||||
GetGlobalEnvironmentsQueryVariables,
|
||||
"user_environment/user_env_does_not_exists"
|
||||
>({
|
||||
query: GetGlobalEnvironmentsDocument,
|
||||
})
|
||||
|
||||
export const createUserGlobalEnvironment = (variables: string) =>
|
||||
runMutation<
|
||||
CreateUserGlobalEnvironmentMutation,
|
||||
CreateUserGlobalEnvironmentMutationVariables,
|
||||
""
|
||||
>(CreateUserGlobalEnvironmentDocument, {
|
||||
variables,
|
||||
})()
|
||||
|
||||
export const runUserEnvironmentCreatedSubscription = () =>
|
||||
runGQLSubscription({
|
||||
query: UserEnvironmentCreatedDocument,
|
||||
})
|
||||
|
||||
export const runUserEnvironmentUpdatedSubscription = () =>
|
||||
runGQLSubscription({
|
||||
query: UserEnvironmentUpdatedDocument,
|
||||
})
|
||||
|
||||
export const runUserEnvironmentDeletedSubscription = () =>
|
||||
runGQLSubscription({
|
||||
query: UserEnvironmentDeletedDocument,
|
||||
})
|
||||
@@ -0,0 +1,219 @@
|
||||
import { authEvents$, def as platformAuth } from "@platform/auth"
|
||||
import {
|
||||
createEnvironment,
|
||||
deleteEnvironment,
|
||||
replaceEnvironments,
|
||||
setGlobalEnvVariables,
|
||||
updateEnvironment,
|
||||
} from "@hoppscotch/common/newstore/environments"
|
||||
|
||||
import { EnvironmentsPlatformDef } from "@hoppscotch/common/src/platform/environments"
|
||||
import { runGQLSubscription } from "@hoppscotch/common/helpers/backend/GQLClient"
|
||||
|
||||
import {
|
||||
environmentsMapper,
|
||||
globalEnvironmentMapper,
|
||||
environnmentsSyncer,
|
||||
} from "@platform/environments/environments.sync"
|
||||
|
||||
import * as E from "fp-ts/Either"
|
||||
import { runDispatchWithOutSyncing } from "@lib/sync"
|
||||
import {
|
||||
createUserGlobalEnvironment,
|
||||
getGlobalEnvironments,
|
||||
getUserEnvironments,
|
||||
runUserEnvironmentCreatedSubscription,
|
||||
runUserEnvironmentDeletedSubscription,
|
||||
runUserEnvironmentUpdatedSubscription,
|
||||
} from "@platform/environments/environments.api"
|
||||
|
||||
export function initEnvironmentsSync() {
|
||||
const currentUser$ = platformAuth.getCurrentUserStream()
|
||||
|
||||
environnmentsSyncer.startStoreSync()
|
||||
environnmentsSyncer.setupSubscriptions(setupSubscriptions)
|
||||
|
||||
currentUser$.subscribe(async (user) => {
|
||||
if (user) {
|
||||
await loadAllEnvironments()
|
||||
}
|
||||
})
|
||||
|
||||
authEvents$.subscribe((event) => {
|
||||
if (event.event == "login" || event.event == "token_refresh") {
|
||||
environnmentsSyncer.startListeningToSubscriptions()
|
||||
}
|
||||
|
||||
if (event.event == "logout") {
|
||||
environnmentsSyncer.stopListeningToSubscriptions()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const def: EnvironmentsPlatformDef = {
|
||||
initEnvironmentsSync,
|
||||
}
|
||||
|
||||
function setupSubscriptions() {
|
||||
let subs: ReturnType<typeof runGQLSubscription>[1][] = []
|
||||
|
||||
const userEnvironmentCreatedSub = setupUserEnvironmentCreatedSubscription()
|
||||
const userEnvironmentUpdatedSub = setupUserEnvironmentUpdatedSubscription()
|
||||
const userEnvironmentDeletedSub = setupUserEnvironmentDeletedSubscription()
|
||||
|
||||
subs = [
|
||||
userEnvironmentCreatedSub,
|
||||
userEnvironmentUpdatedSub,
|
||||
userEnvironmentDeletedSub,
|
||||
]
|
||||
|
||||
return () => {
|
||||
subs.forEach((sub) => sub.unsubscribe())
|
||||
}
|
||||
}
|
||||
|
||||
async function loadUserEnvironments() {
|
||||
const res = await getUserEnvironments()
|
||||
|
||||
if (E.isRight(res)) {
|
||||
const environments = res.right.me.environments
|
||||
|
||||
if (environments.length > 0) {
|
||||
environments.forEach((env, index) => {
|
||||
environmentsMapper.addEntry(index, env.id)
|
||||
})
|
||||
|
||||
runDispatchWithOutSyncing(() => {
|
||||
replaceEnvironments(
|
||||
environments.map(({ id, variables, name }) => ({
|
||||
id,
|
||||
name,
|
||||
variables: JSON.parse(variables),
|
||||
}))
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadGlobalEnvironments() {
|
||||
const res = await getGlobalEnvironments()
|
||||
|
||||
if (E.isRight(res)) {
|
||||
const globalEnv = res.right.me.globalEnvironments
|
||||
|
||||
if (globalEnv) {
|
||||
runDispatchWithOutSyncing(() => {
|
||||
setGlobalEnvVariables(JSON.parse(globalEnv.variables))
|
||||
})
|
||||
globalEnvironmentMapper.addEntry(0, globalEnv.id)
|
||||
}
|
||||
} else if (res.left.error == "user_environment/user_env_does_not_exists") {
|
||||
const res = await createUserGlobalEnvironment(JSON.stringify([]))
|
||||
|
||||
if (E.isRight(res)) {
|
||||
const backendId = res.right.createUserGlobalEnvironment.id
|
||||
globalEnvironmentMapper.addEntry(0, backendId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadAllEnvironments() {
|
||||
await loadUserEnvironments()
|
||||
await loadGlobalEnvironments()
|
||||
}
|
||||
|
||||
function setupUserEnvironmentCreatedSubscription() {
|
||||
const [userEnvironmentCreated$, userEnvironmentCreatedSub] =
|
||||
runUserEnvironmentCreatedSubscription()
|
||||
|
||||
userEnvironmentCreated$.subscribe((res) => {
|
||||
console.group("Subscription: User Environment Created")
|
||||
console.log(res)
|
||||
console.groupEnd()
|
||||
|
||||
if (E.isRight(res)) {
|
||||
const { name, variables } = res.right.userEnvironmentCreated
|
||||
|
||||
if (name) {
|
||||
runDispatchWithOutSyncing(() => {
|
||||
createEnvironment(name, JSON.parse(variables))
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return userEnvironmentCreatedSub
|
||||
}
|
||||
|
||||
function setupUserEnvironmentUpdatedSubscription() {
|
||||
const [userEnvironmentUpdated$, userEnvironmentUpdatedSub] =
|
||||
runUserEnvironmentUpdatedSubscription()
|
||||
|
||||
userEnvironmentUpdated$.subscribe((res) => {
|
||||
console.group("Subscription: User Environment Updated")
|
||||
console.log(res)
|
||||
console.groupEnd()
|
||||
|
||||
if (E.isRight(res)) {
|
||||
const { name, variables, id, isGlobal } = res.right.userEnvironmentUpdated
|
||||
|
||||
// handle the case for global environments
|
||||
if (isGlobal) {
|
||||
runDispatchWithOutSyncing(() => {
|
||||
setGlobalEnvVariables(JSON.parse(variables))
|
||||
})
|
||||
} else {
|
||||
// handle the case for normal environments
|
||||
|
||||
const localIndex = environmentsMapper.getIndexByBackendId(id)
|
||||
|
||||
if (localIndex && name) {
|
||||
runDispatchWithOutSyncing(() => {
|
||||
updateEnvironment(localIndex, {
|
||||
name,
|
||||
variables: JSON.parse(variables),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return userEnvironmentUpdatedSub
|
||||
}
|
||||
|
||||
function setupUserEnvironmentDeletedSubscription() {
|
||||
console.log("setting up user environments for user deleted")
|
||||
|
||||
const [userEnvironmentDeleted$, userEnvironmentDeletedSub] =
|
||||
runUserEnvironmentDeletedSubscription()
|
||||
|
||||
userEnvironmentDeleted$.subscribe((res) => {
|
||||
console.group("Subscription: User Environment Deleted")
|
||||
console.log(res)
|
||||
console.groupEnd()
|
||||
|
||||
if (E.isRight(res)) {
|
||||
const { id } = res.right.userEnvironmentDeleted
|
||||
|
||||
const localIndex = environmentsMapper.getIndexByBackendId(id)
|
||||
|
||||
if (localIndex) {
|
||||
runDispatchWithOutSyncing(() => {
|
||||
deleteEnvironment(localIndex)
|
||||
})
|
||||
|
||||
environmentsMapper.removeEntry(id)
|
||||
} else {
|
||||
console.log("could not find the localIndex")
|
||||
// TODO:
|
||||
// handle order of events
|
||||
// eg: update coming before create
|
||||
// skipping for this release
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return userEnvironmentDeletedSub
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import { environmentsStore } from "@hoppscotch/common/newstore/environments"
|
||||
import {
|
||||
getSettingSubject,
|
||||
settingsStore,
|
||||
} from "@hoppscotch/common/newstore/settings"
|
||||
|
||||
import { getSyncInitFunction } from "../../lib/sync"
|
||||
|
||||
import * as E from "fp-ts/Either"
|
||||
|
||||
import { StoreSyncDefinitionOf } from "../../lib/sync"
|
||||
import { createMapper } from "../../lib/sync/mapper"
|
||||
import {
|
||||
clearGlobalEnvironmentVariables,
|
||||
createUserEnvironment,
|
||||
deleteUserEnvironment,
|
||||
updateUserEnvironment,
|
||||
} from "./environments.api"
|
||||
|
||||
export const environmentsMapper = createMapper()
|
||||
export const globalEnvironmentMapper = createMapper()
|
||||
|
||||
export const storeSyncDefinition: StoreSyncDefinitionOf<
|
||||
typeof environmentsStore
|
||||
> = {
|
||||
async createEnvironment({ name, variables }) {
|
||||
const lastCreatedEnvIndex = environmentsStore.value.environments.length - 1
|
||||
const res = await createUserEnvironment(name, JSON.stringify(variables))
|
||||
|
||||
if (E.isRight(res)) {
|
||||
const id = res.right.createUserEnvironment.id
|
||||
environmentsMapper.addEntry(lastCreatedEnvIndex, id)
|
||||
}
|
||||
},
|
||||
async appendEnvironments({ envs }) {
|
||||
const appendListLength = envs.length
|
||||
let appendStart =
|
||||
environmentsStore.value.environments.length - appendListLength - 1
|
||||
|
||||
envs.forEach((env) => {
|
||||
const envId = ++appendStart
|
||||
|
||||
;(async function () {
|
||||
const res = await createUserEnvironment(
|
||||
env.name,
|
||||
JSON.stringify(env.variables)
|
||||
)
|
||||
|
||||
if (E.isRight(res)) {
|
||||
const id = res.right.createUserEnvironment.id
|
||||
environmentsMapper.addEntry(envId, id)
|
||||
}
|
||||
})()
|
||||
})
|
||||
},
|
||||
async duplicateEnvironment({ envIndex }) {
|
||||
const environmentToDuplicate = environmentsStore.value.environments.find(
|
||||
(_, index) => index === envIndex
|
||||
)
|
||||
|
||||
const lastCreatedEnvIndex = environmentsStore.value.environments.length - 1
|
||||
|
||||
if (environmentToDuplicate) {
|
||||
const res = await createUserEnvironment(
|
||||
environmentToDuplicate?.name,
|
||||
JSON.stringify(environmentToDuplicate?.variables)
|
||||
)
|
||||
|
||||
if (E.isRight(res)) {
|
||||
const id = res.right.createUserEnvironment.id
|
||||
environmentsMapper.addEntry(lastCreatedEnvIndex, id)
|
||||
}
|
||||
}
|
||||
},
|
||||
updateEnvironment({ envIndex, updatedEnv }) {
|
||||
const backendId = environmentsMapper.getBackendIdByIndex(envIndex)
|
||||
console.log(environmentsMapper)
|
||||
|
||||
if (backendId) {
|
||||
updateUserEnvironment(backendId, updatedEnv)()
|
||||
}
|
||||
},
|
||||
async deleteEnvironment({ envIndex }) {
|
||||
const backendId = environmentsMapper.getBackendIdByIndex(envIndex)
|
||||
|
||||
if (backendId) {
|
||||
await deleteUserEnvironment(backendId)()
|
||||
environmentsMapper.removeEntry(backendId)
|
||||
}
|
||||
},
|
||||
setGlobalVariables({ entries }) {
|
||||
const backendId = globalEnvironmentMapper.getBackendIdByIndex(0)
|
||||
|
||||
if (backendId) {
|
||||
updateUserEnvironment(backendId, { name: "", variables: entries })()
|
||||
}
|
||||
},
|
||||
clearGlobalVariables() {
|
||||
const backendId = globalEnvironmentMapper.getBackendIdByIndex(0)
|
||||
|
||||
if (backendId) {
|
||||
clearGlobalEnvironmentVariables(backendId)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export const environnmentsSyncer = getSyncInitFunction(
|
||||
environmentsStore,
|
||||
storeSyncDefinition,
|
||||
() => settingsStore.value.syncEnvironments,
|
||||
getSettingSubject("syncEnvironments")
|
||||
)
|
||||
@@ -14,7 +14,9 @@
|
||||
"noEmit": true,
|
||||
"paths": {
|
||||
"@hoppscotch/common": [ "../hoppscotch-common/src/index.ts" ],
|
||||
"@hoppscotch/common/*": [ "../hoppscotch-common/src/*" ]
|
||||
"@hoppscotch/common/*": [ "../hoppscotch-common/src/*" ],
|
||||
"@platform/*": ["./src/platform/*"],
|
||||
"@lib/*": ["./src/lib/*"],
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
@@ -58,7 +58,8 @@ export default defineConfig({
|
||||
"../hoppscotch-common/src/helpers/functional"
|
||||
),
|
||||
"@workers": path.resolve(__dirname, "../hoppscotch-common/src/workers"),
|
||||
|
||||
"@platform": path.resolve(__dirname, "./src/platform"),
|
||||
"@lib": path.resolve(__dirname, "./src/lib"),
|
||||
stream: "stream-browserify",
|
||||
util: "util",
|
||||
},
|
||||
@@ -117,6 +118,11 @@ export default defineConfig({
|
||||
prefix: "icon",
|
||||
customCollections: ["hopp", "auth", "brands"],
|
||||
}),
|
||||
(compName: string) => {
|
||||
if (compName.startsWith("Hopp"))
|
||||
return { name: compName, from: "@hoppscotch/ui" }
|
||||
else return undefined
|
||||
},
|
||||
],
|
||||
types: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user