You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

225 line
8.9 KiB

  1. const fs = require('fs-extra');
  2. const debug = require('debug')('server-connect:setup:routes');
  3. const config = require('./config');
  4. const { map } = require('../core/async');
  5. const { posix, extname } = require('path');
  6. const { cache, serverConnect, templateView } = require('../core/middleware');
  7. const database = require('./database');
  8. const webhooks = require('./webhooks');
  9. module.exports = async function (app) {
  10. app.use((req, res, next) => {
  11. req.fragment = (req.headers['accept'] || '*/*').includes('fragment');
  12. next();
  13. });
  14. if (fs.existsSync('extensions/server_connect/routes')) {
  15. const entries = fs.readdirSync('extensions/server_connect/routes', { withFileTypes: true });
  16. for (let entry of entries) {
  17. if (entry.isFile() && extname(entry.name) == '.js') {
  18. let hook = require(`../../extensions/server_connect/routes/${entry.name}`);
  19. if (hook.before) hook.before(app);
  20. if (hook.handler) hook.handler(app);
  21. debug(`Custom router ${entry.name} loaded`);
  22. }
  23. }
  24. }
  25. if (config.createApiRoutes) {
  26. fs.ensureDirSync('app/api');
  27. createApiRoutes('app/api');
  28. }
  29. if (fs.existsSync('app/config/routes.json')) {
  30. const { routes, layouts } = fs.readJSONSync('app/config/routes.json');
  31. parseRoutes(routes, null);
  32. function parseRoutes(routes, parent) {
  33. for (let route of routes) {
  34. if (!route.path) continue;
  35. createRoute(route, parent);
  36. if (Array.isArray(route.routes)) {
  37. parseRoutes(route.routes, route);
  38. }
  39. }
  40. }
  41. function createRoute({ path, method, redirect, url, page, layout, exec, data, ttl, status }, parent) {
  42. method = method || 'all';
  43. data = data || {};
  44. if (page) page = page.replace(/^\//, '');
  45. if (layout) layout = layout.replace(/^\//, '');
  46. if (parent && parent.path) path = parent.path + path;
  47. if (redirect) {
  48. app.get(path, (req, res) => res.redirect(status == 302 ? 302 : 301, redirect));
  49. } else if (url) {
  50. app[method](path, (req, res, next) => {
  51. next(parent && !req.fragment ? 'route' : null);
  52. }, (req, res) => {
  53. res.sendFile(url, { root: 'public' })
  54. });
  55. if (parent) {
  56. createRoute({
  57. path,
  58. method: parent.method,
  59. redirect: parent.redirect,
  60. url: parent.url,
  61. page: parent.page,
  62. layout: parent.layout,
  63. exec: parent.exec,
  64. data: parent.data
  65. });
  66. }
  67. } else if (page) {
  68. if (exec) {
  69. if (fs.existsSync(`app/${exec}.json`)) {
  70. let json = fs.readJSONSync(`app/${exec}.json`);
  71. if (json.exec && json.exec.steps) {
  72. json = json.exec.steps;
  73. } else if (json.steps) {
  74. json = json.steps;
  75. }
  76. if (!Array.isArray(json)) {
  77. json = [json];
  78. }
  79. if (layout && layouts && layouts[layout]) {
  80. if (layouts[layout].data) {
  81. data = Object.assign({}, layouts[layout].data, data);
  82. }
  83. if (layouts[layout].exec) {
  84. if (fs.existsSync(`app/${layouts[layout].exec}.json`)) {
  85. let _json = fs.readJSONSync(`app/${layouts[layout].exec}.json`);
  86. if (_json.exec && _json.exec.steps) {
  87. _json = _json.exec.steps;
  88. } else if (_json.steps) {
  89. _json = _json.steps;
  90. }
  91. if (!Array.isArray(_json)) {
  92. _json = [_json];
  93. }
  94. json = _json.concat(json);
  95. } else {
  96. debug(`Route ${path} skipped, "app/${exec}.json" not found`);
  97. return;
  98. }
  99. }
  100. }
  101. app[method](path, (req, res, next) => {
  102. next(parent && !req.fragment ? 'route' : null);
  103. }, cache({ttl}), templateView(layout, page, data, json));
  104. } else {
  105. debug(`Route ${path} skipped, "app/${exec}.json" not found`);
  106. return;
  107. }
  108. } else {
  109. let json = [];
  110. if (layout && layouts && layouts[layout]) {
  111. if (layouts[layout].data) {
  112. data = Object.assign({}, layouts[layout].data, data);
  113. }
  114. if (layouts[layout].exec) {
  115. if (fs.existsSync(`app/${layouts[layout].exec}.json`)) {
  116. let _json = fs.readJSONSync(`app/${layouts[layout].exec}.json`);
  117. if (_json.exec && _json.exec.steps) {
  118. _json = _json.exec.steps;
  119. } else if (_json.steps) {
  120. _json = _json.steps;
  121. }
  122. if (!Array.isArray(_json)) {
  123. _json = [_json];
  124. }
  125. json = _json.concat(json);
  126. } else {
  127. debug(`Route ${path} skipped, "app/${exec}.json" not found`);
  128. return;
  129. }
  130. }
  131. }
  132. app[method](path, (req, res, next) => {
  133. next(parent && !req.fragment ? 'route' : null);
  134. }, cache({ttl}), templateView(layout, page, data, json));
  135. }
  136. if (parent) {
  137. createRoute({
  138. path,
  139. method: parent.method,
  140. redirect: parent.redirect,
  141. url: parent.url,
  142. page: parent.page,
  143. layout: parent.layout,
  144. exec: parent.exec,
  145. data: parent.data
  146. });
  147. }
  148. } else if (exec) {
  149. if (fs.existsSync(`app/${exec}.json`)) {
  150. let json = fs.readJSONSync(`app/${exec}.json`);
  151. app[method](path, cache({ttl}), serverConnect(json));
  152. return;
  153. }
  154. }
  155. }
  156. }
  157. database(app);
  158. webhooks(app);
  159. if (fs.existsSync('extensions/server_connect/routes')) {
  160. const entries = fs.readdirSync('extensions/server_connect/routes', { withFileTypes: true });
  161. for (let entry of entries) {
  162. if (entry.isFile() && extname(entry.name) == '.js') {
  163. let hook = require(`../../extensions/server_connect/routes/${entry.name}`);
  164. if (hook.after) hook.after(app);
  165. debug(`Custom router ${entry.name} loaded`);
  166. }
  167. }
  168. }
  169. function createApiRoutes(dir) {
  170. const entries = fs.readdirSync(dir, { withFileTypes: true });
  171. return map(entries, async (entry) => {
  172. let path = posix.join(dir, entry.name);
  173. if (entry.isFile() && extname(path) == '.json') {
  174. let json = fs.readJSONSync(path);
  175. let routePath = path.replace(/^app/i, '').replace(/.json$/, '(.json)?');
  176. let ttl = (json.settings && json.settings.options && json.settings.options.ttl) ? json.settings.options.ttl : 0;
  177. app.all(routePath, cache({ttl}), serverConnect(json));
  178. debug(`Api route ${routePath} created`);
  179. }
  180. if (entry.isDirectory()) {
  181. return createApiRoutes(path);
  182. }
  183. });
  184. }
  185. };