mirror of
https://github.com/wassname/talk.git
synced 2026-07-15 11:26:58 +08:00
Merge branch 'next' into rest-next
This commit is contained in:
@@ -30,3 +30,39 @@
|
||||
2. Tenant RedisPubSub Publisher
|
||||
3. Management RedisPubSub Subscriber
|
||||
4. Management RedisPubSub Publisher
|
||||
|
||||
## Scripts
|
||||
|
||||
### Embed
|
||||
|
||||
Embed Script - Renders the iFrame <-- does not have a html page in production (should be on server?)
|
||||
|
||||
/dist/static/assets/embed.js /static/embed.js
|
||||
|
||||
### Stream
|
||||
|
||||
Stream - Renders the comment stream <-- data
|
||||
|
||||
/dist/static/assets/stream.<HASH>.css /static/assets/stream.<HASH>.css
|
||||
/dist/static/assets/stream.<HASH>.js /static/assets/stream.<HASH>.js
|
||||
/dist/static/stream.html /embed/stream
|
||||
|
||||
### Admin
|
||||
|
||||
Admin - Renders the Admin page <-- data
|
||||
|
||||
/dist/static/assets/admin.<HASH>.css /static/assets/admin.<HASH>.css
|
||||
/dist/static/assets/admin.<HASH>.js /static/assets/admin.<HASH>.js
|
||||
/dist/static/admin.html /admin
|
||||
|
||||
## Development Routes
|
||||
|
||||
|
||||
localhost:3000
|
||||
/ -> /admin
|
||||
/dev <-- server side html for dev/iframe integration
|
||||
|
||||
localhost:8080
|
||||
/ -> localhost:3000/dev
|
||||
/embed/stream <-- stream html (now is at /)
|
||||
/admin <-- stream html (now is not there)
|
||||
+1
-1
@@ -10,7 +10,7 @@ const config: Config = {
|
||||
watchers: {
|
||||
compileSchema: {
|
||||
paths: ["core/server/**/*.graphql"],
|
||||
executor: new CommandExecutor("npm run compile:schema", {
|
||||
executor: new CommandExecutor("npx gulp server:schema", {
|
||||
runOnInit: true,
|
||||
}),
|
||||
},
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
const path = require("path");
|
||||
const json = require("comment-json");
|
||||
const fs = require("fs");
|
||||
const del = require("del");
|
||||
const gulp = require("gulp");
|
||||
const ts = require("gulp-typescript");
|
||||
const sourcemaps = require("gulp-sourcemaps");
|
||||
const babel = require("gulp-babel");
|
||||
const generateTypescriptTypes = require("./scripts/generateSchemaTypes");
|
||||
const _ = require("lodash");
|
||||
|
||||
// Parse the tsconfig.json file (which contains comments).
|
||||
const tsconfig = json.parse(fs.readFileSync("./src/tsconfig.json").toString());
|
||||
|
||||
// Create the typescript project.
|
||||
const tsProject = ts.createProject("./src/tsconfig.json");
|
||||
|
||||
const resolveDistFolder = (...paths) => "./" + path.join("dist", ...paths);
|
||||
|
||||
gulp.task("clean", () => del([resolveDistFolder()]));
|
||||
|
||||
gulp.task("server:schema", () => generateTypescriptTypes());
|
||||
|
||||
gulp.task("server:scripts", () =>
|
||||
gulp
|
||||
.src([
|
||||
"./src/**/*.ts",
|
||||
"./src/**/.*.ts",
|
||||
// Exclude client files from this, that's for webpack.
|
||||
"!./src/core/client/**/*.ts",
|
||||
"!./src/core/client/**/.*.ts",
|
||||
])
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(tsProject())
|
||||
.pipe(
|
||||
babel({
|
||||
plugins: [
|
||||
[
|
||||
"module-resolver",
|
||||
{
|
||||
root: [resolveDistFolder()],
|
||||
alias: _.reduce(
|
||||
tsconfig.compilerOptions.paths,
|
||||
(alias, [pathGlob], prefixBlob) => ({
|
||||
...alias,
|
||||
[prefixBlob.replace(/\/\*/g, "")]: pathGlob
|
||||
.replace(/\/\*/g, "")
|
||||
.replace(/^\./g, resolveDistFolder()),
|
||||
}),
|
||||
{}
|
||||
),
|
||||
},
|
||||
],
|
||||
],
|
||||
})
|
||||
)
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest(resolveDistFolder()))
|
||||
);
|
||||
|
||||
gulp.task("server:static", () =>
|
||||
gulp
|
||||
.src(["./src/core/server/**/*", "!./src/core/server/**/*.ts"])
|
||||
.pipe(gulp.dest(resolveDistFolder() + "/core/server"))
|
||||
);
|
||||
|
||||
gulp.task(
|
||||
"server",
|
||||
gulp.series("server:schema", gulp.parallel("server:scripts", "server:static"))
|
||||
);
|
||||
|
||||
gulp.task("default", gulp.series("clean", "server"));
|
||||
Generated
+1730
-281
File diff suppressed because it is too large
Load Diff
+16
-5
@@ -5,7 +5,7 @@
|
||||
"scripts": {
|
||||
"build": "npm-run-all compile --parallel build:*",
|
||||
"build:client": "ts-node ./scripts/build.ts",
|
||||
"build:server": "tsc -p ./src/tsconfig.json",
|
||||
"build:server": "gulp server",
|
||||
"compile": "npm-run-all --parallel compile:*",
|
||||
"compile:css-types": "tcm src/core/client/",
|
||||
"compile:relay-stream": "ts-node ./scripts/compileRelay --src ./src/core/client/stream --schema tenant",
|
||||
@@ -27,7 +27,7 @@
|
||||
"tscheck:client": "tsc --project ./src/core/client/tsconfig.json --noEmit",
|
||||
"tscheck:client-embed": "tsc --project ./src/core/client/embed/tsconfig.json --noEmit",
|
||||
"tscheck:scripts": "tsc --project ./tsconfig.json --noEmit",
|
||||
"watch": "cross-env NODE_ENV=development ts-node ./scripts/watcher/bin/watcher.ts --config ./config/watcher.ts"
|
||||
"watch": "NODE_ENV=development ts-node ./scripts/watcher/bin/watcher.ts --config ./config/watcher.ts"
|
||||
},
|
||||
"author": "",
|
||||
"license": "Apache-2.0",
|
||||
@@ -36,6 +36,7 @@
|
||||
"apollo-server-express": "^1.3.6",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"bunyan": "^1.8.12",
|
||||
"consolidate": "0.14.0",
|
||||
"convict": "^4.3.1",
|
||||
"dataloader": "^1.4.0",
|
||||
"dotenv": "^6.0.0",
|
||||
@@ -56,6 +57,7 @@
|
||||
"lodash": "^4.17.10",
|
||||
"luxon": "^1.3.1",
|
||||
"mongodb": "^3.1.1",
|
||||
"nunjucks": "^3.1.3",
|
||||
"passport": "^0.4.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"passport-oauth2": "^1.4.0",
|
||||
@@ -78,6 +80,7 @@
|
||||
"@types/chokidar": "^1.7.5",
|
||||
"@types/classnames": "^2.2.4",
|
||||
"@types/commander": "^2.12.2",
|
||||
"@types/consolidate": "0.0.34",
|
||||
"@types/convict": "^4.2.0",
|
||||
"@types/cross-spawn": "^6.0.0",
|
||||
"@types/dotenv": "^4.0.3",
|
||||
@@ -85,7 +88,6 @@
|
||||
"@types/enzyme-adapter-react-16": "^1.0.2",
|
||||
"@types/eventemitter2": "^4.1.0",
|
||||
"@types/express": "^4.16.0",
|
||||
"@types/extract-text-webpack-plugin": "^3.0.3",
|
||||
"@types/fs-extra": "^5.0.4",
|
||||
"@types/graphql": "^0.13.3",
|
||||
"@types/html-webpack-plugin": "^2.30.4",
|
||||
@@ -97,8 +99,10 @@
|
||||
"@types/linkify-it": "^2.0.3",
|
||||
"@types/lodash": "^4.14.111",
|
||||
"@types/luxon": "^0.5.3",
|
||||
"@types/mini-css-extract-plugin": "^0.2.0",
|
||||
"@types/mongodb": "^3.1.1",
|
||||
"@types/node": "^10.5.2",
|
||||
"@types/nunjucks": "^3.0.0",
|
||||
"@types/passport": "^0.4.6",
|
||||
"@types/passport-local": "^1.0.33",
|
||||
"@types/passport-oauth2": "^1.4.5",
|
||||
@@ -123,6 +127,7 @@
|
||||
"autoprefixer": "^8.6.5",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-loader": "^8.0.0-beta",
|
||||
"babel-plugin-module-resolver": "^3.1.1",
|
||||
"babel-plugin-relay": "github:coralproject/patched#babel-plugin-relay",
|
||||
"babel-preset-react-optimize": "^1.0.1",
|
||||
"case-sensitive-paths-webpack-plugin": "^2.1.2",
|
||||
@@ -130,16 +135,16 @@
|
||||
"chokidar": "^2.0.4",
|
||||
"classnames": "^2.2.5",
|
||||
"commander": "^2.16.0",
|
||||
"comment-json": "^1.1.3",
|
||||
"copy-webpack-plugin": "^4.5.1",
|
||||
"cross-env": "^5.2.0",
|
||||
"cross-spawn": "^6.0.5",
|
||||
"css-loader": "^0.28.11",
|
||||
"del": "^3.0.0",
|
||||
"docz": "^0.5.8",
|
||||
"enzyme": "^3.3.0",
|
||||
"enzyme-adapter-react-16": "^1.1.1",
|
||||
"enzyme-to-json": "^3.3.4",
|
||||
"eventemitter2": "^5.0.1",
|
||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||
"final-form": "^4.8.1",
|
||||
"flat": "^4.1.0",
|
||||
"fluent": "^0.6.4",
|
||||
@@ -148,6 +153,11 @@
|
||||
"fluent-react": "^0.7.0",
|
||||
"graphql-playground-middleware-express": "^1.7.2",
|
||||
"graphql-schema-typescript": "^1.2.1",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-babel": "^8.0.0-beta.2",
|
||||
"gulp-cli": "^2.0.1",
|
||||
"gulp-sourcemaps": "^2.6.4",
|
||||
"gulp-typescript": "^5.0.0-alpha.3",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"jest": "^23.4.1",
|
||||
"jest-junit": "^5.1.0",
|
||||
@@ -155,6 +165,7 @@
|
||||
"jsdom": "^11.11.0",
|
||||
"loader-utils": "^1.1.0",
|
||||
"material-design-icons": "^3.0.1",
|
||||
"mini-css-extract-plugin": "^0.4.1",
|
||||
"npm-run-all": "^4.1.3",
|
||||
"postcss-advanced-variables": "^2.3.3",
|
||||
"postcss-css-variables": "^0.9.0",
|
||||
|
||||
@@ -77,14 +77,20 @@ async function main() {
|
||||
return files;
|
||||
}
|
||||
|
||||
main()
|
||||
.then(files => {
|
||||
for (const { fileName } of files) {
|
||||
module.exports = main;
|
||||
|
||||
if (require.main === module) {
|
||||
// Only run the main module on file load if this is the main module (we're
|
||||
// executing this file directly).
|
||||
main()
|
||||
.then(files => {
|
||||
for (const { fileName } of files) {
|
||||
// tslint:disable-next-line:no-console
|
||||
console.log(`Generated ${fileName}`);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
// tslint:disable-next-line:no-console
|
||||
console.log(`Generated ${fileName}`);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
// tslint:disable-next-line:no-console
|
||||
console.error(err);
|
||||
});
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import CaseSensitivePathsPlugin from "case-sensitive-paths-webpack-plugin";
|
||||
import ExtractTextPlugin from "extract-text-webpack-plugin";
|
||||
import HtmlWebpackPlugin, { Options } from "html-webpack-plugin";
|
||||
import MiniCssExtractPlugin from "mini-css-extract-plugin";
|
||||
import path from "path";
|
||||
import InterpolateHtmlPlugin from "react-dev-utils/InterpolateHtmlPlugin";
|
||||
import WatchMissingNodeModulesPlugin from "react-dev-utils/WatchMissingNodeModulesPlugin";
|
||||
@@ -8,6 +8,7 @@ import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin";
|
||||
import UglifyJsPlugin from "uglifyjs-webpack-plugin";
|
||||
import webpack, { Configuration } from "webpack";
|
||||
import ManifestPlugin from "webpack-manifest-plugin";
|
||||
|
||||
import paths from "./paths";
|
||||
|
||||
interface CreateWebpackConfig {
|
||||
@@ -59,27 +60,6 @@ export default function createWebpackConfig({
|
||||
},
|
||||
};
|
||||
|
||||
const cssLoaders = [
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
modules: true,
|
||||
importLoaders: 1,
|
||||
localIdentName: "[name]-[local]-[hash:base64:5]",
|
||||
minimize: isProduction,
|
||||
sourceMap: isProduction && !disableSourcemaps,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("postcss-loader"),
|
||||
options: {
|
||||
config: {
|
||||
path: paths.appPostCssConfig,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const localesOptions = {
|
||||
pathToLocales: paths.appLocales,
|
||||
|
||||
@@ -127,13 +107,9 @@ export default function createWebpackConfig({
|
||||
},
|
||||
sourceMap: !disableSourcemaps,
|
||||
}),
|
||||
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
|
||||
new ExtractTextPlugin({
|
||||
// We use [md5:contenthash:hex:20] instead of [contenthash:8]
|
||||
// because of this bug https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/763.
|
||||
// TODO: Repalce with mini-css-extract-plugin once it supports HMR.
|
||||
// https://github.com/webpack-contrib/mini-css-extract-plugin
|
||||
filename: "assets/css/[name].[md5:contenthash:hex:20].css",
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "assets/css/[name].[hash].css",
|
||||
chunkFilename: "assets/css/[id].[hash].css",
|
||||
}),
|
||||
]
|
||||
: [
|
||||
@@ -316,19 +292,27 @@ export default function createWebpackConfig({
|
||||
// in development "style" loader enables hot editing of CSS.
|
||||
{
|
||||
test: /\.css$/,
|
||||
loader:
|
||||
(isProduction &&
|
||||
ExtractTextPlugin.extract({
|
||||
fallback: styleLoader,
|
||||
use: cssLoaders,
|
||||
})) ||
|
||||
undefined,
|
||||
use:
|
||||
(!isProduction && [
|
||||
require.resolve("style-loader"),
|
||||
...cssLoaders,
|
||||
]) ||
|
||||
undefined,
|
||||
use: [
|
||||
isProduction ? MiniCssExtractPlugin.loader : styleLoader,
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
modules: true,
|
||||
importLoaders: 1,
|
||||
localIdentName: "[name]-[local]-[hash:base64:5]",
|
||||
minimize: isProduction,
|
||||
sourceMap: isProduction && !disableSourcemaps,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("postcss-loader"),
|
||||
options: {
|
||||
config: {
|
||||
path: paths.appPostCssConfig,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// "file" loader makes sure those assets get served by WebpackDevServer.
|
||||
// When you `import` an asset, you get its (virtual) filename.
|
||||
|
||||
@@ -14,7 +14,6 @@ export interface SignupBody {
|
||||
username: string;
|
||||
password: string;
|
||||
email: string;
|
||||
displayName?: string;
|
||||
}
|
||||
|
||||
const SignupBodySchema = Joi.object().keys({
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const streamHandler: RequestHandler = (req, res) => {
|
||||
res.render("stream");
|
||||
};
|
||||
@@ -1,7 +1,10 @@
|
||||
import cons from "consolidate";
|
||||
import { Express } from "express";
|
||||
import http from "http";
|
||||
import { Redis } from "ioredis";
|
||||
import { Db } from "mongodb";
|
||||
import nunjucks from "nunjucks";
|
||||
import path from "path";
|
||||
|
||||
import { Config } from "talk-common/config";
|
||||
import { notFoundMiddleware } from "talk-server/app/middleware/notFound";
|
||||
@@ -29,6 +32,9 @@ export interface AppOptions {
|
||||
* createApp will create a Talk Express app that can be used to handle requests.
|
||||
*/
|
||||
export async function createApp(options: AppOptions): Promise<Express> {
|
||||
// Configure the application.
|
||||
configureApplication(options);
|
||||
|
||||
// Pull the parent out of the options.
|
||||
const { parent } = options;
|
||||
|
||||
@@ -46,7 +52,7 @@ export async function createApp(options: AppOptions): Promise<Express> {
|
||||
);
|
||||
|
||||
// Static Files
|
||||
parent.use(serveStatic);
|
||||
parent.use("/assets", serveStatic);
|
||||
|
||||
// Error Handling
|
||||
parent.use(notFoundMiddleware);
|
||||
@@ -70,6 +76,38 @@ export const listenAndServe = (
|
||||
const httpServer = app.listen(port, () => resolve(httpServer));
|
||||
});
|
||||
|
||||
function configureApplication(options: AppOptions) {
|
||||
const { parent } = options;
|
||||
|
||||
// Trust the first proxy in front of us, this will enable us to trust the fact
|
||||
// that SSL was terminated correctly.
|
||||
parent.set("trust proxy", 1);
|
||||
|
||||
// Setup the view config.
|
||||
setupViews(options);
|
||||
}
|
||||
|
||||
function setupViews(options: AppOptions) {
|
||||
const { parent } = options;
|
||||
|
||||
// configure the default views directory.
|
||||
const views = path.join(__dirname, "..", "..", "..", "static");
|
||||
parent.set("views", views);
|
||||
|
||||
// Reconfigure nunjucks.
|
||||
(cons.requires as any).nunjucks = nunjucks.configure(views, {
|
||||
// In development, we should enable file watch mode.
|
||||
watch: options.config.get("env") === "development",
|
||||
});
|
||||
|
||||
// assign the nunjucks engine to .njk and .html files.
|
||||
parent.engine("njk", cons.nunjucks);
|
||||
parent.engine("html", cons.nunjucks);
|
||||
|
||||
// set .html as the default extension.
|
||||
parent.set("view engine", "html");
|
||||
}
|
||||
|
||||
/**
|
||||
* attachSubscriptionHandlers attaches all the handlers to the http.Server to
|
||||
* handle websocket traffic by upgrading their http connections to websocket.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const notFoundMiddleware: RequestHandler = (req, res, next) => {
|
||||
// FIXME: (wyattjoh) send an error that won't log as crazily as this one does.
|
||||
next(new Error("not found"));
|
||||
};
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import serveStatic from "express-static-gzip";
|
||||
import path from "path";
|
||||
|
||||
export default serveStatic(path.join(__dirname, "..", "..", "dist"), {});
|
||||
const staticPath = path.resolve(
|
||||
path.join(__dirname, "..", "..", "..", "..", "static", "assets")
|
||||
);
|
||||
|
||||
export default serveStatic(staticPath, { index: false });
|
||||
|
||||
@@ -28,6 +28,9 @@ export default (options: MiddlewareOptions) => async (
|
||||
// Attach the tenant to the request.
|
||||
req.tenant = tenant;
|
||||
|
||||
// Attach the tenant to the view locals.
|
||||
res.locals.tenant = tenant;
|
||||
|
||||
next();
|
||||
} catch (err) {
|
||||
next(err);
|
||||
|
||||
@@ -2,6 +2,7 @@ import express from "express";
|
||||
import passport from "passport";
|
||||
|
||||
import { signupHandler } from "talk-server/app/handlers/auth/local";
|
||||
import { streamHandler } from "talk-server/app/handlers/embed/stream";
|
||||
import { apiErrorHandler } from "talk-server/app/middleware/error";
|
||||
import { errorLogger } from "talk-server/app/middleware/logging";
|
||||
import { wrapAuthn } from "talk-server/app/middleware/passport";
|
||||
@@ -134,5 +135,8 @@ export async function createRouter(app: AppOptions, options: RouterOptions) {
|
||||
);
|
||||
}
|
||||
|
||||
// Handle the stream handler.
|
||||
router.get("/embed/stream", streamHandler);
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user