@foxtware/mineral 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/api/utils.js CHANGED
@@ -1134,6 +1134,10 @@ class ArgsWarden {
1134
1134
  }
1135
1135
  }
1136
1136
 
1137
+ const gidToId = (gid) => {
1138
+ return gid.split('/').pop();
1139
+ };
1140
+
1137
1141
  module.exports = {
1138
1142
  wait,
1139
1143
  timeMs,
@@ -1162,4 +1166,5 @@ module.exports = {
1162
1166
  Getter,
1163
1167
  sentenceCaseString,
1164
1168
  ArgsWarden,
1169
+ gidToId,
1165
1170
  };
package/bin/mineral.js CHANGED
@@ -11,6 +11,12 @@ if (command === 'host') {
11
11
  return;
12
12
  }
13
13
 
14
+ if (command === 'hosting_preview') {
15
+ const { startHostingPreview } = require('../hosting/hostingPreview');
16
+ startHostingPreview();
17
+ return;
18
+ }
19
+
14
20
  const { startServer } = require('../server');
15
21
 
16
22
  startServer();
@@ -1,8 +1,20 @@
1
1
  const fs = require('fs');
2
2
  const { wrapHostedFunction } = require('./hosting.utils');
3
3
 
4
+ const requirePathForHostedJs = (modulePath) => {
5
+ if (modulePath === './hosting/wrappers.js') {
6
+ return './wrappers.js';
7
+ }
8
+
9
+ if (modulePath.startsWith('./api/')) {
10
+ return `../${ modulePath.slice(2) }`;
11
+ }
12
+
13
+ return modulePath;
14
+ };
15
+
4
16
  const formatResolvedWrapperForHostedJs = ({ modulePath, wrapperName }) => (
5
- `require('${ modulePath }').${ wrapperName }`
17
+ `require('${ requirePathForHostedJs(modulePath) }').${ wrapperName }`
6
18
  );
7
19
 
8
20
  const formatWrapperList = (resolvedWrappers = []) => {
@@ -53,7 +65,7 @@ const generateHostedJs = ({
53
65
  });
54
66
 
55
67
  exportLines.push(
56
- ` ${ hostedName }: wrapHostedFunction(() => require('${ requirePath }'), '${ handlerName }'${ wrappersArg }),`,
68
+ ` ${ hostedName }: wrapHostedFunction(() => require('${ requirePathForHostedJs(requirePath) }'), '${ handlerName }'${ wrappersArg }),`,
57
69
  );
58
70
  }
59
71
 
@@ -77,6 +89,14 @@ const writeHostedJs = ({
77
89
  });
78
90
 
79
91
  fs.mkdirSync(getHostingDir(workspace), { recursive: true });
92
+
93
+ if (fs.existsSync(hostedPath)) {
94
+ const existingContent = fs.readFileSync(hostedPath, 'utf8');
95
+ if (existingContent === content) {
96
+ return hostedPath;
97
+ }
98
+ }
99
+
80
100
  fs.writeFileSync(hostedPath, content);
81
101
  return hostedPath;
82
102
  };
@@ -0,0 +1,160 @@
1
+ const http = require('http');
2
+ const { createRequire } = require('module');
3
+ const { respondJson, errorToReadable } = require('../server.utils');
4
+ const { getWorkspace, setWorkspace, loadWorkspaceEnv, toAbsolutePath } = require('../api/workspace');
5
+ const { getApiDirs, readCliFlag } = require('../cli');
6
+ const { loadHandlers } = require('../server');
7
+ const {
8
+ readHostingYml,
9
+ resolveHostedHandlersForDeploy,
10
+ wrapHostedFunction,
11
+ } = require('./hosting.utils');
12
+ const { copyCredsToEnv } = require('./copyCredsToEnv');
13
+
14
+ const getConfig = (options = {}) => ({
15
+ port: Number(options.port ?? process.env.PORT ?? 8000),
16
+ workspace: toAbsolutePath(
17
+ options.workspace
18
+ ?? readCliFlag('--workspace')
19
+ ?? process.env.MINERAL_WORKSPACE
20
+ ?? process.cwd(),
21
+ ),
22
+ api_dirs: getApiDirs(options),
23
+ });
24
+
25
+ const handlerByRouteName = (handlers) => {
26
+ const byName = new Map();
27
+
28
+ for (const handler of handlers.values()) {
29
+ byName.set(handler.routeName, handler);
30
+ }
31
+
32
+ return byName;
33
+ };
34
+
35
+ const loadHostedRoutes = (config) => {
36
+ const { functions } = readHostingYml(config.workspace);
37
+ const handlers = loadHandlers({
38
+ ...config,
39
+ host_mode: true,
40
+ });
41
+ const handlersByName = handlerByRouteName(handlers);
42
+ const hostedHandlers = resolveHostedHandlersForDeploy({
43
+ functions,
44
+ workspace: config.workspace,
45
+ handlersByName,
46
+ });
47
+
48
+ const workspaceRequire = createRequire(`${ config.workspace.replace(/\/$/, '') }/package.json`);
49
+ const routes = new Map();
50
+
51
+ for (const hostedHandler of hostedHandlers) {
52
+ const {
53
+ hostedName,
54
+ handlerName,
55
+ resolvedBeforeWrappers = [],
56
+ resolvedAfterWrappers = [],
57
+ requirePath,
58
+ } = hostedHandler;
59
+
60
+ const beforeWrappers = resolvedBeforeWrappers.map(({ modulePath, wrapperName }) => (
61
+ workspaceRequire(modulePath)[wrapperName]
62
+ ));
63
+ const afterWrappers = resolvedAfterWrappers.map(({ modulePath, wrapperName }) => (
64
+ workspaceRequire(modulePath)[wrapperName]
65
+ ));
66
+
67
+ routes.set(
68
+ `/${ hostedName }`,
69
+ wrapHostedFunction(
70
+ () => workspaceRequire(requirePath),
71
+ handlerName,
72
+ {
73
+ beforeWrappers,
74
+ afterWrappers,
75
+ },
76
+ ),
77
+ );
78
+ }
79
+
80
+ return routes;
81
+ };
82
+
83
+ const createHostedPreviewServer = (handlers) => http.createServer(async (req, res) => {
84
+ if (req.method === 'GET' && req.url === '/') {
85
+ respondJson(res, 200, {
86
+ ok: true,
87
+ data: {
88
+ mode: 'hosting_preview',
89
+ routes: [...handlers.keys()].sort(),
90
+ workspace: getWorkspace(),
91
+ },
92
+ });
93
+ return;
94
+ }
95
+
96
+ const route = (req.url || '/').split('?')[0];
97
+ const handler = handlers.get(route);
98
+
99
+ if (!handler) {
100
+ respondJson(res, 404, {
101
+ ok: false,
102
+ error: {
103
+ code: 'NOT_FOUND',
104
+ message: `No hosted handler found for route ${ route }`,
105
+ },
106
+ });
107
+ return;
108
+ }
109
+
110
+ try {
111
+ await handler(req, res);
112
+ } catch (error) {
113
+ if (res.headersSent) {
114
+ return;
115
+ }
116
+
117
+ respondJson(res, 500, {
118
+ ok: false,
119
+ error: {
120
+ code: 'UNHANDLED_ERROR',
121
+ message: 'Unhandled server error.',
122
+ details: errorToReadable(error),
123
+ },
124
+ });
125
+ }
126
+ });
127
+
128
+ const startHostingPreview = (options = {}) => {
129
+ process.env.HOSTED = 'true';
130
+
131
+ const config = getConfig(options);
132
+
133
+ setWorkspace(config.workspace);
134
+ copyCredsToEnv(config.workspace);
135
+ loadWorkspaceEnv();
136
+
137
+ const handlers = loadHostedRoutes(config);
138
+ const server = createHostedPreviewServer(handlers);
139
+
140
+ server.listen(config.port, () => {
141
+ console.log(`Hosting preview running on port ${ config.port }`);
142
+ console.log(`Workspace: ${ config.workspace }`);
143
+ console.log('Hosted routes:');
144
+
145
+ for (const route of [...handlers.keys()].sort()) {
146
+ console.log(route);
147
+ }
148
+ });
149
+
150
+ return server;
151
+ };
152
+
153
+ module.exports = {
154
+ startHostingPreview,
155
+ loadHostedRoutes,
156
+ };
157
+
158
+ if (require.main === module) {
159
+ startHostingPreview();
160
+ }
@@ -22,7 +22,7 @@ const allowCrossOriginCallsAndHandleOptions = async (req, res) => {
22
22
 
23
23
  res.setHeader('Access-Control-Allow-Origin', origin || '*');
24
24
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
25
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, x-wf-token, x-wf-value');
25
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, x-wf-token, x-wf-value, x-wf-app');
26
26
 
27
27
  if (req.method === 'OPTIONS') {
28
28
  res.writeHead(204);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foxtware/mineral",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "bin": {
5
5
  "mineral": "bin/mineral.js"
6
6
  },
@@ -10,7 +10,9 @@
10
10
  },
11
11
  "scripts": {
12
12
  "creds_to_env": "node hosting/copyCredsToEnv.js",
13
- "dev": "node --watch --watch-path=./api --watch-path=./server.js --watch-path=./server.utils.js --watch-path=./.creds.yml server.js",
13
+ "dev": "node --watch --watch-path=./api --watch-path=./server.js --watch-path=./server.utils.js --watch-path=./hosting --watch-path=./.creds.yml server.js",
14
+ "hosting_preview": "node --watch --watch-path=./api --watch-path=./hosting/.hosting.yml --watch-path=./hosting/wrappers.js --watch-path=./.creds.yml hosting/hostingPreview.js",
15
+ "tunnel": "ngrok http http://localhost:8000",
14
16
  "new": "node _build_scripts/createNewFunction.js",
15
17
  "serve": "PORT=8100 node server.js",
16
18
  "start": "node server.js",
@@ -22,5 +24,8 @@
22
24
  "json-2-csv": "^5.5.9",
23
25
  "xml2js": "^0.6.2",
24
26
  "yaml": "^2.9.0"
27
+ },
28
+ "devDependencies": {
29
+ "ngrok": "^5.0.0-beta.2"
25
30
  }
26
31
  }