Merge branch 'feat/cm-env-tooltip'
This commit is contained in:
@@ -136,44 +136,43 @@ a {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tippy-popper {
|
.tooltip-theme {
|
||||||
.tooltip-theme {
|
@apply bg-tooltip;
|
||||||
@apply bg-tooltip;
|
@apply text-primary;
|
||||||
@apply text-primary;
|
@apply font-semibold;
|
||||||
@apply font-semibold;
|
@apply py-1 px-2;
|
||||||
@apply py-1 px-2;
|
@apply rounded;
|
||||||
|
@apply truncate;
|
||||||
|
@apply shadow;
|
||||||
|
|
||||||
|
font-size: 88%;
|
||||||
|
line-height: var(--body-line-height);
|
||||||
|
|
||||||
|
kbd {
|
||||||
|
@apply inline-flex;
|
||||||
|
@apply font-sans;
|
||||||
|
@apply bg-gray-500;
|
||||||
|
@apply bg-opacity-45;
|
||||||
|
@apply text-primaryLight;
|
||||||
|
@apply rounded-sm;
|
||||||
|
@apply px-1;
|
||||||
|
@apply ml-1;
|
||||||
@apply truncate;
|
@apply truncate;
|
||||||
@apply shadow;
|
|
||||||
|
|
||||||
font-size: 88%;
|
|
||||||
line-height: var(--body-line-height);
|
|
||||||
|
|
||||||
kbd {
|
|
||||||
@apply inline-flex;
|
|
||||||
@apply font-sans;
|
|
||||||
@apply bg-gray-500;
|
|
||||||
@apply bg-opacity-45;
|
|
||||||
@apply text-primaryLight;
|
|
||||||
@apply rounded-sm;
|
|
||||||
@apply px-1;
|
|
||||||
@apply ml-1;
|
|
||||||
@apply truncate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.popover-theme {
|
.popover-theme {
|
||||||
@apply bg-popover;
|
@apply bg-popover;
|
||||||
@apply text-secondary;
|
@apply text-secondary;
|
||||||
@apply p-2;
|
@apply p-2;
|
||||||
@apply shadow-lg;
|
@apply shadow-lg;
|
||||||
@apply focus:outline-none;
|
@apply focus:outline-none;
|
||||||
|
|
||||||
font-size: var(--body-font-size);
|
font-size: var(--body-font-size);
|
||||||
line-height: var(--body-line-height);
|
line-height: var(--body-line-height);
|
||||||
|
|
||||||
.tippy-roundarrow svg {
|
.tippy-roundarrow svg {
|
||||||
@apply fill-popover;
|
@apply fill-popover;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ useCodemirror(bulkEditor, bulkHeaders, {
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const variableEditor = ref<any | null>(null)
|
const variableEditor = ref<any | null>(null)
|
||||||
@@ -318,6 +319,7 @@ useCodemirror(variableEditor, variableString, {
|
|||||||
},
|
},
|
||||||
linter: jsonLinter,
|
linter: jsonLinter,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const queryEditor = ref<any | null>(null)
|
const queryEditor = ref<any | null>(null)
|
||||||
@@ -330,6 +332,7 @@ useCodemirror(queryEditor, gqlQueryString, {
|
|||||||
},
|
},
|
||||||
linter: createGQLQueryLinter(schemaString),
|
linter: createGQLQueryLinter(schemaString),
|
||||||
completer: queryCompleter(schemaString),
|
completer: queryCompleter(schemaString),
|
||||||
|
environmentHighlights: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const copyQueryIcon = ref("copy")
|
const copyQueryIcon = ref("copy")
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ useCodemirror(
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: false,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -409,6 +409,7 @@ useCodemirror(
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: false,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ useCodemirror(generatedCode, requestCode, {
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ useCodemirror(bulkEditor, bulkHeaders, {
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(bulkHeaders, () => {
|
watch(bulkHeaders, () => {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ useCodemirror(curlEditor, curl, {
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
defineProps<{ show: boolean }>()
|
defineProps<{ show: boolean }>()
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ useCodemirror(bulkEditor, bulkParams, {
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const params$ = useReadonlyStream(restParams$, [])
|
const params$ = useReadonlyStream(restParams$, [])
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ useCodemirror(
|
|||||||
},
|
},
|
||||||
linter,
|
linter,
|
||||||
completer,
|
completer,
|
||||||
|
environmentHighlights: false,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ useCodemirror(
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ useCodemirror(
|
|||||||
},
|
},
|
||||||
linter,
|
linter,
|
||||||
completer,
|
completer,
|
||||||
|
environmentHighlights: false,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ useCodemirror(
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ const { cursor } = useCodemirror(
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ useCodemirror(
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ useCodemirror(
|
|||||||
},
|
},
|
||||||
linter: null,
|
linter: null,
|
||||||
completer: null,
|
completer: null,
|
||||||
|
environmentHighlights: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,11 @@ import { GQLLanguage } from "@hoppscotch/codemirror-lang-graphql"
|
|||||||
import { pipe } from "fp-ts/function"
|
import { pipe } from "fp-ts/function"
|
||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
import { isJSONContentType } from "../utils/contenttypes"
|
import { isJSONContentType } from "../utils/contenttypes"
|
||||||
|
import { useStreamSubscriber } from "../utils/composables"
|
||||||
import { Completer } from "./completion"
|
import { Completer } from "./completion"
|
||||||
import { LinterDefinition } from "./linting/linter"
|
import { LinterDefinition } from "./linting/linter"
|
||||||
import { basicSetup, baseTheme, baseHighlightStyle } from "./themes/baseTheme"
|
import { basicSetup, baseTheme, baseHighlightStyle } from "./themes/baseTheme"
|
||||||
|
import { HoppEnvironmentPlugin } from "./extensions/HoppEnvironment"
|
||||||
|
|
||||||
type ExtendedEditorConfig = {
|
type ExtendedEditorConfig = {
|
||||||
mode: string
|
mode: string
|
||||||
@@ -45,6 +47,9 @@ type CodeMirrorOptions = {
|
|||||||
extendedEditorConfig: Partial<ExtendedEditorConfig>
|
extendedEditorConfig: Partial<ExtendedEditorConfig>
|
||||||
linter: LinterDefinition | null
|
linter: LinterDefinition | null
|
||||||
completer: Completer | null
|
completer: Completer | null
|
||||||
|
|
||||||
|
// NOTE: This property is not reactive
|
||||||
|
environmentHighlights: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const hoppCompleterExt = (completer: Completer): Extension => {
|
const hoppCompleterExt = (completer: Completer): Extension => {
|
||||||
@@ -148,6 +153,8 @@ export function useCodemirror(
|
|||||||
value: Ref<string>,
|
value: Ref<string>,
|
||||||
options: CodeMirrorOptions
|
options: CodeMirrorOptions
|
||||||
): { cursor: Ref<{ line: number; ch: number }> } {
|
): { cursor: Ref<{ line: number; ch: number }> } {
|
||||||
|
const { subscribeToStream } = useStreamSubscriber()
|
||||||
|
|
||||||
const language = new Compartment()
|
const language = new Compartment()
|
||||||
const lineWrapping = new Compartment()
|
const lineWrapping = new Compartment()
|
||||||
const placeholderConfig = new Compartment()
|
const placeholderConfig = new Compartment()
|
||||||
@@ -165,64 +172,70 @@ export function useCodemirror(
|
|||||||
|
|
||||||
const view = ref<EditorView>()
|
const view = ref<EditorView>()
|
||||||
|
|
||||||
|
const environmentTooltip = options.environmentHighlights
|
||||||
|
? new HoppEnvironmentPlugin(subscribeToStream, view)
|
||||||
|
: null
|
||||||
|
|
||||||
const initView = (el: any) => {
|
const initView = (el: any) => {
|
||||||
|
const extensions = [
|
||||||
|
basicSetup,
|
||||||
|
baseTheme,
|
||||||
|
baseHighlightStyle,
|
||||||
|
ViewPlugin.fromClass(
|
||||||
|
class {
|
||||||
|
update(update: ViewUpdate) {
|
||||||
|
if (update.selectionSet) {
|
||||||
|
const cursorPos = update.state.selection.main.head
|
||||||
|
|
||||||
|
const line = update.state.doc.lineAt(cursorPos)
|
||||||
|
|
||||||
|
cachedCursor.value = {
|
||||||
|
line: line.number - 1,
|
||||||
|
ch: cursorPos - line.from,
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.value = {
|
||||||
|
line: cachedCursor.value.line,
|
||||||
|
ch: cachedCursor.value.ch,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (update.docChanged) {
|
||||||
|
// Expensive on big files ?
|
||||||
|
cachedValue.value = update.state.doc
|
||||||
|
.toJSON()
|
||||||
|
.join(update.state.lineBreak)
|
||||||
|
if (!options.extendedEditorConfig.readOnly)
|
||||||
|
value.value = cachedValue.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
EditorState.changeFilter.of(() => !options.extendedEditorConfig.readOnly),
|
||||||
|
placeholderConfig.of(
|
||||||
|
placeholder(options.extendedEditorConfig.placeholder ?? "")
|
||||||
|
),
|
||||||
|
language.of(
|
||||||
|
getEditorLanguage(
|
||||||
|
options.extendedEditorConfig.mode ?? "",
|
||||||
|
options.linter ?? undefined,
|
||||||
|
options.completer ?? undefined
|
||||||
|
)
|
||||||
|
),
|
||||||
|
lineWrapping.of(
|
||||||
|
options.extendedEditorConfig.lineWrapping
|
||||||
|
? [EditorView.lineWrapping]
|
||||||
|
: []
|
||||||
|
),
|
||||||
|
keymap.of(defaultKeymap),
|
||||||
|
]
|
||||||
|
|
||||||
|
if (environmentTooltip) extensions.push(environmentTooltip.extension)
|
||||||
|
|
||||||
view.value = new EditorView({
|
view.value = new EditorView({
|
||||||
parent: el,
|
parent: el,
|
||||||
state: EditorState.create({
|
state: EditorState.create({
|
||||||
doc: value.value,
|
doc: value.value,
|
||||||
extensions: [
|
extensions,
|
||||||
basicSetup,
|
|
||||||
baseTheme,
|
|
||||||
baseHighlightStyle,
|
|
||||||
ViewPlugin.fromClass(
|
|
||||||
class {
|
|
||||||
update(update: ViewUpdate) {
|
|
||||||
if (update.selectionSet) {
|
|
||||||
const cursorPos = update.state.selection.main.head
|
|
||||||
|
|
||||||
const line = update.state.doc.lineAt(cursorPos)
|
|
||||||
|
|
||||||
cachedCursor.value = {
|
|
||||||
line: line.number - 1,
|
|
||||||
ch: cursorPos - line.from,
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor.value = {
|
|
||||||
line: cachedCursor.value.line,
|
|
||||||
ch: cachedCursor.value.ch,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (update.docChanged) {
|
|
||||||
// Expensive on big files ?
|
|
||||||
cachedValue.value = update.state.doc
|
|
||||||
.toJSON()
|
|
||||||
.join(update.state.lineBreak)
|
|
||||||
if (!options.extendedEditorConfig.readOnly)
|
|
||||||
value.value = cachedValue.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
EditorState.changeFilter.of(
|
|
||||||
() => !options.extendedEditorConfig.readOnly
|
|
||||||
),
|
|
||||||
placeholderConfig.of(
|
|
||||||
placeholder(options.extendedEditorConfig.placeholder ?? "")
|
|
||||||
),
|
|
||||||
language.of(
|
|
||||||
getEditorLanguage(
|
|
||||||
options.extendedEditorConfig.mode ?? "",
|
|
||||||
options.linter ?? undefined,
|
|
||||||
options.completer ?? undefined
|
|
||||||
)
|
|
||||||
),
|
|
||||||
lineWrapping.of(
|
|
||||||
options.extendedEditorConfig.lineWrapping
|
|
||||||
? [EditorView.lineWrapping]
|
|
||||||
: []
|
|
||||||
),
|
|
||||||
keymap.of(defaultKeymap),
|
|
||||||
],
|
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
import { Compartment } from "@codemirror/state"
|
||||||
|
import { hoverTooltip } from "@codemirror/tooltip"
|
||||||
|
import {
|
||||||
|
Decoration,
|
||||||
|
EditorView,
|
||||||
|
MatchDecorator,
|
||||||
|
ViewPlugin,
|
||||||
|
} from "@codemirror/view"
|
||||||
|
import { Ref } from "@nuxtjs/composition-api"
|
||||||
|
import { StreamSubscriberFunc } from "~/helpers/utils/composables"
|
||||||
|
import {
|
||||||
|
AggregateEnvironment,
|
||||||
|
aggregateEnvs$,
|
||||||
|
getAggregateEnvs,
|
||||||
|
} from "~/newstore/environments"
|
||||||
|
|
||||||
|
const HOPP_ENVIRONMENT_REGEX = /(<<\w+>>)/g
|
||||||
|
|
||||||
|
const HOPP_ENV_HIGHLIGHT =
|
||||||
|
"cursor-help transition rounded px-1 focus:outline-none mx-0.5"
|
||||||
|
const HOPP_ENV_HIGHLIGHT_FOUND =
|
||||||
|
"bg-accentDark text-accentContrast hover:bg-accent"
|
||||||
|
const HOPP_ENV_HIGHLIGHT_NOT_FOUND = "bg-red-400 text-red-50 hover:bg-red-600"
|
||||||
|
|
||||||
|
const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
|
||||||
|
hoverTooltip((view, pos, side) => {
|
||||||
|
const { from, to, text } = view.state.doc.lineAt(pos)
|
||||||
|
|
||||||
|
// TODO: When Codemirror 6 allows this to work (not make the
|
||||||
|
// popups appear half of the time) use this implementation
|
||||||
|
// const wordSelection = view.state.wordAt(pos)
|
||||||
|
// if (!wordSelection) return null
|
||||||
|
// const word = view.state.doc.sliceString(
|
||||||
|
// wordSelection.from - 2,
|
||||||
|
// wordSelection.to + 2
|
||||||
|
// )
|
||||||
|
// if (!HOPP_ENVIRONMENT_REGEX.test(word)) return null
|
||||||
|
|
||||||
|
// Tracking the start and the end of the words
|
||||||
|
let start = pos
|
||||||
|
let end = pos
|
||||||
|
|
||||||
|
while (start > from && /\w/.test(text[start - from - 1])) start--
|
||||||
|
while (end < to && /\w/.test(text[end - from])) end++
|
||||||
|
|
||||||
|
if (
|
||||||
|
(start === pos && side < 0) ||
|
||||||
|
(end === pos && side > 0) ||
|
||||||
|
!HOPP_ENVIRONMENT_REGEX.test(text.slice(start - from - 2, end - from + 2))
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
|
||||||
|
const envName =
|
||||||
|
aggregateEnvs.find(
|
||||||
|
(env) => env.key === text.slice(start - from, end - from)
|
||||||
|
// env.key === word.slice(wordSelection.from + 2, wordSelection.to - 2)
|
||||||
|
)?.sourceEnv ?? "choose an environment"
|
||||||
|
|
||||||
|
const envValue = (
|
||||||
|
aggregateEnvs.find(
|
||||||
|
(env) => env.key === text.slice(start - from, end - from)
|
||||||
|
// env.key === word.slice(wordSelection.from + 2, wordSelection.to - 2)
|
||||||
|
)?.value ?? "not found"
|
||||||
|
).replace(/"/g, """)
|
||||||
|
|
||||||
|
const textContent = `${envName} <kbd>${envValue}</kbd>`
|
||||||
|
|
||||||
|
return {
|
||||||
|
pos: start,
|
||||||
|
end: to,
|
||||||
|
above: true,
|
||||||
|
create() {
|
||||||
|
const dom = document.createElement("span")
|
||||||
|
dom.innerHTML = textContent
|
||||||
|
dom.className = "tooltip-theme"
|
||||||
|
return { dom }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function checkEnv(env: string, aggregateEnvs: AggregateEnvironment[]) {
|
||||||
|
const className = aggregateEnvs.find(
|
||||||
|
(k: { key: string }) => k.key === env.slice(2, -2)
|
||||||
|
)
|
||||||
|
? HOPP_ENV_HIGHLIGHT_FOUND
|
||||||
|
: HOPP_ENV_HIGHLIGHT_NOT_FOUND
|
||||||
|
|
||||||
|
return Decoration.mark({
|
||||||
|
class: `${HOPP_ENV_HIGHLIGHT} ${className}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMatchDecorator = (aggregateEnvs: AggregateEnvironment[]) =>
|
||||||
|
new MatchDecorator({
|
||||||
|
regexp: HOPP_ENVIRONMENT_REGEX,
|
||||||
|
decoration: (m) => checkEnv(m[0], aggregateEnvs),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const environmentHighlightStyle = (
|
||||||
|
aggregateEnvs: AggregateEnvironment[]
|
||||||
|
) => {
|
||||||
|
const decorator = getMatchDecorator(aggregateEnvs)
|
||||||
|
|
||||||
|
return ViewPlugin.define(
|
||||||
|
(view) => ({
|
||||||
|
decorations: decorator.createDeco(view),
|
||||||
|
update(u) {
|
||||||
|
this.decorations = decorator.updateDeco(u, this.decorations)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
decorations: (v) => v.decorations,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HoppEnvironmentPlugin {
|
||||||
|
private compartment = new Compartment()
|
||||||
|
|
||||||
|
private envs: AggregateEnvironment[] = []
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
subscribeToStream: StreamSubscriberFunc,
|
||||||
|
private editorView: Ref<EditorView | undefined>
|
||||||
|
) {
|
||||||
|
this.envs = getAggregateEnvs()
|
||||||
|
|
||||||
|
subscribeToStream(aggregateEnvs$, (envs) => {
|
||||||
|
this.envs = envs
|
||||||
|
|
||||||
|
this.editorView.value?.dispatch({
|
||||||
|
effects: this.compartment.reconfigure([
|
||||||
|
cursorTooltipField(this.envs),
|
||||||
|
environmentHighlightStyle(this.envs),
|
||||||
|
]),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
get extension() {
|
||||||
|
return this.compartment.of([
|
||||||
|
cursorTooltipField(this.envs),
|
||||||
|
environmentHighlightStyle(this.envs),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -100,11 +100,20 @@ export function pluckMultipleFromRef<T, K extends Array<keyof T>>(
|
|||||||
return Object.fromEntries(keys.map((x) => [x, pluckRef(sourceRef, x)])) as any
|
return Object.fromEntries(keys.map((x) => [x, pluckRef(sourceRef, x)])) as any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type StreamSubscriberFunc = <T>(
|
||||||
|
stream: Observable<T>,
|
||||||
|
next?: ((value: T) => void) | undefined,
|
||||||
|
error?: ((e: any) => void) | undefined,
|
||||||
|
complete?: (() => void) | undefined
|
||||||
|
) => void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A composable that provides the ability to run streams
|
* A composable that provides the ability to run streams
|
||||||
* and subscribe to them and respect the component lifecycle.
|
* and subscribe to them and respect the component lifecycle.
|
||||||
*/
|
*/
|
||||||
export function useStreamSubscriber() {
|
export function useStreamSubscriber(): {
|
||||||
|
subscribeToStream: StreamSubscriberFunc
|
||||||
|
} {
|
||||||
const subs: Subscription[] = []
|
const subs: Subscription[] = []
|
||||||
|
|
||||||
const runAndSubscribe = <T>(
|
const runAndSubscribe = <T>(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { cloneDeep } from "lodash"
|
import { cloneDeep } from "lodash"
|
||||||
import isEqual from "lodash/isEqual"
|
import isEqual from "lodash/isEqual"
|
||||||
import { combineLatest } from "rxjs"
|
import { combineLatest, Observable } from "rxjs"
|
||||||
import { distinctUntilChanged, map, pluck } from "rxjs/operators"
|
import { distinctUntilChanged, map, pluck } from "rxjs/operators"
|
||||||
import DispatchingStore, {
|
import DispatchingStore, {
|
||||||
defineDispatchers,
|
defineDispatchers,
|
||||||
@@ -285,17 +285,22 @@ export const currentEnvironment$ = combineLatest([
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export type AggregateEnvironment = {
|
||||||
|
key: string
|
||||||
|
value: string
|
||||||
|
sourceEnv: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stream returning all the environment variables accessible in
|
* Stream returning all the environment variables accessible in
|
||||||
* the current state (Global + The Selected Environment).
|
* the current state (Global + The Selected Environment).
|
||||||
* NOTE: The source environment attribute will be "Global" for Global Env as source.
|
* NOTE: The source environment attribute will be "Global" for Global Env as source.
|
||||||
*/
|
*/
|
||||||
export const aggregateEnvs$ = combineLatest([
|
export const aggregateEnvs$: Observable<AggregateEnvironment[]> = combineLatest(
|
||||||
currentEnvironment$,
|
[currentEnvironment$, globalEnv$]
|
||||||
globalEnv$,
|
).pipe(
|
||||||
]).pipe(
|
|
||||||
map(([selectedEnv, globalVars]) => {
|
map(([selectedEnv, globalVars]) => {
|
||||||
const results: { key: string; value: string; sourceEnv: string }[] = []
|
const results: AggregateEnvironment[] = []
|
||||||
|
|
||||||
selectedEnv.variables.forEach(({ key, value }) =>
|
selectedEnv.variables.forEach(({ key, value }) =>
|
||||||
results.push({ key, value, sourceEnv: selectedEnv.name })
|
results.push({ key, value, sourceEnv: selectedEnv.name })
|
||||||
@@ -309,6 +314,29 @@ export const aggregateEnvs$ = combineLatest([
|
|||||||
distinctUntilChanged(isEqual)
|
distinctUntilChanged(isEqual)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export function getAggregateEnvs() {
|
||||||
|
const currentEnv = getCurrentEnvironment()
|
||||||
|
|
||||||
|
return [
|
||||||
|
...currentEnv.variables.map(
|
||||||
|
(x) =>
|
||||||
|
<AggregateEnvironment>{
|
||||||
|
key: x.key,
|
||||||
|
value: x.value,
|
||||||
|
sourceEnv: currentEnv.name,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
...getGlobalVariables().map(
|
||||||
|
(x) =>
|
||||||
|
<AggregateEnvironment>{
|
||||||
|
key: x.key,
|
||||||
|
value: x.value,
|
||||||
|
sourceEnv: "Global",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
export function getCurrentEnvironment(): Environment {
|
export function getCurrentEnvironment(): Environment {
|
||||||
if (environmentsStore.value.currentEnvironmentIndex === -1) {
|
if (environmentsStore.value.currentEnvironmentIndex === -1) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
"@codemirror/search": "^0.19.4",
|
"@codemirror/search": "^0.19.4",
|
||||||
"@codemirror/state": "^0.19.6",
|
"@codemirror/state": "^0.19.6",
|
||||||
"@codemirror/text": "^0.19.5",
|
"@codemirror/text": "^0.19.5",
|
||||||
|
"@codemirror/tooltip": "^0.19.10",
|
||||||
"@codemirror/view": "^0.19.26",
|
"@codemirror/view": "^0.19.26",
|
||||||
"@hoppscotch/codemirror-lang-graphql": "workspace:^0.1.0",
|
"@hoppscotch/codemirror-lang-graphql": "workspace:^0.1.0",
|
||||||
"@hoppscotch/data": "workspace:^0.1.0",
|
"@hoppscotch/data": "workspace:^0.1.0",
|
||||||
|
|||||||
23
pnpm-lock.yaml
generated
23
pnpm-lock.yaml
generated
@@ -60,6 +60,7 @@ importers:
|
|||||||
'@codemirror/search': ^0.19.4
|
'@codemirror/search': ^0.19.4
|
||||||
'@codemirror/state': ^0.19.6
|
'@codemirror/state': ^0.19.6
|
||||||
'@codemirror/text': ^0.19.5
|
'@codemirror/text': ^0.19.5
|
||||||
|
'@codemirror/tooltip': ^0.19.10
|
||||||
'@codemirror/view': ^0.19.26
|
'@codemirror/view': ^0.19.26
|
||||||
'@graphql-codegen/add': ^3.1.0
|
'@graphql-codegen/add': ^3.1.0
|
||||||
'@graphql-codegen/cli': 2.3.0
|
'@graphql-codegen/cli': 2.3.0
|
||||||
@@ -180,6 +181,7 @@ importers:
|
|||||||
'@codemirror/search': 0.19.4
|
'@codemirror/search': 0.19.4
|
||||||
'@codemirror/state': 0.19.6
|
'@codemirror/state': 0.19.6
|
||||||
'@codemirror/text': 0.19.5
|
'@codemirror/text': 0.19.5
|
||||||
|
'@codemirror/tooltip': 0.19.10
|
||||||
'@codemirror/view': 0.19.26
|
'@codemirror/view': 0.19.26
|
||||||
'@hoppscotch/codemirror-lang-graphql': link:../codemirror-lang-graphql
|
'@hoppscotch/codemirror-lang-graphql': link:../codemirror-lang-graphql
|
||||||
'@hoppscotch/data': link:../hoppscotch-data
|
'@hoppscotch/data': link:../hoppscotch-data
|
||||||
@@ -1746,7 +1748,7 @@ packages:
|
|||||||
'@codemirror/panel': 0.19.0
|
'@codemirror/panel': 0.19.0
|
||||||
'@codemirror/rangeset': 0.19.2
|
'@codemirror/rangeset': 0.19.2
|
||||||
'@codemirror/state': 0.19.6
|
'@codemirror/state': 0.19.6
|
||||||
'@codemirror/tooltip': 0.19.8
|
'@codemirror/tooltip': 0.19.10
|
||||||
'@codemirror/view': 0.19.26
|
'@codemirror/view': 0.19.26
|
||||||
crelt: 1.0.5
|
crelt: 1.0.5
|
||||||
dev: false
|
dev: false
|
||||||
@@ -1815,13 +1817,6 @@ packages:
|
|||||||
'@codemirror/view': 0.19.26
|
'@codemirror/view': 0.19.26
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@codemirror/tooltip/0.19.8:
|
|
||||||
resolution: {integrity: sha512-Xg1H50utH3z1rmyzk5l/dfE0Lko+5pkxzaVlVzAbcqHlDsG9vARDkgRX+fEEpWg/rrvR83GVQhdKwl+wNxjOAg==}
|
|
||||||
dependencies:
|
|
||||||
'@codemirror/state': 0.19.6
|
|
||||||
'@codemirror/view': 0.19.26
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@codemirror/view/0.19.26:
|
/@codemirror/view/0.19.26:
|
||||||
resolution: {integrity: sha512-7QfXtFLDqXY2TfdxPCQ/NvXjINGaqXQ6SAHKQmxZ+jDcTCWmhFcxaAkrDneqcfGmtp72tUPOXG9PiwCbRWgRLw==}
|
resolution: {integrity: sha512-7QfXtFLDqXY2TfdxPCQ/NvXjINGaqXQ6SAHKQmxZ+jDcTCWmhFcxaAkrDneqcfGmtp72tUPOXG9PiwCbRWgRLw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3506,11 +3501,11 @@ packages:
|
|||||||
ufo: 0.7.9
|
ufo: 0.7.9
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@nuxt/kit-edge/3.0.0-27307420.6a25d3e:
|
/@nuxt/kit-edge/3.0.0-27319101.3e82f0f:
|
||||||
resolution: {integrity: sha512-JieTRigkV52VEQy+oqa6OqR/qOuL9ZmoaH9fDHNwHJXN7hLmil4HbRQ9502G7ura7hkHeAhjZTthXdQDKx1Q5Q==}
|
resolution: {integrity: sha512-WASRt4RJp1Zdrm9AbW+diEVss6qv89cCuPbbqnqdmZMQPYepfXfB75dB/GiULeoy5sIokXJLNz7WqSCSL0INjw==}
|
||||||
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0}
|
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-27307420.6a25d3e
|
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-27319101.3e82f0f
|
||||||
consola: 2.15.3
|
consola: 2.15.3
|
||||||
defu: 5.0.0
|
defu: 5.0.0
|
||||||
dotenv: 10.0.0
|
dotenv: 10.0.0
|
||||||
@@ -3531,7 +3526,7 @@ packages:
|
|||||||
/@nuxt/kit/0.8.1-edge:
|
/@nuxt/kit/0.8.1-edge:
|
||||||
resolution: {integrity: sha512-7kU+mYxRy3w9UohFK/rfrPkKXM9A4LWsTqpFN3MH7mxohy98SFBkf87B6nqE6ulXmztInK+MptS0Lr+VQa0E6w==}
|
resolution: {integrity: sha512-7kU+mYxRy3w9UohFK/rfrPkKXM9A4LWsTqpFN3MH7mxohy98SFBkf87B6nqE6ulXmztInK+MptS0Lr+VQa0E6w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nuxt/kit-edge': 3.0.0-27307420.6a25d3e
|
'@nuxt/kit-edge': 3.0.0-27319101.3e82f0f
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@nuxt/loading-screen/2.0.4:
|
/@nuxt/loading-screen/2.0.4:
|
||||||
@@ -3554,8 +3549,8 @@ packages:
|
|||||||
node-fetch: 2.6.6
|
node-fetch: 2.6.6
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@nuxt/schema-edge/3.0.0-27307420.6a25d3e:
|
/@nuxt/schema-edge/3.0.0-27319101.3e82f0f:
|
||||||
resolution: {integrity: sha512-QB6zMvxMQ+H5kwqd/6vZO7UAxGLIMZGV5zEc9rlYIyoilNnMO3opBJWuaUaokDLW7JpA1bGOfakLWWg8e8LGgQ==}
|
resolution: {integrity: sha512-D5ekvoG6KV85Ko40+8j4jUtv8JifgeXoD44gY1b/dOZu++UkwH7COr+zU80UCa3hTaIcKFwQ0yRg7CTl1susTA==}
|
||||||
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0}
|
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
create-require: 1.1.1
|
create-require: 1.1.1
|
||||||
|
|||||||
Reference in New Issue
Block a user