@mapl/web 0.1.16 → 0.2.0-alpha.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/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  A compiled web framework for all runtimes.
2
2
 
3
3
  ```ts
4
- import { router, handle, layer, compile } from '@mapl/web';
4
+ import { router, handle, layer } from '@mapl/web';
5
+ import { compileToHandler } from '@mapl/web/compiler/jit';
5
6
 
6
7
  const api = router.init([], [
7
8
  handle.get('/', () => 'Hi')
@@ -19,6 +20,195 @@ const app = router.init(
19
20
  );
20
21
 
21
22
  export default {
22
- fetch: compile(app)
23
+ fetch: compileToHandler(app)
23
24
  };
24
25
  ```
26
+
27
+ ## AOT compilation (experimental)
28
+ Build `@mapl/web` to improve startup time.
29
+
30
+ Setup:
31
+ ```ts
32
+ // main.ts
33
+ import { handle, layer, router } from '@mapl/web';
34
+
35
+ export default router(
36
+ [
37
+ layer.tap((c) => {
38
+ console.log(c.req);
39
+ }),
40
+ layer.attach('id', () => performance.now()),
41
+ ],
42
+ [handle.any('/path', (c) => c.id)],
43
+ {
44
+ '/api': router(
45
+ [layer.parse('body', async (c) => c.req.text())],
46
+ [handle.post('/body', (c) => c.body)],
47
+ ),
48
+ },
49
+ );
50
+
51
+ // build.ts
52
+ import app from './main.ts';
53
+ import { compileToString } from '@mapl/web/compiler/jit';
54
+
55
+ import { rolldown } from 'rolldown';
56
+ import { minifySync } from '@swc/core';
57
+ import { writeFileSync, readFileSync } from 'node:fs';
58
+
59
+ const ENTRY = '/path/to/output.js';
60
+
61
+ writeFileSync(
62
+ ENTRY,
63
+ `
64
+ import app from '${import.meta.resolve('./main.ts')}';
65
+ import hydrate from '@mapl/web/compiler/aot';
66
+
67
+ // Compatible with Bun, Deno, Cloudflare, ...
68
+ export default {
69
+ fetch: (${compileToString(app)})(...hydrate(app))
70
+ };
71
+ `
72
+ );
73
+ const input = await rolldown({
74
+ input: ENTRY,
75
+ transform: {
76
+ typescript: {
77
+ rewriteImportExtensions: true,
78
+ },
79
+ },
80
+ });
81
+ const output = await input.generate();
82
+ const code = minifySync(output.output[0].code, { module: true }).code;
83
+ writeFileSync(ENTRY, code);
84
+ ```
85
+
86
+ Example output (formatted):
87
+ ```js
88
+ // router()
89
+ var e = (e, t, l) => [e, t, , l];
90
+ // handle.route()
91
+ let t = (e, t) => [1, t, e],
92
+ l = { type: null },
93
+ n = (e, t, n, ...r) => [
94
+ e,
95
+ t,
96
+ n,
97
+ 0 === r.length ? l : Object.assign({ type: null }, ...r),
98
+ ];
99
+ var r = e(
100
+ [
101
+ // inlined layer.tap()
102
+ [
103
+ 0,
104
+ (e) => {
105
+ console.log(e.req);
106
+ },
107
+ ],
108
+ // layer.attach()
109
+ t("id", () => performance.now()),
110
+ ],
111
+ // handle.any()
112
+ [((...e) => n("", ...e))("/path", (e) => e.id)],
113
+ {
114
+ "/api": e(
115
+ // layer.attach()
116
+ [t("body", async (e) => e.req.text())],
117
+ // handle.post()
118
+ [((...e) => n("POST", ...e))("/body", (e) => e.body)],
119
+ ),
120
+ },
121
+ );
122
+ // hydration code
123
+ let a = (e, t) => {
124
+ let l = e + t;
125
+ return /.\/$/.test(l) ? e : l;
126
+ },
127
+ s = (async () => {}).constructor,
128
+ o = [, , , , ,],
129
+ u = (e) => (e[3] ??= o[4](e[2][0], e[2][1], e)),
130
+ i = (e) => {
131
+ null != e[2] && (e[3] = null);
132
+ },
133
+ p = (e) => (e[1] ? "" : ((e[1] = !0), i(e), o[2])),
134
+ c = (e) => (e[0] ? "" : ((e[0] = !0), i(e), "return (async()=>{")),
135
+ d = (e) => (e[4] ? "t" : ((e[4] = !0), "let t")),
136
+ f = (e, t, l) => {
137
+ null != e[2] && ((t[2] = e[2]), (t[3] = null));
138
+ for (let l = 0, n = e[0]; l < n.length; l++) {
139
+ let e = n[l],
140
+ r = e[1],
141
+ a = e[0];
142
+ -1 === a
143
+ ? r(t)
144
+ : (o[1].push(r),
145
+ r.length > 0 && p(t),
146
+ r instanceof s && c(t),
147
+ 1 === a
148
+ ? p(t)
149
+ : 2 === a
150
+ ? (d(t), u(t))
151
+ : 3 === a && (d(t), u(t), p(t)));
152
+ }
153
+ for (let n = 0, r = e[1]; n < r.length; n++) {
154
+ let e = r[n],
155
+ s = a(l, e[1]);
156
+ o[3](e[2], e[3], s, t);
157
+ }
158
+ let n = e[3];
159
+ if (null != n) for (let e in n) f(n[e], t.slice(), "/" === e ? l : l + e);
160
+ },
161
+ y = Symbol.for("@safe-std/error");
162
+ var h = {
163
+ // built content
164
+ fetch: ((e, t, l, n, r, a, s) => {
165
+ var o = ["text/html", "application/json"].map((e) => ["Content-Type", e]),
166
+ [u, i] = o,
167
+ [p, c] = o.map((e) => ({ headers: [e] })),
168
+ [d, f] = [404, 400].map((e) => new Response(null, { status: e }));
169
+ return (e) => {
170
+ let o = e.url,
171
+ u = o.indexOf("/", 12) + 1,
172
+ i = o.indexOf("?", u),
173
+ p = -1 === i ? o.slice(u) : o.slice(u, i);
174
+ if ("POST" === e.method && "api/body" === p) {
175
+ let r = t(e);
176
+ return (
177
+ l(r),
178
+ (r.id = n()),
179
+ (async () => ((r.body = await a(r)), new Response(s(r), r)))()
180
+ );
181
+ }
182
+ if ("path" === p) {
183
+ let a = t(e);
184
+ return (l(a), (a.id = n()), new Response(r(a), a));
185
+ }
186
+ return d;
187
+ };
188
+ })(
189
+ ...((o[0] = {}),
190
+ (o[1] = []),
191
+ (o[2] = "let c=mwc(r);"),
192
+ (o[3] = (e) => (o[1].push(e), "")),
193
+ (o[4] = (e) => (o[1].push(e), "")),
194
+ f(r, [!1, !1, , "return mwb", !1], ""),
195
+
196
+ // inject dependencies
197
+ [
198
+ (e) => Array.isArray(e) && e[0] === y,
199
+ (e) => ({ status: 200, req: e, headers: [] }),
200
+ ].concat(o[1])),
201
+ ),
202
+ };
203
+ export { h as default };
204
+ ```
205
+
206
+ ### Hydration
207
+ ```ts
208
+ import { isHydrating } from '@mapl/web/compiler/config';
209
+
210
+ // false while building the output string
211
+ // true while only building dependencies
212
+ // Use this to for minifiedrs to eliminate unused code path in final output
213
+ isHydrating();
214
+ ```
@@ -0,0 +1,3 @@
1
+ import type { RouterTag } from "../core/index.js";
2
+ declare const _default: (router: RouterTag) => any[];
3
+ export default _default;
@@ -0,0 +1 @@
1
+ import{hydrateDependency,compilerState as state}from"@mapl/framework";import{isErr}from"@safe-std/error";import createContext from"../core/context.js";let compileHandler=fn=>{state[1].push(fn);return``};let compileErrorHandler=fn=>{``+state[1].push(fn);return``};export default router=>{state[0]={};state[1]=[];state[2]=`let c=mwc(r);`;state[3]=compileHandler;state[4]=compileErrorHandler;hydrateDependency(router,[false,false,,`return mwb`,false],``);return[isErr,createContext].concat(state[1])};
@@ -0,0 +1,5 @@
1
+ export declare const isHydrating: () => boolean;
2
+ /**
3
+ * @private
4
+ */
5
+ export declare const notHydrating: () => void;
@@ -0,0 +1 @@
1
+ let hydrateDependency=true;export let isHydrating=()=>hydrateDependency;export let notHydrating=()=>{hydrateDependency=false};
@@ -0,0 +1,3 @@
1
+ import type { RouterTag } from "../core/index.js";
2
+ export declare const compileToString: (router: RouterTag) => string;
3
+ export declare const compileToHandler: (router: RouterTag) => ((req: Request) => any);
@@ -0,0 +1 @@
1
+ import{compileGroup,createArgSet,AsyncFunction,compilerState as state}from"@mapl/framework";import compile from"@mapl/router/method/compiler";import{countParams}from"@mapl/router/path";import{isErr}from"@safe-std/error";import createContext from"../core/context.js";import{notHydrating}from"./config.js";notHydrating();let paramArgs=createArgSet(new Array(16).fill(0).map((_1,i)=>`q`+i));let compileReturn=(dat,fnAsync,scopeAsync,contextCreated,result)=>{let typ=dat.type;if(typ===`raw`)return`return `+result;fnAsync&&(result=`await `+result);let str=typ==null?`return new Response(`+result+(contextCreated?`,c)`:`)`):contextCreated?`c.headers.push(`+(typ===`json`?`mwj`:`mwh`)+`);return new Response(`+(typ===`json`?`JSON.stringify(`+result+`)`:result)+`,c)`:`return new Response(`+(typ===`json`?`JSON.stringify(`+result+`),mwoj`:result+`,mwoh`)+`)`;return fnAsync&&!scopeAsync?`return (async()=>{`+str+`})()`:str};let compileHandler=(fn,dat,path,scope)=>{let call=`f`+state[1].push(fn)+`(`;let paramCount=countParams(path);paramCount>0&&(call+=paramArgs[paramCount]);if(fn.length>paramCount){call+=paramCount===0?`c`:`,c`;if(!scope[1])return state[2]+compileReturn(dat,fn instanceof AsyncFunction,scope[0],true,call+`)`)}return compileReturn(dat,fn instanceof AsyncFunction,scope[0],scope[1],call+`)`)};let compileErrorHandler=(fn,dat,scope)=>{let call=`f`+state[1].push(fn)+`(t`;if(fn.length>1){call+=`,c`;if(!scope[1])return state[2]+compileReturn(dat,fn instanceof AsyncFunction,scope[0],true,call+`)`)}return compileReturn(dat,fn instanceof AsyncFunction,scope[0],scope[1],call+`)`)};let compileToState=router=>{state[0]={};state[1]=[];state[2]=`let c=mwc(r);`;state[3]=compileHandler;state[4]=compileErrorHandler;compileGroup(router,[false,false,,`return mwb`,false],``,``)};let stateToString=()=>`"use strict";var t=["text/html","application/json"].map(c=>["Content-Type",c]),[mwh,mwj]=t,[mwoh,mwoj]=t.map(c=>({headers:[c]})),[mwn,mwb]=[404,400].map(s=>new Response(null,{status:s}));return(r)=>{`+compile(state[0],`r.method`,`let u=r.url,s=u.indexOf("/",12)+1,e=u.indexOf("?",s),p=e===-1?u.slice(s):u.slice(s,e);`,1)+`return mwn}`;let stateToArgs=()=>{let depsString=`me,mwc`;let deps=state[1];for(let i=0;i<deps.length;i++)depsString+=`,f`+(i+1);return depsString};export let compileToString=router=>{compileToState(router);return`(`+stateToArgs()+`)=>{`+stateToString()+`}`};export let compileToHandler=router=>{compileToState(router);return Function(stateToArgs(),stateToString())(isErr,createContext,...state[1])};
package/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { default as router } from "./core/index.js";
2
+ export * as layer from "./core/middleware.js";
3
+ export * as handle from "./core/handler.js";
4
+ export * as cors from "./utils/cors.js";
5
+ export { default as headers } from "./utils/headers.js";
6
+ export { default as secureHeaders } from "./utils/secure-headers.js";
package/index.js ADDED
@@ -0,0 +1 @@
1
+ export{default as router}from"./core/index.js";export*as layer from"./core/middleware.js";export*as handle from"./core/handler.js";export*as cors from"./utils/cors.js";export{default as headers}from"./utils/headers.js";export{default as secureHeaders}from"./utils/secure-headers.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapl/web",
3
- "version": "0.1.16",
3
+ "version": "0.2.0-alpha.1",
4
4
  "description": "A compiled web framework for all runtimes",
5
5
  "keywords": ["fast", "lightweight", "cross-runtime", "framework", "web", "backend"],
6
6
  "repository": {
@@ -12,7 +12,7 @@
12
12
  "main": "./index.js",
13
13
  "types": "./index.d.ts",
14
14
  "dependencies": {
15
- "@mapl/framework": "^0.2.8",
15
+ "@mapl/framework": "^0.3.3",
16
16
  "@mapl/router": "^0.6.2",
17
17
  "@safe-std/error": "^1.0.1"
18
18
  },
@@ -21,14 +21,17 @@
21
21
  },
22
22
  "exports": {
23
23
  "./constants": "./constants.js",
24
- "./core/compile": "./core/compile.js",
24
+ ".": "./index.js",
25
25
  "./core/utils": "./core/utils.js",
26
- "./utils/secure-headers": "./utils/secure-headers.js",
27
- "./utils/headers": "./utils/headers.js",
28
- "./core": "./core/index.js",
29
26
  "./core/middleware": "./core/middleware.js",
30
- "./core/context": "./core/context.js",
27
+ "./core": "./core/index.js",
31
28
  "./utils/cors": "./utils/cors.js",
32
- "./core/handler": "./core/handler.js"
29
+ "./core/handler": "./core/handler.js",
30
+ "./core/context": "./core/context.js",
31
+ "./utils/headers": "./utils/headers.js",
32
+ "./compiler/aot": "./compiler/aot.js",
33
+ "./compiler/jit": "./compiler/jit.js",
34
+ "./utils/secure-headers": "./utils/secure-headers.js",
35
+ "./compiler/config": "./compiler/config.js"
33
36
  }
34
37
  }
package/core/compile.d.ts DELETED
@@ -1,6 +0,0 @@
1
- import type { RouterTag } from "./index.js";
2
- export declare const compileToState: (router: RouterTag) => void;
3
- export declare const stateToString: () => string;
4
- export declare const stateToArgs: () => string;
5
- declare const _default: (router: RouterTag) => ((req: Request) => any);
6
- export default _default;
package/core/compile.js DELETED
@@ -1 +0,0 @@
1
- import{compileGroup,createArgSet,AsyncFunction,compilerState as state}from"@mapl/framework";import compile from"@mapl/router/method/compiler";import{countParams}from"@mapl/router/path";import{isErr}from"@safe-std/error";import createContext from"./context.js";let paramArgs=createArgSet(new Array(16).fill(0).map((_1,i)=>`q`+i));let compileReturn=(dat,fnAsync,scopeAsync,contextCreated,result)=>{let typ=dat.type;if(typ===`raw`)return`return `+result;fnAsync&&(result=`await `+result);let str=typ==null?`return new Response(`+result+(contextCreated?`,c)`:`)`):contextCreated?`c.headers.push(`+(typ===`json`?`mwj`:`mwh`)+`);return new Response(`+(typ===`json`?`JSON.stringify(`+result+`)`:result)+`,c)`:`return new Response(`+(typ===`json`?`JSON.stringify(`+result+`),mwoj`:result+`,mwoh`)+`)`;return fnAsync&&!scopeAsync?`return (async()=>{`+str+`})()`:str};let compileHandler=(fn,dat,path,scope)=>{let call=`f`+state[1].push(fn)+`(`;let paramCount=countParams(path);paramCount>0&&(call+=paramArgs[paramCount]);if(fn.length>paramCount){call+=paramCount===0?`c`:`,c`;if(!scope[1])return state[2]+compileReturn(dat,fn instanceof AsyncFunction,scope[0],true,call+`)`)}return compileReturn(dat,fn instanceof AsyncFunction,scope[0],scope[1],call+`)`)};let compileErrorHandler=(fn,dat,scope)=>{let call=`f`+state[1].push(fn)+`(t`;if(fn.length>1){call+=`,c`;if(!scope[1])return state[2]+compileReturn(dat,fn instanceof AsyncFunction,scope[0],true,call+`)`)}return compileReturn(dat,fn instanceof AsyncFunction,scope[0],scope[1],call+`)`)};export let compileToState=router=>{state[0]={};state[1]=[];state[2]=`let c=mwc(r);`;state[3]=compileHandler;state[4]=compileErrorHandler;compileGroup(router,[false,false,,`return mwb`,false],``,``)};export let stateToString=()=>`"use strict";var t=["text/html","application/json"].map(c=>["Content-Type",c]),[mwh,mwj]=t,[mwoh,mwoj]=t.map(c=>({headers:[c]})),[mwn,mwb]=[404,400].map(s=>new Response(null,{status:s}));return(r)=>{`+compile(state[0],`r.method`,`let u=r.url,s=u.indexOf("/",12)+1,e=u.indexOf("?",s),p=e===-1?u.slice(s):u.slice(s,e);`,1)+`return mwn}`;export let stateToArgs=()=>{let depsString=`me,mwc`;let deps=state[1];for(let i=0;i<deps.length;i++)depsString+=`,f`+(i+1);return depsString};export default router=>{compileToState(router);return Function(stateToArgs(),stateToString())(isErr,createContext,...state[1])};