feat: url and params rewrite index.vue

This commit is contained in:
Andrew Bastin
2021-07-11 21:33:11 -04:00
parent 498d0e18b9
commit 54d21c4950
5 changed files with 205 additions and 3 deletions

View File

@@ -0,0 +1,10 @@
export type HoppRESTParam = {
key: string
value: string
active: boolean
}
export interface HoppRESTRequest {
endpoint: string
params: HoppRESTParam[]
}

View File

@@ -0,0 +1,37 @@
import { combineLatest, Observable } from "rxjs"
import { map } from "rxjs/operators"
import { HoppRESTRequest } from "../types/HoppRESTRequest"
import { Environment } from "~/newstore/environments"
interface EffectiveHoppRESTRequest extends HoppRESTRequest {
/**
* The effective final URL.
*
* This contains path, params and environment variables all applied to it
*/
effectiveFinalURL: string
}
/**
* Creates an Observable Stream that emits HoppRESTRequests whenever
* the input streams emit a value
*
* @param request$ The request stream containing request data
* @param environment$ The environment stream containing environment data to apply
*
* @returns Observable Stream for the Effective Request Object
*/
export function getEffectiveRESTRequestStream(
request$: Observable<HoppRESTRequest>,
environment$: Observable<Environment>
): Observable<EffectiveHoppRESTRequest> {
return combineLatest([request$, environment$]).pipe(
map(([request, _env]) => {
// TODO: Change this
return {
...request,
effectiveFinalURL: request.endpoint,
}
})
)
}

View File

@@ -0,0 +1,24 @@
import { combineLatest, Observable } from "rxjs"
import { map } from "rxjs/operators"
/**
* Constructs a stream of a object from a collection of other observables
*
* @param streamObj The object containing key of observables to assemble from
*
* @returns The constructed object observable
*/
export function constructFromStreams<T>(
streamObj: { [key in keyof T]: Observable<T[key]> }
): Observable<T> {
return combineLatest(Object.values<Observable<T[keyof T]>>(streamObj)).pipe(
map((streams) => {
const keys = Object.keys(streamObj) as (keyof T)[]
return keys.reduce(
(acc, s, i) => Object.assign(acc, { [s]: streams[i] }),
{}
) as T
})
)
}

121
newstore/RESTSession.ts Normal file
View File

@@ -0,0 +1,121 @@
import { pluck, distinctUntilChanged } from "rxjs/operators"
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
import { HoppRESTParam, HoppRESTRequest } from "~/helpers/types/HoppRESTRequest"
function getParamsInURL(url: string): { key: string; value: string }[] {
const result: { key: string; value: string }[] = []
try {
const uriObj = new URL(url)
uriObj.searchParams.forEach((value, key) => {
result.push({ key, value })
})
} catch (_e) {}
return result
}
function recalculateParams(
oldURL: string,
currentParams: HoppRESTParam[],
newParams: { key: string; value: string }[]
): HoppRESTParam[] {
const paramsInOldURL = getParamsInURL(oldURL).map((x) => x.key)
const checkingParams = currentParams.filter(
(x) => !paramsInOldURL.includes(x.key)
)
const result: HoppRESTParam[] = []
const addedKeys: string[] = []
newParams.forEach(({ key, value }) => {
const currentParam = checkingParams.find(
({ key: currentKey }) => currentKey === key
)
if (!currentParam) {
addedKeys.push(key)
result.push({ key, value, active: true })
}
})
result.push(...checkingParams.filter((x) => !addedKeys.includes(x.key)))
return result
}
type RESTSession = {
request: HoppRESTRequest
}
const defaultRESTSession: RESTSession = {
request: {
endpoint: "https://httpbin.org/",
params: [],
},
}
const dispatchers = defineDispatchers({
setEndpoint(curr: RESTSession, { newEndpoint }: { newEndpoint: string }) {
const paramsInNewURL = getParamsInURL(newEndpoint)
const updatedParams = recalculateParams(
curr.request.endpoint,
curr.request.params,
paramsInNewURL
)
return {
request: {
...curr.request,
endpoint: newEndpoint,
params: updatedParams,
},
}
},
addParam(curr: RESTSession, { newParam }: { newParam: HoppRESTParam }) {
return {
request: {
...curr.request,
params: [...curr.request.params, newParam],
},
}
},
})
const restSessionStore = new DispatchingStore(defaultRESTSession, dispatchers)
export function setRESTEndpoint(newEndpoint: string) {
restSessionStore.dispatch({
dispatcher: "setEndpoint",
payload: {
newEndpoint,
},
})
}
export function addRESTParam(newParam: HoppRESTParam) {
restSessionStore.dispatch({
dispatcher: "addParam",
payload: {
newParam,
},
})
}
export const restRequest$ = restSessionStore.subject$.pipe(
pluck("request"),
distinctUntilChanged()
)
export const restEndpoint$ = restSessionStore.subject$.pipe(
pluck("request", "endpoint"),
distinctUntilChanged()
)
export const restParams$ = restSessionStore.subject$.pipe(
pluck("request", "params"),
distinctUntilChanged()
)

View File

@@ -72,7 +72,7 @@
id="url"
name="url"
type="text"
v-model="uri"
v-model="newEndpoint$"
spellcheck="false"
@input="pathInputHandler"
:placeholder="$t('url')"
@@ -254,13 +254,13 @@
:label="
$t('parameters') +
`${
params.length !== 0 ? ' \xA0 • \xA0 ' + params.length : ''
newParams$.length !== 0 ? ' \xA0 • \xA0 ' + newParams$.length : ''
}`
"
:selected="true"
>
<HttpParameters
:params="params"
:params="newParams$"
@clear-content="clearContent"
@remove-request-param="removeRequestParam"
@add-request-param="addRequestParam"
@@ -864,6 +864,7 @@ import { generateCodeWithGenerator } from "~/helpers/codegen/codegen"
import { getSettingSubject, applySetting } from "~/newstore/settings"
import { addRESTHistoryEntry } from "~/newstore/history"
import clone from "lodash/clone"
import { restEndpoint$, restParams$, restRequest$, setRESTEndpoint } from "~/newstore/RESTSession"
export default {
components: { Splitpanes, Pane },
@@ -912,6 +913,9 @@ export default {
"PATCH",
"CUSTOM",
],
newEndpoint$: "",
newParams$: []
}
},
subscriptions() {
@@ -922,9 +926,14 @@ export default {
EXPERIMENTAL_URL_BAR_ENABLED: getSettingSubject(
"EXPERIMENTAL_URL_BAR_ENABLED"
),
newEndpoint$: restEndpoint$,
newParams$: restParams$
}
},
watch: {
newEndpoint$(newVal) {
setRESTEndpoint(newVal)
},
canListParameters: {
immediate: true,
handler(canListParameters) {
@@ -2172,6 +2181,7 @@ export default {
},
},
async mounted() {
restRequest$.subscribe(x => console.log(x))
this._keyListener = function (e) {
if (e.key === "g" && (e.ctrlKey || e.metaKey)) {
e.preventDefault()