Revamp of the Settings State System along with TypeScript support (#1560)
* Add vue-rx, rxjs and lodash as dependencies * Added vue-rx plugin integration to nuxt config * Initial settings store implementation * Add babel plugin for private class properties to for Jest * Add DispatchingStore test spec * Initial settings code * Reactive Streams for fb current user and id token * Fix typo * Migrate index and graphql pages to the new store * Migrate network strategy to the new store * Fixed Section.vue errors * Fix getSettingSubject issue * Migrate fb settings reference in components to the new state system * Add typings for lodash as dev dependency * Load setting * Load initial sync setting values * Update proxy url * Add typescript support * Rewrite Settings store to TypeScript * Port Settings page to TypeScript as reference * Move all store migrations to a separate file * Delete test file for fb.js * Add ts-jest as dev dependency * Remove firebase-mock as dependency * Remove FRAME_COLORS_ENABLED settings value
This commit is contained in:
@@ -5,6 +5,9 @@ function isBabelLoader(caller) {
|
|||||||
module.exports = function (api) {
|
module.exports = function (api) {
|
||||||
if (api.env("test") && !api.caller(isBabelLoader)) {
|
if (api.env("test") && !api.caller(isBabelLoader)) {
|
||||||
return {
|
return {
|
||||||
|
plugins: [
|
||||||
|
"@babel/plugin-proposal-class-properties"
|
||||||
|
],
|
||||||
presets: [
|
presets: [
|
||||||
[
|
[
|
||||||
"@babel/preset-env",
|
"@babel/preset-env",
|
||||||
|
|||||||
@@ -34,14 +34,15 @@ fieldset {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
export default {
|
import Vue from "vue"
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
computed: {
|
computed: {
|
||||||
sectionString() {
|
sectionString(): string {
|
||||||
return `${this.$route.path.replace(/\/+$/, "")}/${this.label}`
|
return `${this.$route.path.replace(/\/+$/, "")}/${this.label}`
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
label: {
|
label: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -58,9 +59,9 @@ export default {
|
|||||||
// Save collapsed section into the collapsedSections array
|
// Save collapsed section into the collapsedSections array
|
||||||
this.$store.commit("setCollapsedSection", this.sectionString)
|
this.$store.commit("setCollapsedSection", this.sectionString)
|
||||||
},
|
},
|
||||||
isCollapsed(label) {
|
isCollapsed(_label: string) {
|
||||||
return this.$store.state.theme.collapsedSections.includes(this.sectionString) || false
|
return this.$store.state.theme.collapsedSections.includes(this.sectionString) || false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -48,16 +49,19 @@ export default {
|
|||||||
name: undefined,
|
name: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncCollections() {
|
syncCollections() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
addNewCollection() {
|
addNewCollection() {
|
||||||
if (!this.$data.name) {
|
if (!this.$data.name) {
|
||||||
|
|||||||
@@ -114,6 +114,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -130,16 +131,19 @@ export default {
|
|||||||
confirmRemove: false,
|
confirmRemove: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncCollections() {
|
syncCollections() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
toggleShowChildren() {
|
toggleShowChildren() {
|
||||||
this.showChildren = !this.showChildren
|
this.showChildren = !this.showChildren
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -50,16 +51,19 @@ export default {
|
|||||||
name: undefined,
|
name: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncCollections() {
|
syncCollections() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
saveCollection() {
|
saveCollection() {
|
||||||
if (!this.$data.name) {
|
if (!this.$data.name) {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -51,16 +52,19 @@ export default {
|
|||||||
name: undefined,
|
name: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncCollections() {
|
syncCollections() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
editFolder() {
|
editFolder() {
|
||||||
this.$store.commit("postwoman/editFolder", {
|
this.$store.commit("postwoman/editFolder", {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -55,16 +56,19 @@ export default {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncCollections() {
|
syncCollections() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
saveRequest() {
|
saveRequest() {
|
||||||
const requestUpdated = {
|
const requestUpdated = {
|
||||||
|
|||||||
@@ -111,6 +111,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "folder",
|
name: "folder",
|
||||||
@@ -129,16 +130,19 @@ export default {
|
|||||||
confirmRemove: false,
|
confirmRemove: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncCollections() {
|
syncCollections() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
toggleShowChildren() {
|
toggleShowChildren() {
|
||||||
this.showChildren = !this.showChildren
|
this.showChildren = !this.showChildren
|
||||||
|
|||||||
@@ -113,6 +113,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -121,6 +122,9 @@ export default {
|
|||||||
showJsonCode: false,
|
showJsonCode: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections")
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
},
|
},
|
||||||
@@ -264,14 +268,12 @@ export default {
|
|||||||
this.fileImported()
|
this.fileImported()
|
||||||
},
|
},
|
||||||
syncToFBCollections() {
|
syncToFBCollections() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
fileImported() {
|
fileImported() {
|
||||||
this.$toast.info(this.$t("file_imported"), {
|
this.$toast.info(this.$t("file_imported"), {
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -84,16 +85,19 @@ export default {
|
|||||||
confirmRemove: false,
|
confirmRemove: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncCollections() {
|
syncCollections() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
selectRequest() {
|
selectRequest() {
|
||||||
this.$store.commit("postwoman/selectRequest", { request: this.request })
|
this.$store.commit("postwoman/selectRequest", { request: this.request })
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -88,6 +89,11 @@ export default {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
}
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
"requestData.collectionIndex": function resetFolderAndRequestIndex() {
|
"requestData.collectionIndex": function resetFolderAndRequestIndex() {
|
||||||
// if user has chosen some folder, than selected other collection, which doesn't have any folders
|
// if user has chosen some folder, than selected other collection, which doesn't have any folders
|
||||||
@@ -144,14 +150,12 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncCollections() {
|
syncCollections() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
saveRequestAs() {
|
saveRequestAs() {
|
||||||
const userDidntSpecifyCollection = this.$data.requestData.collectionIndex === undefined
|
const userDidntSpecifyCollection = this.$data.requestData.collectionIndex === undefined
|
||||||
|
|||||||
@@ -87,6 +87,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -111,6 +112,11 @@ export default {
|
|||||||
filterText: "",
|
filterText: "",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
collections() {
|
collections() {
|
||||||
return fb.currentUser !== null
|
return fb.currentUser !== null
|
||||||
@@ -242,14 +248,12 @@ export default {
|
|||||||
this.$data.editingRequestIndex = undefined
|
this.$data.editingRequestIndex = undefined
|
||||||
},
|
},
|
||||||
syncCollections() {
|
syncCollections() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -48,13 +49,16 @@ export default {
|
|||||||
name: undefined,
|
name: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments")
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncEnvironments() {
|
syncEnvironments() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[1]) {
|
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
|
||||||
if (fb.currentSettings[1].value) {
|
|
||||||
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
addNewEnvironment() {
|
addNewEnvironment() {
|
||||||
if (!this.$data.name) {
|
if (!this.$data.name) {
|
||||||
|
|||||||
@@ -102,6 +102,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -115,6 +116,11 @@ export default {
|
|||||||
doneButton: '<i class="material-icons">done</i>',
|
doneButton: '<i class="material-icons">done</i>',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments")
|
||||||
|
}
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
editingEnvironment(update) {
|
editingEnvironment(update) {
|
||||||
this.name =
|
this.name =
|
||||||
@@ -135,11 +141,9 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncEnvironments() {
|
syncEnvironments() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[1]) {
|
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
|
||||||
if (fb.currentSettings[1].value) {
|
|
||||||
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
clearContent({ target }) {
|
clearContent({ target }) {
|
||||||
this.$store.commit("postwoman/removeVariables", [])
|
this.$store.commit("postwoman/removeVariables", [])
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -49,13 +50,16 @@ export default {
|
|||||||
confirmRemove: false,
|
confirmRemove: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments")
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
syncEnvironments() {
|
syncEnvironments() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[1]) {
|
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
|
||||||
if (fb.currentSettings[1].value) {
|
|
||||||
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
removeEnvironment() {
|
removeEnvironment() {
|
||||||
this.$store.commit("postwoman/removeEnvironment", this.environmentIndex)
|
this.$store.commit("postwoman/removeEnvironment", this.environmentIndex)
|
||||||
|
|||||||
@@ -113,6 +113,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -121,6 +122,11 @@ export default {
|
|||||||
showJsonCode: false,
|
showJsonCode: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments")
|
||||||
|
}
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
},
|
},
|
||||||
@@ -256,11 +262,9 @@ export default {
|
|||||||
this.fileImported()
|
this.fileImported()
|
||||||
},
|
},
|
||||||
syncToFBEnvironments() {
|
syncToFBEnvironments() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[1]) {
|
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
|
||||||
if (fb.currentSettings[1].value) {
|
|
||||||
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
fileImported() {
|
fileImported() {
|
||||||
this.$toast.info(this.$t("file_imported"), {
|
this.$toast.info(this.$t("file_imported"), {
|
||||||
|
|||||||
@@ -66,6 +66,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -82,6 +83,11 @@ export default {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments"),
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
environments() {
|
environments() {
|
||||||
return fb.currentUser !== null
|
return fb.currentUser !== null
|
||||||
@@ -153,11 +159,9 @@ export default {
|
|||||||
this.$data.editingEnvironmentIndex = undefined
|
this.$data.editingEnvironmentIndex = undefined
|
||||||
},
|
},
|
||||||
syncEnvironments() {
|
syncEnvironments() {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[1]) {
|
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
|
||||||
if (fb.currentSettings[1].value) {
|
|
||||||
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
83
helpers/__tests__/network-ExtDisabled.spec.js
Normal file
83
helpers/__tests__/network-ExtDisabled.spec.js
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import { cancelRunningRequest, sendNetworkRequest } from "../network"
|
||||||
|
|
||||||
|
import AxiosStrategy, { cancelRunningAxiosRequest } from "../strategies/AxiosStrategy"
|
||||||
|
import ExtensionStrategy, {
|
||||||
|
cancelRunningExtensionRequest,
|
||||||
|
hasExtensionInstalled,
|
||||||
|
} from "../strategies/ExtensionStrategy"
|
||||||
|
|
||||||
|
jest.mock("../strategies/AxiosStrategy", () => ({
|
||||||
|
__esModule: true,
|
||||||
|
default: jest.fn(() => Promise.resolve()),
|
||||||
|
cancelRunningAxiosRequest: jest.fn(() => Promise.resolve()),
|
||||||
|
}))
|
||||||
|
|
||||||
|
jest.mock("../strategies/ExtensionStrategy", () => ({
|
||||||
|
__esModule: true,
|
||||||
|
default: jest.fn(() => Promise.resolve()),
|
||||||
|
cancelRunningExtensionRequest: jest.fn(() => Promise.resolve()),
|
||||||
|
hasExtensionInstalled: jest.fn(),
|
||||||
|
}))
|
||||||
|
|
||||||
|
jest.mock("~/newstore/settings", () => {
|
||||||
|
return {
|
||||||
|
settingsStore: {
|
||||||
|
value: {
|
||||||
|
EXTENSIONS_ENABLED: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
global.$nuxt = {
|
||||||
|
$loading: {
|
||||||
|
finish: jest.fn(() => Promise.resolve()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks() // Reset the call count for the mock functions
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("cancelRunningRequest", () => {
|
||||||
|
test("cancels only axios request if extension not allowed in settings and extension is installed", () => {
|
||||||
|
hasExtensionInstalled.mockReturnValue(true)
|
||||||
|
|
||||||
|
cancelRunningRequest()
|
||||||
|
|
||||||
|
expect(cancelRunningExtensionRequest).not.toHaveBeenCalled()
|
||||||
|
expect(cancelRunningAxiosRequest).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("cancels only axios request if extension is not allowed and not installed", () => {
|
||||||
|
hasExtensionInstalled.mockReturnValue(false)
|
||||||
|
|
||||||
|
cancelRunningRequest()
|
||||||
|
|
||||||
|
expect(cancelRunningExtensionRequest).not.toHaveBeenCalled()
|
||||||
|
expect(cancelRunningAxiosRequest).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("sendNetworkRequest", () => {
|
||||||
|
|
||||||
|
test("runs only axios request if extension not allowed in settings and extension is installed and clears the progress bar", async () => {
|
||||||
|
hasExtensionInstalled.mockReturnValue(true)
|
||||||
|
|
||||||
|
await sendNetworkRequest({})
|
||||||
|
|
||||||
|
expect(ExtensionStrategy).not.toHaveBeenCalled()
|
||||||
|
expect(AxiosStrategy).toHaveBeenCalled()
|
||||||
|
expect(global.$nuxt.$loading.finish).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("runs only axios request if extension is not allowed and not installed and clears the progress bar", async () => {
|
||||||
|
hasExtensionInstalled.mockReturnValue(false)
|
||||||
|
|
||||||
|
await sendNetworkRequest({})
|
||||||
|
|
||||||
|
expect(ExtensionStrategy).not.toHaveBeenCalled()
|
||||||
|
expect(AxiosStrategy).toHaveBeenCalled()
|
||||||
|
expect(global.$nuxt.$loading.finish).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
82
helpers/__tests__/network-ExtEnabled.spec.js
Normal file
82
helpers/__tests__/network-ExtEnabled.spec.js
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
|
||||||
|
import { cancelRunningRequest, sendNetworkRequest } from "../network"
|
||||||
|
|
||||||
|
import AxiosStrategy, { cancelRunningAxiosRequest } from "../strategies/AxiosStrategy"
|
||||||
|
import ExtensionStrategy, {
|
||||||
|
cancelRunningExtensionRequest,
|
||||||
|
hasExtensionInstalled,
|
||||||
|
} from "../strategies/ExtensionStrategy"
|
||||||
|
|
||||||
|
jest.mock("../strategies/AxiosStrategy", () => ({
|
||||||
|
__esModule: true,
|
||||||
|
default: jest.fn(() => Promise.resolve()),
|
||||||
|
cancelRunningAxiosRequest: jest.fn(() => Promise.resolve()),
|
||||||
|
}))
|
||||||
|
|
||||||
|
jest.mock("../strategies/ExtensionStrategy", () => ({
|
||||||
|
__esModule: true,
|
||||||
|
default: jest.fn(() => Promise.resolve()),
|
||||||
|
cancelRunningExtensionRequest: jest.fn(() => Promise.resolve()),
|
||||||
|
hasExtensionInstalled: jest.fn(),
|
||||||
|
}))
|
||||||
|
|
||||||
|
jest.mock("~/newstore/settings", () => {
|
||||||
|
return {
|
||||||
|
settingsStore: {
|
||||||
|
value: {
|
||||||
|
EXTENSIONS_ENABLED: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
global.$nuxt = {
|
||||||
|
$loading: {
|
||||||
|
finish: jest.fn(() => Promise.resolve()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks() // Reset the call count for the mock functions
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("cancelRunningRequest", () => {
|
||||||
|
test("cancels only extension request if extension allowed in settings and is installed", () => {
|
||||||
|
hasExtensionInstalled.mockReturnValue(true)
|
||||||
|
|
||||||
|
cancelRunningRequest()
|
||||||
|
|
||||||
|
expect(cancelRunningAxiosRequest).not.toHaveBeenCalled()
|
||||||
|
expect(cancelRunningExtensionRequest).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
test("cancels only axios request if extension is allowed but not installed", () => {
|
||||||
|
hasExtensionInstalled.mockReturnValue(false)
|
||||||
|
|
||||||
|
cancelRunningRequest()
|
||||||
|
|
||||||
|
expect(cancelRunningExtensionRequest).not.toHaveBeenCalled()
|
||||||
|
expect(cancelRunningAxiosRequest).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("sendNetworkRequest", () => {
|
||||||
|
test("runs only extension request if extension allowed in settings and is installed and clears the progress bar", async () => {
|
||||||
|
hasExtensionInstalled.mockReturnValue(true)
|
||||||
|
|
||||||
|
await sendNetworkRequest({})
|
||||||
|
|
||||||
|
expect(AxiosStrategy).not.toHaveBeenCalled()
|
||||||
|
expect(ExtensionStrategy).toHaveBeenCalled()
|
||||||
|
expect(global.$nuxt.$loading.finish).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("runs only axios request if extension is allowed but not installed and clears the progress bar", async () => {
|
||||||
|
hasExtensionInstalled.mockReturnValue(false)
|
||||||
|
|
||||||
|
await sendNetworkRequest({})
|
||||||
|
|
||||||
|
expect(ExtensionStrategy).not.toHaveBeenCalled()
|
||||||
|
expect(AxiosStrategy).toHaveBeenCalled()
|
||||||
|
expect(global.$nuxt.$loading.finish).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
import { cancelRunningRequest, sendNetworkRequest } from "../network"
|
|
||||||
|
|
||||||
import AxiosStrategy, { cancelRunningAxiosRequest } from "../strategies/AxiosStrategy"
|
|
||||||
import ExtensionStrategy, {
|
|
||||||
cancelRunningExtensionRequest,
|
|
||||||
hasExtensionInstalled,
|
|
||||||
} from "../strategies/ExtensionStrategy"
|
|
||||||
|
|
||||||
jest.mock("../strategies/AxiosStrategy", () => ({
|
|
||||||
__esModule: true,
|
|
||||||
default: jest.fn(() => Promise.resolve()),
|
|
||||||
cancelRunningAxiosRequest: jest.fn(() => Promise.resolve()),
|
|
||||||
}))
|
|
||||||
|
|
||||||
jest.mock("../strategies/ExtensionStrategy", () => ({
|
|
||||||
__esModule: true,
|
|
||||||
default: jest.fn(() => Promise.resolve()),
|
|
||||||
cancelRunningExtensionRequest: jest.fn(() => Promise.resolve()),
|
|
||||||
hasExtensionInstalled: jest.fn(),
|
|
||||||
}))
|
|
||||||
|
|
||||||
const extensionAllowedStore = {
|
|
||||||
state: {
|
|
||||||
postwoman: {
|
|
||||||
settings: {
|
|
||||||
EXTENSIONS_ENABLED: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const extensionNotAllowedStore = {
|
|
||||||
state: {
|
|
||||||
postwoman: {
|
|
||||||
settings: {
|
|
||||||
EXTENSIONS_ENABLED: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const extensionUndefinedStore = {
|
|
||||||
state: {
|
|
||||||
postwoman: {
|
|
||||||
settings: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
global.$nuxt = {
|
|
||||||
$loading: {
|
|
||||||
finish: jest.fn(() => Promise.resolve()),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.clearAllMocks() // Reset the call count for the mock functions
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("cancelRunningRequest", () => {
|
|
||||||
test("cancels only extension request if extension allowed in settings and is installed", () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(true)
|
|
||||||
|
|
||||||
cancelRunningRequest(extensionAllowedStore)
|
|
||||||
|
|
||||||
expect(cancelRunningAxiosRequest).not.toHaveBeenCalled()
|
|
||||||
expect(cancelRunningExtensionRequest).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("cancels only extension request if extension setting is undefined and extension is installed", () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(true)
|
|
||||||
|
|
||||||
cancelRunningRequest(extensionUndefinedStore)
|
|
||||||
|
|
||||||
expect(cancelRunningAxiosRequest).not.toHaveBeenCalled()
|
|
||||||
expect(cancelRunningExtensionRequest).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("cancels only axios request if extension not allowed in settings and extension is installed", () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(true)
|
|
||||||
|
|
||||||
cancelRunningRequest(extensionNotAllowedStore)
|
|
||||||
|
|
||||||
expect(cancelRunningExtensionRequest).not.toHaveBeenCalled()
|
|
||||||
expect(cancelRunningAxiosRequest).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("cancels only axios request if extension is allowed but not installed", () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(false)
|
|
||||||
|
|
||||||
cancelRunningRequest(extensionAllowedStore)
|
|
||||||
|
|
||||||
expect(cancelRunningExtensionRequest).not.toHaveBeenCalled()
|
|
||||||
expect(cancelRunningAxiosRequest).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("cancels only axios request if extension is not allowed and not installed", () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(false)
|
|
||||||
|
|
||||||
cancelRunningRequest(extensionNotAllowedStore)
|
|
||||||
|
|
||||||
expect(cancelRunningExtensionRequest).not.toHaveBeenCalled()
|
|
||||||
expect(cancelRunningAxiosRequest).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("cancels only axios request if extension setting is undefined and not installed", () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(false)
|
|
||||||
|
|
||||||
cancelRunningRequest(extensionUndefinedStore)
|
|
||||||
|
|
||||||
expect(cancelRunningExtensionRequest).not.toHaveBeenCalled()
|
|
||||||
expect(cancelRunningAxiosRequest).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("sendNetworkRequest", () => {
|
|
||||||
test("runs only extension request if extension allowed in settings and is installed and clears the progress bar", async () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(true)
|
|
||||||
|
|
||||||
await sendNetworkRequest({}, extensionAllowedStore)
|
|
||||||
|
|
||||||
expect(AxiosStrategy).not.toHaveBeenCalled()
|
|
||||||
expect(ExtensionStrategy).toHaveBeenCalled()
|
|
||||||
expect(global.$nuxt.$loading.finish).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("runs only extension request if extension setting is undefined and extension is installed and clears the progress bar", async () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(true)
|
|
||||||
|
|
||||||
await sendNetworkRequest({}, extensionUndefinedStore)
|
|
||||||
|
|
||||||
expect(AxiosStrategy).not.toHaveBeenCalled()
|
|
||||||
expect(ExtensionStrategy).toHaveBeenCalled()
|
|
||||||
expect(global.$nuxt.$loading.finish).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("runs only axios request if extension not allowed in settings and extension is installed and clears the progress bar", async () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(true)
|
|
||||||
|
|
||||||
await sendNetworkRequest({}, extensionNotAllowedStore)
|
|
||||||
|
|
||||||
expect(ExtensionStrategy).not.toHaveBeenCalled()
|
|
||||||
expect(AxiosStrategy).toHaveBeenCalled()
|
|
||||||
expect(global.$nuxt.$loading.finish).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("runs only axios request if extension is allowed but not installed and clears the progress bar", async () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(false)
|
|
||||||
|
|
||||||
await sendNetworkRequest({}, extensionAllowedStore)
|
|
||||||
|
|
||||||
expect(ExtensionStrategy).not.toHaveBeenCalled()
|
|
||||||
expect(AxiosStrategy).toHaveBeenCalled()
|
|
||||||
expect(global.$nuxt.$loading.finish).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("runs only axios request if extension is not allowed and not installed and clears the progress bar", async () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(false)
|
|
||||||
|
|
||||||
await sendNetworkRequest({}, extensionNotAllowedStore)
|
|
||||||
|
|
||||||
expect(ExtensionStrategy).not.toHaveBeenCalled()
|
|
||||||
expect(AxiosStrategy).toHaveBeenCalled()
|
|
||||||
expect(global.$nuxt.$loading.finish).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("runs only axios request if extension setting is undefined and not installed and clears the progress bar", async () => {
|
|
||||||
hasExtensionInstalled.mockReturnValue(false)
|
|
||||||
|
|
||||||
await sendNetworkRequest({}, extensionUndefinedStore)
|
|
||||||
|
|
||||||
expect(ExtensionStrategy).not.toHaveBeenCalled()
|
|
||||||
expect(AxiosStrategy).toHaveBeenCalled()
|
|
||||||
expect(global.$nuxt.$loading.finish).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import firebase from "firebase/app"
|
import firebase from "firebase/app"
|
||||||
import "firebase/firestore"
|
import "firebase/firestore"
|
||||||
import "firebase/auth"
|
import "firebase/auth"
|
||||||
|
import { ReplaySubject } from "rxjs"
|
||||||
|
import { getSettingSubject, applySetting } from "~/newstore/settings"
|
||||||
|
|
||||||
// Initialize Firebase, copied from cloud console
|
// Initialize Firebase, copied from cloud console
|
||||||
const firebaseConfig = {
|
const firebaseConfig = {
|
||||||
@@ -38,6 +40,41 @@ export class FirebaseInstance {
|
|||||||
this.currentGraphqlCollections = []
|
this.currentGraphqlCollections = []
|
||||||
this.currentEnvironments = []
|
this.currentEnvironments = []
|
||||||
|
|
||||||
|
this.currentUser$ = new ReplaySubject(1)
|
||||||
|
this.idToken$ = new ReplaySubject(1)
|
||||||
|
|
||||||
|
let loadedSettings = false
|
||||||
|
|
||||||
|
getSettingSubject("syncCollections").subscribe((status) => {
|
||||||
|
if (this.currentUser && loadedSettings) {
|
||||||
|
this.writeSettings("syncCollections", status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
getSettingSubject("syncHistory").subscribe((status) => {
|
||||||
|
if (this.currentUser && loadedSettings) {
|
||||||
|
this.writeSettings("syncHistory", status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
getSettingSubject("syncEnvironments").subscribe((status) => {
|
||||||
|
if (this.currentUser && loadedSettings) {
|
||||||
|
this.writeSettings("syncEnvironments", status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.app.auth().onIdTokenChanged((user) => {
|
||||||
|
if (user) {
|
||||||
|
user.getIdToken().then((token) => {
|
||||||
|
this.idToken = token
|
||||||
|
this.idToken$.next(token)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.idToken = null
|
||||||
|
this.idToken$.next(null)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
this.app.auth().onAuthStateChanged((user) => {
|
this.app.auth().onAuthStateChanged((user) => {
|
||||||
if (user) {
|
if (user) {
|
||||||
this.currentUser = user
|
this.currentUser = user
|
||||||
@@ -87,6 +124,14 @@ export class FirebaseInstance {
|
|||||||
settings.push(setting)
|
settings.push(setting)
|
||||||
})
|
})
|
||||||
this.currentSettings = settings
|
this.currentSettings = settings
|
||||||
|
|
||||||
|
settings.forEach((e) => {
|
||||||
|
if (e && e.name && e.value != null) {
|
||||||
|
applySetting(e.name, e.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
loadedSettings = true
|
||||||
})
|
})
|
||||||
|
|
||||||
this.usersCollection
|
this.usersCollection
|
||||||
|
|||||||
17
helpers/migrations.ts
Normal file
17
helpers/migrations.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { settingsStore, applySetting } from "~/newstore/settings"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains all the migrations we have to perform overtime in various (persisted)
|
||||||
|
* state/store entries
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function performMigrations(): void {
|
||||||
|
|
||||||
|
// Migrate old default proxy URL to the new proxy URL (if not set / overridden)
|
||||||
|
if (
|
||||||
|
settingsStore.value.PROXY_URL === "https://hoppscotch.apollosoftware.xyz/"
|
||||||
|
) {
|
||||||
|
applySetting("PROXY_URL", "https://proxy.hoppscotch.io/")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,26 +3,25 @@ import ExtensionStrategy, {
|
|||||||
cancelRunningExtensionRequest,
|
cancelRunningExtensionRequest,
|
||||||
hasExtensionInstalled,
|
hasExtensionInstalled,
|
||||||
} from "./strategies/ExtensionStrategy"
|
} from "./strategies/ExtensionStrategy"
|
||||||
|
import { settingsStore } from "~/newstore/settings"
|
||||||
|
|
||||||
export const cancelRunningRequest = (store) => {
|
export const cancelRunningRequest = () => {
|
||||||
if (isExtensionsAllowed(store) && hasExtensionInstalled()) {
|
if (isExtensionsAllowed() && hasExtensionInstalled()) {
|
||||||
cancelRunningExtensionRequest()
|
cancelRunningExtensionRequest()
|
||||||
} else {
|
} else {
|
||||||
cancelRunningAxiosRequest()
|
cancelRunningAxiosRequest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isExtensionsAllowed = ({ state }) =>
|
const isExtensionsAllowed = () => settingsStore.value.EXTENSIONS_ENABLED
|
||||||
typeof state.postwoman.settings.EXTENSIONS_ENABLED === "undefined" ||
|
|
||||||
state.postwoman.settings.EXTENSIONS_ENABLED
|
|
||||||
|
|
||||||
const runAppropriateStrategy = (req, store) => {
|
const runAppropriateStrategy = (req) => {
|
||||||
if (isExtensionsAllowed(store) && hasExtensionInstalled()) {
|
if (isExtensionsAllowed() && hasExtensionInstalled()) {
|
||||||
return ExtensionStrategy(req, store)
|
return ExtensionStrategy(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
return AxiosStrategy(req, store)
|
return AxiosStrategy(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sendNetworkRequest = (req, store) =>
|
export const sendNetworkRequest = (req) =>
|
||||||
runAppropriateStrategy(req, store).finally(() => window.$nuxt.$loading.finish())
|
runAppropriateStrategy(req).finally(() => window.$nuxt.$loading.finish())
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
import { decodeB64StringToArrayBuffer } from "../utils/b64"
|
import { decodeB64StringToArrayBuffer } from "../utils/b64"
|
||||||
|
import { settingsStore } from "~/newstore/settings"
|
||||||
|
|
||||||
let cancelSource = axios.CancelToken.source()
|
let cancelSource = axios.CancelToken.source()
|
||||||
|
|
||||||
@@ -10,10 +11,10 @@ export const cancelRunningAxiosRequest = () => {
|
|||||||
cancelSource = axios.CancelToken.source()
|
cancelSource = axios.CancelToken.source()
|
||||||
}
|
}
|
||||||
|
|
||||||
const axiosWithProxy = async (req, { state }) => {
|
const axiosWithProxy = async (req) => {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.post(
|
const { data } = await axios.post(
|
||||||
state.postwoman.settings.PROXY_URL || "https://proxy.hoppscotch.io",
|
settingsStore.value.PROXY_URL || "https://proxy.hoppscotch.io",
|
||||||
{
|
{
|
||||||
...req,
|
...req,
|
||||||
wantsBinary: true,
|
wantsBinary: true,
|
||||||
@@ -60,11 +61,11 @@ const axiosWithoutProxy = async (req, _store) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const axiosStrategy = (req, store) => {
|
const axiosStrategy = (req) => {
|
||||||
if (store.state.postwoman.settings.PROXY_ENABLED) {
|
if (settingsStore.value.PROXY_ENABLED) {
|
||||||
return axiosWithProxy(req, store)
|
return axiosWithProxy(req)
|
||||||
}
|
}
|
||||||
return axiosWithoutProxy(req, store)
|
return axiosWithoutProxy(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const testables = {
|
export const testables = {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { decodeB64StringToArrayBuffer } from "../utils/b64"
|
import { decodeB64StringToArrayBuffer } from "../utils/b64"
|
||||||
|
import { settingsStore } from "~/newstore/settings"
|
||||||
|
|
||||||
export const hasExtensionInstalled = () =>
|
export const hasExtensionInstalled = () =>
|
||||||
typeof window.__POSTWOMAN_EXTENSION_HOOK__ !== "undefined"
|
typeof window.__POSTWOMAN_EXTENSION_HOOK__ !== "undefined"
|
||||||
@@ -15,12 +16,12 @@ export const cancelRunningExtensionRequest = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const extensionWithProxy = async (req, { state }) => {
|
const extensionWithProxy = async (req) => {
|
||||||
const backupTimeDataStart = new Date().getTime()
|
const backupTimeDataStart = new Date().getTime()
|
||||||
|
|
||||||
const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
|
const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
|
||||||
method: "post",
|
method: "post",
|
||||||
url: state.postwoman.settings.PROXY_URL || "https://proxy.hoppscotch.io",
|
url: settingsStore.value.PROXY_URL || "https://proxy.hoppscotch.io/",
|
||||||
data: {
|
data: {
|
||||||
...req,
|
...req,
|
||||||
wantsBinary: true,
|
wantsBinary: true,
|
||||||
@@ -53,7 +54,7 @@ const extensionWithProxy = async (req, { state }) => {
|
|||||||
return parsedData
|
return parsedData
|
||||||
}
|
}
|
||||||
|
|
||||||
const extensionWithoutProxy = async (req, _store) => {
|
const extensionWithoutProxy = async (req) => {
|
||||||
const backupTimeDataStart = new Date().getTime()
|
const backupTimeDataStart = new Date().getTime()
|
||||||
|
|
||||||
const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
|
const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
|
||||||
@@ -74,11 +75,11 @@ const extensionWithoutProxy = async (req, _store) => {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
const extensionStrategy = (req, store) => {
|
const extensionStrategy = (req) => {
|
||||||
if (store.state.postwoman.settings.PROXY_ENABLED) {
|
if (settingsStore.value.PROXY_ENABLED) {
|
||||||
return extensionWithProxy(req, store)
|
return extensionWithProxy(req)
|
||||||
}
|
}
|
||||||
return extensionWithoutProxy(req, store)
|
return extensionWithoutProxy(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default extensionStrategy
|
export default extensionStrategy
|
||||||
|
|||||||
@@ -2,24 +2,25 @@ import axios from "axios"
|
|||||||
import axiosStrategy from "../AxiosStrategy"
|
import axiosStrategy from "../AxiosStrategy"
|
||||||
|
|
||||||
jest.mock("axios")
|
jest.mock("axios")
|
||||||
|
jest.mock("~/newstore/settings", () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
settingsStore: {
|
||||||
|
value: {
|
||||||
|
PROXY_ENABLED: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
axios.CancelToken.source.mockReturnValue({ token: "test" })
|
axios.CancelToken.source.mockReturnValue({ token: "test" })
|
||||||
axios.mockResolvedValue({})
|
axios.mockResolvedValue({})
|
||||||
|
|
||||||
describe("axiosStrategy", () => {
|
describe("axiosStrategy", () => {
|
||||||
describe("No-Proxy Requests", () => {
|
describe("No-Proxy Requests", () => {
|
||||||
const store = {
|
|
||||||
state: {
|
|
||||||
postwoman: {
|
|
||||||
settings: {
|
|
||||||
PROXY_ENABLED: false,
|
|
||||||
PROXY_URL: "test",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
test("sends request to the actual sender if proxy disabled", async () => {
|
test("sends request to the actual sender if proxy disabled", async () => {
|
||||||
await axiosStrategy({ url: "test" }, store)
|
await axiosStrategy({ url: "test" })
|
||||||
|
|
||||||
expect(axios).toBeCalledWith(
|
expect(axios).toBeCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -29,7 +30,7 @@ describe("axiosStrategy", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("asks axios to return data as arraybuffer", async () => {
|
test("asks axios to return data as arraybuffer", async () => {
|
||||||
await axiosStrategy({ url: "test" }, store)
|
await axiosStrategy({ url: "test" })
|
||||||
|
|
||||||
expect(axios).toBeCalledWith(
|
expect(axios).toBeCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -39,21 +40,21 @@ describe("axiosStrategy", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("resolves successful requests", async () => {
|
test("resolves successful requests", async () => {
|
||||||
await expect(axiosStrategy({}, store)).resolves.toBeDefined()
|
await expect(axiosStrategy({})).resolves.toBeDefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("rejects cancel errors with text 'cancellation'", async () => {
|
test("rejects cancel errors with text 'cancellation'", async () => {
|
||||||
axios.isCancel.mockReturnValueOnce(true)
|
axios.isCancel.mockReturnValueOnce(true)
|
||||||
axios.mockRejectedValue("err")
|
axios.mockRejectedValue("err")
|
||||||
|
|
||||||
expect(axiosStrategy({}, store)).rejects.toBe("cancellation")
|
expect(axiosStrategy({})).rejects.toBe("cancellation")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("rejects non-cancellation errors as-is", async () => {
|
test("rejects non-cancellation errors as-is", async () => {
|
||||||
axios.isCancel.mockReturnValueOnce(false)
|
axios.isCancel.mockReturnValueOnce(false)
|
||||||
axios.mockRejectedValue("err")
|
axios.mockRejectedValue("err")
|
||||||
|
|
||||||
expect(axiosStrategy({}, store)).rejects.toBe("err")
|
expect(axiosStrategy({})).rejects.toBe("err")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,17 @@ jest.mock("../../utils/b64", () => ({
|
|||||||
__esModule: true,
|
__esModule: true,
|
||||||
decodeB64StringToArrayBuffer: jest.fn((data) => `${data}-converted`),
|
decodeB64StringToArrayBuffer: jest.fn((data) => `${data}-converted`),
|
||||||
}))
|
}))
|
||||||
|
jest.mock("~/newstore/settings", () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
settingsStore: {
|
||||||
|
value: {
|
||||||
|
PROXY_ENABLED: true,
|
||||||
|
PROXY_URL: "test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
describe("cancelRunningAxiosRequest", () => {
|
describe("cancelRunningAxiosRequest", () => {
|
||||||
test("cancels axios request and does that only 1 time", () => {
|
test("cancels axios request and does that only 1 time", () => {
|
||||||
@@ -17,16 +28,6 @@ describe("cancelRunningAxiosRequest", () => {
|
|||||||
|
|
||||||
describe("axiosStrategy", () => {
|
describe("axiosStrategy", () => {
|
||||||
describe("Proxy Requests", () => {
|
describe("Proxy Requests", () => {
|
||||||
const store = {
|
|
||||||
state: {
|
|
||||||
postwoman: {
|
|
||||||
settings: {
|
|
||||||
PROXY_ENABLED: true,
|
|
||||||
PROXY_URL: "test",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
test("sends POST request to proxy if proxy is enabled", async () => {
|
test("sends POST request to proxy if proxy is enabled", async () => {
|
||||||
let passedURL
|
let passedURL
|
||||||
@@ -36,7 +37,7 @@ describe("axiosStrategy", () => {
|
|||||||
return Promise.resolve({ data: { success: true, isBinary: false } })
|
return Promise.resolve({ data: { success: true, isBinary: false } })
|
||||||
})
|
})
|
||||||
|
|
||||||
await axiosStrategy({}, store)
|
await axiosStrategy({})
|
||||||
|
|
||||||
expect(passedURL).toEqual("test")
|
expect(passedURL).toEqual("test")
|
||||||
})
|
})
|
||||||
@@ -55,7 +56,7 @@ describe("axiosStrategy", () => {
|
|||||||
return Promise.resolve({ data: { success: true, isBinary: false } })
|
return Promise.resolve({ data: { success: true, isBinary: false } })
|
||||||
})
|
})
|
||||||
|
|
||||||
await axiosStrategy(reqFields, store)
|
await axiosStrategy(reqFields)
|
||||||
|
|
||||||
expect(passedFields).toMatchObject(reqFields)
|
expect(passedFields).toMatchObject(reqFields)
|
||||||
})
|
})
|
||||||
@@ -68,7 +69,7 @@ describe("axiosStrategy", () => {
|
|||||||
return Promise.resolve({ data: { success: true, isBinary: false } })
|
return Promise.resolve({ data: { success: true, isBinary: false } })
|
||||||
})
|
})
|
||||||
|
|
||||||
await axiosStrategy({}, store)
|
await axiosStrategy({})
|
||||||
|
|
||||||
expect(passedFields).toHaveProperty("wantsBinary")
|
expect(passedFields).toHaveProperty("wantsBinary")
|
||||||
})
|
})
|
||||||
@@ -83,7 +84,7 @@ describe("axiosStrategy", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(axiosStrategy({}, store)).rejects.toThrow("test message")
|
await expect(axiosStrategy({})).rejects.toThrow("test message")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("checks for proxy response success field and throws error 'Proxy Error' for non-success", async () => {
|
test("checks for proxy response success field and throws error 'Proxy Error' for non-success", async () => {
|
||||||
@@ -94,7 +95,7 @@ describe("axiosStrategy", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(axiosStrategy({}, store)).rejects.toThrow("Proxy Error")
|
await expect(axiosStrategy({})).rejects.toThrow("Proxy Error")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("checks for proxy response success and doesn't throw for success", async () => {
|
test("checks for proxy response success and doesn't throw for success", async () => {
|
||||||
@@ -105,7 +106,7 @@ describe("axiosStrategy", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(axiosStrategy({}, store)).resolves.toBeDefined()
|
await expect(axiosStrategy({})).resolves.toBeDefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("checks isBinary response field and resolve with the converted value if so", async () => {
|
test("checks isBinary response field and resolve with the converted value if so", async () => {
|
||||||
@@ -117,7 +118,7 @@ describe("axiosStrategy", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(axiosStrategy({}, store)).resolves.toMatchObject({
|
await expect(axiosStrategy({})).resolves.toMatchObject({
|
||||||
data: "testdata-converted",
|
data: "testdata-converted",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -131,7 +132,7 @@ describe("axiosStrategy", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(axiosStrategy({}, store)).resolves.toMatchObject({
|
await expect(axiosStrategy({})).resolves.toMatchObject({
|
||||||
data: "testdata",
|
data: "testdata",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -140,14 +141,14 @@ describe("axiosStrategy", () => {
|
|||||||
jest.spyOn(axios, "post").mockRejectedValue("errr")
|
jest.spyOn(axios, "post").mockRejectedValue("errr")
|
||||||
jest.spyOn(axios, "isCancel").mockReturnValueOnce(true)
|
jest.spyOn(axios, "isCancel").mockReturnValueOnce(true)
|
||||||
|
|
||||||
await expect(axiosStrategy({}, store)).rejects.toBe("cancellation")
|
await expect(axiosStrategy({})).rejects.toBe("cancellation")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("non-cancellation errors are thrown", async () => {
|
test("non-cancellation errors are thrown", async () => {
|
||||||
jest.spyOn(axios, "post").mockRejectedValue("errr")
|
jest.spyOn(axios, "post").mockRejectedValue("errr")
|
||||||
jest.spyOn(axios, "isCancel").mockReturnValueOnce(false)
|
jest.spyOn(axios, "isCancel").mockReturnValueOnce(false)
|
||||||
|
|
||||||
await expect(axiosStrategy({}, store)).rejects.toBe("errr")
|
await expect(axiosStrategy({})).rejects.toBe("errr")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
220
helpers/strategies/__tests__/ExtensionStrategy-NoProxy.spec.js
Normal file
220
helpers/strategies/__tests__/ExtensionStrategy-NoProxy.spec.js
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
|
||||||
|
import extensionStrategy, {
|
||||||
|
hasExtensionInstalled,
|
||||||
|
hasChromeExtensionInstalled,
|
||||||
|
hasFirefoxExtensionInstalled,
|
||||||
|
cancelRunningExtensionRequest,
|
||||||
|
} from "../ExtensionStrategy"
|
||||||
|
|
||||||
|
jest.mock("../../utils/b64", () => ({
|
||||||
|
__esModule: true,
|
||||||
|
decodeB64StringToArrayBuffer: jest.fn((data) => `${data}-converted`),
|
||||||
|
}))
|
||||||
|
|
||||||
|
jest.mock("~/newstore/settings", () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
settingsStore: {
|
||||||
|
value: {
|
||||||
|
EXTENSIONS_ENABLED: true,
|
||||||
|
PROXY_ENABLED: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("hasExtensionInstalled", () => {
|
||||||
|
test("returns true if extension is present and hooked", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {}
|
||||||
|
|
||||||
|
expect(hasExtensionInstalled()).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns false if extension not present or not hooked", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = undefined
|
||||||
|
|
||||||
|
expect(hasExtensionInstalled()).toEqual(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("hasChromeExtensionInstalled", () => {
|
||||||
|
test("returns true if extension is hooked and browser is chrome", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {}
|
||||||
|
jest.spyOn(navigator, "userAgent", "get").mockReturnValue("Chrome")
|
||||||
|
jest.spyOn(navigator, "vendor", "get").mockReturnValue("Google")
|
||||||
|
|
||||||
|
expect(hasChromeExtensionInstalled()).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns false if extension is hooked and browser is not chrome", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {}
|
||||||
|
jest.spyOn(navigator, "userAgent", "get").mockReturnValue("Firefox")
|
||||||
|
jest.spyOn(navigator, "vendor", "get").mockReturnValue("Google")
|
||||||
|
|
||||||
|
expect(hasChromeExtensionInstalled()).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns false if extension not installed and browser is chrome", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = undefined
|
||||||
|
jest.spyOn(navigator, "userAgent", "get").mockReturnValue("Chrome")
|
||||||
|
jest.spyOn(navigator, "vendor", "get").mockReturnValue("Google")
|
||||||
|
|
||||||
|
expect(hasChromeExtensionInstalled()).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns false if extension not installed and browser is not chrome", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = undefined
|
||||||
|
jest.spyOn(navigator, "userAgent", "get").mockReturnValue("Firefox")
|
||||||
|
jest.spyOn(navigator, "vendor", "get").mockReturnValue("Google")
|
||||||
|
|
||||||
|
expect(hasChromeExtensionInstalled()).toEqual(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("hasFirefoxExtensionInstalled", () => {
|
||||||
|
test("returns true if extension is hooked and browser is firefox", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {}
|
||||||
|
jest.spyOn(navigator, "userAgent", "get").mockReturnValue("Firefox")
|
||||||
|
|
||||||
|
expect(hasFirefoxExtensionInstalled()).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns false if extension is hooked and browser is not firefox", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {}
|
||||||
|
jest.spyOn(navigator, "userAgent", "get").mockReturnValue("Chrome")
|
||||||
|
|
||||||
|
expect(hasFirefoxExtensionInstalled()).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns false if extension not installed and browser is firefox", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = undefined
|
||||||
|
jest.spyOn(navigator, "userAgent", "get").mockReturnValue("Firefox")
|
||||||
|
|
||||||
|
expect(hasFirefoxExtensionInstalled()).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns false if extension not installed and browser is not firefox", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = undefined
|
||||||
|
jest.spyOn(navigator, "userAgent", "get").mockReturnValue("Chrome")
|
||||||
|
|
||||||
|
expect(hasFirefoxExtensionInstalled()).toEqual(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("cancelRunningExtensionRequest", () => {
|
||||||
|
const cancelFunc = jest.fn()
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cancelFunc.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("cancels request if extension installed and function present in hook", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
||||||
|
cancelRunningRequest: cancelFunc,
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelRunningExtensionRequest()
|
||||||
|
expect(cancelFunc).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("does not cancel request if extension not installed", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = undefined
|
||||||
|
|
||||||
|
cancelRunningExtensionRequest()
|
||||||
|
expect(cancelFunc).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("does not cancel request if extension installed but function not present", () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {}
|
||||||
|
|
||||||
|
cancelRunningExtensionRequest()
|
||||||
|
expect(cancelFunc).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("extensionStrategy", () => {
|
||||||
|
const sendReqFunc = jest.fn()
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
sendReqFunc.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("Non-Proxy Requests", () => {
|
||||||
|
|
||||||
|
test("ask extension to send request", async () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
||||||
|
sendRequest: sendReqFunc,
|
||||||
|
}
|
||||||
|
|
||||||
|
sendReqFunc.mockResolvedValue({
|
||||||
|
data: '{"success":true,"data":""}',
|
||||||
|
})
|
||||||
|
|
||||||
|
await extensionStrategy({})
|
||||||
|
|
||||||
|
expect(sendReqFunc).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("sends request to the actual sender if proxy disabled", async () => {
|
||||||
|
let passedUrl
|
||||||
|
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
||||||
|
sendRequest: sendReqFunc,
|
||||||
|
}
|
||||||
|
|
||||||
|
sendReqFunc.mockImplementation(({ method, url }) => {
|
||||||
|
passedUrl = url
|
||||||
|
|
||||||
|
return Promise.resolve({
|
||||||
|
data: '{"success":true,"data":""}',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await extensionStrategy({ url: "test" })
|
||||||
|
|
||||||
|
expect(passedUrl).toEqual("test")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("asks extension to get binary data", async () => {
|
||||||
|
let passedFields
|
||||||
|
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
||||||
|
sendRequest: sendReqFunc,
|
||||||
|
}
|
||||||
|
|
||||||
|
sendReqFunc.mockImplementation((fields) => {
|
||||||
|
passedFields = fields
|
||||||
|
|
||||||
|
return Promise.resolve({
|
||||||
|
data: '{"success":true,"data":""}',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await extensionStrategy({})
|
||||||
|
|
||||||
|
expect(passedFields).toHaveProperty("wantsBinary")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("resolves successful requests", async () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
||||||
|
sendRequest: sendReqFunc,
|
||||||
|
}
|
||||||
|
|
||||||
|
sendReqFunc.mockResolvedValue({
|
||||||
|
data: '{"success":true,"data":""}',
|
||||||
|
})
|
||||||
|
|
||||||
|
await expect(extensionStrategy({})).resolves.toBeDefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("rejects errors as-is", async () => {
|
||||||
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
||||||
|
sendRequest: sendReqFunc,
|
||||||
|
}
|
||||||
|
|
||||||
|
sendReqFunc.mockRejectedValue("err")
|
||||||
|
|
||||||
|
await expect(extensionStrategy({})).rejects.toBe("err")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -10,6 +10,19 @@ jest.mock("../../utils/b64", () => ({
|
|||||||
decodeB64StringToArrayBuffer: jest.fn((data) => `${data}-converted`),
|
decodeB64StringToArrayBuffer: jest.fn((data) => `${data}-converted`),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
jest.mock("~/newstore/settings", () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
settingsStore: {
|
||||||
|
value: {
|
||||||
|
EXTENSIONS_ENABLED: true,
|
||||||
|
PROXY_ENABLED: true,
|
||||||
|
PROXY_URL: "test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
describe("hasExtensionInstalled", () => {
|
describe("hasExtensionInstalled", () => {
|
||||||
test("returns true if extension is present and hooked", () => {
|
test("returns true if extension is present and hooked", () => {
|
||||||
global.__POSTWOMAN_EXTENSION_HOOK__ = {}
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {}
|
||||||
@@ -127,16 +140,6 @@ describe("extensionStrategy", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe("Proxy Requests", () => {
|
describe("Proxy Requests", () => {
|
||||||
const store = {
|
|
||||||
state: {
|
|
||||||
postwoman: {
|
|
||||||
settings: {
|
|
||||||
PROXY_ENABLED: true,
|
|
||||||
PROXY_URL: "testURL",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
test("asks extension to send request", async () => {
|
test("asks extension to send request", async () => {
|
||||||
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
||||||
@@ -147,7 +150,7 @@ describe("extensionStrategy", () => {
|
|||||||
data: '{"success":true,"data":""}',
|
data: '{"success":true,"data":""}',
|
||||||
})
|
})
|
||||||
|
|
||||||
await extensionStrategy({}, store)
|
await extensionStrategy({})
|
||||||
|
|
||||||
expect(sendReqFunc).toHaveBeenCalledTimes(1)
|
expect(sendReqFunc).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
@@ -169,9 +172,9 @@ describe("extensionStrategy", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
await extensionStrategy({}, store)
|
await extensionStrategy({})
|
||||||
|
|
||||||
expect(passedUrl).toEqual(store.state.postwoman.settings.PROXY_URL)
|
expect(passedUrl).toEqual("test")
|
||||||
expect(passedMethod).toEqual("post")
|
expect(passedMethod).toEqual("post")
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -196,7 +199,7 @@ describe("extensionStrategy", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
await extensionStrategy(reqFields, store)
|
await extensionStrategy(reqFields)
|
||||||
|
|
||||||
expect(passedFields).toMatchObject(reqFields)
|
expect(passedFields).toMatchObject(reqFields)
|
||||||
})
|
})
|
||||||
@@ -216,7 +219,7 @@ describe("extensionStrategy", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
await extensionStrategy({}, store)
|
await extensionStrategy({})
|
||||||
|
|
||||||
expect(passedFields).toHaveProperty("wantsBinary")
|
expect(passedFields).toHaveProperty("wantsBinary")
|
||||||
})
|
})
|
||||||
@@ -230,7 +233,7 @@ describe("extensionStrategy", () => {
|
|||||||
data: '{"success":false,"data": { "message": "testerr" } }',
|
data: '{"success":false,"data": { "message": "testerr" } }',
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(extensionStrategy({}, store)).rejects.toThrow("testerr")
|
await expect(extensionStrategy({})).rejects.toThrow("testerr")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("checks for proxy response success field and throws error 'Proxy Error' for non-success", async () => {
|
test("checks for proxy response success field and throws error 'Proxy Error' for non-success", async () => {
|
||||||
@@ -242,7 +245,7 @@ describe("extensionStrategy", () => {
|
|||||||
data: '{"success":false,"data": {} }',
|
data: '{"success":false,"data": {} }',
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(extensionStrategy({}, store)).rejects.toThrow("Proxy Error")
|
await expect(extensionStrategy({})).rejects.toThrow("Proxy Error")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("checks for proxy response success and doesn't throw for success", async () => {
|
test("checks for proxy response success and doesn't throw for success", async () => {
|
||||||
@@ -254,7 +257,7 @@ describe("extensionStrategy", () => {
|
|||||||
data: '{"success":true,"data": {} }',
|
data: '{"success":true,"data": {} }',
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(extensionStrategy({}, store)).resolves.toBeDefined()
|
await expect(extensionStrategy({})).resolves.toBeDefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("checks isBinary response field and resolve with the converted value if so", async () => {
|
test("checks isBinary response field and resolve with the converted value if so", async () => {
|
||||||
@@ -266,7 +269,7 @@ describe("extensionStrategy", () => {
|
|||||||
data: '{"success": true, "isBinary": true, "data": "testdata" }',
|
data: '{"success": true, "isBinary": true, "data": "testdata" }',
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(extensionStrategy({}, store)).resolves.toMatchObject({
|
await expect(extensionStrategy({})).resolves.toMatchObject({
|
||||||
data: "testdata-converted",
|
data: "testdata-converted",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -280,7 +283,7 @@ describe("extensionStrategy", () => {
|
|||||||
data: '{"success": true, "isBinary": false, "data": "testdata" }',
|
data: '{"success": true, "isBinary": false, "data": "testdata" }',
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(extensionStrategy({}, store)).resolves.toMatchObject({
|
await expect(extensionStrategy({})).resolves.toMatchObject({
|
||||||
data: "testdata",
|
data: "testdata",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -292,96 +295,7 @@ describe("extensionStrategy", () => {
|
|||||||
|
|
||||||
sendReqFunc.mockRejectedValue("err")
|
sendReqFunc.mockRejectedValue("err")
|
||||||
|
|
||||||
await expect(extensionStrategy({}, store)).rejects.toBe("err")
|
await expect(extensionStrategy({})).rejects.toBe("err")
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("Non-Proxy Requests", () => {
|
|
||||||
const store = {
|
|
||||||
state: {
|
|
||||||
postwoman: {
|
|
||||||
settings: {
|
|
||||||
PROXY_ENABLED: false,
|
|
||||||
PROXY_URL: "testURL",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
test("ask extension to send request", async () => {
|
|
||||||
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
|
||||||
sendRequest: sendReqFunc,
|
|
||||||
}
|
|
||||||
|
|
||||||
sendReqFunc.mockResolvedValue({
|
|
||||||
data: '{"success":true,"data":""}',
|
|
||||||
})
|
|
||||||
|
|
||||||
await extensionStrategy({}, store)
|
|
||||||
|
|
||||||
expect(sendReqFunc).toHaveBeenCalledTimes(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("sends request to the actual sender if proxy disabled", async () => {
|
|
||||||
let passedUrl
|
|
||||||
|
|
||||||
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
|
||||||
sendRequest: sendReqFunc,
|
|
||||||
}
|
|
||||||
|
|
||||||
sendReqFunc.mockImplementation(({ method, url }) => {
|
|
||||||
passedUrl = url
|
|
||||||
|
|
||||||
return Promise.resolve({
|
|
||||||
data: '{"success":true,"data":""}',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
await extensionStrategy({ url: "test" }, store)
|
|
||||||
|
|
||||||
expect(passedUrl).toEqual("test")
|
|
||||||
})
|
|
||||||
|
|
||||||
test("asks extension to get binary data", async () => {
|
|
||||||
let passedFields
|
|
||||||
|
|
||||||
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
|
||||||
sendRequest: sendReqFunc,
|
|
||||||
}
|
|
||||||
|
|
||||||
sendReqFunc.mockImplementation((fields) => {
|
|
||||||
passedFields = fields
|
|
||||||
|
|
||||||
return Promise.resolve({
|
|
||||||
data: '{"success":true,"data":""}',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
await extensionStrategy({}, store)
|
|
||||||
|
|
||||||
expect(passedFields).toHaveProperty("wantsBinary")
|
|
||||||
})
|
|
||||||
|
|
||||||
test("resolves successful requests", async () => {
|
|
||||||
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
|
||||||
sendRequest: sendReqFunc,
|
|
||||||
}
|
|
||||||
|
|
||||||
sendReqFunc.mockResolvedValue({
|
|
||||||
data: '{"success":true,"data":""}',
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(extensionStrategy({}, store)).resolves.toBeDefined()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("rejects errors as-is", async () => {
|
|
||||||
global.__POSTWOMAN_EXTENSION_HOOK__ = {
|
|
||||||
sendRequest: sendReqFunc,
|
|
||||||
}
|
|
||||||
|
|
||||||
sendReqFunc.mockRejectedValue("err")
|
|
||||||
|
|
||||||
await expect(extensionStrategy({}, store)).rejects.toBe("err")
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -14,6 +14,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { setupLocalPersistence } from "~/newstore/localpersistence"
|
||||||
|
import { performMigrations } from "~/helpers/migrations"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
let color = localStorage.getItem("THEME_COLOR") || "green"
|
let color = localStorage.getItem("THEME_COLOR") || "green"
|
||||||
@@ -24,13 +27,7 @@ export default {
|
|||||||
document.body.classList.add("afterLoad")
|
document.body.classList.add("afterLoad")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate old default proxy URL to the new proxy URL (if not set / overridden)
|
performMigrations()
|
||||||
if (
|
|
||||||
this.$store.state.postwoman.settings.PROXY_URL &&
|
|
||||||
this.$store.state.postwoman.settings.PROXY_URL === "https://hoppscotch.apollosoftware.xyz/"
|
|
||||||
) {
|
|
||||||
this.$store.state.postwoman.settings.PROXY_URL = "https://proxy.hoppscotch.io/"
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
"%cWe ❤︎ open source!",
|
"%cWe ❤︎ open source!",
|
||||||
@@ -61,6 +58,8 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupLocalPersistence()
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
document.removeEventListener("keydown", this._keyListener)
|
document.removeEventListener("keydown", this._keyListener)
|
||||||
|
|||||||
56
newstore/DispatchingStore.ts
Normal file
56
newstore/DispatchingStore.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { Subject, BehaviorSubject } from "rxjs"
|
||||||
|
import { map } from "rxjs/operators"
|
||||||
|
import assign from "lodash/assign"
|
||||||
|
import clone from "lodash/clone"
|
||||||
|
|
||||||
|
|
||||||
|
type Dispatch<StoreType, DispatchersType extends Dispatchers<StoreType>, K extends keyof DispatchersType> = {
|
||||||
|
dispatcher: K & string,
|
||||||
|
payload: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Dispatchers<StoreType> = {
|
||||||
|
[ key: string ]: (currentVal: StoreType, payload: any) => Partial<StoreType>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class DispatchingStore<StoreType, DispatchersType extends Dispatchers<StoreType>> {
|
||||||
|
|
||||||
|
#state$: BehaviorSubject<StoreType>
|
||||||
|
#dispatchers: Dispatchers<StoreType>
|
||||||
|
#dispatches$: Subject<Dispatch<StoreType, DispatchersType, keyof DispatchersType>> = new Subject()
|
||||||
|
|
||||||
|
constructor(initialValue: StoreType, dispatchers: DispatchersType) {
|
||||||
|
this.#state$ = new BehaviorSubject(initialValue)
|
||||||
|
this.#dispatchers = dispatchers
|
||||||
|
|
||||||
|
this.#dispatches$
|
||||||
|
.pipe(
|
||||||
|
map(
|
||||||
|
({ dispatcher, payload }) => this.#dispatchers[dispatcher](this.value, payload)
|
||||||
|
)
|
||||||
|
).subscribe(val => {
|
||||||
|
const data = clone(this.value)
|
||||||
|
assign(data, val)
|
||||||
|
|
||||||
|
this.#state$.next(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
get subject$() {
|
||||||
|
return this.#state$
|
||||||
|
}
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.subject$.value
|
||||||
|
}
|
||||||
|
|
||||||
|
get dispatches$() {
|
||||||
|
return this.#dispatches$
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch({ dispatcher, payload }: Dispatch<StoreType, DispatchersType, keyof DispatchersType>) {
|
||||||
|
if (!this.#dispatchers[dispatcher]) throw new Error(`Undefined dispatch type '${dispatcher}'`)
|
||||||
|
|
||||||
|
this.#dispatches$.next({ dispatcher, payload })
|
||||||
|
}
|
||||||
|
}
|
||||||
185
newstore/__tests__/DispatchingStore.spec.js
Normal file
185
newstore/__tests__/DispatchingStore.spec.js
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
import { BehaviorSubject, Subject } from "rxjs"
|
||||||
|
import isEqual from "lodash/isEqual"
|
||||||
|
import DispatchingStore from "~/newstore/DispatchingStore"
|
||||||
|
|
||||||
|
describe("DispatchingStore", () => {
|
||||||
|
|
||||||
|
test("'subject$' property properly returns an BehaviorSubject", () => {
|
||||||
|
const store = new DispatchingStore({}, {})
|
||||||
|
|
||||||
|
expect(store.subject$ instanceof BehaviorSubject).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("'value' property properly returns the current state value", () => {
|
||||||
|
const store = new DispatchingStore({}, {})
|
||||||
|
|
||||||
|
expect(store.value).toEqual({})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("'dispatches$' property properly returns a Subject", () => {
|
||||||
|
const store = new DispatchingStore({}, {})
|
||||||
|
|
||||||
|
expect(store.dispatches$ instanceof Subject).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("dispatch with invalid dispatcher are thrown", () => {
|
||||||
|
const store = new DispatchingStore({}, {})
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
store.dispatch({
|
||||||
|
dispatcher: "non-existent",
|
||||||
|
payload: {}
|
||||||
|
})
|
||||||
|
}).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("valid dispatcher calls run without throwing", () => {
|
||||||
|
const store = new DispatchingStore({}, {
|
||||||
|
testDispatcher(_currentValue, _payload) {
|
||||||
|
// Nothing here
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
store.dispatch({
|
||||||
|
dispatcher: "testDispatcher",
|
||||||
|
payload: {}
|
||||||
|
})
|
||||||
|
}).not.toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("only correct dispatcher method is ran", () => {
|
||||||
|
const dispatchFn = jest.fn().mockReturnValue({})
|
||||||
|
const dontCallDispatchFn = jest.fn().mockReturnValue({})
|
||||||
|
|
||||||
|
const store = new DispatchingStore({}, {
|
||||||
|
testDispatcher: dispatchFn,
|
||||||
|
dontCallDispatcher: dontCallDispatchFn
|
||||||
|
})
|
||||||
|
|
||||||
|
store.dispatch({
|
||||||
|
dispatcher: "testDispatcher",
|
||||||
|
payload: {}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(dispatchFn).toHaveBeenCalledTimes(1)
|
||||||
|
expect(dontCallDispatchFn).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("passes current value and the payload to the dispatcher", () => {
|
||||||
|
const testInitValue = { name: "bob" }
|
||||||
|
const testPayload = { name: "alice" }
|
||||||
|
|
||||||
|
const testDispatchFn = jest.fn().mockReturnValue({})
|
||||||
|
|
||||||
|
const store = new DispatchingStore(testInitValue, {
|
||||||
|
testDispatcher: testDispatchFn
|
||||||
|
})
|
||||||
|
|
||||||
|
store.dispatch({
|
||||||
|
dispatcher: "testDispatcher",
|
||||||
|
payload: testPayload
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(testDispatchFn).toHaveBeenCalledWith(testInitValue, testPayload)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("dispatcher returns are used to update the store correctly", () => {
|
||||||
|
const testInitValue = { name: "bob" }
|
||||||
|
const testDispatchReturnVal = { name: "alice" }
|
||||||
|
|
||||||
|
const testDispatchFn = jest.fn().mockReturnValue(testDispatchReturnVal)
|
||||||
|
|
||||||
|
const store = new DispatchingStore(testInitValue, {
|
||||||
|
testDispatcher: testDispatchFn
|
||||||
|
})
|
||||||
|
|
||||||
|
store.dispatch({
|
||||||
|
dispatcher: "testDispatcher",
|
||||||
|
payload: {} // Payload doesn't matter because the function is mocked
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.value).toEqual(testDispatchReturnVal)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("dispatching patches in new values if not existing on the store", () => {
|
||||||
|
const testInitValue = { name: "bob" }
|
||||||
|
const testDispatchReturnVal = { age: 25 }
|
||||||
|
|
||||||
|
const testDispatchFn = jest.fn().mockReturnValue(testDispatchReturnVal)
|
||||||
|
|
||||||
|
const store = new DispatchingStore(testInitValue, {
|
||||||
|
testDispatcher: testDispatchFn
|
||||||
|
})
|
||||||
|
|
||||||
|
store.dispatch({
|
||||||
|
dispatcher: "testDispatcher",
|
||||||
|
payload: {}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.value).toEqual({
|
||||||
|
name: "bob",
|
||||||
|
age: 25
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("emits the current store value to the new subscribers", done => {
|
||||||
|
const testInitValue = { name: "bob" }
|
||||||
|
|
||||||
|
const testDispatchFn = jest.fn().mockReturnValue({})
|
||||||
|
|
||||||
|
const store = new DispatchingStore(testInitValue, {
|
||||||
|
testDispatcher: testDispatchFn
|
||||||
|
})
|
||||||
|
|
||||||
|
store.subject$.subscribe(value => {
|
||||||
|
if (value === testInitValue) {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("emits the dispatched store value to the subscribers", done => {
|
||||||
|
const testInitValue = { name: "bob" }
|
||||||
|
const testDispatchReturnVal = { age: 25 }
|
||||||
|
|
||||||
|
const testDispatchFn = jest.fn().mockReturnValue(testDispatchReturnVal)
|
||||||
|
|
||||||
|
const store = new DispatchingStore(testInitValue, {
|
||||||
|
testDispatcher: testDispatchFn
|
||||||
|
})
|
||||||
|
|
||||||
|
store.subject$.subscribe(value => {
|
||||||
|
if (isEqual(value, { name: "bob", age: 25 })) {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
store.dispatch({
|
||||||
|
dispatcher: "testDispatcher",
|
||||||
|
payload: {}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("dispatching emits the new dispatch requests to the subscribers", () => {
|
||||||
|
const testInitValue = { name: "bob" }
|
||||||
|
const testPayload = { age: 25 }
|
||||||
|
|
||||||
|
const testDispatchFn = jest.fn().mockReturnValue({})
|
||||||
|
|
||||||
|
const store = new DispatchingStore(testInitValue, {
|
||||||
|
testDispatcher: testDispatchFn
|
||||||
|
})
|
||||||
|
|
||||||
|
store.dispatches$.subscribe(value => {
|
||||||
|
if (isEqual(value, { dispatcher: "testDispatcher", payload: testPayload })) {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
store.dispatch({
|
||||||
|
dispatcher: "testDispatcher",
|
||||||
|
payload: {}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
36
newstore/localpersistence.ts
Normal file
36
newstore/localpersistence.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { settingsStore, bulkApplySettings, defaultSettings } from "./settings"
|
||||||
|
import clone from "lodash/clone"
|
||||||
|
import assign from "lodash/assign"
|
||||||
|
|
||||||
|
function checkAndMigrateOldSettings() {
|
||||||
|
// Don't do migration if the new settings object exists
|
||||||
|
if (window.localStorage.getItem("settings")) return
|
||||||
|
|
||||||
|
const vuexData = JSON.parse(window.localStorage.getItem("vuex") || "{}")
|
||||||
|
if (vuexData === {}) return
|
||||||
|
|
||||||
|
const settingsData = clone(defaultSettings)
|
||||||
|
assign(settingsData, vuexData.postwoman.settings)
|
||||||
|
|
||||||
|
window.localStorage.setItem("settings", JSON.stringify(settingsData))
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupSettingsPersistence() {
|
||||||
|
const settingsData = JSON.parse(window.localStorage.getItem("settings") || "{}")
|
||||||
|
|
||||||
|
if (settingsData) {
|
||||||
|
bulkApplySettings(settingsData)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
settingsStore.subject$
|
||||||
|
.subscribe(settings => {
|
||||||
|
window.localStorage.setItem("settings", JSON.stringify(settings))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setupLocalPersistence() {
|
||||||
|
checkAndMigrateOldSettings()
|
||||||
|
|
||||||
|
setupSettingsPersistence()
|
||||||
|
}
|
||||||
91
newstore/settings.ts
Normal file
91
newstore/settings.ts
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import { pluck, distinctUntilChanged } from "rxjs/operators"
|
||||||
|
import has from "lodash/has"
|
||||||
|
import DispatchingStore from "./DispatchingStore"
|
||||||
|
import type { Dispatchers } from "./DispatchingStore"
|
||||||
|
import { Observable } from "rxjs"
|
||||||
|
import type { KeysMatching } from "~/types/ts-utils"
|
||||||
|
|
||||||
|
|
||||||
|
export const defaultSettings = {
|
||||||
|
syncCollections: true,
|
||||||
|
syncHistory: true,
|
||||||
|
syncEnvironments: true,
|
||||||
|
|
||||||
|
SCROLL_INTO_ENABLED: true,
|
||||||
|
PROXY_ENABLED: false,
|
||||||
|
PROXY_URL: "https://proxy.hoppscotch.io/",
|
||||||
|
PROXY_KEY: "",
|
||||||
|
EXTENSIONS_ENABLED: true,
|
||||||
|
EXPERIMENTAL_URL_BAR_ENABLED: false,
|
||||||
|
URL_EXCLUDES: {
|
||||||
|
auth: true,
|
||||||
|
httpUser: true,
|
||||||
|
httpPassword: true,
|
||||||
|
bearerToken: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SettingsType = typeof defaultSettings
|
||||||
|
|
||||||
|
const validKeys = Object.keys(defaultSettings)
|
||||||
|
|
||||||
|
const dispatchers: Dispatchers<SettingsType> = {
|
||||||
|
bulkApplySettings(_currentState, payload: Partial<SettingsType>) {
|
||||||
|
return payload
|
||||||
|
},
|
||||||
|
toggleSetting(currentState, { settingKey }: { settingKey: KeysMatching<SettingsType, boolean> }) {
|
||||||
|
if (!has(currentState, settingKey)) {
|
||||||
|
console.log(`Toggling of a non-existent setting key '${settingKey}' ignored.`)
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result: Partial<SettingsType> = {}
|
||||||
|
result[settingKey] = !currentState[settingKey]
|
||||||
|
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
applySetting<K extends keyof SettingsType>(_currentState: SettingsType, { settingKey, value }: { settingKey: K, value: SettingsType[K] }) {
|
||||||
|
if (!validKeys.includes(settingKey)) {
|
||||||
|
console.log(`Ignoring non-existent setting key '${settingKey}' assignment`)
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result: Partial<SettingsType> = {}
|
||||||
|
result[settingKey] = value
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const settingsStore = new DispatchingStore(defaultSettings, dispatchers)
|
||||||
|
|
||||||
|
export function getSettingSubject<K extends keyof SettingsType>(settingKey: K): Observable<SettingsType[K]> {
|
||||||
|
return settingsStore.subject$.pipe(pluck(settingKey), distinctUntilChanged())
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bulkApplySettings(settingsObj: Partial<SettingsType>) {
|
||||||
|
settingsStore.dispatch({
|
||||||
|
dispatcher: "bulkApplySettings",
|
||||||
|
payload: settingsObj
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toggleSetting(settingKey: KeysMatching<SettingsType, boolean>) {
|
||||||
|
settingsStore.dispatch({
|
||||||
|
dispatcher: "toggleSetting",
|
||||||
|
payload: {
|
||||||
|
settingKey
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applySetting<K extends keyof SettingsType>(settingKey: K, value: SettingsType[K]) {
|
||||||
|
settingsStore.dispatch({
|
||||||
|
dispatcher: "applySetting",
|
||||||
|
payload: {
|
||||||
|
settingKey,
|
||||||
|
value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -92,6 +92,7 @@ export default {
|
|||||||
plugins: [
|
plugins: [
|
||||||
"~/plugins/vuex-persist",
|
"~/plugins/vuex-persist",
|
||||||
"~/plugins/v-tooltip",
|
"~/plugins/v-tooltip",
|
||||||
|
"~/plugins/vue-rx",
|
||||||
{ src: "~/plugins/web-worker", ssr: false },
|
{ src: "~/plugins/web-worker", ssr: false },
|
||||||
],
|
],
|
||||||
|
|
||||||
@@ -112,6 +113,8 @@ export default {
|
|||||||
"@nuxtjs/color-mode",
|
"@nuxtjs/color-mode",
|
||||||
// https: //github.com/nuxt-community/google-fonts-module
|
// https: //github.com/nuxt-community/google-fonts-module
|
||||||
"@nuxtjs/google-fonts",
|
"@nuxtjs/google-fonts",
|
||||||
|
// https://github.com/nuxt/typescript
|
||||||
|
"@nuxt/typescript-build",
|
||||||
],
|
],
|
||||||
|
|
||||||
// Modules (https://go.nuxtjs.dev/config-modules)
|
// Modules (https://go.nuxtjs.dev/config-modules)
|
||||||
|
|||||||
38473
package-lock.json
generated
38473
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@@ -32,33 +32,39 @@
|
|||||||
"firebase": "^8.3.1",
|
"firebase": "^8.3.1",
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^15.5.0",
|
||||||
"graphql-language-service-interface": "^2.8.2",
|
"graphql-language-service-interface": "^2.8.2",
|
||||||
|
"lodash": "^4.17.20",
|
||||||
"mustache": "^4.1.0",
|
"mustache": "^4.1.0",
|
||||||
"nuxt": "^2.15.3",
|
"nuxt": "^2.15.3",
|
||||||
"nuxt-i18n": "^6.21.1",
|
"nuxt-i18n": "^6.21.1",
|
||||||
"paho-mqtt": "^1.1.0",
|
"paho-mqtt": "^1.1.0",
|
||||||
|
"rxjs": "^6.6.3",
|
||||||
"socket.io-client": "^4.0.0",
|
"socket.io-client": "^4.0.0",
|
||||||
"socketio-wildcard": "^2.0.0",
|
"socketio-wildcard": "^2.0.0",
|
||||||
"tern": "^0.24.3",
|
"tern": "^0.24.3",
|
||||||
"v-tooltip": "^2.1.3",
|
"v-tooltip": "^2.1.3",
|
||||||
|
"vue-rx": "^6.2.0",
|
||||||
"vuejs-auto-complete": "^0.9.0",
|
"vuejs-auto-complete": "^0.9.0",
|
||||||
"vuex-persist": "^3.1.3",
|
"vuex-persist": "^3.1.3",
|
||||||
"yargs-parser": "^20.2.7"
|
"yargs-parser": "^20.2.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.13.10",
|
"@babel/core": "^7.13.10",
|
||||||
|
"@babel/plugin-proposal-class-properties": "^7.12.13",
|
||||||
"@babel/preset-env": "^7.13.10",
|
"@babel/preset-env": "^7.13.10",
|
||||||
|
"@nuxt/types": "^2.15.3",
|
||||||
|
"@nuxt/typescript-build": "^2.1.0",
|
||||||
"@nuxtjs/color-mode": "^2.0.5",
|
"@nuxtjs/color-mode": "^2.0.5",
|
||||||
"@nuxtjs/google-analytics": "^2.4.0",
|
"@nuxtjs/google-analytics": "^2.4.0",
|
||||||
"@nuxtjs/google-fonts": "^1.3.0",
|
"@nuxtjs/google-fonts": "^1.3.0",
|
||||||
"@nuxtjs/pwa": "^3.3.5",
|
"@nuxtjs/pwa": "^3.3.5",
|
||||||
"@nuxtjs/tailwindcss": "^4.0.1",
|
"@nuxtjs/tailwindcss": "^4.0.1",
|
||||||
"@testing-library/jest-dom": "^5.11.9",
|
"@testing-library/jest-dom": "^5.11.9",
|
||||||
|
"@types/lodash": "^4.14.168",
|
||||||
"@vue/test-utils": "^1.1.3",
|
"@vue/test-utils": "^1.1.3",
|
||||||
"babel-core": "^7.0.0-bridge.0",
|
"babel-core": "^7.0.0-bridge.0",
|
||||||
"babel-jest": "^26.6.3",
|
"babel-jest": "^26.6.3",
|
||||||
"eslint": "^7.22.0",
|
"eslint": "^7.22.0",
|
||||||
"eslint-plugin-vue": "^7.7.0",
|
"eslint-plugin-vue": "^7.7.0",
|
||||||
"firebase-mock": "^2.3.2",
|
|
||||||
"husky": "^5.2.0",
|
"husky": "^5.2.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"jest-serializer-vue": "^2.0.2",
|
"jest-serializer-vue": "^2.0.2",
|
||||||
@@ -68,11 +74,13 @@
|
|||||||
"raw-loader": "^4.0.2",
|
"raw-loader": "^4.0.2",
|
||||||
"sass": "^1.32.8",
|
"sass": "^1.32.8",
|
||||||
"sass-loader": "^10.1.1",
|
"sass-loader": "^10.1.1",
|
||||||
|
"ts-jest": "^26.5.4",
|
||||||
"vue-jest": "^3.0.7",
|
"vue-jest": "^3.0.7",
|
||||||
"worker-loader": "^3.0.8"
|
"worker-loader": "^3.0.8"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"moduleFileExtensions": [
|
"moduleFileExtensions": [
|
||||||
|
"ts",
|
||||||
"js",
|
"js",
|
||||||
"json",
|
"json",
|
||||||
"vue"
|
"vue"
|
||||||
@@ -98,6 +106,7 @@
|
|||||||
"<rootDir>/components/**/*.vue",
|
"<rootDir>/components/**/*.vue",
|
||||||
"<rootDir>/pages/*.vue"
|
"<rootDir>/pages/*.vue"
|
||||||
],
|
],
|
||||||
"testURL": "http://localhost/"
|
"testURL": "http://localhost/",
|
||||||
|
"preset": "ts-jest/presets/js-with-babel"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ import * as gql from "graphql"
|
|||||||
import { commonHeaders } from "~/helpers/headers"
|
import { commonHeaders } from "~/helpers/headers"
|
||||||
import { getPlatformSpecialKey } from "~/helpers/platformutils"
|
import { getPlatformSpecialKey } from "~/helpers/platformutils"
|
||||||
import { sendNetworkRequest } from "~/helpers/network"
|
import { sendNetworkRequest } from "~/helpers/network"
|
||||||
import { fb } from "~/helpers/fb"
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -469,13 +469,11 @@ export default {
|
|||||||
activeSidebar: true,
|
activeSidebar: true,
|
||||||
editRequest: {},
|
editRequest: {},
|
||||||
showSaveRequestModal: false,
|
showSaveRequestModal: false,
|
||||||
|
}
|
||||||
settings: {
|
|
||||||
SCROLL_INTO_ENABLED:
|
|
||||||
typeof this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED !== "undefined"
|
|
||||||
? this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED
|
|
||||||
: true,
|
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SCROLL_INTO_ENABLED: getSettingSubject("SCROLL_INTO_ENABLED"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -681,7 +679,7 @@ export default {
|
|||||||
const rootTypeName = this.resolveRootType(type).name
|
const rootTypeName = this.resolveRootType(type).name
|
||||||
|
|
||||||
const target = document.getElementById(`type_${rootTypeName}`)
|
const target = document.getElementById(`type_${rootTypeName}`)
|
||||||
if (target && this.settings.SCROLL_INTO_ENABLED) {
|
if (target && this.SCROLL_INTO_ENABLED) {
|
||||||
this.$refs.gqlTabs.$el
|
this.$refs.gqlTabs.$el
|
||||||
.querySelector(".gqlTabs")
|
.querySelector(".gqlTabs")
|
||||||
.scrollTo({ top: target.offsetTop, behavior: "smooth" })
|
.scrollTo({ top: target.offsetTop, behavior: "smooth" })
|
||||||
@@ -739,7 +737,7 @@ export default {
|
|||||||
this.$nuxt.$loading.start()
|
this.$nuxt.$loading.start()
|
||||||
|
|
||||||
this.response = this.$t("loading")
|
this.response = this.$t("loading")
|
||||||
if (this.settings.SCROLL_INTO_ENABLED) this.scrollInto("response")
|
if (this.SCROLL_INTO_ENABLED) this.scrollInto("response")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let headers = {}
|
let headers = {}
|
||||||
@@ -769,7 +767,7 @@ export default {
|
|||||||
star: false,
|
star: false,
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
}
|
}
|
||||||
const res = await sendNetworkRequest(reqOptions, this.$store)
|
const res = await sendNetworkRequest(reqOptions)
|
||||||
|
|
||||||
// HACK: Temporary trailing null character issue from the extension fix
|
// HACK: Temporary trailing null character issue from the extension fix
|
||||||
const responseText = new TextDecoder("utf-8").decode(res.data).replace(/\0+$/, "")
|
const responseText = new TextDecoder("utf-8").decode(res.data).replace(/\0+$/, "")
|
||||||
@@ -946,7 +944,7 @@ export default {
|
|||||||
this.$nuxt.$loading.start()
|
this.$nuxt.$loading.start()
|
||||||
|
|
||||||
this.schema = this.$t("loading")
|
this.schema = this.$t("loading")
|
||||||
if (this.settings.SCROLL_INTO_ENABLED) this.scrollInto("schema")
|
if (this.SCROLL_INTO_ENABLED) this.scrollInto("schema")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query = JSON.stringify({
|
const query = JSON.stringify({
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
<li>
|
<li>
|
||||||
<label for="url">{{ $t("url") }}</label>
|
<label for="url">{{ $t("url") }}</label>
|
||||||
<input
|
<input
|
||||||
v-if="!this.$store.state.postwoman.settings.EXPERIMENTAL_URL_BAR_ENABLED"
|
v-if="!EXPERIMENTAL_URL_BAR_ENABLED"
|
||||||
:class="{ error: !isValidURL }"
|
:class="{ error: !isValidURL }"
|
||||||
class="border-dashed md:border-l border-brdColor"
|
class="border-dashed md:border-l border-brdColor"
|
||||||
@keyup.enter="isValidURL ? sendRequest() : null"
|
@keyup.enter="isValidURL ? sendRequest() : null"
|
||||||
@@ -280,7 +280,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="row-wrapper">
|
<div class="row-wrapper">
|
||||||
<SmartToggle :on="!urlExcludes.auth" @change="setExclude('auth', !$event)">
|
<SmartToggle :on="!URL_EXCLUDES.auth" @change="setExclude('auth', !$event)">
|
||||||
{{ $t("include_in_url") }}
|
{{ $t("include_in_url") }}
|
||||||
</SmartToggle>
|
</SmartToggle>
|
||||||
</div>
|
</div>
|
||||||
@@ -665,6 +665,8 @@ import { parseUrlAndPath } from "~/helpers/utils/uri"
|
|||||||
import { httpValid } from "~/helpers/utils/valid"
|
import { httpValid } from "~/helpers/utils/valid"
|
||||||
import { knownContentTypes, isJSONContentType } from "~/helpers/utils/contenttypes"
|
import { knownContentTypes, isJSONContentType } from "~/helpers/utils/contenttypes"
|
||||||
import { generateCodeWithGenerator } from "~/helpers/codegen/codegen"
|
import { generateCodeWithGenerator } from "~/helpers/codegen/codegen"
|
||||||
|
import { getSettingSubject, applySetting } from "~/newstore/settings"
|
||||||
|
import clone from "lodash/clone"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -693,7 +695,6 @@ export default {
|
|||||||
showTokenRequestList: false,
|
showTokenRequestList: false,
|
||||||
showSaveRequestModal: false,
|
showSaveRequestModal: false,
|
||||||
editRequest: {},
|
editRequest: {},
|
||||||
urlExcludes: {},
|
|
||||||
activeSidebar: true,
|
activeSidebar: true,
|
||||||
fb,
|
fb,
|
||||||
customMethod: false,
|
customMethod: false,
|
||||||
@@ -701,12 +702,6 @@ export default {
|
|||||||
filenames: "",
|
filenames: "",
|
||||||
navigatorShare: navigator.share,
|
navigatorShare: navigator.share,
|
||||||
runningRequest: false,
|
runningRequest: false,
|
||||||
settings: {
|
|
||||||
SCROLL_INTO_ENABLED:
|
|
||||||
typeof this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED !== "undefined"
|
|
||||||
? this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED
|
|
||||||
: true,
|
|
||||||
},
|
|
||||||
currentMethodIndex: 0,
|
currentMethodIndex: 0,
|
||||||
methodMenuItems: [
|
methodMenuItems: [
|
||||||
"GET",
|
"GET",
|
||||||
@@ -722,16 +717,18 @@ export default {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SCROLL_INTO_ENABLED: getSettingSubject("SCROLL_INTO_ENABLED"),
|
||||||
|
PROXY_ENABLED: getSettingSubject("PROXY_ENABLED"),
|
||||||
|
URL_EXCLUDES: getSettingSubject("URL_EXCLUDES"),
|
||||||
|
EXPERIMENTAL_URL_BAR_ENABLED: getSettingSubject("EXPERIMENTAL_URL_BAR_ENABLED"),
|
||||||
|
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
SYNC_HISTORY: getSettingSubject("syncHistory"),
|
||||||
|
}
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
urlExcludes: {
|
|
||||||
deep: true,
|
|
||||||
handler() {
|
|
||||||
this.$store.commit("postwoman/applySetting", [
|
|
||||||
"URL_EXCLUDES",
|
|
||||||
Object.assign({}, this.urlExcludes),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
},
|
|
||||||
canListParameters: {
|
canListParameters: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler(canListParameters) {
|
handler(canListParameters) {
|
||||||
@@ -1230,7 +1227,7 @@ export default {
|
|||||||
this.requestType = entry.requestType
|
this.requestType = entry.requestType
|
||||||
this.testScript = entry.testScript
|
this.testScript = entry.testScript
|
||||||
this.testsEnabled = entry.usesPostScripts
|
this.testsEnabled = entry.usesPostScripts
|
||||||
if (this.settings.SCROLL_INTO_ENABLED) this.scrollInto("request")
|
if (this.SCROLL_INTO_ENABLED) this.scrollInto("request")
|
||||||
},
|
},
|
||||||
async makeRequest(auth, headers, requestBody, preRequestScript) {
|
async makeRequest(auth, headers, requestBody, preRequestScript) {
|
||||||
const requestOptions = {
|
const requestOptions = {
|
||||||
@@ -1260,14 +1257,14 @@ export default {
|
|||||||
if (typeof requestOptions.data === "string") {
|
if (typeof requestOptions.data === "string") {
|
||||||
requestOptions.data = parseTemplateString(requestOptions.data)
|
requestOptions.data = parseTemplateString(requestOptions.data)
|
||||||
}
|
}
|
||||||
return await sendNetworkRequest(requestOptions, this.$store)
|
return await sendNetworkRequest(requestOptions)
|
||||||
},
|
},
|
||||||
cancelRequest() {
|
cancelRequest() {
|
||||||
cancelRunningRequest(this.$store)
|
cancelRunningRequest()
|
||||||
},
|
},
|
||||||
async sendRequest() {
|
async sendRequest() {
|
||||||
this.$toast.clear()
|
this.$toast.clear()
|
||||||
if (this.settings.SCROLL_INTO_ENABLED) this.scrollInto("response")
|
if (this.SCROLL_INTO_ENABLED) this.scrollInto("response")
|
||||||
if (!this.isValidURL) {
|
if (!this.isValidURL) {
|
||||||
this.$toast.error(this.$t("url_invalid_format"), {
|
this.$toast.error(this.$t("url_invalid_format"), {
|
||||||
icon: "error",
|
icon: "error",
|
||||||
@@ -1396,11 +1393,9 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.$refs.historyComponent.addEntry(entry)
|
this.$refs.historyComponent.addEntry(entry)
|
||||||
if (fb.currentUser !== null && fb.currentSettings[2]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[2].value) {
|
|
||||||
fb.writeHistory(entry)
|
fb.writeHistory(entry)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})()
|
})()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.runningRequest = false
|
this.runningRequest = false
|
||||||
@@ -1456,11 +1451,9 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.$refs.historyComponent.addEntry(entry)
|
this.$refs.historyComponent.addEntry(entry)
|
||||||
if (fb.currentUser !== null && fb.currentSettings[2]) {
|
if (fb.currentUser !== null && this.SYNC_HISTORY) {
|
||||||
if (fb.currentSettings[2].value) {
|
|
||||||
fb.writeHistory(entry)
|
fb.writeHistory(entry)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
this.response.status = error.message
|
this.response.status = error.message
|
||||||
@@ -1468,7 +1461,7 @@ export default {
|
|||||||
this.$toast.error(`${error} ${this.$t("f12_details")}`, {
|
this.$toast.error(`${error} ${this.$t("f12_details")}`, {
|
||||||
icon: "error",
|
icon: "error",
|
||||||
})
|
})
|
||||||
if (!this.$store.state.postwoman.settings.PROXY_ENABLED) {
|
if (!this.PROXY_ENABLED) {
|
||||||
this.$toast.info(this.$t("enable_proxy"), {
|
this.$toast.info(this.$t("enable_proxy"), {
|
||||||
icon: "help",
|
icon: "help",
|
||||||
duration: 8000,
|
duration: 8000,
|
||||||
@@ -1629,10 +1622,10 @@ export default {
|
|||||||
"method",
|
"method",
|
||||||
"url",
|
"url",
|
||||||
"path",
|
"path",
|
||||||
!this.urlExcludes.auth ? "auth" : null,
|
!this.URL_EXCLUDES.auth ? "auth" : null,
|
||||||
!this.urlExcludes.httpUser ? "httpUser" : null,
|
!this.URL_EXCLUDES.httpUser ? "httpUser" : null,
|
||||||
!this.urlExcludes.httpPassword ? "httpPassword" : null,
|
!this.URL_EXCLUDES.httpPassword ? "httpPassword" : null,
|
||||||
!this.urlExcludes.bearerToken ? "bearerToken" : null,
|
!this.URL_EXCLUDES.bearerToken ? "bearerToken" : null,
|
||||||
"contentType",
|
"contentType",
|
||||||
]
|
]
|
||||||
.filter((item) => item !== null)
|
.filter((item) => item !== null)
|
||||||
@@ -1818,14 +1811,19 @@ export default {
|
|||||||
this.editRequest = {}
|
this.editRequest = {}
|
||||||
},
|
},
|
||||||
setExclude(excludedField, excluded) {
|
setExclude(excludedField, excluded) {
|
||||||
|
const update = clone(this.URL_EXCLUDES)
|
||||||
|
|
||||||
if (excludedField === "auth") {
|
if (excludedField === "auth") {
|
||||||
this.urlExcludes.auth = excluded
|
update.auth = excluded
|
||||||
this.urlExcludes.httpUser = excluded
|
update.httpUser = excluded
|
||||||
this.urlExcludes.httpPassword = excluded
|
update.httpPassword = excluded
|
||||||
this.urlExcludes.bearerToken = excluded
|
update.bearerToken = excluded
|
||||||
} else {
|
} else {
|
||||||
this.urlExcludes[excludedField] = excluded
|
update[excludedField] = excluded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applySetting("URL_EXCLUDES", update)
|
||||||
|
|
||||||
this.setRouteQueryState()
|
this.setRouteQueryState()
|
||||||
},
|
},
|
||||||
updateRawBody(rawParams) {
|
updateRawBody(rawParams) {
|
||||||
@@ -1987,13 +1985,6 @@ export default {
|
|||||||
await this.oauthRedirectReq()
|
await this.oauthRedirectReq()
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.urlExcludes = this.$store.state.postwoman.settings.URL_EXCLUDES || {
|
|
||||||
// Exclude authentication by default for security reasons.
|
|
||||||
auth: true,
|
|
||||||
httpUser: true,
|
|
||||||
httpPassword: true,
|
|
||||||
bearerToken: true,
|
|
||||||
}
|
|
||||||
if (Object.keys(this.$route.query).length) this.setRouteQueries(this.$route.query)
|
if (Object.keys(this.$route.query).length) this.setRouteQueries(this.$route.query)
|
||||||
this.$watch(
|
this.$watch(
|
||||||
(vm) => [
|
(vm) => [
|
||||||
|
|||||||
@@ -24,16 +24,33 @@
|
|||||||
</button>
|
</button>
|
||||||
<br />
|
<br />
|
||||||
<FirebaseLogout />
|
<FirebaseLogout />
|
||||||
<p v-for="setting in fb.currentSettings" :key="setting.id">
|
<p>
|
||||||
<SmartToggle
|
<SmartToggle
|
||||||
:key="setting.name"
|
:on="SYNC_COLLECTIONS"
|
||||||
:on="setting.value"
|
@change="toggleSettings('syncCollections', !SYNC_COLLECTIONS)"
|
||||||
@change="toggleSettings(setting.name, setting.value)"
|
|
||||||
>
|
>
|
||||||
{{ $t(setting.name) + " " + $t("sync") }}
|
{{ $t("syncCollections") + " " + $t("sync") }}
|
||||||
{{ setting.value ? $t("enabled") : $t("disabled") }}
|
{{ SYNC_COLLECTIONS ? $t("enabled") : $t("disabled") }}
|
||||||
</SmartToggle>
|
</SmartToggle>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<SmartToggle
|
||||||
|
:on="SYNC_ENVIRONMENTS"
|
||||||
|
@change="toggleSettings('syncEnvironments', !SYNC_ENVIRONMENTS)"
|
||||||
|
>
|
||||||
|
{{ $t("syncEnvironments") + " " + $t("sync") }}
|
||||||
|
{{ SYNC_ENVIRONMENTS ? $t("enabled") : $t("disabled") }}
|
||||||
|
</SmartToggle>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<SmartToggle :on="SYNC_HISTORY" @change="toggleSettings('syncHistory', !SYNC_HISTORY)">
|
||||||
|
{{ $t("syncHistory") + " " + $t("sync") }}
|
||||||
|
{{ SYNC_HISTORY ? $t("enabled") : $t("disabled") }}
|
||||||
|
</SmartToggle>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p v-if="fb.currentSettings.length !== 3">
|
<p v-if="fb.currentSettings.length !== 3">
|
||||||
<button @click="initSettings">
|
<button @click="initSettings">
|
||||||
<i class="material-icons">sync</i>
|
<i class="material-icons">sync</i>
|
||||||
@@ -56,12 +73,9 @@
|
|||||||
<SmartColorModePicker />
|
<SmartColorModePicker />
|
||||||
<SmartAccentModePicker />
|
<SmartAccentModePicker />
|
||||||
<span>
|
<span>
|
||||||
<SmartToggle
|
<SmartToggle :on="SCROLL_INTO_ENABLED" @change="toggleSetting('SCROLL_INTO_ENABLED')">
|
||||||
:on="settings.SCROLL_INTO_ENABLED"
|
|
||||||
@change="toggleSetting('SCROLL_INTO_ENABLED')"
|
|
||||||
>
|
|
||||||
{{ $t("scrollInto_use_toggle") }}
|
{{ $t("scrollInto_use_toggle") }}
|
||||||
{{ settings.SCROLL_INTO_ENABLED ? $t("enabled") : $t("disabled") }}
|
{{ SCROLL_INTO_ENABLED ? $t("enabled") : $t("disabled") }}
|
||||||
</SmartToggle>
|
</SmartToggle>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -71,10 +85,7 @@
|
|||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<label>{{ $t("extensions") }}</label>
|
<label>{{ $t("extensions") }}</label>
|
||||||
<div class="row-wrapper">
|
<div class="row-wrapper">
|
||||||
<SmartToggle
|
<SmartToggle :on="EXTENSIONS_ENABLED" @change="toggleSetting('EXTENSIONS_ENABLED')">
|
||||||
:on="settings.EXTENSIONS_ENABLED"
|
|
||||||
@change="toggleSetting('EXTENSIONS_ENABLED')"
|
|
||||||
>
|
|
||||||
{{ $t("extensions_use_toggle") }}
|
{{ $t("extensions_use_toggle") }}
|
||||||
</SmartToggle>
|
</SmartToggle>
|
||||||
</div>
|
</div>
|
||||||
@@ -92,9 +103,9 @@
|
|||||||
<label>{{ $t("proxy") }}</label>
|
<label>{{ $t("proxy") }}</label>
|
||||||
<div class="row-wrapper">
|
<div class="row-wrapper">
|
||||||
<span>
|
<span>
|
||||||
<SmartToggle :on="settings.PROXY_ENABLED" @change="toggleSetting('PROXY_ENABLED')">
|
<SmartToggle :on="PROXY_ENABLED" @change="toggleSetting('PROXY_ENABLED')">
|
||||||
{{ $t("proxy") }}
|
{{ $t("proxy") }}
|
||||||
{{ settings.PROXY_ENABLED ? $t("enabled") : $t("disabled") }}
|
{{ PROXY_ENABLED ? $t("enabled") : $t("disabled") }}
|
||||||
</SmartToggle>
|
</SmartToggle>
|
||||||
</span>
|
</span>
|
||||||
<a
|
<a
|
||||||
@@ -116,8 +127,8 @@
|
|||||||
<input
|
<input
|
||||||
id="url"
|
id="url"
|
||||||
type="url"
|
type="url"
|
||||||
v-model="settings.PROXY_URL"
|
v-model="PROXY_URL"
|
||||||
:disabled="!settings.PROXY_ENABLED"
|
:disabled="!PROXY_ENABLED"
|
||||||
:placeholder="$t('url')"
|
:placeholder="$t('url')"
|
||||||
/>
|
/>
|
||||||
<p class="info">
|
<p class="info">
|
||||||
@@ -166,7 +177,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<div class="row-wrapper">
|
<div class="row-wrapper">
|
||||||
<SmartToggle
|
<SmartToggle
|
||||||
:on="settings.EXPERIMENTAL_URL_BAR_ENABLED"
|
:on="EXPERIMENTAL_URL_BAR_ENABLED"
|
||||||
@change="toggleSetting('EXPERIMENTAL_URL_BAR_ENABLED')"
|
@change="toggleSetting('EXPERIMENTAL_URL_BAR_ENABLED')"
|
||||||
>
|
>
|
||||||
{{ $t("use_experimental_url_bar") }}
|
{{ $t("use_experimental_url_bar") }}
|
||||||
@@ -177,40 +188,54 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { fb } from "~/helpers/fb"
|
import { fb } from "~/helpers/fb"
|
||||||
import { hasExtensionInstalled } from "../helpers/strategies/ExtensionStrategy"
|
import { hasExtensionInstalled } from "../helpers/strategies/ExtensionStrategy"
|
||||||
|
import {
|
||||||
|
getSettingSubject,
|
||||||
|
applySetting,
|
||||||
|
toggleSetting,
|
||||||
|
defaultSettings,
|
||||||
|
} from "~/newstore/settings"
|
||||||
|
import type { KeysMatching } from "~/types/ts-utils"
|
||||||
|
|
||||||
export default {
|
import Vue from "vue"
|
||||||
|
|
||||||
|
type SettingsType = typeof defaultSettings
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
extensionVersion: hasExtensionInstalled()
|
extensionVersion: hasExtensionInstalled()
|
||||||
? window.__POSTWOMAN_EXTENSION_HOOK__.getVersion()
|
? window.__POSTWOMAN_EXTENSION_HOOK__.getVersion()
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
settings: {
|
|
||||||
SCROLL_INTO_ENABLED:
|
|
||||||
typeof this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED !== "undefined"
|
|
||||||
? this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED
|
|
||||||
: true,
|
|
||||||
|
|
||||||
PROXY_ENABLED: this.$store.state.postwoman.settings.PROXY_ENABLED || false,
|
|
||||||
PROXY_URL: this.$store.state.postwoman.settings.PROXY_URL || "https://proxy.hoppscotch.io",
|
|
||||||
PROXY_KEY: this.$store.state.postwoman.settings.PROXY_KEY || "",
|
|
||||||
|
|
||||||
EXTENSIONS_ENABLED:
|
|
||||||
typeof this.$store.state.postwoman.settings.EXTENSIONS_ENABLED !== "undefined"
|
|
||||||
? this.$store.state.postwoman.settings.EXTENSIONS_ENABLED
|
|
||||||
: true,
|
|
||||||
|
|
||||||
EXPERIMENTAL_URL_BAR_ENABLED:
|
|
||||||
typeof this.$store.state.postwoman.settings.EXPERIMENTAL_URL_BAR_ENABLED !== "undefined"
|
|
||||||
? this.$store.state.postwoman.settings.EXPERIMENTAL_URL_BAR_ENABLED
|
|
||||||
: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
doneButton: '<i class="material-icons">done</i>',
|
doneButton: '<i class="material-icons">done</i>',
|
||||||
fb,
|
fb,
|
||||||
|
|
||||||
|
SYNC_COLLECTIONS: true,
|
||||||
|
SYNC_ENVIRONMENTS: true,
|
||||||
|
SYNC_HISTORY: true,
|
||||||
|
|
||||||
|
PROXY_URL: "",
|
||||||
|
PROXY_KEY: "",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SCROLL_INTO_ENABLED: getSettingSubject("SCROLL_INTO_ENABLED"),
|
||||||
|
|
||||||
|
PROXY_ENABLED: getSettingSubject("PROXY_ENABLED"),
|
||||||
|
PROXY_URL: getSettingSubject("PROXY_URL"),
|
||||||
|
PROXY_KEY: getSettingSubject("PROXY_KEY"),
|
||||||
|
|
||||||
|
EXTENSIONS_ENABLED: getSettingSubject("EXTENSIONS_ENABLED"),
|
||||||
|
|
||||||
|
EXPERIMENTAL_URL_BAR_ENABLED: getSettingSubject("EXPERIMENTAL_URL_BAR_ENABLED"),
|
||||||
|
|
||||||
|
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
|
||||||
|
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments"),
|
||||||
|
SYNC_HISTORY: getSettingSubject("syncHistory"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -223,16 +248,15 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
applySetting(key, value) {
|
applySetting<K extends keyof SettingsType>(key: K, value: SettingsType[K]) {
|
||||||
this.settings[key] = value
|
applySetting(key, value)
|
||||||
this.$store.commit("postwoman/applySetting", [key, value])
|
|
||||||
},
|
},
|
||||||
toggleSetting(key) {
|
toggleSetting<K extends KeysMatching<SettingsType, boolean>>(key: K) {
|
||||||
this.settings[key] = !this.settings[key]
|
toggleSetting(key)
|
||||||
this.$store.commit("postwoman/applySetting", [key, this.settings[key]])
|
|
||||||
},
|
},
|
||||||
toggleSettings(name, value) {
|
toggleSettings<K extends KeysMatching<SettingsType, boolean>>(name: K, value: SettingsType[K]) {
|
||||||
fb.writeSettings(name, !value)
|
this.applySetting(name, value)
|
||||||
|
|
||||||
if (name === "syncCollections" && value) {
|
if (name === "syncCollections" && value) {
|
||||||
this.syncCollections()
|
this.syncCollections()
|
||||||
}
|
}
|
||||||
@@ -241,21 +265,21 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
initSettings() {
|
initSettings() {
|
||||||
fb.writeSettings("syncHistory", true)
|
applySetting("syncHistory", true)
|
||||||
fb.writeSettings("syncCollections", true)
|
applySetting("syncCollections", true)
|
||||||
fb.writeSettings("syncEnvironments", true)
|
applySetting("syncEnvironments", true)
|
||||||
},
|
},
|
||||||
resetProxy({ target }) {
|
resetProxy({ target }: { target: HTMLElement }) {
|
||||||
this.settings.PROXY_URL = `https://proxy.hoppscotch.io`
|
applySetting("PROXY_URL", `https://proxy.hoppscotch.io/`)
|
||||||
|
|
||||||
target.innerHTML = this.doneButton
|
target.innerHTML = this.doneButton
|
||||||
this.$toast.info(this.$t("cleared"), {
|
this.$toast.info(this.$t("cleared"), {
|
||||||
icon: "clear_all",
|
icon: "clear_all",
|
||||||
})
|
})
|
||||||
setTimeout(() => (target.innerHTML = '<i class="material-icons">clear_all</i>'), 1000)
|
setTimeout(() => (target.innerHTML = '<i class="material-icons">clear_all</i>'), 1000)
|
||||||
},
|
},
|
||||||
syncCollections() {
|
syncCollections(): void {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[0]) {
|
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
|
||||||
if (fb.currentSettings[0].value) {
|
|
||||||
fb.writeCollections(
|
fb.writeCollections(
|
||||||
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
|
||||||
"collections"
|
"collections"
|
||||||
@@ -265,21 +289,18 @@ export default {
|
|||||||
"collectionsGraphql"
|
"collectionsGraphql"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
syncEnvironments() {
|
syncEnvironments(): void {
|
||||||
if (fb.currentUser !== null && fb.currentSettings[1]) {
|
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
|
||||||
if (fb.currentSettings[1].value) {
|
|
||||||
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
proxySettings() {
|
proxySettings(): { url: string; key: string } {
|
||||||
return {
|
return {
|
||||||
url: this.settings.PROXY_URL,
|
url: this.PROXY_URL,
|
||||||
key: this.settings.PROXY_KEY,
|
key: this.PROXY_KEY,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -288,5 +309,5 @@ export default {
|
|||||||
title: `Settings • Hoppscotch`,
|
title: `Settings • Hoppscotch`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
4
plugins/vue-rx.js
Normal file
4
plugins/vue-rx.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import Vue from "vue"
|
||||||
|
import VueRx from "vue-rx"
|
||||||
|
|
||||||
|
Vue.use(VueRx)
|
||||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2018",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"lib": ["ESNext", "ESNext.AsyncIterable", "DOM"],
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"~/*": ["./*"],
|
||||||
|
"@/*": ["./*"]
|
||||||
|
},
|
||||||
|
"types": ["@types/node", "@nuxt/types", "nuxt-i18n", "@nuxtjs/toast", "vue-rx"]
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
21
types/pw-ext-hook.d.ts
vendored
Normal file
21
types/pw-ext-hook.d.ts
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
interface PWExtensionRequestInfo {
|
||||||
|
method: string
|
||||||
|
url: string
|
||||||
|
data: any & { wantsBinary: boolean }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PWExtensionResponse {
|
||||||
|
data: any
|
||||||
|
config?: {
|
||||||
|
timeData?: {
|
||||||
|
startTime: number
|
||||||
|
endTime: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PWExtensionHook {
|
||||||
|
getVersion: () => { major: number, minor: number }
|
||||||
|
sendRequest: (req: PWExtensionRequestInfo) => Promise<PWExtensionResponse>
|
||||||
|
cancelRunningRequest: () => void
|
||||||
|
}
|
||||||
1
types/ts-utils.d.ts
vendored
Normal file
1
types/ts-utils.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export type KeysMatching<T, V> = {[K in keyof T]-?: T[K] extends V ? K : never}[keyof T];
|
||||||
7
types/window.d.ts
vendored
Normal file
7
types/window.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export {}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
__POSTWOMAN_EXTENSION_HOOK__: PWExtensionHook
|
||||||
|
}
|
||||||
|
}
|
||||||
4
vue-shim.d.ts
vendored
Normal file
4
vue-shim.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
declare module "*.vue" {
|
||||||
|
import Vue from 'vue'
|
||||||
|
export default Vue
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user