-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapi.ts
156 lines (130 loc) · 5.67 KB
/
api.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/// <reference lib="deno.unstable" />
import { SEPARATOR, basename, extname, join, dirname } from "https://deno.land/std/path/mod.ts";
import { ensureDir } from "https://deno.land/[email protected]/fs/ensure_dir.ts";
self?.postMessage && self?.addEventListener("unhandledrejection", async event => {
// Prevent this being reported (Firefox doesn't currently respect this)
event.preventDefault();
console.log('API UNHANDLED ERROR', event)
// // clean up isolates
// const cmd = new Deno.Command(`${import.meta.url.slice(0,import.meta.url.lastIndexOf('/'))}/kill_zombie_processes.sh`);
// let { code, stdout, stderr } = await cmd.output();
self?.postMessage({
message: event.reason.message,
stack: event.reason.stack,
});
});
import server from "./functions/src/server/main.ts";
import Proxy from "./functions/src/proxy/main.ts";
import getEnv from "./functions/src/utils/environmentVariables.ts";
import replaceTemplate from "./functions/src/utils/template.ts";
import axionDenoConfig from "./deno.json" with { type: "json" };
const env = await getEnv();
const axionConfigs = new Map<string, string>();
const denoConfigs = new Map<string, any>();
let adapters: any;
let shouldUpgradeAfter: number = 0;
(async () => {
server({
requestHandler: async (req: Request) => {
env.DEBUG === 'true' && console.log('Received request in API from', req.url);
const fileLoaderUrl = new URL(env.FILE_LOADER_URL || "http://localhost:9000");
let functionsDir = env.FUNCTIONS_DIR || ".";
functionsDir.endsWith('/') && (functionsDir = functionsDir.slice(0, -1));
let _adapters: any = {
url: req.url,
headers: req.headers,
env
};
if (!adapters) {
env.DEBUG === 'true' && console.log('Loading Adapters', new URL(`${functionsDir}/adapters`, fileLoaderUrl).href);
adapters = await import(new URL(`${functionsDir}/adapters`, fileLoaderUrl).href)
.then((m: any) => m.default)
.catch((err: any) => {
console.log(
`Error trying to load adapters: ${err.toString()}`
.replaceAll(new URL(functionsDir, fileLoaderUrl).href, '')
)
}) || ((a: any) => a);
}
try {
_adapters = await adapters(_adapters);
} catch (err) {
return new Response(JSON.stringify({ error: { message: err.message, status: (err.status || 500) } }), { status: err.status || 500, headers: { 'content-type': 'application/json; charset=utf-8' } });
}
const { loaderConfig, shouldUpgradeAfter: _shouldUpgradeAfter, ...adaptersData } = _adapters || {};
shouldUpgradeAfter = _shouldUpgradeAfter || shouldUpgradeAfter;
fileLoaderUrl.username = (loaderConfig?.username || 'local');
loaderConfig?.password && (fileLoaderUrl.password = loaderConfig?.password);
let axionConfig: any = axionConfigs.get(new URL(req.url).origin);
if (!axionConfig) {
axionConfig = await fetch(new URL('axion.config.json', fileLoaderUrl).href)
.then(async (res) => await res.json())
.catch((_) => null) || {};
axionConfigs.set(new URL(req.url).origin, axionConfig);
}
functionsDir = axionConfig?.functionsDir || functionsDir;
let denoConfig = denoConfigs.get(new URL(req.url).origin) || {};
if (!Object.keys(denoConfig).length) {
denoConfig = await fetch(new URL('deno.json', fileLoaderUrl).href)
.then(async (res) => await res.json())
.catch((_) => null) || {};
denoConfig.imports = denoConfig?.imports || {};
denoConfig.scopes = denoConfig?.scopes || {};
const nodeConfig = await fetch(new URL('package.json', fileLoaderUrl).href)
.then(async (res) => await res.json())
.catch((_) => null) || {};
Object.entries(nodeConfig?.dependencies || {}).map(([key, value]: any) => {
if (value.startsWith('http') || value.startsWith('file') || value.startsWith('npm:') || value.startsWith('node:')) {
denoConfig.imports[key] = value;
} else {
denoConfig.imports[key] = `npm:${value}`;
}
});
denoConfigs.set(new URL(req.url).origin, { ...denoConfig });
};
denoConfig.imports = { ...axionDenoConfig.imports, ...denoConfig.imports };
denoConfig.scopes = { ...axionDenoConfig.scopes, ...denoConfig.scopes };
return Proxy({
config: {
loaderUrl: fileLoaderUrl.href,
dirEntrypoint: env.DIR_ENTRYPOINT || "index",
shouldUpgradeAfter,
functionsDir,
...axionConfig,
denoConfig,
...adaptersData,
},
modules: {
path: { SEPARATOR, basename, extname, join, dirname },
template: replaceTemplate,
fs: { ensureDir }
},
})(req);
},
config: {
PORT: env.PORT || 9002,
}
});
self?.postMessage && self?.postMessage({ message: { 'status': 'ok' } });
Deno.env.get('WATCH') && watchFiles(env);
return
})();
async function watchFiles(env: any) {
for await (const event of Deno.watchFs("./", { recursive: true })) {
if (event.kind === "modify" && event.paths.some(path => /\.(html|js|jsx|tsx|ts)$/.test(path))) {
const dir = Deno.cwd();
const files = event.paths.map(path => path.split(dir).join(''));
if (files.some(file =>
file.indexOf('data') > -1 && (
(file.indexOf('cache') > file.indexOf('data')) ||
(file.lastIndexOf('data') > file.indexOf('data'))
)
)) continue
shouldUpgradeAfter = new Date().getTime();
event.paths.forEach(path => {
// self?.postMessage && self?.postMessage({ message: `Files modified: ${files}` });
})
}
}
return
}