chore: Remove env variables in webpack bundle (#1353)
* chore: Remove env variables in webpack bundle * remove unused globals * refactor: consolidate window.env calls to single file * fix: Slack client side integration auth * fix: developers url
This commit is contained in:
parent
24448c7504
commit
67981a351e
|
@ -58,14 +58,5 @@
|
|||
},
|
||||
"env": {
|
||||
"jest": true
|
||||
},
|
||||
"globals": {
|
||||
"__DEV__": true,
|
||||
"SLACK_KEY": true,
|
||||
"DEPLOYMENT": true,
|
||||
"BASE_URL": true,
|
||||
"SENTRY_DSN": true,
|
||||
"afterAll": true,
|
||||
"Sentry": true
|
||||
}
|
||||
}
|
|
@ -9,8 +9,9 @@ WORKDIR $APP_PATH
|
|||
COPY . $APP_PATH
|
||||
|
||||
RUN yarn install --pure-lockfile
|
||||
RUN yarn build
|
||||
RUN cp -r /opt/outline/node_modules /opt/node_modules
|
||||
|
||||
CMD yarn build && yarn start
|
||||
CMD yarn start
|
||||
|
||||
EXPOSE 3000
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
/* global ga */
|
||||
import * as React from "react";
|
||||
import env from "env";
|
||||
|
||||
type Props = {
|
||||
children?: React.Node,
|
||||
|
@ -8,7 +9,7 @@ type Props = {
|
|||
|
||||
export default class Analytics extends React.Component<Props> {
|
||||
componentDidMount() {
|
||||
if (!process.env.GOOGLE_ANALYTICS_ID) return;
|
||||
if (!env.GOOGLE_ANALYTICS_ID) return;
|
||||
|
||||
// standard Google Analytics script
|
||||
window.ga =
|
||||
|
@ -20,7 +21,7 @@ export default class Analytics extends React.Component<Props> {
|
|||
|
||||
// $FlowIssue
|
||||
ga.l = +new Date();
|
||||
ga("create", process.env.GOOGLE_ANALYTICS_ID, "auto");
|
||||
ga("create", env.GOOGLE_ANALYTICS_ID, "auto");
|
||||
ga("set", { dimension1: "true" });
|
||||
ga("send", "pageview");
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import { Redirect } from "react-router-dom";
|
|||
import AuthStore from "stores/AuthStore";
|
||||
import LoadingIndicator from "components/LoadingIndicator";
|
||||
import { isCustomSubdomain } from "shared/utils/domains";
|
||||
import env from "env";
|
||||
|
||||
type Props = {
|
||||
auth: AuthStore,
|
||||
|
@ -23,7 +24,7 @@ const Authenticated = observer(({ auth, children }: Props) => {
|
|||
// If we're authenticated but viewing a subdomain that doesn't match the
|
||||
// currently authenticated team then kick the user to the teams subdomain.
|
||||
if (
|
||||
process.env.SUBDOMAINS_ENABLED &&
|
||||
env.SUBDOMAINS_ENABLED &&
|
||||
team.subdomain &&
|
||||
isCustomSubdomain(hostname) &&
|
||||
!hostname.startsWith(`${team.subdomain}.`)
|
||||
|
|
|
@ -14,7 +14,7 @@ class CopyToClipboard extends React.PureComponent<Props> {
|
|||
const { text, onCopy, children } = this.props;
|
||||
const elem = React.Children.only(children);
|
||||
copy(text, {
|
||||
debug: !!__DEV__,
|
||||
debug: process.env.NODE_ENV !== "production",
|
||||
});
|
||||
|
||||
if (onCopy) onCopy();
|
||||
|
|
|
@ -23,7 +23,7 @@ class ErrorBoundary extends React.Component<Props> {
|
|||
console.error(error);
|
||||
|
||||
if (window.Sentry) {
|
||||
Sentry.captureException(error);
|
||||
window.Sentry.captureException(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import HeaderBlock from "./components/HeaderBlock";
|
|||
import Version from "./components/Version";
|
||||
import PoliciesStore from "stores/PoliciesStore";
|
||||
import AuthStore from "stores/AuthStore";
|
||||
import env from "env";
|
||||
|
||||
type Props = {
|
||||
history: RouterHistory,
|
||||
|
@ -146,7 +147,7 @@ class SettingsSidebar extends React.Component<Props> {
|
|||
</Section>
|
||||
)}
|
||||
{can.update &&
|
||||
process.env.DEPLOYMENT !== "hosted" && (
|
||||
env.DEPLOYMENT !== "hosted" && (
|
||||
<Section>
|
||||
<Header>Installation</Header>
|
||||
<Version />
|
||||
|
|
|
@ -13,6 +13,7 @@ import PoliciesStore from "stores/PoliciesStore";
|
|||
import ViewsStore from "stores/ViewsStore";
|
||||
import AuthStore from "stores/AuthStore";
|
||||
import UiStore from "stores/UiStore";
|
||||
import env from "env";
|
||||
|
||||
export const SocketContext: any = React.createContext();
|
||||
|
||||
|
@ -34,7 +35,7 @@ class SocketProvider extends React.Component<Props> {
|
|||
@observable socket;
|
||||
|
||||
componentDidMount() {
|
||||
if (!process.env.WEBSOCKETS_ENABLED) return;
|
||||
if (!env.WEBSOCKETS_ENABLED) return;
|
||||
|
||||
this.socket = io(window.location.origin, {
|
||||
path: "/realtime",
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
// @flow
|
||||
const env = window.env;
|
||||
export default env;
|
|
@ -10,9 +10,10 @@ import ScrollToTop from "components/ScrollToTop";
|
|||
import Toasts from "components/Toasts";
|
||||
import Theme from "components/Theme";
|
||||
import Routes from "./routes";
|
||||
import env from "env";
|
||||
|
||||
let DevTools;
|
||||
if (__DEV__) {
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
DevTools = require("mobx-react-devtools").default; // eslint-disable-line global-require
|
||||
}
|
||||
|
||||
|
@ -44,7 +45,7 @@ if (element) {
|
|||
window.addEventListener("load", async () => {
|
||||
// installation does not use Google Analytics, or tracking is blocked on client
|
||||
// no point loading the rest of the analytics bundles
|
||||
if (!process.env.GOOGLE_ANALYTICS_ID || !window.ga) return;
|
||||
if (!env.GOOGLE_ANALYTICS_ID || !window.ga) return;
|
||||
|
||||
// https://github.com/googleanalytics/autotrack/issues/137#issuecomment-305890099
|
||||
await import("autotrack/autotrack.js");
|
||||
|
|
|
@ -17,6 +17,7 @@ import Service from "./Service";
|
|||
import Notices from "./Notices";
|
||||
import AuthStore from "stores/AuthStore";
|
||||
import getQueryVariable from "shared/utils/getQueryVariable";
|
||||
import env from "env";
|
||||
|
||||
type Props = {
|
||||
auth: AuthStore,
|
||||
|
@ -62,7 +63,7 @@ class Login extends React.Component<Props, State> {
|
|||
);
|
||||
|
||||
const header =
|
||||
process.env.DEPLOYMENT === "hosted" &&
|
||||
env.DEPLOYMENT === "hosted" &&
|
||||
(config.hostname ? (
|
||||
<Back href={process.env.URL}>
|
||||
<BackIcon color="currentColor" /> Back to home
|
||||
|
@ -101,8 +102,8 @@ class Login extends React.Component<Props, State> {
|
|||
<Centered align="center" justify="center" column auto>
|
||||
<PageTitle title="Login" />
|
||||
<Logo>
|
||||
{process.env.TEAM_LOGO && process.env.DEPLOYMENT !== "hosted" ? (
|
||||
<TeamLogo src={process.env.TEAM_LOGO} />
|
||||
{env.TEAM_LOGO && env.DEPLOYMENT !== "hosted" ? (
|
||||
<TeamLogo src={env.TEAM_LOGO} />
|
||||
) : (
|
||||
<OutlineLogo size={38} fill="currentColor" />
|
||||
)}
|
||||
|
|
|
@ -13,6 +13,7 @@ import CenteredContent from "components/CenteredContent";
|
|||
import PageTitle from "components/PageTitle";
|
||||
import HelpText from "components/HelpText";
|
||||
import Flex from "components/Flex";
|
||||
import env from "env";
|
||||
|
||||
type Props = {
|
||||
auth: AuthStore,
|
||||
|
@ -115,7 +116,7 @@ class Details extends React.Component<Props> {
|
|||
required
|
||||
short
|
||||
/>
|
||||
{process.env.SUBDOMAINS_ENABLED && (
|
||||
{env.SUBDOMAINS_ENABLED && (
|
||||
<React.Fragment>
|
||||
<Input
|
||||
label="Subdomain"
|
||||
|
@ -129,7 +130,7 @@ class Details extends React.Component<Props> {
|
|||
/>
|
||||
{this.subdomain && (
|
||||
<HelpText small>
|
||||
Your knowledgebase will be accessible at{" "}
|
||||
Your knowledge base will be accessible at{" "}
|
||||
<strong>{this.subdomain}.getoutline.com</strong>
|
||||
</HelpText>
|
||||
)}
|
||||
|
|
|
@ -14,6 +14,7 @@ import IntegrationsStore from "stores/IntegrationsStore";
|
|||
import AuthStore from "stores/AuthStore";
|
||||
import Notice from "components/Notice";
|
||||
import getQueryVariable from "shared/utils/getQueryVariable";
|
||||
import env from "env";
|
||||
|
||||
type Props = {
|
||||
collections: CollectionsStore,
|
||||
|
@ -68,7 +69,7 @@ class Slack extends React.Component<Props> {
|
|||
) : (
|
||||
<SlackButton
|
||||
scopes={["commands", "links:read", "links:write"]}
|
||||
redirectUri={`${BASE_URL}/auth/slack.commands`}
|
||||
redirectUri={`${env.URL}/auth/slack.commands`}
|
||||
state={teamId}
|
||||
/>
|
||||
)}
|
||||
|
@ -105,7 +106,7 @@ class Slack extends React.Component<Props> {
|
|||
<strong>{collection.name}</strong>
|
||||
<SlackButton
|
||||
scopes={["incoming-webhook"]}
|
||||
redirectUri={`${BASE_URL}/auth/slack.post`}
|
||||
redirectUri={`${env.URL}/auth/slack.post`}
|
||||
state={collection.id}
|
||||
label="Connect"
|
||||
/>
|
||||
|
|
|
@ -4,6 +4,7 @@ import styled from "styled-components";
|
|||
import { slackAuth } from "shared/utils/routeHelpers";
|
||||
import SlackLogo from "components/SlackLogo";
|
||||
import Button from "components/Button";
|
||||
import env from "env";
|
||||
|
||||
type Props = {
|
||||
scopes?: string[],
|
||||
|
@ -14,7 +15,12 @@ type Props = {
|
|||
|
||||
function SlackButton({ state, scopes, redirectUri, label }: Props) {
|
||||
const handleClick = () =>
|
||||
(window.location.href = slackAuth(state, scopes, redirectUri));
|
||||
(window.location.href = slackAuth(
|
||||
state,
|
||||
scopes,
|
||||
env.SLACK_KEY,
|
||||
redirectUri
|
||||
));
|
||||
|
||||
return (
|
||||
<Button
|
||||
|
|
|
@ -3,7 +3,7 @@ import { observable, action, computed, autorun, runInAction } from "mobx";
|
|||
import invariant from "invariant";
|
||||
import { getCookie, setCookie, removeCookie } from "tiny-cookie";
|
||||
import { client } from "utils/ApiClient";
|
||||
import { getCookieDomain } from "shared/utils/domains";
|
||||
import { getCookieDomain } from "utils/domains";
|
||||
import RootStore from "stores/RootStore";
|
||||
import User from "models/User";
|
||||
import Team from "models/Team";
|
||||
|
@ -102,7 +102,7 @@ export default class AuthStore {
|
|||
this.team = new Team(team);
|
||||
|
||||
if (window.Sentry) {
|
||||
Sentry.configureScope(function(scope) {
|
||||
window.Sentry.configureScope(function(scope) {
|
||||
scope.setUser({ id: user.id });
|
||||
scope.setExtra("team", team.name);
|
||||
scope.setExtra("teamId", team.id);
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// @flow
|
||||
import { stripSubdomain } from "shared/utils/domains";
|
||||
import env from "env";
|
||||
|
||||
export function getCookieDomain(domain: string) {
|
||||
return env.SUBDOMAINS_ENABLED ? stripSubdomain(domain) : domain;
|
||||
}
|
|
@ -1,11 +1,4 @@
|
|||
// @flow
|
||||
declare var __DEV__: string;
|
||||
declare var SLACK_KEY: string;
|
||||
declare var SLACK_APP_ID: string;
|
||||
declare var BASE_URL: string;
|
||||
declare var SENTRY_DSN: ?string;
|
||||
declare var DEPLOYMENT: string;
|
||||
declare var Sentry: any;
|
||||
declare var process: {
|
||||
env: {
|
||||
[string]: string,
|
||||
|
|
|
@ -51,7 +51,7 @@ function filterServices(team) {
|
|||
|
||||
router.post("auth.config", async ctx => {
|
||||
// If self hosted AND there is only one team then that team becomes the
|
||||
// brand for the knowledgebase and it's guest signin option is used for the
|
||||
// brand for the knowledge base and it's guest signin option is used for the
|
||||
// root login page.
|
||||
if (process.env.DEPLOYMENT !== "hosted") {
|
||||
const teams = await Team.findAll();
|
||||
|
|
|
@ -33,30 +33,33 @@ if (process.env.NODE_ENV === "development") {
|
|||
const compile = webpack(config);
|
||||
/* eslint-enable global-require */
|
||||
|
||||
app.use(
|
||||
convert(
|
||||
devMiddleware(compile, {
|
||||
// display no info to console (only warnings and errors)
|
||||
noInfo: true,
|
||||
const middleware = devMiddleware(compile, {
|
||||
// display no info to console (only warnings and errors)
|
||||
noInfo: true,
|
||||
|
||||
// display nothing to the console
|
||||
quiet: false,
|
||||
// display nothing to the console
|
||||
quiet: false,
|
||||
|
||||
// switch into lazy mode
|
||||
// that means no watching, but recompilation on every request
|
||||
lazy: false,
|
||||
// switch into lazy mode
|
||||
// that means no watching, but recompilation on every request
|
||||
lazy: false,
|
||||
|
||||
// public path to bind the middleware to
|
||||
// use the same as in webpack
|
||||
publicPath: config.output.publicPath,
|
||||
// public path to bind the middleware to
|
||||
// use the same as in webpack
|
||||
publicPath: config.output.publicPath,
|
||||
|
||||
// options for formatting the statistics
|
||||
stats: {
|
||||
colors: true,
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
// options for formatting the statistics
|
||||
stats: {
|
||||
colors: true,
|
||||
},
|
||||
});
|
||||
|
||||
app.use(async (ctx, next) => {
|
||||
ctx.webpackConfig = config;
|
||||
ctx.devMiddleware = middleware;
|
||||
await next();
|
||||
});
|
||||
app.use(convert(middleware));
|
||||
app.use(
|
||||
convert(
|
||||
hotMiddleware(compile, {
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
import bodyParser from "koa-bodyparser";
|
||||
import Koa from "koa";
|
||||
import Router from "koa-router";
|
||||
import addMonths from "date-fns/add_months";
|
||||
import validation from "../middlewares/validation";
|
||||
import auth from "../middlewares/authentication";
|
||||
import addMonths from "date-fns/add_months";
|
||||
import { getCookieDomain } from "../utils/domains";
|
||||
import { Team } from "../models";
|
||||
import { getCookieDomain } from "../../shared/utils/domains";
|
||||
|
||||
import slack from "./slack";
|
||||
import google from "./google";
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// @flow
|
||||
import Sequelize from "sequelize";
|
||||
import Router from "koa-router";
|
||||
import auth from "../middlewares/authentication";
|
||||
import addHours from "date-fns/add_hours";
|
||||
import { getCookieDomain } from "../../shared/utils/domains";
|
||||
import auth from "../middlewares/authentication";
|
||||
import { getCookieDomain } from "../utils/domains";
|
||||
import { slackAuth } from "../../shared/utils/routeHelpers";
|
||||
import {
|
||||
Authentication,
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// @flow
|
||||
export default {
|
||||
URL: process.env.URL,
|
||||
DEPLOYMENT: process.env.DEPLOYMENT,
|
||||
SENTRY_DSN: process.env.SENTRY_DSN,
|
||||
TEAM_LOGO: process.env.TEAM_LOGO,
|
||||
SLACK_KEY: process.env.SLACK_KEY,
|
||||
SLACK_APP_ID: process.env.SLACK_APP_ID,
|
||||
SUBDOMAINS_ENABLED: process.env.SUBDOMAINS_ENABLED === "true",
|
||||
WEBSOCKETS_ENABLED: process.env.WEBSOCKETS_ENABLED === "true",
|
||||
GOOGLE_ANALYTICS_ID: process.env.GOOGLE_ANALYTICS_ID,
|
||||
};
|
|
@ -3,10 +3,10 @@ import JWT from "jsonwebtoken";
|
|||
import { type Context } from "koa";
|
||||
import { User, ApiKey } from "../models";
|
||||
import { getUserForJWT } from "../utils/jwt";
|
||||
import { getCookieDomain } from "../utils/domains";
|
||||
import { AuthenticationError, UserSuspendedError } from "../errors";
|
||||
import addMonths from "date-fns/add_months";
|
||||
import addMinutes from "date-fns/add_minutes";
|
||||
import { getCookieDomain } from "../../shared/utils/domains";
|
||||
|
||||
export default function auth(options?: { required?: boolean } = {}) {
|
||||
return async function authMiddleware(ctx: Context, next: () => Promise<*>) {
|
||||
|
|
|
@ -2,15 +2,40 @@
|
|||
import path from "path";
|
||||
import Koa from "koa";
|
||||
import Router from "koa-router";
|
||||
import fs from "fs";
|
||||
import util from "util";
|
||||
import sendfile from "koa-sendfile";
|
||||
import serve from "koa-static";
|
||||
import apexRedirect from "./middlewares/apexRedirect";
|
||||
import { robotsResponse } from "./utils/robots";
|
||||
import { opensearchResponse } from "./utils/opensearch";
|
||||
import environment from "./env";
|
||||
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
const koa = new Koa();
|
||||
const router = new Router();
|
||||
const readFile = util.promisify(fs.readFile);
|
||||
|
||||
const readIndexFile = async ctx => {
|
||||
if (isProduction) {
|
||||
return readFile(path.join(__dirname, "../dist/index.html"));
|
||||
}
|
||||
|
||||
const middleware = ctx.devMiddleware;
|
||||
await new Promise(resolve => middleware.waitUntilValid(resolve));
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
middleware.fileSystem.readFile(
|
||||
`${ctx.webpackConfig.output.path}/index.html`,
|
||||
(err, result) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// serve static assets
|
||||
koa.use(
|
||||
|
@ -49,11 +74,15 @@ router.get("*", async (ctx, next) => {
|
|||
return next();
|
||||
}
|
||||
|
||||
if (isProduction) {
|
||||
await sendfile(ctx, path.join(__dirname, "../dist/index.html"));
|
||||
} else {
|
||||
await sendfile(ctx, path.join(__dirname, "./static/dev.html"));
|
||||
}
|
||||
const page = await readIndexFile(ctx);
|
||||
const env = `
|
||||
window.env = ${JSON.stringify(environment)};
|
||||
`;
|
||||
ctx.body = page
|
||||
.toString()
|
||||
.replace(/\/\/inject-env\/\//g, env)
|
||||
.replace(/\/\/inject-sentry-dsn\/\//g, process.env.SENTRY_DSN || "")
|
||||
.replace(/\/\/inject-slack-app-id\/\//g, process.env.SLACK_APP_ID || "");
|
||||
});
|
||||
|
||||
// middleware
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Outline</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="shortcut icon" type="image/png" href="favicon-32.png" sizes="32x32" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link
|
||||
rel="search"
|
||||
type="application/opensearchdescription+xml"
|
||||
href="/opensearch.xml"
|
||||
title="Outline"
|
||||
/>
|
||||
<style>
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#root {
|
||||
flex: 1;
|
||||
min-height: 100vh;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
if (window.localStorage.getItem("theme") === "dark") {
|
||||
window.document.querySelector('#root').style.background = "#111319";
|
||||
}
|
||||
</script>
|
||||
<script src="/static/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,47 +1,43 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Outline</title>
|
||||
<meta name="slack-app-id" content="<%= SLACK_APP_ID %>" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="shortcut icon" type="image/png" href="favicon-32.png" sizes="32x32" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link
|
||||
rel="search"
|
||||
type="application/opensearchdescription+xml"
|
||||
href="/opensearch.xml"
|
||||
title="Outline"
|
||||
/>
|
||||
<style>
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
<head>
|
||||
<title>Outline</title>
|
||||
<meta name="slack-app-id" content="//inject-slack-app-id//" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="shortcut icon" type="image/png" href="favicon-32.png" sizes="32x32" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="Outline" />
|
||||
<style>
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#root {
|
||||
flex: 1;
|
||||
min-height: 100vh;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script
|
||||
src="https://browser.sentry-cdn.com/5.12.1/bundle.min.js"
|
||||
integrity="sha384-y+an4eARFKvjzOivf/Z7JtMJhaN6b+lLQ5oFbBbUwZNNVir39cYtkjW1r6Xjbxg3"
|
||||
crossorigin="anonymous"
|
||||
>
|
||||
body {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#root {
|
||||
flex: 1;
|
||||
min-height: 100vh;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script>//inject-env//</script>
|
||||
<script src="https://browser.sentry-cdn.com/5.12.1/bundle.min.js"
|
||||
integrity="sha384-y+an4eARFKvjzOivf/Z7JtMJhaN6b+lLQ5oFbBbUwZNNVir39cYtkjW1r6Xjbxg3" crossorigin="anonymous">
|
||||
</script>
|
||||
<script>
|
||||
<script>
|
||||
if ('//inject-sentry-dsn//') {
|
||||
Sentry.init({
|
||||
dsn: '<%= SENTRY_DSN %>',
|
||||
dsn: '//inject-sentry-dsn//',
|
||||
ignoreErrors: [
|
||||
'AuthorizationError',
|
||||
'NetworkError',
|
||||
|
@ -50,10 +46,12 @@
|
|||
'UpdateRequiredError',
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (window.localStorage.getItem("theme") === "dark") {
|
||||
window.document.querySelector('#root').style.background = "#111319";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
if (window.localStorage.getItem("theme") === "dark") {
|
||||
window.document.querySelector('#root').style.background = "#111319";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
// @flow
|
||||
import { stripSubdomain } from "../../shared/utils/domains";
|
||||
|
||||
export function getCookieDomain(domain: string) {
|
||||
return process.env.SUBDOMAINS_ENABLED === "true"
|
||||
? stripSubdomain(domain)
|
||||
: domain;
|
||||
}
|
|
@ -52,14 +52,6 @@ export function parseDomain(url: string): ?Domain {
|
|||
return null;
|
||||
}
|
||||
|
||||
export function getCookieDomain(domain: string) {
|
||||
// TODO: All the process.env parsing needs centralizing
|
||||
return process.env.SUBDOMAINS_ENABLED === "true" ||
|
||||
process.env.SUBDOMAINS_ENABLED === true
|
||||
? stripSubdomain(domain)
|
||||
: domain;
|
||||
}
|
||||
|
||||
export function stripSubdomain(hostname: string) {
|
||||
const parsed = parseDomain(hostname);
|
||||
if (!parsed) return hostname;
|
||||
|
|
|
@ -8,11 +8,12 @@ export function slackAuth(
|
|||
"identity.avatar",
|
||||
"identity.team",
|
||||
],
|
||||
clientId: string = process.env.SLACK_KEY,
|
||||
redirectUri: string = `${process.env.URL}/auth/slack.callback`
|
||||
): string {
|
||||
const baseUrl = "https://slack.com/oauth/authorize";
|
||||
const params = {
|
||||
client_id: process.env.SLACK_KEY,
|
||||
client_id: clientId,
|
||||
scope: scopes ? scopes.join(" ") : "",
|
||||
redirect_uri: redirectUri,
|
||||
state,
|
||||
|
@ -53,12 +54,8 @@ export function mailToUrl(): string {
|
|||
return "mailto:hello@getoutline.com";
|
||||
}
|
||||
|
||||
export function features(): string {
|
||||
return `${process.env.URL}/#features`;
|
||||
}
|
||||
|
||||
export function developers(): string {
|
||||
return `${process.env.URL}/developers`;
|
||||
return `https://www.getoutline.com/developers`;
|
||||
}
|
||||
|
||||
export function changelog(): string {
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
/* eslint-disable */
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const commonWebpackConfig = require('./webpack.config');
|
||||
const webpack = require("webpack");
|
||||
const commonWebpackConfig = require("./webpack.config");
|
||||
|
||||
const developmentWebpackConfig = Object.assign(commonWebpackConfig, {
|
||||
cache: true,
|
||||
devtool: 'eval-source-map',
|
||||
devtool: "eval-source-map",
|
||||
entry: [
|
||||
'babel-polyfill',
|
||||
'babel-regenerator-runtime',
|
||||
'webpack-hot-middleware/client',
|
||||
'./app/index',
|
||||
"babel-polyfill",
|
||||
"babel-regenerator-runtime",
|
||||
"webpack-hot-middleware/client",
|
||||
"./app/index",
|
||||
],
|
||||
});
|
||||
|
||||
developmentWebpackConfig.plugins = [
|
||||
...developmentWebpackConfig.plugins,
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
title: 'Outline',
|
||||
new webpack.DefinePlugin({
|
||||
"process.env.NODE_ENV": JSON.stringify("development"),
|
||||
}),
|
||||
];
|
||||
|
||||
|
|
|
@ -1,27 +1,10 @@
|
|||
/* eslint-disable */
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
require('dotenv').config({ silent: true });
|
||||
|
||||
const definePlugin = new webpack.DefinePlugin({
|
||||
__DEV__: JSON.stringify(JSON.parse(process.env.NODE_ENV !== 'production')),
|
||||
__PRERELEASE__: JSON.stringify(
|
||||
JSON.parse(process.env.BUILD_PRERELEASE || 'false')
|
||||
),
|
||||
SLACK_APP_ID: JSON.stringify(process.env.SLACK_APP_ID),
|
||||
BASE_URL: JSON.stringify(process.env.URL),
|
||||
SENTRY_DSN: JSON.stringify(process.env.SENTRY_DSN),
|
||||
'process.env': {
|
||||
DEPLOYMENT: JSON.stringify(process.env.DEPLOYMENT),
|
||||
URL: JSON.stringify(process.env.URL),
|
||||
TEAM_LOGO: JSON.stringify(process.env.TEAM_LOGO),
|
||||
SLACK_KEY: JSON.stringify(process.env.SLACK_KEY),
|
||||
SUBDOMAINS_ENABLED: JSON.stringify(process.env.SUBDOMAINS_ENABLED === 'true'),
|
||||
WEBSOCKETS_ENABLED: JSON.stringify(process.env.WEBSOCKETS_ENABLED === 'true')
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
output: {
|
||||
path: path.join(__dirname, 'dist'),
|
||||
|
@ -65,11 +48,13 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
plugins: [
|
||||
definePlugin,
|
||||
new webpack.ProvidePlugin({
|
||||
fetch: 'imports-loader?this=>global!exports-loader?global.fetch!isomorphic-fetch',
|
||||
}),
|
||||
new webpack.IgnorePlugin(/unicode\/category\/So/),
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'server/static/index.html',
|
||||
}),
|
||||
],
|
||||
stats: {
|
||||
assets: false,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* eslint-disable */
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
||||
|
||||
|
@ -21,9 +20,6 @@ productionWebpackConfig = Object.assign(commonWebpackConfig, {
|
|||
productionWebpackConfig.plugins = [
|
||||
...productionWebpackConfig.plugins,
|
||||
new ManifestPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'server/static/index.html',
|
||||
}),
|
||||
new UglifyJsPlugin({
|
||||
sourceMap: true,
|
||||
uglifyOptions: {
|
||||
|
@ -32,13 +28,7 @@ productionWebpackConfig.plugins = [
|
|||
}
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.DEPLOYMENT': JSON.stringify(process.env.DEPLOYMENT),
|
||||
'process.env.URL': JSON.stringify(process.env.URL),
|
||||
'process.env.TEAM_LOGO': JSON.stringify(process.env.TEAM_LOGO),
|
||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||
'process.env.GOOGLE_ANALYTICS_ID': JSON.stringify(process.env.GOOGLE_ANALYTICS_ID),
|
||||
'process.env.SUBDOMAINS_ENABLED': JSON.stringify(process.env.SUBDOMAINS_ENABLED === 'true'),
|
||||
'process.env.WEBSOCKETS_ENABLED': JSON.stringify(process.env.WEBSOCKETS_ENABLED === 'true'),
|
||||
}),
|
||||
];
|
||||
|
||||
|
|
Reference in New Issue