This commit is contained in:
Manuel Bouza
2020-06-15 10:52:02 +02:00
parent 88765e5c9a
commit 1cbf5b5702
9 changed files with 134 additions and 141 deletions

View File

@@ -11,6 +11,11 @@
.moco-bx-options { .moco-bx-options {
padding: 0rem 2rem 2rem; padding: 0rem 2rem 2rem;
a {
color: $blue;
text-decoration: none;
}
p { p {
margin: 0.5rem 0; margin: 0.5rem 0;
} }
@@ -45,9 +50,13 @@
} }
&__host-overrides { &__host-overrides {
padding-bottom: 1rem; margin-bottom: 1.5rem;
text-align: center; text-align: center;
font-weight: normal; font-weight: normal;
} }
small {
font-size: 0.8rem;
}
} }
} }

View File

@@ -119,7 +119,7 @@ class App extends Component {
chrome.runtime.onMessage.removeListener(this.handleSetFormErrors) chrome.runtime.onMessage.removeListener(this.handleSetFormErrors)
} }
handleChange = event => { handleChange = (event) => {
const { projects } = this.props const { projects } = this.props
const { const {
target: { name, value }, target: { name, value },
@@ -133,11 +133,11 @@ class App extends Component {
} }
} }
handleSelectDate = date => { handleSelectDate = (date) => {
this.changeset.date = formatDate(date) this.changeset.date = formatDate(date)
} }
handleStopTimer = timedActivity => { handleStopTimer = (timedActivity) => {
const { service } = this.props const { service } = this.props
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
@@ -146,7 +146,7 @@ class App extends Component {
}) })
} }
handleSubmit = event => { handleSubmit = (event) => {
event.preventDefault() event.preventDefault()
const { service } = this.props const { service } = this.props
@@ -159,7 +159,7 @@ class App extends Component {
}) })
} }
handleKeyDown = event => { handleKeyDown = (event) => {
if (event.keyCode === 27) { if (event.keyCode === 27) {
event.stopPropagation() event.stopPropagation()
chrome.runtime.sendMessage({ type: "closePopup" }) chrome.runtime.sendMessage({ type: "closePopup" })
@@ -204,7 +204,7 @@ class App extends Component {
return ( return (
<Spring native from={{ opacity: 0 }} to={{ opacity: 1 }} config={config.stiff}> <Spring native from={{ opacity: 0 }} to={{ opacity: 1 }} config={config.stiff}>
{props => ( {(props) => (
<animated.div className="moco-bx-app-container" style={props}> <animated.div className="moco-bx-app-container" style={props}>
<Header subdomain={subdomain} /> <Header subdomain={subdomain} />
<Observer> <Observer>

View File

@@ -3,8 +3,7 @@ import { observable } from "mobx"
import { observer } from "mobx-react" import { observer } from "mobx-react"
import { isChrome, getSettings, setStorage } from "utils/browser" import { isChrome, getSettings, setStorage } from "utils/browser"
import ApiClient from "api/Client" import ApiClient from "api/Client"
import remoteServices from "../remoteServices" import { pipe, toPairs, fromPairs, map } from "lodash/fp"
import { pipe, toPairs, fromPairs, prop, map, sortedUniqBy, filter } from "lodash/fp"
function upperCaseFirstLetter(input) { function upperCaseFirstLetter(input) {
return input[0].toUpperCase() + input.slice(1) return input[0].toUpperCase() + input.slice(1)
@@ -14,15 +13,6 @@ function removePathFromUrl(url) {
return url.replace(/(\.[a-z]+)\/.*$/, "$1") return url.replace(/(\.[a-z]+)\/.*$/, "$1")
} }
const overridableRemoveServices = pipe(
filter(prop("allowHostOverride")),
map((remoteService) => ({
name: remoteService.name,
host: remoteService.host,
})),
sortedUniqBy("name"),
)(remoteServices)
@observer @observer
class Options extends Component { class Options extends Component {
@observable subdomain = "" @observable subdomain = ""
@@ -33,10 +23,10 @@ class Options extends Component {
@observable showHostOverrideOptions = false @observable showHostOverrideOptions = false
componentDidMount() { componentDidMount() {
getSettings(false).then((storeData) => { getSettings(false).then((settings) => {
this.subdomain = storeData.subdomain || "" this.subdomain = settings.subdomain || ""
this.apiKey = storeData.apiKey || "" this.apiKey = settings.apiKey || ""
this.hostOverrides = storeData.hostOverrides this.hostOverrides = settings.hostOverrides
}) })
} }
@@ -132,27 +122,42 @@ class Options extends Component {
{!this.showHostOverrideOptions && ( {!this.showHostOverrideOptions && (
<div className="moco-bx-options__host-overrides"> <div className="moco-bx-options__host-overrides">
<a href="#" className="moco-bx-btn__secondary" onClick={this.toggleHostOverrideOptions}> <a href="#" className="moco-bx-btn__secondary" onClick={this.toggleHostOverrideOptions}>
URLs für Dienste anpassen? Service-URLs überschreiben?
</a> </a>
</div> </div>
)} )}
{this.showHostOverrideOptions && ( {this.showHostOverrideOptions && (
<div style={{ marginBottom: "1rem" }}> <div style={{ marginBottom: "1.5rem" }}>
<h3>URLs für Dienste</h3> <h3 style={{ marginBottom: 0 }}>Service-URLs</h3>
{overridableRemoveServices.map((remoteService) => ( <small>
<div className="form-group" key={remoteService.name} style={{ margin: "0.5rem 0" }}> Doppelpunkt für Platzhalter verwenden, z.B.{" "}
<span style={{ backgroundColor: "rgba(100, 100, 100, 0.1)" }}>:org</span>. Siehe{" "}
<a
href="https://github.com/hundertzehn/mocoapp-browser-extension#remote-service-configuration"
target="_blank"
rel="noopener noreferrer"
>
Online-Doku
</a>
.
</small>
<br />
{pipe(
Object.entries,
Array.from,
)(this.hostOverrides).map(([name, host]) => (
<div className="form-group" key={name} style={{ margin: "0.5rem 0" }}>
<div className="input-group"> <div className="input-group">
<span <span
className="input-group-addon input-group-addon--left" className="input-group-addon input-group-addon--left"
style={{ display: "inline-block", width: "70px", textAlign: "left" }} style={{ display: "inline-block", width: "70px", textAlign: "left" }}
> >
{upperCaseFirstLetter(remoteService.name)} {upperCaseFirstLetter(name)}
</span> </span>
<input <input
type="text" type="text"
name={remoteService.name} name={name}
value={this.hostOverrides[remoteService.name] || ""} value={host}
placeholder={remoteService.host}
onKeyDown={this.handleInputKeyDown} onKeyDown={this.handleInputKeyDown}
onChange={this.handleChangeHostOverrides} onChange={this.handleChangeHostOverrides}
/> />

View File

@@ -1,3 +1,4 @@
import "mobx-react-lite/batchingForReactDom"
import React from "react" import React from "react"
import ReactDOM from "react-dom" import ReactDOM from "react-dom"
import Options from "./components/Options" import Options from "./components/Options"

View File

@@ -1,3 +1,4 @@
import "mobx-react-lite/batchingForReactDom"
import React from "react" import React from "react"
import ReactDOM from "react-dom" import ReactDOM from "react-dom"
import App from "./components/App" import App from "./components/App"

View File

@@ -8,8 +8,8 @@ export default {
name: "asana", name: "asana",
host: "https://app.asana.com", host: "https://app.asana.com",
urlPatterns: [ urlPatterns: [
[/^__HOST__\/0\/([^/]+)\/(\d+)/, ["domainUserId", "id"]], [/^:host:\/0\/([^/]+)\/(\d+)/, ["domainUserId", "id"]],
[/^__HOST__\/0\/search\/([^/]+)\/(\d+)/, ["domainUserId", "id"]], [/^:host:\/0\/search\/([^/]+)\/(\d+)/, ["domainUserId", "id"]],
], ],
description: (document) => description: (document) =>
document.querySelector(".ItemRow--highlighted textarea")?.textContent?.trim() || document.querySelector(".ItemRow--highlighted textarea")?.textContent?.trim() ||
@@ -23,32 +23,32 @@ export default {
"github-pr": { "github-pr": {
name: "github", name: "github",
host: "https://github.com", host: "https://github.com",
urlPatterns: ["__HOST__/:org/:repo/pull/:id(/:tab)"], urlPatterns: [":host:/:org/:repo/pull/:id(/:tab)"],
id: (document, service, { org, repo, id }) => [service.key, org, repo, id].join("."), id: (document, service, { org, repo, id }) => [service.key, org, repo, id].join("."),
description: (document) => document.querySelector(".js-issue-title")?.textContent?.trim(), description: (document) => document.querySelector(".js-issue-title")?.textContent?.trim(),
projectId: projectIdentifierBySelector(".js-issue-title"), projectId: projectIdentifierBySelector(".js-issue-title"),
allowHostOverride: true, allowHostOverride: false,
}, },
"github-issue": { "github-issue": {
name: "github", name: "github",
host: "https://github.com", host: "https://github.com",
urlPatterns: ["__HOST__/:org/:repo/issues/:id"], urlPatterns: [":host:/:org/:repo/issues/:id"],
id: (document, service, { org, repo, id }) => [service.key, org, repo, id].join("."), id: (document, service, { org, repo, id }) => [service.key, org, repo, id].join("."),
description: (document, service, { org, repo, id }) => description: (document, service, { org, repo, id }) =>
document.querySelector(".js-issue-title")?.textContent?.trim(), document.querySelector(".js-issue-title")?.textContent?.trim(),
projectId: projectIdentifierBySelector(".js-issue-title"), projectId: projectIdentifierBySelector(".js-issue-title"),
allowHostOverride: true, allowHostOverride: false,
}, },
jira: { jira: {
name: "jira", name: "jira",
host: "https://:org.atlassian.net", host: "https://:org.atlassian.net",
urlPatterns: [ urlPatterns: [
"__HOST__/secure/RapidBoard.jspa", ":host:/secure/RapidBoard.jspa",
"__HOST__/browse/:id", ":host:/browse/:id",
"__HOST__/jira/software/projects/:projectId/boards/:board", ":host:/jira/software/projects/:projectId/boards/:board",
"__HOST__/jira/software/projects/:projectId/boards/:board/backlog", ":host:/jira/software/projects/:projectId/boards/:board/backlog",
], ],
queryParams: { queryParams: {
id: "selectedIssue", id: "selectedIssue",
@@ -69,7 +69,7 @@ export default {
meistertask: { meistertask: {
name: "meistertask", name: "meistertask",
host: "https://www.meistertask.com", host: "https://www.meistertask.com",
urlPatterns: ["/app/task/:id/:slug"], urlPatterns: [":host:/app/task/:id/:slug"],
description: (document) => { description: (document) => {
const json = document.getElementById("mt-toggl-data")?.dataset?.togglJson || "{}" const json = document.getElementById("mt-toggl-data")?.dataset?.togglJson || "{}"
const data = JSON.parse(json) const data = JSON.parse(json)
@@ -87,7 +87,7 @@ export default {
trello: { trello: {
name: "trello", name: "trello",
host: "https://trello.com", host: "https://trello.com",
urlPatterns: ["__HOST__/c/:id/:title"], urlPatterns: [":host:/c/:id/:title"],
description: (document, service, { title }) => description: (document, service, { title }) =>
document.querySelector(".js-title-helper")?.textContent?.trim() || title, document.querySelector(".js-title-helper")?.textContent?.trim() || title,
projectId: (document) => projectId: (document) =>
@@ -99,7 +99,7 @@ export default {
youtrack: { youtrack: {
name: "youtrack", name: "youtrack",
host: "https://:org.myjetbrains.com", host: "https://:org.myjetbrains.com",
urlPatterns: ["__HOST__/youtrack/issue/:id"], urlPatterns: [":host:/youtrack/issue/:id"],
description: (document) => document.querySelector("yt-issue-body h1")?.textContent?.trim(), description: (document) => document.querySelector("yt-issue-body h1")?.textContent?.trim(),
projectId: projectIdentifierBySelector("yt-issue-body h1"), projectId: projectIdentifierBySelector("yt-issue-body h1"),
allowHostOverride: true, allowHostOverride: true,
@@ -109,8 +109,8 @@ export default {
name: "wrike", name: "wrike",
host: "https://www.wrike.com", host: "https://www.wrike.com",
urlPatterns: [ urlPatterns: [
"__HOST__/workspace.htm#path=mywork", ":host:/workspace.htm#path=mywork",
"__HOST__/workspace.htm#path=folder", ":host:/workspace.htm#path=folder",
"https\\://app-eu.wrike.com/workspace.htm#path=mywork", "https\\://app-eu.wrike.com/workspace.htm#path=mywork",
"https\\://app-eu.wrike.com/workspace.htm#path=folder", "https\\://app-eu.wrike.com/workspace.htm#path=folder",
], ],
@@ -125,7 +125,7 @@ export default {
wunderlist: { wunderlist: {
name: "wunderlist", name: "wunderlist",
host: "https://www.wunderlist.com", host: "https://www.wunderlist.com",
urlPatterns: ["__HOST__/(webapp)#/tasks/:id(/*)"], urlPatterns: [":host:/(webapp)#/tasks/:id(/*)"],
description: (document) => description: (document) =>
document document
.querySelector(".taskItem.selected .taskItem-titleWrapper-title") .querySelector(".taskItem.selected .taskItem-titleWrapper-title")
@@ -138,8 +138,8 @@ export default {
name: "gitlab", name: "gitlab",
host: "https://gitlab.com", host: "https://gitlab.com",
urlPatterns: [ urlPatterns: [
"__HOST__/:org/:group/:projectId/-/merge_requests/:id", ":host:/:org/:group/:projectId/-/merge_requests/:id",
"__HOST__/:org/:projectId/-/merge_requests/:id", ":host:/:org/:projectId/-/merge_requests/:id",
], ],
description: (document, service, { id }) => { description: (document, service, { id }) => {
const title = document.querySelector("h2.title")?.textContent?.trim() const title = document.querySelector("h2.title")?.textContent?.trim()
@@ -152,8 +152,8 @@ export default {
name: "gitlab", name: "gitlab",
host: "https://gitlab.com", host: "https://gitlab.com",
urlPatterns: [ urlPatterns: [
"__HOST__/:org/:group/:projectId/-/issues/:id", ":host:/:org/:group/:projectId/-/issues/:id",
"__HOST__/:org/:projectId/-/issues/:id", ":host:/:org/:projectId/-/issues/:id",
], ],
description: (document, service, { id }) => { description: (document, service, { id }) => {
const title = document.querySelector("h2.title")?.textContent?.trim() const title = document.querySelector("h2.title")?.textContent?.trim()

View File

@@ -1,36 +1,46 @@
import { head } from "lodash/fp" import { head, pick, reduce, filter, prop, pipe } from "lodash/fp"
import remoteServices from "../remoteServices"
const DEFAULT_SUBDOMAIN = "unset"
export const isChrome = () => typeof browser === "undefined" && chrome export const isChrome = () => typeof browser === "undefined" && chrome
export const isFirefox = () => typeof browser !== "undefined" && chrome export const isFirefox = () => typeof browser !== "undefined" && chrome
const DEFAULT_SUBDOMAIN = "unset" export const defaultHostOverrides = pipe(
const DEFAULT_HOST_OVERRIDES = { filter(prop("allowHostOverride")),
github: "https://github.com", reduce((acc, remoteService) => {
gitlab: "https://gitlab.com", acc[remoteService.name] = remoteService.host
jira: "https://:org.atlassian.net", return acc
youtrack: "https://:org.myjetbrains.com", }, {}),
} )(remoteServices)
// We pick only the keys defined in `defaultHostOverrides`, so that
// deleted host overrides get cleared from the settings
const getHostOverrides = (settings) => ({
...defaultHostOverrides,
...pick(Object.keys(defaultHostOverrides), settings.hostOverrides || {}),
})
export const getSettings = (withDefaultSubdomain = true) => { export const getSettings = (withDefaultSubdomain = true) => {
const keys = ["subdomain", "apiKey", "settingTimeTrackingHHMM", "hostOverrides"] const keys = ["subdomain", "apiKey", "settingTimeTrackingHHMM", "hostOverrides"]
const { version } = chrome.runtime.getManifest() const { version } = chrome.runtime.getManifest()
if (isChrome()) { if (isChrome()) {
return new Promise((resolve) => { return new Promise((resolve) => {
chrome.storage.sync.get(keys, (data) => { chrome.storage.sync.get(keys, (settings) => {
if (withDefaultSubdomain) { if (withDefaultSubdomain) {
data.subdomain = data.subdomain || DEFAULT_SUBDOMAIN settings.subdomain = settings.subdomain || DEFAULT_SUBDOMAIN
} }
data.hostOverrides = { ...DEFAULT_HOST_OVERRIDES, ...(data.hostOverrides || {}) } settings.hostOverrides = getHostOverrides(settings)
resolve({ ...data, version }) resolve({ ...settings, version })
}) })
}) })
} else { } else {
return browser.storage.sync.get(keys).then((data) => { return browser.storage.sync.get(keys).then((settings) => {
if (withDefaultSubdomain) { if (withDefaultSubdomain) {
data.subdomain = data.subdomain || DEFAULT_SUBDOMAIN settings.subdomain = settings.subdomain || DEFAULT_SUBDOMAIN
} }
data.hostOverrides = { ...DEFAULT_HOST_OVERRIDES, ...(data.hostOverrides || {}) } settings.hostOverrides = getHostOverrides(settings)
return { ...data, version } return { ...settings, version }
}) })
} }
} }

View File

@@ -17,41 +17,30 @@ import {
import { startOfWeek, endOfWeek } from "date-fns" import { startOfWeek, endOfWeek } from "date-fns"
import { format } from "date-fns" import { format } from "date-fns"
const nilToArray = input => input || [] const nilToArray = (input) => input || []
export const ERROR_UNAUTHORIZED = "unauthorized" export const ERROR_UNAUTHORIZED = "unauthorized"
export const ERROR_UPGRADE_REQUIRED = "upgrade-required" export const ERROR_UPGRADE_REQUIRED = "upgrade-required"
export const ERROR_UNKNOWN = "unknown" export const ERROR_UNKNOWN = "unknown"
export const noop = () => null export const noop = () => null
export const asArray = input => (Array.isArray(input) ? input : [input]) export const asArray = (input) => (Array.isArray(input) ? input : [input])
export const findProjectBy = prop => val => projects => { export const findProjectBy = (prop) => (val) => (projects) => {
if (!val) { if (!val) {
return undefined return undefined
} }
return compose( return compose(find(pathEq(prop, val)), flatMap(get("options")))(projects)
find(pathEq(prop, val)),
flatMap(get("options")),
)(projects)
} }
export const findProjectByIdentifier = findProjectBy("identifier") export const findProjectByIdentifier = findProjectBy("identifier")
export const findProjectByValue = findProjectBy("value") export const findProjectByValue = findProjectBy("value")
export const findTask = id => export const findTask = (id) => compose(find(pathEq("value", Number(id))), get("tasks"))
compose(
find(pathEq("value", Number(id))),
get("tasks"),
)
export const defaultTask = tasks => export const defaultTask = (tasks) =>
compose( compose(defaultTo(head(tasks)), find(pathEq("isDefault", true)), nilToArray)(tasks)
defaultTo(head(tasks)),
find(pathEq("isDefault", true)),
nilToArray,
)(tasks)
function taskOptions(tasks) { function taskOptions(tasks) {
return tasks.map(({ id, name, billable, default: isDefault }) => ({ return tasks.map(({ id, name, billable, default: isDefault }) => ({
@@ -63,7 +52,7 @@ function taskOptions(tasks) {
} }
export function projectOptions(projects) { export function projectOptions(projects) {
return projects.map(project => ({ return projects.map((project) => ({
value: project.id, value: project.id,
label: project.intern ? `(${project.name})` : project.name, label: project.intern ? `(${project.name})` : project.name,
identifier: project.identifier, identifier: project.identifier,
@@ -82,17 +71,9 @@ export const groupedProjectOptions = compose(
nilToArray, nilToArray,
) )
export const serializeProps = attrs => export const serializeProps = (attrs) => compose(mapValues(JSON.stringify), pick(attrs))
compose(
mapValues(JSON.stringify),
pick(attrs),
)
export const parseProps = attrs => export const parseProps = (attrs) => compose(mapValues(JSON.parse), pick(attrs))
compose(
mapValues(JSON.parse),
pick(attrs),
)
export const trace = curry((tag, value) => { export const trace = curry((tag, value) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
@@ -101,13 +82,13 @@ export const trace = curry((tag, value) => {
}) })
export const weekStartsOn = 1 export const weekStartsOn = 1
export const formatDate = date => format(date, "yyyy-MM-dd") export const formatDate = (date) => format(date, "yyyy-MM-dd")
export const getStartOfWeek = () => startOfWeek(new Date(), { weekStartsOn }) export const getStartOfWeek = () => startOfWeek(new Date(), { weekStartsOn })
export const getEndOfWeek = () => endOfWeek(new Date(), { weekStartsOn }) export const getEndOfWeek = () => endOfWeek(new Date(), { weekStartsOn })
export const extensionSettingsUrl = () => `chrome://extensions/?id=${chrome.runtime.id}` export const extensionSettingsUrl = () => `chrome://extensions/?id=${chrome.runtime.id}`
export const extractAndSetTag = changeset => { export const extractAndSetTag = (changeset) => {
let { description } = changeset let { description } = changeset
const match = description.match(/^#(\S+)/) const match = description.match(/^#(\S+)/)
if (!match) { if (!match) {

View File

@@ -1,5 +1,5 @@
import UrlPattern from "url-pattern" import UrlPattern from "url-pattern"
import { isFunction, isUndefined, compose, toPairs, map, pipe, isNil, convert } from "lodash/fp" import { isFunction, isUndefined, compose, toPairs, map, pipe, isNil, reduce } from "lodash/fp"
import { asArray } from "./index" import { asArray } from "./index"
import queryString from "query-string" import queryString from "query-string"
@@ -19,7 +19,7 @@ function parseUrl(url) {
function extractQueryParams(queryParams, query) { function extractQueryParams(queryParams, query) {
return toPairs(queryParams).reduce((acc, [key, params]) => { return toPairs(queryParams).reduce((acc, [key, params]) => {
const param = asArray(params).find(param => !isNil(query[param])) const param = asArray(params).find((param) => !isNil(query[param]))
if (param) { if (param) {
acc[key] = query[param] acc[key] = query[param]
} }
@@ -27,7 +27,7 @@ function extractQueryParams(queryParams, query) {
}, {}) }, {})
} }
const createEvaluator = args => fnOrValue => { const createEvaluator = (args) => (fnOrValue) => {
if (isUndefined(fnOrValue)) { if (isUndefined(fnOrValue)) {
return return
} }
@@ -40,20 +40,15 @@ const createEvaluator = args => fnOrValue => {
} }
const prepareHostForRegExp = (host) => { const prepareHostForRegExp = (host) => {
if (isUndefined(host)) {
return
}
return host.replace(":", "\\:") return host.replace(":", "\\:")
} }
const replaceHostInPattern = (host, pattern) => { const replaceHostInPattern = (host, pattern) => {
if(typeof pattern === "string") { if (typeof pattern === "string") {
return pattern.replace("__HOST__", prepareHostForRegExp(host)) return pattern.replace(":host:", prepareHostForRegExp(host))
} else if(pattern instanceof RegExp) { } else if (pattern instanceof RegExp) {
return new RegExp(pattern.source.replace("__HOST__", prepareHostForRegExp(host))) return new RegExp(pattern.source.replace(":host:", prepareHostForRegExp(host)))
} else { } else {
console.error("Invalid type for pattern %v, no host replacement performed", pattern)
return pattern return pattern
} }
} }
@@ -62,11 +57,9 @@ const parseServices = compose(
map(([key, config]) => ({ map(([key, config]) => ({
...config, ...config,
key, key,
patterns: config.urlPatterns.map(pattern => { patterns: config.urlPatterns.map((pattern) => {
if (Array.isArray(pattern)) { if (Array.isArray(pattern)) {
return new UrlPattern( return new UrlPattern(...pattern.map((p) => replaceHostInPattern(config.host, p)))
...pattern.map((p, index) => (index === 0 ? replaceHostInPattern(config.host, p) : p)),
)
} }
return new UrlPattern(replaceHostInPattern(config.host, pattern)) return new UrlPattern(replaceHostInPattern(config.host, pattern))
}), }),
@@ -74,7 +67,7 @@ const parseServices = compose(
toPairs, toPairs,
) )
export const createEnhancer = document => service => { export const createEnhancer = (document) => (service) => {
if (!service) { if (!service) {
return return
} }
@@ -93,38 +86,34 @@ export const createEnhancer = document => service => {
} }
} }
const applyHostOverrides = (remoteServices, hostOverrides) => { const applyHostOverrides = (remoteServices, hostOverrides) =>
let appliedRemoteServices = Object.assign(remoteServices) pipe(
if (isUndefined(hostOverrides)) { toPairs,
console.error("No overrides found.") reduce((acc, [key, remoteService]) => {
return remoteServices acc[key] = {
} ...remoteService,
key,
Object.keys(remoteServices).forEach((key) => { host: hostOverrides[remoteService.name] || remoteService.host,
const remoteService = remoteServices[key] }
appliedRemoteServices[key] = { return acc
...remoteService, }, {}),
key, )(remoteServices)
host: (hostOverrides && hostOverrides[remoteService.name]) || remoteService.host,
}
})
return appliedRemoteServices
}
export const createMatcher = (remoteServices, hostOverrides) => { export const createMatcher = (remoteServices, hostOverrides) => {
const services = parseServices(applyHostOverrides(remoteServices, hostOverrides)) const services = parseServices(applyHostOverrides(remoteServices, hostOverrides))
return tabUrl => { return (tabUrl) => {
const { origin, pathname, hash, query } = parseUrl(tabUrl) const { origin, pathname, hash, query } = parseUrl(tabUrl)
const url = `${origin}${pathname}${hash}` const url = `${origin}${pathname}${hash}`
const service = services.find(service => service.patterns.some(pattern => pattern.match(url))) const service = services.find((service) => {
return service.patterns.some((pattern) => pattern.match(url))
})
if (!service) { if (!service) {
return return
} }
const pattern = service.patterns.find(pattern => pattern.match(url)) const pattern = service.patterns.find((pattern) => pattern.match(url))
let match = pattern.match(url) let match = pattern.match(url)
if (service.queryParams) { if (service.queryParams) {
const extractedQueryParams = extractQueryParams(service.queryParams, query) const extractedQueryParams = extractQueryParams(service.queryParams, query)
@@ -140,11 +129,8 @@ export const createMatcher = (remoteServices, hostOverrides) => {
} }
} }
export const createServiceFinder = (remoteServices, hostOverrides) => document => { export const createServiceFinder = (remoteServices, hostOverrides) => (document) => {
const matcher = createMatcher(remoteServices, hostOverrides) const matcher = createMatcher(remoteServices, hostOverrides)
const enhancer = createEnhancer(document) const enhancer = createEnhancer(document)
return pipe( return pipe(matcher, enhancer)
matcher,
enhancer,
)
} }