UNPKG

4.24 kBJavaScriptView Raw
1"use strict";
2
3/* External Libraries */
4const fs = require("fs"),
5 path = require("path"),
6 shell = require("shelljs");
7/* Environment Variables */
8
9
10const NODE_ENV = "production" || "development";
11/* Meta Information */
12// const {name} = JSON.parse(shell.cat(path.join(__dirname, "package.json")));
13
14const {
15 name
16} = require(path.join(__dirname, "package.json"));
17/* File Directories */
18
19
20const rootPath = __dirname;
21const appPath = path.join(rootPath, "app");
22const staticPath = path.join(rootPath, process.env.CANON_STATIC_FOLDER || "static");
23const canonPath = name === "@datawheel/canon-core" ? rootPath : path.join(rootPath, "node_modules/@datawheel/canon-core/");
24const serverPath = NODE_ENV === "development" ? __dirname : path.join(canonPath, "bin/server/");
25const paths = {
26 appPath,
27 canonPath,
28 rootPath,
29 serverPath,
30 staticPath
31};
32/* Internal Helper Functions */
33
34const moduleName = require(path.join(serverPath, "helpers/moduleName")),
35 title = require(path.join(serverPath, "helpers/title"));
36/* Build Steps */
37
38
39const stepCache = require(path.join(serverPath, "steps/cache")),
40 stepDb = require(path.join(serverPath, "steps/db")),
41 stepRouter = require(path.join(serverPath, "steps/router")),
42 stepStore = require(path.join(serverPath, "steps/store"));
43/**
44 Main server spinup function.
45*/
46
47
48async function start() {
49 /* Detects which directories to load server files from ("api/", "db/", etc) */
50 title("Detecting Canon Plugins", "🧩");
51 const modules = [rootPath];
52 const moduleFolder = path.join(rootPath, "node_modules/@datawheel/");
53
54 if (shell.test("-d", moduleFolder)) {
55 fs.readdirSync(moduleFolder).forEach(folder => {
56 const fullPath = path.join(moduleFolder, folder);
57 shell.echo(moduleName(fullPath) || folder);
58 modules.unshift(path.join(fullPath, "src/"));
59 });
60 } else {
61 shell.echo("no canon plugins detected");
62 }
63
64 if (name.includes("@datawheel/canon")) modules.unshift(path.join(rootPath, "src/"));
65 title("Registering Services", "🛎️");
66 const opbeatApp = process.env.CANON_OPBEAT_APP;
67 const opbeatOrg = process.env.CANON_OPBEAT_ORG;
68 const opbeatToken = process.env.CANON_OPBEAT_TOKEN;
69 const opbeat = opbeatApp && opbeatOrg && opbeatToken ? require("opbeat").start({
70 appId: opbeatApp,
71 organizationId: opbeatOrg,
72 secretToken: opbeatToken
73 }) : false;
74 shell.echo(`Opbeat: ${opbeat ? "Enabled" : "Disabled"}`);
75 shell.cp(path.join(rootPath, "node_modules/normalize.css/normalize.css"), path.join(staticPath, "assets/normalize.css"));
76 /* define some globally used internal variables */
77
78 const config = {
79 NODE_ENV,
80 modules,
81 opbeat,
82 name,
83 paths
84 };
85 const {
86 files: storeFiles
87 } = await stepStore(config);
88 const {
89 files: dbFiles
90 } = await stepDb(config);
91 const {
92 files: cacheFiles
93 } = await stepCache(config);
94 const routerInit = stepRouter(config);
95 let server = routerInit.server;
96 const routerFiles = routerInit.files;
97 /** Process to reboot the DB when changes are detected */
98
99 async function rebootDb() {
100 await config.db.close();
101 await stepDb(config);
102 }
103 /** Process to reboot the Express API when changes are detected */
104
105
106 function rebootApi() {
107 server.destroy();
108 const routerConfig = stepRouter(config);
109 server = routerConfig.server;
110 }
111
112 const watchFiles = [path.join(appPath, "style.yml"), ...storeFiles, ...cacheFiles, ...dbFiles, ...routerFiles];
113
114 if (NODE_ENV === "development") {
115 const chokidar = require("chokidar");
116
117 chokidar.watch(watchFiles, {
118 ignoreInitial: true
119 }).on("all", async (event, path) => {
120 if (["change", "add", "unlink"].includes(event)) {
121 title(`Change detected: ${path.replace(paths.rootPath, "")}`, "👀️");
122 config.change = path;
123 delete require.cache[path];
124
125 if (storeFiles.some(f => path.startsWith(f))) {
126 stepStore(config);
127 } else if (cacheFiles.some(f => path.startsWith(f))) {
128 await stepCache(config);
129 } else if (dbFiles.some(f => path.startsWith(f))) {
130 await rebootDb();
131 }
132
133 rebootApi();
134 }
135 });
136 }
137
138 if (process.send) process.send("ready");
139}
140
141start();
\No newline at end of file