feat: history migration from legacy request object

This commit is contained in:
Andrew Bastin
2021-08-23 11:48:21 +05:30
parent 91df36ccca
commit 97b92ba35b
6 changed files with 156 additions and 42 deletions

View File

@@ -85,7 +85,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api" import { defineComponent, PropType } from "@nuxtjs/composition-api"
import { useReadonlyStream } from "~/helpers/utils/composables" import { useReadonlyStream } from "~/helpers/utils/composables"
import { import {
restHistory$, restHistory$,
@@ -101,7 +101,7 @@ import { setRESTRequest } from "~/newstore/RESTSession"
export default defineComponent({ export default defineComponent({
props: { props: {
page: { type: String, default: null }, page: { type: String as PropType<"rest" | "graphql">, default: null },
}, },
setup(props) { setup(props) {
return { return {

View File

@@ -7,7 +7,7 @@
:title="duration" :title="duration"
@click="$emit('use-entry')" @click="$emit('use-entry')"
> >
{{ entry.method }} {{ entry.request.method }}
</span> </span>
<span <span
class=" class="
@@ -24,7 +24,7 @@
@click="$emit('use-entry')" @click="$emit('use-entry')"
> >
<span class="truncate"> <span class="truncate">
{{ `${entry.endpoint}` }} {{ entry.request.endpoint }}
</span> </span>
</span> </span>
<ButtonSecondary <ButtonSecondary
@@ -48,31 +48,53 @@
</div> </div>
</template> </template>
<script> <script lang="ts">
import {
computed,
defineComponent,
PropType,
useContext,
} from "@nuxtjs/composition-api"
import findStatusGroup from "~/helpers/findStatusGroup" import findStatusGroup from "~/helpers/findStatusGroup"
import { RESTHistoryEntry } from "~/newstore/history"
export default { export default defineComponent({
props: { props: {
entry: { type: Object, default: () => {} }, entry: { type: Object as PropType<RESTHistoryEntry>, default: () => {} },
showMore: Boolean, showMore: Boolean,
}, },
computed: { setup(props) {
duration() { const {
if (this.entry.meta.responseDuration) { app: { i18n },
const responseDuration = this.entry.meta.responseDuration } = useContext()
const $t = i18n.t.bind(i18n)
const duration = computed(() => {
if (props.entry.responseMeta.duration) {
const responseDuration = props.entry.responseMeta.duration
if (!responseDuration) return ""
return responseDuration > 0 return responseDuration > 0
? `${this.$t("request.duration")}: ${responseDuration}ms` ? `${$t("request.duration").toString()}: ${responseDuration}ms`
: this.$t("error.no_duration") : $t("error.no_duration").toString()
} else return this.$t("error.no_duration") } else return $t("error.no_duration").toString()
}, })
entryStatus() {
const foundStatusGroup = findStatusGroup(this.entry.statusCode) const entryStatus = computed(() => {
const foundStatusGroup = findStatusGroup(
props.entry.responseMeta.statusCode
)
return ( return (
foundStatusGroup || { foundStatusGroup || {
className: "", className: "",
} }
) )
}, })
return {
duration,
entryStatus,
}
}, },
} })
</script> </script>

View File

@@ -37,6 +37,7 @@ export type HoppRESTReqBody =
export interface HoppRESTRequest { export interface HoppRESTRequest {
v: string v: string
id?: string // Firebase Firestore ID
name: string name: string
method: string method: string
@@ -85,11 +86,19 @@ export function translateToNewRequest(x: any): HoppRESTRequest {
// Old format // Old format
const endpoint: string = `${x.url}${x.path}` const endpoint: string = `${x.url}${x.path}`
const headers: HoppRESTHeader[] = x.headers const headers: HoppRESTHeader[] = x.headers ?? []
// Remove old keys from params // Remove old keys from params
const params: HoppRESTParam[] = (x.params as any[]).map( const params: HoppRESTParam[] = (x.params ?? []).map(
({ key, value, active }) => ({ ({
key,
value,
active,
}: {
key: string
value: string
active: boolean
}) => ({
key, key,
value, value,
active, active,
@@ -117,6 +126,7 @@ export function translateToNewRequest(x: any): HoppRESTRequest {
body, body,
auth, auth,
v: RESTReqSchemaVersion, v: RESTReqSchemaVersion,
id: x.id, // Pass-through Firebase Firestore ID
} }
return result return result

View File

@@ -2,9 +2,46 @@ import eq from "lodash/eq"
import { pluck } from "rxjs/operators" import { pluck } from "rxjs/operators"
import DispatchingStore, { defineDispatchers } from "./DispatchingStore" import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
import { completedRESTResponse$ } from "./RESTSession" import { completedRESTResponse$ } from "./RESTSession"
import {
HoppRESTRequest,
translateToNewRequest,
} from "~/helpers/types/HoppRESTRequest"
export type RESTHistoryEntry = {
request: HoppRESTRequest
responseMeta: {
duration: number | null
statusCode: number | null
}
star: boolean
id?: string // For when Firebase Firestore is set
}
export function translateToNewRESTHistory(x: any): RESTHistoryEntry {
const request = translateToNewRequest(x)
const star = x.star ?? false
const duration = x.duration ?? null
const statusCode = x.status ?? null
const obj: RESTHistoryEntry = {
request,
star,
responseMeta: {
duration,
statusCode,
},
}
if (x.id) obj.id = x.id
return obj
}
export const defaultRESTHistoryState = { export const defaultRESTHistoryState = {
state: [] as any[], state: [] as RESTHistoryEntry[],
} }
export const defaultGraphqlHistoryState = { export const defaultGraphqlHistoryState = {
@@ -16,21 +53,24 @@ export const HISTORY_LIMIT = 50
type RESTHistoryType = typeof defaultRESTHistoryState type RESTHistoryType = typeof defaultRESTHistoryState
type GraphqlHistoryType = typeof defaultGraphqlHistoryState type GraphqlHistoryType = typeof defaultGraphqlHistoryState
const HistoryDispatcher = defineDispatchers({ const RESTHistoryDispatchers = defineDispatchers({
setEntries( setEntries(_: RESTHistoryType, { entries }: { entries: RESTHistoryEntry[] }) {
_: RESTHistoryType | GraphqlHistoryType,
{ entries }: { entries: any[] }
) {
return { return {
state: entries, state: entries,
} }
}, },
addEntry(currentVal: RESTHistoryType | GraphqlHistoryType, { entry }) { addEntry(
currentVal: RESTHistoryType,
{ entry }: { entry: RESTHistoryEntry }
) {
return { return {
state: [entry, ...currentVal.state].slice(0, HISTORY_LIMIT), state: [entry, ...currentVal.state].slice(0, HISTORY_LIMIT),
} }
}, },
deleteEntry(currentVal: RESTHistoryType | GraphqlHistoryType, { entry }) { deleteEntry(
currentVal: RESTHistoryType,
{ entry }: { entry: RESTHistoryEntry }
) {
return { return {
state: currentVal.state.filter((e) => !eq(e, entry)), state: currentVal.state.filter((e) => !eq(e, entry)),
} }
@@ -40,7 +80,46 @@ const HistoryDispatcher = defineDispatchers({
state: [], state: [],
} }
}, },
toggleStar(currentVal: RESTHistoryType | GraphqlHistoryType, { entry }) { toggleStar(
currentVal: RESTHistoryType,
{ entry }: { entry: RESTHistoryEntry }
) {
return {
state: currentVal.state.map((e) => {
if (eq(e, entry) && e.star !== undefined) {
return {
...e,
star: !e.star,
}
}
return e
}),
}
},
})
const GQLHistoryDispatchers = defineDispatchers({
setEntries(_: GraphqlHistoryType, { entries }: { entries: any[] }) {
return {
state: entries,
}
},
addEntry(currentVal: GraphqlHistoryType, { entry }) {
return {
state: [entry, ...currentVal.state].slice(0, HISTORY_LIMIT),
}
},
deleteEntry(currentVal: GraphqlHistoryType, { entry }) {
return {
state: currentVal.state.filter((e) => !eq(e, entry)),
}
},
clearHistory() {
return {
state: [],
}
},
toggleStar(currentVal: GraphqlHistoryType, { entry }) {
return { return {
state: currentVal.state.map((e) => { state: currentVal.state.map((e) => {
if (eq(e, entry) && e.star !== undefined) { if (eq(e, entry) && e.star !== undefined) {
@@ -57,32 +136,32 @@ const HistoryDispatcher = defineDispatchers({
export const restHistoryStore = new DispatchingStore( export const restHistoryStore = new DispatchingStore(
defaultRESTHistoryState, defaultRESTHistoryState,
HistoryDispatcher RESTHistoryDispatchers
) )
export const graphqlHistoryStore = new DispatchingStore( export const graphqlHistoryStore = new DispatchingStore(
defaultGraphqlHistoryState, defaultGraphqlHistoryState,
HistoryDispatcher GQLHistoryDispatchers
) )
export const restHistory$ = restHistoryStore.subject$.pipe(pluck("state")) export const restHistory$ = restHistoryStore.subject$.pipe(pluck("state"))
export const graphqlHistory$ = graphqlHistoryStore.subject$.pipe(pluck("state")) export const graphqlHistory$ = graphqlHistoryStore.subject$.pipe(pluck("state"))
export function setRESTHistoryEntries(entries: any[]) { export function setRESTHistoryEntries(entries: RESTHistoryEntry[]) {
restHistoryStore.dispatch({ restHistoryStore.dispatch({
dispatcher: "setEntries", dispatcher: "setEntries",
payload: { entries }, payload: { entries },
}) })
} }
export function addRESTHistoryEntry(entry: any) { export function addRESTHistoryEntry(entry: RESTHistoryEntry) {
restHistoryStore.dispatch({ restHistoryStore.dispatch({
dispatcher: "addEntry", dispatcher: "addEntry",
payload: { entry }, payload: { entry },
}) })
} }
export function deleteRESTHistoryEntry(entry: any) { export function deleteRESTHistoryEntry(entry: RESTHistoryEntry) {
restHistoryStore.dispatch({ restHistoryStore.dispatch({
dispatcher: "deleteEntry", dispatcher: "deleteEntry",
payload: { entry }, payload: { entry },
@@ -96,7 +175,7 @@ export function clearRESTHistory() {
}) })
} }
export function toggleRESTHistoryEntryStar(entry: any) { export function toggleRESTHistoryEntryStar(entry: RESTHistoryEntry) {
restHistoryStore.dispatch({ restHistoryStore.dispatch({
dispatcher: "toggleStar", dispatcher: "toggleStar",
payload: { entry }, payload: { entry },
@@ -144,10 +223,11 @@ completedRESTResponse$.subscribe((res) => {
if (res.type === "loading" || res.type === "network_fail") return if (res.type === "loading" || res.type === "network_fail") return
addRESTHistoryEntry({ addRESTHistoryEntry({
...res.req, request: res.req,
type: res.type, responseMeta: {
meta: res.meta, duration: res.meta.responseDuration,
statusCode: res.statusCode, statusCode: res.statusCode,
},
star: false, star: false,
}) })
} }

View File

@@ -16,6 +16,7 @@ import {
graphqlHistoryStore, graphqlHistoryStore,
setRESTHistoryEntries, setRESTHistoryEntries,
setGraphqlHistoryEntries, setGraphqlHistoryEntries,
translateToNewRESTHistory,
} from "./history" } from "./history"
import { import {
restCollectionStore, restCollectionStore,
@@ -109,7 +110,7 @@ function setupSettingsPersistence() {
function setupHistoryPersistence() { function setupHistoryPersistence() {
const restHistoryData = JSON.parse( const restHistoryData = JSON.parse(
window.localStorage.getItem("history") || "[]" window.localStorage.getItem("history") || "[]"
) ).map(translateToNewRESTHistory)
const graphqlHistoryData = JSON.parse( const graphqlHistoryData = JSON.parse(
window.localStorage.getItem("graphqlHistory") || "[]" window.localStorage.getItem("graphqlHistory") || "[]"

1
package-lock.json generated
View File

@@ -5,6 +5,7 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "hoppscotch",
"version": "1.12.0", "version": "1.12.0",
"dependencies": { "dependencies": {
"@apollo/client": "^3.4.8", "@apollo/client": "^3.4.8",