Merge branch 'next' into next-passport

This commit is contained in:
Wyatt Johnson
2018-07-04 09:57:07 -06:00
16 changed files with 624 additions and 54 deletions
+2
View File
@@ -11,6 +11,8 @@
"cwd": "${workspaceFolder}",
"program": "${workspaceFolder}/node_modules/.bin/ts-node",
"args": [
"--project",
"${workspaceFolder}/src/tsconfig.json",
"-r",
"tsconfig-paths/register",
"${workspaceFolder}/src/index.ts"
+3
View File
@@ -1,5 +1,8 @@
{
"editor.formatOnSave": true,
"files.associations": {
"*.css": "postcss"
},
"files.exclude": {
"**/.git": true,
"**/.svn": true,
+41
View File
@@ -0,0 +1,41 @@
import path from "path";
import {
CommandExecutor,
Config,
LongRunningExecutor,
} from "../scripts/watcher";
const config: Config = {
rootDir: path.resolve(__dirname, "../src"),
watchers: {
compileRelayStream: {
paths: [
"core/client/stream/**/*.ts",
"core/client/stream/**/*.tsx",
"core/client/stream/**/*.graphql",
"core/client/server/**/*.graphql",
],
ignore: ["core/**/*.d.ts"],
executor: new CommandExecutor("npm run compile:relay-stream", {
runOnInit: true,
}),
},
compileCSSTypes: {
paths: ["**/*.css"],
executor: new CommandExecutor("npm run compile:css-types", {
runOnInit: true,
}),
},
runServer: {
paths: ["core/**/*.ts", "core/locales/**/*.ftl"],
ignore: ["core/client/**/*"],
executor: new LongRunningExecutor("npm run start:development"),
},
runWebpackDevServer: {
paths: [],
executor: new LongRunningExecutor("npm run start:webpackDevServer"),
},
},
};
export default config;
+97 -15
View File
@@ -1437,12 +1437,31 @@
"@types/node": "*"
}
},
"@types/chokidar": {
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/@types/chokidar/-/chokidar-1.7.5.tgz",
"integrity": "sha512-PDkSRY7KltW3M60hSBlerxI8SFPXsO3AL/aRVsO4Kh9IHRW74Ih75gUuTd/aE4LSSFqypb10UIX3QzOJwBQMGQ==",
"dev": true,
"requires": {
"@types/events": "*",
"@types/node": "*"
}
},
"@types/classnames": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.4.tgz",
"integrity": "sha512-UWUmNYhaIGDx8Kv0NSqFRwP6HWnBMXam4nBacOrjIiPBKKCdWMCe77+Nbn6rI9+Us9c+BhE26u84xeYQv2bKeA==",
"dev": true
},
"@types/commander": {
"version": "2.12.2",
"resolved": "https://registry.npmjs.org/@types/commander/-/commander-2.12.2.tgz",
"integrity": "sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q==",
"dev": true,
"requires": {
"commander": "*"
}
},
"@types/connect": {
"version": "3.4.32",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
@@ -1457,6 +1476,15 @@
"integrity": "sha512-p+gNRe4RPjpl1lTBUomFJ42P8ymArH/P93DFJ0iY873BJ4ZmogcKc6TbHgZQmtQMsy3jxcAo0HcTjidXwo8uKg==",
"dev": true
},
"@types/cross-spawn": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.0.tgz",
"integrity": "sha512-evp2ZGsFw9YKprDbg8ySgC9NA15g3YgiI8ANkGmKKvvi0P2aDGYLPxQIC5qfeKNUOe3TjABVGuah6omPRpIYhg==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/dotenv": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-4.0.3.tgz",
@@ -1531,9 +1559,9 @@
"dev": true
},
"@types/joi": {
"version": "13.0.8",
"resolved": "https://registry.npmjs.org/@types/joi/-/joi-13.0.8.tgz",
"integrity": "sha512-GXYdIVpwBP5ZBOlHitSYfQdH+vWXVahhkeQwalX0LkoX7Mx0D3L3tg4vXXhr6nYHkEpWlAzWuEjgWEBtcp5NZA==",
"version": "13.3.0",
"resolved": "https://registry.npmjs.org/@types/joi/-/joi-13.3.0.tgz",
"integrity": "sha512-nOnsbHvoo5DsQEh8VGlbQlfg9+/iFSxE5RQKLNkAODIqyupdEkBCZf6RCNxR+9X0egMIkJ43NnwkEJKxLogsIA==",
"dev": true
},
"@types/jsonwebtoken": {
@@ -4988,23 +5016,24 @@
"dev": true
},
"chokidar": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz",
"integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
"integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==",
"dev": true,
"requires": {
"anymatch": "^2.0.0",
"async-each": "^1.0.0",
"braces": "^2.3.0",
"fsevents": "^1.1.2",
"fsevents": "^1.2.2",
"glob-parent": "^3.1.0",
"inherits": "^2.0.1",
"is-binary-path": "^1.0.0",
"is-glob": "^4.0.0",
"lodash.debounce": "^4.0.8",
"normalize-path": "^2.1.1",
"path-is-absolute": "^1.0.0",
"readdirp": "^2.0.0",
"upath": "^1.0.0"
"upath": "^1.0.5"
}
},
"chownr": {
@@ -5156,6 +5185,19 @@
"p-finally": "^1.0.0",
"signal-exit": "^3.0.0",
"strip-eof": "^1.0.0"
},
"dependencies": {
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
"integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
"dev": true,
"requires": {
"lru-cache": "^4.0.1",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
}
}
}
}
@@ -5349,9 +5391,9 @@
}
},
"commander": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
"version": "2.16.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz",
"integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==",
"dev": true
},
"commondir": {
@@ -5840,12 +5882,14 @@
}
},
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
"integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"dev": true,
"requires": {
"lru-cache": "^4.0.1",
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
@@ -6973,6 +7017,17 @@
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
}
},
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
"integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
"dev": true,
"requires": {
"lru-cache": "^4.0.1",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
}
}
}
@@ -7510,6 +7565,19 @@
"p-finally": "^1.0.0",
"signal-exit": "^3.0.0",
"strip-eof": "^1.0.0"
},
"dependencies": {
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
"integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
"dev": true,
"requires": {
"lru-cache": "^4.0.1",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
}
}
},
"exit": {
@@ -9586,6 +9654,14 @@
"param-case": "2.1.x",
"relateurl": "0.2.x",
"uglify-js": "3.4.x"
},
"dependencies": {
"commander": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
"dev": true
}
}
},
"html-webpack-plugin": {
@@ -19704,6 +19780,12 @@
"source-map": "~0.6.1"
},
"dependencies": {
"commander": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
"dev": true
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+17 -16
View File
@@ -5,26 +5,21 @@
"scripts": {
"start": "node dist/index.js",
"test": "node scripts/test.js --env=jsdom",
"build": "npm-run-all --parallel compile:* && npm-run-all --parallel build:*",
"build": "npm-run-all --parallel compile:* --parallel build:*",
"build:client": "node ./scripts/build.js",
"build:server": "tsc",
"watch": "NODE_ENV=development npm-run-all compile:* --parallel watch:*",
"watch:client": "node ./scripts/start.js",
"watch:css-types": "tcm src/core/client/ --watch",
"watch:relay-stream": "nodemon --config ./config/nodemon/relay-stream.json",
"watch:server": "nodemon --config ./config/nodemon/server.json",
"watch:types": "nodemon --config ./config/nodemon/types.json",
"build:server": "tsc -p ./src/tsconfig.json",
"watch": "NODE_ENV=development ts-node ./scripts/watcher/bin/watcher.ts ./config/watcher.ts",
"compile:css-types": "tcm src/core/client/",
"compile:relay-stream": "relay-compiler --src ./src/core/client/stream --schema ./src/core/server/graph/tenant/schema/schema.graphql --language typescript --artifactDirectory ./src/core/client/stream/__generated__ --no-watchman",
"compile:server:types": "node ./scripts/types.js",
"start:development": "NODE_ENV=development ts-node -r tsconfig-paths/register src/index.ts",
"watch:types": "nodemon --config ./config/nodemon/types.json",
"compile:relay-stream": "relay-compiler --src ./src/core/client/stream --schema $(ts-node ./scripts/schemaPath.ts tenant) --language typescript --artifactDirectory ./src/core/client/stream/__generated__ --no-watchman",
"start:development": "NODE_ENV=development ts-node --project ./src/tsconfig.json -r tsconfig-paths/register ./src/index.ts",
"start:webpackDevServer": "node ./scripts/start.js",
"lint-fix": "npm run lint:server -- --fix && npm run lint:client -- --fix && npm run lint:scripts -- --fix",
"lint": "npm-run-all --parallel lint:*",
"lint:server": "tslint --project ./tsconfig.json",
"lint:server": "tslint --project ./src/tsconfig.json",
"lint:client": "tslint --project ./src/core/client/tsconfig.json",
"docz:watch": "docz dev",
"postinstall": "node ./scripts/types.js",
"lint:scripts": "tslint ./config/**/*.js ./scripts/**/*.js ./doczrc.js ./src/**/.*.js"
"lint:scripts": "tslint --project ./tsconfig.json",
"docz:watch": "docz dev"
},
"author": "",
"license": "Apache-2.0",
@@ -64,8 +59,11 @@
"@babel/preset-env": "7.0.0-beta.49",
"@babel/preset-react": "7.0.0-beta.49",
"@types/bunyan": "^1.8.4",
"@types/chokidar": "^1.7.5",
"@types/classnames": "^2.2.4",
"@types/commander": "^2.12.2",
"@types/convict": "^4.2.0",
"@types/cross-spawn": "^6.0.0",
"@types/dotenv": "^4.0.3",
"@types/express": "^4.16.0",
"@types/graphql": "^0.13.1",
@@ -93,8 +91,11 @@
"babel-preset-react-optimize": "^1.0.1",
"case-sensitive-paths-webpack-plugin": "^2.1.2",
"chalk": "^2.4.1",
"chokidar": "^2.0.4",
"classnames": "^2.2.5",
"commander": "^2.16.0",
"copy-webpack-plugin": "^4.5.1",
"cross-spawn": "^6.0.5",
"css-loader": "^0.28.11",
"docz": "^0.2.6",
"docz-theme-default": "^0.2.10",
@@ -149,4 +150,4 @@
"webpack-hot-client": "^4.0.3",
"webpack-manifest-plugin": "^2.0.3"
}
}
}
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env ts-node
import program from "commander";
import fs from "fs";
import path from "path";
const config = JSON.parse(
fs.readFileSync(path.resolve(__dirname, "../.graphqlconfig"), "utf8")
);
program
.version("0.1.0")
.usage("<project>")
.arguments("<project>")
.description(
"Returns the schema graph in `.graphqlconfig` based on <project>"
)
.action(project => {
if (!config.projects) {
// tslint:disable-next-line:no-console
console.error("Missing projects key in .graphqconfig");
process.exit(1);
}
if (!config.projects[project]) {
// tslint:disable-next-line:no-console
console.error(`Project ${project} not found in .graphqconfig`);
process.exit(1);
}
if (!config.projects[project].schemaPath) {
// tslint:disable-next-line:no-console
console.error(
`SchemaPath for project ${project} not found in .graphqconfig`
);
process.exit(1);
}
// tslint:disable-next-line:no-console
console.log(config.projects[project].schemaPath);
})
.parse(process.argv);
+81
View File
@@ -0,0 +1,81 @@
import chokidar from "chokidar";
import { Watcher, WatchOptions } from "./types";
export default class ChokidarWatcher implements Watcher {
public watch(
paths: ReadonlyArray<string>,
options: WatchOptions = {}
): AsyncIterable<string> {
const client = chokidar.watch(paths as string[], {
ignored: options.ignore,
});
// An array to hold all changes, that has not yet been yield.
const queue: string[] = [];
let firstError: Error | null = null;
// If this is set, a pending promise is waiting for the next result.
let pending:
| ({ resolve: (result: string) => void; reject: (error: Error) => void })
| null = null;
// Listen for errors
client.on("error", (error: Error) => {
// Resolve pending request.
if (pending) {
pending.reject(error);
pending = null;
return;
}
if (!firstError) {
firstError = error;
}
});
// Listen for changes
client.on("change", (pathFile: string) => {
// Resolve pending request.
if (pending) {
pending.resolve(pathFile);
pending = null;
return;
}
// There is no pending request, save it into the queue.
queue.unshift(pathFile);
});
return {
[Symbol.asyncIterator]() {
return {
next: () =>
new Promise<IteratorResult<string>>((resolve, reject) => {
const wrapped = {
resolve: (pathFile: string) =>
resolve({
done: false,
value: pathFile,
}),
reject: (error: Error) =>
reject({
done: true,
value: error,
}),
};
// We already have a change to return
if (firstError) {
wrapped.reject(firstError);
return;
}
if (queue.length) {
wrapped.resolve(queue.pop()!);
return;
}
// We need to wait for the next change event.
pending = wrapped;
}),
};
},
};
}
}
+81
View File
@@ -0,0 +1,81 @@
import spawn from "cross-spawn";
import { Cancelable, debounce } from "lodash";
import { Executor } from "./types";
interface CommandExecutorOptions {
args?: ReadonlyArray<string>;
// If true, allow spawning multiple processes.
spawnMutiple?: boolean;
// Specify the period in which the process is started at max once.
debounce?: number | false;
// If true, will run command upon initialization.
runOnInit?: boolean;
}
export default class CommandExecutor implements Executor {
private cmd: string;
private args?: ReadonlyArray<string>;
private spawnMultiple: boolean;
private runOnInit: boolean;
private isRunning: boolean = false;
private shouldRespawn: boolean = false;
private spawnProcessDebounced?: (() => void) & Cancelable;
constructor(cmd: string, opts: CommandExecutorOptions = {}) {
this.cmd = cmd;
this.args = opts.args;
this.spawnMultiple = opts.spawnMutiple || false;
this.runOnInit = opts.runOnInit || false;
const wait = opts.debounce === undefined ? 500 : opts.debounce;
if (wait) {
this.spawnProcessDebounced = debounce(() => this.spawnProcess(), wait);
}
}
// This is called before watching starts.
public onInit(): void {
if (this.runOnInit) {
this.spawnProcessPotentiallyDebounced();
}
}
private spawnProcessPotentiallyDebounced() {
if (this.spawnProcessDebounced) {
this.spawnProcessDebounced();
return;
}
this.spawnProcess();
}
private spawnProcess() {
if (this.isRunning && !this.spawnMultiple) {
this.shouldRespawn = true;
return;
}
this.isRunning = true;
this.shouldRespawn = false;
const child = spawn(this.cmd, this.args as string[], {
stdio: "inherit",
shell: !this.args,
});
child.on("close", (code: number) => {
this.isRunning = false;
if (code !== 0) {
// tslint:disable-next-line: no-console
console.log(`We had an error building ${code}`);
}
if (this.shouldRespawn) {
this.spawnProcessPotentiallyDebounced();
}
});
}
public execute(filePath: string) {
this.spawnProcessPotentiallyDebounced();
}
}
+88
View File
@@ -0,0 +1,88 @@
import { ChildProcess } from "child_process";
import spawn from "cross-spawn";
import { Cancelable, debounce } from "lodash";
import { Executor } from "./types";
interface LongRunningExecutorOptions {
args?: ReadonlyArray<string>;
// Specify the period in which the process is restarted at max once.
debounce?: number;
}
export default class LongRunningExecutor implements Executor {
private cmd: string;
private args?: ReadonlyArray<string>;
private process: ChildProcess | null = null;
private isRunning: boolean = false;
private shouldRestart: boolean = false;
private restartDebounced: (() => void) & Cancelable;
constructor(cmd: string, opts: LongRunningExecutorOptions = {}) {
this.cmd = cmd;
this.args = opts.args;
this.restartDebounced = debounce(
() => this.restart(),
opts.debounce || 500
);
}
private spawnProcess() {
this.isRunning = true;
this.process = spawn(this.cmd, this.args as string[], {
stdio: "inherit",
// Have all child processes in their own group.
// See `process.kill` below.
detached: true,
shell: !this.args,
});
this.process!.on("exit", (code: number) => {
this.isRunning = false;
if (code !== 0 && code !== null) {
// tslint:disable-next-line: no-console
console.error(`Exit code returned ${code}`);
return;
}
if (this.shouldRestart) {
this.spawnProcess();
}
});
}
private restart(): void {
this.shouldRestart = true;
// Using the `-` will kill all child procceses in the group.
// See: https://azimi.me/2014/12/31/kill-child_process-node-js.html
process.kill(-this.process!.pid, "SIGTERM");
}
private kill(): void {
this.shouldRestart = false;
// Using the `-` will kill all child procceses in the group.
// See: https://azimi.me/2014/12/31/kill-child_process-node-js.html
process.kill(-this.process!.pid, "SIGTERM");
}
// This is called before watching starts.
public onInit(): void {
this.spawnProcess();
}
// This is called before exiting.
public onCleanup() {
this.restartDebounced.cancel();
if (this.isRunning) {
this.kill();
}
}
public execute(filePath: string) {
if (this.isRunning) {
this.restartDebounced();
return;
}
this.spawnProcess();
}
}
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env ts-node
import program from "commander";
import path from "path";
import watch from "../";
program
.version("0.1.0")
.usage("<configFile>")
.arguments("<configFile>")
.description("Run watchers defined in <configFile>")
.action(configFile => {
let config: any = require(path.resolve(configFile));
if (config.__esModule) {
config = config.default;
}
watch(config);
})
.parse(process.argv);
+5
View File
@@ -0,0 +1,5 @@
export { default as ChokidarWatcher } from "./ChokidarWatcher";
export { default as CommandExecutor } from "./CommandExecutor";
export { default as LongRunningExecutor } from "./LongRunningExecutor";
export { default } from "./watch";
export * from "./types";
+50
View File
@@ -0,0 +1,50 @@
import Joi from "joi";
export interface WatchOptions {
ignore?: ReadonlyArray<string>;
}
export interface Watcher {
watch(
paths: ReadonlyArray<string>,
options?: WatchOptions
): AsyncIterable<string>;
}
export interface Executor {
onInit?(): void;
onCleanup?(): void;
execute(filePath: string): void;
}
export interface Config {
rootDir?: string;
backend?: Watcher;
watchers: {
[key: string]: WatchConfig;
};
}
export interface WatchConfig {
paths: ReadonlyArray<string>;
ignore?: ReadonlyArray<string>;
executor: Executor;
}
export const configSchema = Joi.object({
rootDir: Joi.string().optional(),
backend: Joi.object().optional(),
watchers: Joi.object().pattern(
/.*/,
Joi.object({
paths: Joi.array()
.items(Joi.string())
.unique(),
ignore: Joi.array()
.items(Joi.string())
.unique()
.optional(),
executor: Joi.object(),
})
),
});
+58
View File
@@ -0,0 +1,58 @@
import Joi from "joi";
import path from "path";
import ChokidarWatcher from "./ChokidarWatcher";
import { Config, configSchema, WatchConfig, Watcher } from "./types";
// Polyfill the asyncIterator symbol.
if (Symbol.asyncIterator === undefined) {
(Symbol as any).asyncIterator = Symbol.for("asyncIterator");
}
async function beginWatch(watcher: Watcher, key: string, config: WatchConfig) {
const { paths, ignore, executor } = config;
if (executor.onInit) {
executor.onInit();
}
for await (const filePath of watcher.watch(paths, { ignore })) {
// tslint:disable-next-line:no-console
console.log(`Execute "${key}"`);
executor.execute(filePath);
}
}
function prependRootDir(prepend: string, cfg: WatchConfig): WatchConfig {
const prependFunc = (p: string) => path.resolve(prepend, p);
return {
...cfg,
paths: cfg.paths.map(prependFunc),
ignore: cfg.ignore ? cfg.ignore.map(prependFunc) : undefined,
};
}
function setupCleanup(config: Config) {
["SIGINT", "SIGTERM"].forEach(signal =>
process.once(signal as any, () => {
for (const key of Object.keys(config.watchers)) {
if (config.watchers[key].executor.onCleanup) {
config.watchers[key].executor.onCleanup!();
}
}
process.exit(0);
})
);
}
export default async function watch(config: Config) {
Joi.assert(config, configSchema);
const watcher = config.backend || new ChokidarWatcher();
setupCleanup(config);
for (const key of Object.keys(config.watchers)) {
// tslint:disable-next-line:no-console
console.log(`Start watcher "${key}"`);
const watcherConfig = config.rootDir
? prependRootDir(config.rootDir, config.watchers[key])
: config.watchers[key];
beginWatch(watcher, key, watcherConfig);
}
}
+1 -2
View File
@@ -4,8 +4,7 @@
"target": "es2015",
"module": "esnext",
"jsx": "preserve",
"noEmit": true,
"strictNullChecks": true,
"allowJs": false,
"lib": [
"dom",
"es7",
+34
View File
@@ -0,0 +1,34 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"allowJs": false,
"sourceMap": true,
"pretty": false,
"removeComments": true,
"noEmit": false,
"outDir": "../dist",
// See https://github.com/prismagraphql/graphql-request/issues/26 for why we
// have to include "dom" here.
"lib": [
"es6",
"esnext.asynciterable",
"dom"
],
"baseUrl": "./",
"paths": {
"talk-server/*": [
"./core/server/*"
],
"talk-common/*": [
"./core/common/*"
]
}
},
"include": [
"./**/*"
],
"exclude": [
"node_modules",
"./core/client"
]
}
+8 -21
View File
@@ -3,6 +3,7 @@
"target": "es5",
"module": "commonjs",
"allowJs": true,
"noEmit": true,
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
@@ -12,32 +13,18 @@
"noImplicitAny": true,
"strictNullChecks": true,
"noErrorTruncation": true,
"sourceMap": true,
"pretty": false,
"removeComments": true,
"outDir": "dist",
// See https://github.com/prismagraphql/graphql-request/issues/26 for why we
// have to include "dom" here.
"lib": [
"es6",
"esnext.asynciterable",
"dom"
],
"baseUrl": "./",
"paths": {
"talk-server/*": [
"./src/core/server/*"
],
"talk-common/*": [
"./src/core/common/*"
]
}
"esnext.asynciterable"
]
},
"include": [
"src/**/*"
"./src/**/.*.js",
"./scripts/**/*",
"./config/**/*",
"*.js"
],
"exclude": [
"node_modules",
"./src/core/client"
"node_modules"
]
}