edge.libx.js 0.0.1
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/LICENSE +21 -0
- package/README.md +49 -0
- package/bin/cli.sh +7 -0
- package/bin/set-secrets.ts +70 -0
- package/bin/test.ts +18 -0
- package/build/Main.d.ts +1 -0
- package/build/Main.js +6 -0
- package/build/Main.js.map +1 -0
- package/build/helpers/EdgeNetwork.d.ts +13 -0
- package/build/helpers/EdgeNetwork.js +100 -0
- package/build/helpers/EdgeNetwork.js.map +1 -0
- package/build/helpers/Exceptions.d.ts +37 -0
- package/build/helpers/Exceptions.js +100 -0
- package/build/helpers/Exceptions.js.map +1 -0
- package/build/helpers/getExpress.d.ts +4 -0
- package/build/helpers/getExpress.js +25 -0
- package/build/helpers/getExpress.js.map +1 -0
- package/build/helpers/index.d.ts +12 -0
- package/build/helpers/index.js +70 -0
- package/build/helpers/index.js.map +1 -0
- package/build/helpers/jwt.d.ts +57 -0
- package/build/helpers/jwt.js +227 -0
- package/build/helpers/jwt.js.map +1 -0
- package/build/helpers/localServer.d.ts +1 -0
- package/build/helpers/localServer.js +54 -0
- package/build/helpers/localServer.js.map +1 -0
- package/build/helpers/require.d.ts +1 -0
- package/build/helpers/require.js +219 -0
- package/build/helpers/require.js.map +1 -0
- package/build/modules/@module.d.ts +6 -0
- package/build/modules/@module.js +16 -0
- package/build/modules/@module.js.map +1 -0
- package/build/modules/RouterWrapper.d.ts +21 -0
- package/build/modules/RouterWrapper.js +62 -0
- package/build/modules/RouterWrapper.js.map +1 -0
- package/build/modules/cors.d.ts +15 -0
- package/build/modules/cors.js +117 -0
- package/build/modules/cors.js.map +1 -0
- package/jest.config.js +26 -0
- package/package.json +65 -0
- package/src/Main.ts +1 -0
- package/src/helpers/EdgeNetwork.ts +113 -0
- package/src/helpers/Exceptions.ts +102 -0
- package/src/helpers/getExpress.ts +25 -0
- package/src/helpers/index.ts +61 -0
- package/src/helpers/jwt.ts +287 -0
- package/src/helpers/localServer.ts +75 -0
- package/src/helpers/require.ts +331 -0
- package/src/modules/@module.ts +13 -0
- package/src/modules/RouterWrapper.ts +68 -0
- package/src/modules/cors.ts +153 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { libx } from 'libx.js/build/bundles/essentials.js';
|
|
2
|
+
|
|
3
|
+
export class Module {
|
|
4
|
+
public constructor(public options?: Partial<ModuleOptions>) {
|
|
5
|
+
this.options = { ...new ModuleOptions(), ...options };
|
|
6
|
+
libx.log.v('Module:ctor');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class ModuleOptions {
|
|
12
|
+
|
|
13
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { libx } from 'libx.js/build/bundles/essentials.js';
|
|
2
|
+
import { Route, Router, RouterType, error, json, cors, withParams, IRequest, text, ResponseHandler } from 'itty-router';
|
|
3
|
+
import { createServerAdapter } from '@whatwg-node/server';
|
|
4
|
+
|
|
5
|
+
type BaseRouterInitializer = (string) => { base: string; router: RouterType<IRequest, any[]> };
|
|
6
|
+
|
|
7
|
+
export class RouterWrapper<TCtx = any> {
|
|
8
|
+
private static cors = cors({ origin: ['*'], allowMethods: ['POST'] });
|
|
9
|
+
private static preflight = this.cors.preflight;
|
|
10
|
+
private static corsify = this.cors.corsify;
|
|
11
|
+
|
|
12
|
+
public constructor(public base: string, public router: RouterType<Request, [], any>) {
|
|
13
|
+
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
private static tryCors(response, request): Response {
|
|
17
|
+
try {
|
|
18
|
+
return this.corsify(response, request);
|
|
19
|
+
} catch (err) {
|
|
20
|
+
libx.log.w('tryCors: failed to perform CORS', err);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public static getNew(base: string) {
|
|
25
|
+
const router = Router({
|
|
26
|
+
base,
|
|
27
|
+
before: [this.preflight],
|
|
28
|
+
catch: this.errorHandler,
|
|
29
|
+
finally: [this.tryCors],
|
|
30
|
+
});
|
|
31
|
+
router.all('*', withParams);
|
|
32
|
+
// router.finally.push(this.corsify);
|
|
33
|
+
|
|
34
|
+
// router.all('*', () => error(404));
|
|
35
|
+
|
|
36
|
+
return new RouterWrapper(base, router);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
public static errorHandler(error) {
|
|
41
|
+
const isObject = libx.isObject(error);
|
|
42
|
+
const errMessage = error?.message ?? error;
|
|
43
|
+
const msg = 'Error: ' + (!isObject ? (errMessage ?? 'Server Error') : JSON.stringify(error));
|
|
44
|
+
const status = parseInt(error?.status ?? error?.statusCode ?? error?.code ?? error?.error?.code) || 500;
|
|
45
|
+
console.error('Server error: ', error, status);
|
|
46
|
+
return new Response(msg, { status })
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public registerRoute(newBase: string, baseRouterInitializer: BaseRouterInitializer) {
|
|
50
|
+
const route = baseRouterInitializer(`${this.base}${newBase}`);
|
|
51
|
+
this.router.all(newBase + '/*', route.router.fetch);
|
|
52
|
+
return this.router;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
public fetchHandler(request: IRequest, ctx: TCtx) {
|
|
56
|
+
// return this.router.fetch(request, ctx).then(json).then(RouterWrapper.corsify).catch(this.errorHandler);
|
|
57
|
+
return this.router.fetch(request, ctx).then(json).catch(RouterWrapper.errorHandler);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public catchNotFound() {
|
|
61
|
+
this.router.all('*', () => error(404));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public createServerAdapter() {
|
|
65
|
+
const ittyServer = createServerAdapter(this.fetchHandler.bind(this));
|
|
66
|
+
return ittyServer;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi purpose CORS lib.
|
|
3
|
+
* Note: Based on the `cors` package in npm but using only
|
|
4
|
+
* web APIs. Feel free to use it in your own projects.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
type StaticOrigin = boolean | string | RegExp | (boolean | string | RegExp)[]
|
|
8
|
+
|
|
9
|
+
type OriginFn = (
|
|
10
|
+
origin: string | undefined,
|
|
11
|
+
req: Request
|
|
12
|
+
) => StaticOrigin | Promise<StaticOrigin>
|
|
13
|
+
|
|
14
|
+
interface CorsOptions {
|
|
15
|
+
origin?: StaticOrigin | OriginFn
|
|
16
|
+
methods?: string | string[]
|
|
17
|
+
allowedHeaders?: string | string[]
|
|
18
|
+
exposedHeaders?: string | string[]
|
|
19
|
+
credentials?: boolean
|
|
20
|
+
maxAge?: number
|
|
21
|
+
preflightContinue?: boolean
|
|
22
|
+
optionsSuccessStatus?: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const defaultOptions: CorsOptions = {
|
|
26
|
+
origin: '*',
|
|
27
|
+
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
|
28
|
+
preflightContinue: false,
|
|
29
|
+
optionsSuccessStatus: 204,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isOriginAllowed(origin: string, allowed: StaticOrigin): boolean {
|
|
33
|
+
return Array.isArray(allowed)
|
|
34
|
+
? allowed.some((o) => isOriginAllowed(origin, o))
|
|
35
|
+
: typeof allowed === 'string'
|
|
36
|
+
? origin === allowed
|
|
37
|
+
: allowed instanceof RegExp
|
|
38
|
+
? allowed.test(origin)
|
|
39
|
+
: !!allowed
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getOriginHeaders(reqOrigin: string | undefined, origin: StaticOrigin) {
|
|
43
|
+
const headers = new Headers()
|
|
44
|
+
|
|
45
|
+
if (origin === '*') {
|
|
46
|
+
// Allow any origin
|
|
47
|
+
headers.set('Access-Control-Allow-Origin', '*')
|
|
48
|
+
} else if (typeof origin === 'string') {
|
|
49
|
+
// Fixed origin
|
|
50
|
+
headers.set('Access-Control-Allow-Origin', origin)
|
|
51
|
+
headers.append('Vary', 'Origin')
|
|
52
|
+
} else {
|
|
53
|
+
const allowed = isOriginAllowed(reqOrigin ?? '', origin)
|
|
54
|
+
|
|
55
|
+
if (allowed && reqOrigin) {
|
|
56
|
+
headers.set('Access-Control-Allow-Origin', reqOrigin)
|
|
57
|
+
}
|
|
58
|
+
headers.append('Vary', 'Origin')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return headers
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// originHeadersFromReq
|
|
65
|
+
|
|
66
|
+
async function originHeadersFromReq(
|
|
67
|
+
req: Request,
|
|
68
|
+
origin: StaticOrigin | OriginFn
|
|
69
|
+
) {
|
|
70
|
+
const reqOrigin = req.headers.get('Origin') || undefined
|
|
71
|
+
const value =
|
|
72
|
+
typeof origin === 'function' ? await origin(reqOrigin, req) : origin
|
|
73
|
+
|
|
74
|
+
if (!value) return
|
|
75
|
+
return getOriginHeaders(reqOrigin, value)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function getAllowedHeaders(req: Request, allowed?: string | string[]) {
|
|
79
|
+
const headers = new Headers()
|
|
80
|
+
|
|
81
|
+
if (!allowed) {
|
|
82
|
+
allowed = req.headers.get('Access-Control-Request-Headers')!
|
|
83
|
+
headers.append('Vary', 'Access-Control-Request-Headers')
|
|
84
|
+
} else if (Array.isArray(allowed)) {
|
|
85
|
+
// If the allowed headers is an array, turn it into a string
|
|
86
|
+
allowed = allowed.join(',')
|
|
87
|
+
}
|
|
88
|
+
if (allowed) {
|
|
89
|
+
headers.set('Access-Control-Allow-Headers', allowed)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return headers
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export default async function cors(
|
|
96
|
+
req: Request,
|
|
97
|
+
res: Response,
|
|
98
|
+
options?: CorsOptions
|
|
99
|
+
) {
|
|
100
|
+
const opts = { ...defaultOptions, ...options }
|
|
101
|
+
const { headers } = res
|
|
102
|
+
const originHeaders = await originHeadersFromReq(req, opts.origin ?? false)
|
|
103
|
+
const mergeHeaders = (v: string, k: string) => {
|
|
104
|
+
if (k === 'Vary') headers.append(k, v)
|
|
105
|
+
else headers.set(k, v)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// If there's no origin we won't touch the response
|
|
109
|
+
if (!originHeaders) return res
|
|
110
|
+
|
|
111
|
+
originHeaders.forEach(mergeHeaders)
|
|
112
|
+
|
|
113
|
+
if (opts.credentials) {
|
|
114
|
+
headers.set('Access-Control-Allow-Credentials', 'true')
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const exposed = Array.isArray(opts.exposedHeaders)
|
|
118
|
+
? opts.exposedHeaders.join(',')
|
|
119
|
+
: opts.exposedHeaders
|
|
120
|
+
|
|
121
|
+
if (exposed) {
|
|
122
|
+
headers.set('Access-Control-Expose-Headers', exposed)
|
|
123
|
+
}
|
|
124
|
+
debugger
|
|
125
|
+
// Handle the preflight request
|
|
126
|
+
if (req.method === 'OPTIONS') {
|
|
127
|
+
if (opts.methods) {
|
|
128
|
+
const methods = Array.isArray(opts.methods)
|
|
129
|
+
? opts.methods.join(',')
|
|
130
|
+
: opts.methods
|
|
131
|
+
|
|
132
|
+
headers.set('Access-Control-Allow-Methods', methods)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
getAllowedHeaders(req, opts.allowedHeaders).forEach(mergeHeaders)
|
|
136
|
+
|
|
137
|
+
if (typeof opts.maxAge === 'number') {
|
|
138
|
+
headers.set('Access-Control-Max-Age', String(opts.maxAge))
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (opts.preflightContinue) return res
|
|
142
|
+
|
|
143
|
+
headers.set('Content-Length', '0')
|
|
144
|
+
return new Response(null, { status: opts.optionsSuccessStatus, headers })
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// If we got here, it's a normal request
|
|
148
|
+
return res
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function initCors(options?: CorsOptions) {
|
|
152
|
+
return (req: Request, res: Response) => cors(req, res, options)
|
|
153
|
+
}
|