instaserve 0.0.44 → 0.1.0
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 +2 -2
- package/bun/http.js +45 -0
- package/deno/server.js +35 -0
- package/package.json +12 -10
- package/public/enigmatic.js +149 -149
- package/public/index.html +12 -7
- package/public/sw.js +17 -17
- package/routes.mjs +3 -3
- package/server.mjs +48 -48
package/README.md
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
# instaserve
|
|
2
|
-
Instant web stack
|
|
1
|
+
# instaserve
|
|
2
|
+
Instant web stack
|
package/bun/http.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {existsSync} from 'fs'
|
|
2
|
+
import routes from '../routes.mjs'
|
|
3
|
+
console.log(routes)
|
|
4
|
+
|
|
5
|
+
class s {
|
|
6
|
+
end(s) {
|
|
7
|
+
this.resp = s
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
Bun.serve({
|
|
12
|
+
port: 3000,
|
|
13
|
+
async fetch(r) {
|
|
14
|
+
|
|
15
|
+
let url = new URL(r.url).pathname
|
|
16
|
+
const data = await r.text()
|
|
17
|
+
|
|
18
|
+
const ru = {method: r.method, url: url}
|
|
19
|
+
const rs = new s()
|
|
20
|
+
|
|
21
|
+
const midware = Object.keys(routes)
|
|
22
|
+
.filter(k => k.startsWith('_'))
|
|
23
|
+
.find(k => routes[k](ru, rs, data))
|
|
24
|
+
|
|
25
|
+
// Routes.mjs
|
|
26
|
+
if(routes[url]) {
|
|
27
|
+
const f = routes[url](ru, rs, data)
|
|
28
|
+
return new Response(rs.resp)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Static
|
|
32
|
+
const fn = (url == '/') ? `public/index.html` : `public/${url}`
|
|
33
|
+
if (existsSync(fn))
|
|
34
|
+
return new Response(Bun.file(fn))
|
|
35
|
+
|
|
36
|
+
return new Response('', { status: 404 })
|
|
37
|
+
|
|
38
|
+
},
|
|
39
|
+
error(e) {
|
|
40
|
+
console.error(e)
|
|
41
|
+
return new Response('', { status: 404 })
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
console.log('Running on 3000')
|
package/deno/server.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { existsSync } from "https://deno.land/std/fs/mod.ts";
|
|
2
|
+
import routes from '../routes.mjs'
|
|
3
|
+
console.log(routes)
|
|
4
|
+
|
|
5
|
+
class s {
|
|
6
|
+
end(s) {
|
|
7
|
+
this.resp = s
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
Deno.serve(async (r) => {
|
|
12
|
+
|
|
13
|
+
const data = await r.text()
|
|
14
|
+
let url = new URL(r.url).pathname
|
|
15
|
+
const ru = { method: r.method, url: url }
|
|
16
|
+
const rs = new s()
|
|
17
|
+
|
|
18
|
+
const midware = Object.keys(routes)
|
|
19
|
+
.filter((k) => k.startsWith('_'))
|
|
20
|
+
.find((k) => routes[k](ru, rs, data))
|
|
21
|
+
|
|
22
|
+
// Routes.mjs
|
|
23
|
+
if (routes[url]) {
|
|
24
|
+
const f = routes[url](ru, rs, data)
|
|
25
|
+
return new Response(rs.resp)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Static
|
|
29
|
+
const fn = (url == '/') ? `public/index.html` : `public/${url}`
|
|
30
|
+
if (existsSync(fn))
|
|
31
|
+
return new Response(await Deno.readTextFile(fn), { headers: { 'Content-Type': 'text/html' } })
|
|
32
|
+
|
|
33
|
+
return new Response('', { status: 404 })
|
|
34
|
+
|
|
35
|
+
}, {port: 3000})
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "instaserve",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "Instant web stack",
|
|
5
|
-
"main": "server.mjs",
|
|
6
|
-
"bin": "./server.mjs",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"start": "node server.mjs"
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "instaserve",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Instant web stack",
|
|
5
|
+
"main": "server.mjs",
|
|
6
|
+
"bin": "./server.mjs",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node server.mjs",
|
|
9
|
+
"deno": "deno run --unstable --allow-net --allow-read deno/server.js",
|
|
10
|
+
"bun": "bun run bun/http.js"
|
|
11
|
+
}
|
|
12
|
+
}
|
package/public/enigmatic.js
CHANGED
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
const w = {}, d = document
|
|
2
|
-
|
|
3
|
-
// helpers
|
|
4
|
-
|
|
5
|
-
w.$ = d.querySelector.bind(d)
|
|
6
|
-
w.$$ = d.querySelectorAll.bind(d)
|
|
7
|
-
w.loadJS = (src) => {
|
|
8
|
-
return new Promise((r, j) => {
|
|
9
|
-
if ($(`script[src="${src}"]`)) return r(true)
|
|
10
|
-
const s = d.createElement('script')
|
|
11
|
-
s.src = src
|
|
12
|
-
s.addEventListener('load', r)
|
|
13
|
-
d.head.appendChild(s)
|
|
14
|
-
})
|
|
15
|
-
}
|
|
16
|
-
w.loadCSS = (src) => {
|
|
17
|
-
return new Promise((r, j) => {
|
|
18
|
-
const s = document.createElement('link')
|
|
19
|
-
s.rel = 'stylesheet'
|
|
20
|
-
s.href = src
|
|
21
|
-
s.addEventListener('load', r)
|
|
22
|
-
d.head.appendChild(s)
|
|
23
|
-
})
|
|
24
|
-
}
|
|
25
|
-
w.wait = (ms) => new Promise((r) => setTimeout(r, ms))
|
|
26
|
-
w.ready = async () => {
|
|
27
|
-
return new Promise((r) => {
|
|
28
|
-
if (document.readyState === 'complete') r(true)
|
|
29
|
-
document.onreadystatechange = () => {
|
|
30
|
-
if (document.readyState === 'complete') r()
|
|
31
|
-
}
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
w.child = (type = 'div', html = '') => {
|
|
35
|
-
const e = d.createElement(type)
|
|
36
|
-
e.innerHTML = html
|
|
37
|
-
d.body.appendChild(e)
|
|
38
|
-
return e
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Custom element
|
|
42
|
-
|
|
43
|
-
w.element = (name, { onMount = x => x, beforeData = x => x, style, template = '' }) => {
|
|
44
|
-
customElements.define(name, class extends HTMLElement {
|
|
45
|
-
async connectedCallback(props) {
|
|
46
|
-
await onMount()
|
|
47
|
-
if (style) {
|
|
48
|
-
const s = document.createElement('style')
|
|
49
|
-
s.innerHTML = `${name} {${style}}`
|
|
50
|
-
d.body.appendChild(s)
|
|
51
|
-
}
|
|
52
|
-
this.template = template
|
|
53
|
-
if (!this.template.match('{'))
|
|
54
|
-
this.innerHTML = this.template
|
|
55
|
-
}
|
|
56
|
-
set(o) {
|
|
57
|
-
this.innerHTML = ''
|
|
58
|
-
o = beforeData(o)
|
|
59
|
-
if (!Array.isArray(o)) o = [o]
|
|
60
|
-
const m = new Function('o', 'return `' + this.template + '`')
|
|
61
|
-
o.map((i) => (this.innerHTML += m(o)))
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (window.components) {
|
|
67
|
-
for (let name in window.components)
|
|
68
|
-
w.element(name, window.components[name])
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Data
|
|
72
|
-
|
|
73
|
-
w.state = new Proxy(
|
|
74
|
-
{}, {
|
|
75
|
-
set: (obj, prop, value) => {
|
|
76
|
-
let ret = []
|
|
77
|
-
for (const e of $$(`[data*=${prop}]`)) {
|
|
78
|
-
console.log(['setting e', e.tagName, e.id, value])
|
|
79
|
-
e.set(value)
|
|
80
|
-
}
|
|
81
|
-
obj[prop] = value
|
|
82
|
-
},
|
|
83
|
-
get: (obj, prop, receiver) => {
|
|
84
|
-
if (prop == '_state') return obj
|
|
85
|
-
return obj[prop]
|
|
86
|
-
},
|
|
87
|
-
}
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
w.dataEvent = (x) => console.log(`dataevent: ${x}`)
|
|
91
|
-
|
|
92
|
-
w.fetchJSON = async (url, key) => {
|
|
93
|
-
const j = await (await fetch(url)).json()
|
|
94
|
-
if (key) state[key] = j
|
|
95
|
-
dataEvent(j)
|
|
96
|
-
return j
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
w.streamJSON = async (url, key) => {
|
|
100
|
-
const ev = new EventSource(url)
|
|
101
|
-
ev.onmessage = (ev) => {
|
|
102
|
-
const j = JSON.parse(ev.data)
|
|
103
|
-
if (key) state[key] = j
|
|
104
|
-
dataEvent(j)
|
|
105
|
-
return j
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// State changes
|
|
110
|
-
|
|
111
|
-
w.trackStateChanges = () =>
|
|
112
|
-
(w.dataEvent = (o) =>
|
|
113
|
-
localStorage.set(new Date().toISOString(), JSON.stringify(o)))
|
|
114
|
-
w.untrackStateChanges = () =>
|
|
115
|
-
(w.dataEvent = (o) => console.log('dataevent:', o))
|
|
116
|
-
|
|
117
|
-
// Startup
|
|
118
|
-
|
|
119
|
-
w.start = async () => {
|
|
120
|
-
await w.ready();
|
|
121
|
-
[...$$('div')].map((e) => {
|
|
122
|
-
if (!e.id)
|
|
123
|
-
e.id = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 3)
|
|
124
|
-
e.pr = {};
|
|
125
|
-
[...e.attributes].map((a) => (e.pr[a.name] = a.value))
|
|
126
|
-
if (e.pr.fetch) e.fetch = fetchJSON.bind(null, e.pr.fetch, e.id)
|
|
127
|
-
if ('immediate' in e.pr) e.fetch()
|
|
128
|
-
if (e.pr.stream) e.stream = streamJSON.bind(null, e.pr.stream, e.id)
|
|
129
|
-
if (e.pr.data) {
|
|
130
|
-
if (e.innerHTML && e.innerHTML.includes('{')) {
|
|
131
|
-
e.template = e.innerHTML.replaceAll('{', '${')
|
|
132
|
-
e.innerHTML = ''
|
|
133
|
-
}
|
|
134
|
-
e.set = (o) => {
|
|
135
|
-
e.innerHTML = ''
|
|
136
|
-
if (!Array.isArray(o)) o = [o]
|
|
137
|
-
const m = new Function('o', 'return `' + e.template + '`')
|
|
138
|
-
o.map((i) => (e.innerHTML += m(i)))
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
})
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
w.enigmatic = { version: '2022-03-05 0.10.2' }
|
|
145
|
-
Object.assign(window, w);
|
|
146
|
-
|
|
147
|
-
(async () => {
|
|
148
|
-
await w.start()
|
|
149
|
-
if (window.main) window.main()
|
|
1
|
+
const w = {}, d = document
|
|
2
|
+
|
|
3
|
+
// helpers
|
|
4
|
+
|
|
5
|
+
w.$ = d.querySelector.bind(d)
|
|
6
|
+
w.$$ = d.querySelectorAll.bind(d)
|
|
7
|
+
w.loadJS = (src) => {
|
|
8
|
+
return new Promise((r, j) => {
|
|
9
|
+
if ($(`script[src="${src}"]`)) return r(true)
|
|
10
|
+
const s = d.createElement('script')
|
|
11
|
+
s.src = src
|
|
12
|
+
s.addEventListener('load', r)
|
|
13
|
+
d.head.appendChild(s)
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
w.loadCSS = (src) => {
|
|
17
|
+
return new Promise((r, j) => {
|
|
18
|
+
const s = document.createElement('link')
|
|
19
|
+
s.rel = 'stylesheet'
|
|
20
|
+
s.href = src
|
|
21
|
+
s.addEventListener('load', r)
|
|
22
|
+
d.head.appendChild(s)
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
w.wait = (ms) => new Promise((r) => setTimeout(r, ms))
|
|
26
|
+
w.ready = async () => {
|
|
27
|
+
return new Promise((r) => {
|
|
28
|
+
if (document.readyState === 'complete') r(true)
|
|
29
|
+
document.onreadystatechange = () => {
|
|
30
|
+
if (document.readyState === 'complete') r()
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
w.child = (type = 'div', html = '') => {
|
|
35
|
+
const e = d.createElement(type)
|
|
36
|
+
e.innerHTML = html
|
|
37
|
+
d.body.appendChild(e)
|
|
38
|
+
return e
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Custom element
|
|
42
|
+
|
|
43
|
+
w.element = (name, { onMount = x => x, beforeData = x => x, style, template = '' }) => {
|
|
44
|
+
customElements.define(name, class extends HTMLElement {
|
|
45
|
+
async connectedCallback(props) {
|
|
46
|
+
await onMount()
|
|
47
|
+
if (style) {
|
|
48
|
+
const s = document.createElement('style')
|
|
49
|
+
s.innerHTML = `${name} {${style}}`
|
|
50
|
+
d.body.appendChild(s)
|
|
51
|
+
}
|
|
52
|
+
this.template = template
|
|
53
|
+
if (!this.template.match('{'))
|
|
54
|
+
this.innerHTML = this.template
|
|
55
|
+
}
|
|
56
|
+
set(o) {
|
|
57
|
+
this.innerHTML = ''
|
|
58
|
+
o = beforeData(o)
|
|
59
|
+
if (!Array.isArray(o)) o = [o]
|
|
60
|
+
const m = new Function('o', 'return `' + this.template + '`')
|
|
61
|
+
o.map((i) => (this.innerHTML += m(o)))
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (window.components) {
|
|
67
|
+
for (let name in window.components)
|
|
68
|
+
w.element(name, window.components[name])
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Data
|
|
72
|
+
|
|
73
|
+
w.state = new Proxy(
|
|
74
|
+
{}, {
|
|
75
|
+
set: (obj, prop, value) => {
|
|
76
|
+
let ret = []
|
|
77
|
+
for (const e of $$(`[data*=${prop}]`)) {
|
|
78
|
+
console.log(['setting e', e.tagName, e.id, value])
|
|
79
|
+
e.set(value)
|
|
80
|
+
}
|
|
81
|
+
obj[prop] = value
|
|
82
|
+
},
|
|
83
|
+
get: (obj, prop, receiver) => {
|
|
84
|
+
if (prop == '_state') return obj
|
|
85
|
+
return obj[prop]
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
w.dataEvent = (x) => console.log(`dataevent: ${x}`)
|
|
91
|
+
|
|
92
|
+
w.fetchJSON = async (url, key) => {
|
|
93
|
+
const j = await (await fetch(url)).json()
|
|
94
|
+
if (key) state[key] = j
|
|
95
|
+
dataEvent(j)
|
|
96
|
+
return j
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
w.streamJSON = async (url, key) => {
|
|
100
|
+
const ev = new EventSource(url)
|
|
101
|
+
ev.onmessage = (ev) => {
|
|
102
|
+
const j = JSON.parse(ev.data)
|
|
103
|
+
if (key) state[key] = j
|
|
104
|
+
dataEvent(j)
|
|
105
|
+
return j
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// State changes
|
|
110
|
+
|
|
111
|
+
w.trackStateChanges = () =>
|
|
112
|
+
(w.dataEvent = (o) =>
|
|
113
|
+
localStorage.set(new Date().toISOString(), JSON.stringify(o)))
|
|
114
|
+
w.untrackStateChanges = () =>
|
|
115
|
+
(w.dataEvent = (o) => console.log('dataevent:', o))
|
|
116
|
+
|
|
117
|
+
// Startup
|
|
118
|
+
|
|
119
|
+
w.start = async () => {
|
|
120
|
+
await w.ready();
|
|
121
|
+
[...$$('div')].map((e) => {
|
|
122
|
+
if (!e.id)
|
|
123
|
+
e.id = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 3)
|
|
124
|
+
e.pr = {};
|
|
125
|
+
[...e.attributes].map((a) => (e.pr[a.name] = a.value))
|
|
126
|
+
if (e.pr.fetch) e.fetch = fetchJSON.bind(null, e.pr.fetch, e.id)
|
|
127
|
+
if ('immediate' in e.pr) e.fetch()
|
|
128
|
+
if (e.pr.stream) e.stream = streamJSON.bind(null, e.pr.stream, e.id)
|
|
129
|
+
if (e.pr.data) {
|
|
130
|
+
if (e.innerHTML && e.innerHTML.includes('{')) {
|
|
131
|
+
e.template = e.innerHTML.replaceAll('{', '${')
|
|
132
|
+
e.innerHTML = ''
|
|
133
|
+
}
|
|
134
|
+
e.set = (o) => {
|
|
135
|
+
e.innerHTML = ''
|
|
136
|
+
if (!Array.isArray(o)) o = [o]
|
|
137
|
+
const m = new Function('o', 'return `' + e.template + '`')
|
|
138
|
+
o.map((i) => (e.innerHTML += m(i)))
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
w.enigmatic = { version: '2022-03-05 0.10.2' }
|
|
145
|
+
Object.assign(window, w);
|
|
146
|
+
|
|
147
|
+
(async () => {
|
|
148
|
+
await w.start()
|
|
149
|
+
if (window.main) window.main()
|
|
150
150
|
})()
|
package/public/index.html
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<script>
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
<
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<script src="enigmatic.js"></script>
|
|
3
|
+
|
|
4
|
+
<script>
|
|
5
|
+
// navigator.serviceWorker.register('sw.js')
|
|
6
|
+
</script>
|
|
7
|
+
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css'>
|
|
8
|
+
|
|
9
|
+
<div class='bg-yellow-200'>hello</div>
|
|
10
|
+
<script>
|
|
11
|
+
document.write(enigmatic.version)
|
|
12
|
+
</script>
|
package/public/sw.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
self.addEventListener('fetch', event => {
|
|
2
|
-
const cache = await caches.open('e')
|
|
3
|
-
const req = event.request
|
|
4
|
-
|
|
5
|
-
event.respondWith(async () => {
|
|
6
|
-
if(!req.url.match(/\.js$|\.css$/))
|
|
7
|
-
return fetch(req)
|
|
8
|
-
|
|
9
|
-
const response = await cache.match(req)
|
|
10
|
-
if(response) return response
|
|
11
|
-
response = await fetch(req)
|
|
12
|
-
|
|
13
|
-
if(response.status == 200)
|
|
14
|
-
cache.put(req, response)
|
|
15
|
-
|
|
16
|
-
return response
|
|
17
|
-
})
|
|
1
|
+
self.addEventListener('fetch', event => {
|
|
2
|
+
const cache = await caches.open('e')
|
|
3
|
+
const req = event.request
|
|
4
|
+
|
|
5
|
+
event.respondWith(async () => {
|
|
6
|
+
if(!req.url.match(/\.js$|\.css$/))
|
|
7
|
+
return fetch(req)
|
|
8
|
+
|
|
9
|
+
const response = await cache.match(req)
|
|
10
|
+
if(response) return response
|
|
11
|
+
response = await fetch(req)
|
|
12
|
+
|
|
13
|
+
if(response.status == 200)
|
|
14
|
+
cache.put(req, response)
|
|
15
|
+
|
|
16
|
+
return response
|
|
17
|
+
})
|
|
18
18
|
})
|
package/routes.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
_debug: ({method, url}, s) => !console.log(method, url),
|
|
3
|
-
_example: (r, s) => console.log('returning a falsy value (above) will stop the chain'),
|
|
4
|
-
'/api': (r, s) => s.end('an example api response')
|
|
2
|
+
_debug: ({method, url}, s, data) => !console.log(method, url, data),
|
|
3
|
+
_example: (r, s, data) => console.log('returning a falsy value (above) will stop the chain'),
|
|
4
|
+
'/api': (r, s, data) => s.end('an example api response')
|
|
5
5
|
}
|
package/server.mjs
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import http from 'node:http'
|
|
4
|
-
import { pathToFileURL } from 'node:url'
|
|
5
|
-
import { resolve } from 'node:path'
|
|
6
|
-
import fs from 'node:fs'
|
|
7
|
-
|
|
8
|
-
const routesfile = resolve('routes.mjs')
|
|
9
|
-
|
|
10
|
-
if (!fs.existsSync(routesfile)) {
|
|
11
|
-
fs.writeFileSync(routesfile, `export default {
|
|
12
|
-
_debug: ({method, url}, s) => !console.log(method, url),
|
|
13
|
-
_example: (r, s) => console.log('returning a falsy value (above) will stop the chain'),
|
|
14
|
-
'/api': (r, s) => s.end('an example api response')
|
|
15
|
-
}`)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const routesurl = pathToFileURL(routesfile).href
|
|
19
|
-
console.log(routesfile, routesurl)
|
|
20
|
-
const routes = (await import(routesurl)).default
|
|
21
|
-
|
|
22
|
-
http
|
|
23
|
-
.createServer(async (r, s) => {
|
|
24
|
-
try {
|
|
25
|
-
let data = ''
|
|
26
|
-
r.on('data', (s) => (data += s.toString()))
|
|
27
|
-
r.on('end', (x) => {
|
|
28
|
-
try {
|
|
29
|
-
data = JSON.parse(data)
|
|
30
|
-
} catch {}
|
|
31
|
-
});
|
|
32
|
-
const midware = Object.keys(routes)
|
|
33
|
-
.filter((k) => k.startsWith('_'))
|
|
34
|
-
.find((k) => routes[k](r, s, data));
|
|
35
|
-
if (r.url == '/') r.url = '/index.html'
|
|
36
|
-
const fn = `./public${r.url.replace('..', '')}`
|
|
37
|
-
if (fs.existsSync(fn)) {
|
|
38
|
-
if (fn.match(/sw\.js/)) s.writeHead(200, { 'Content-Type': 'application/javascript' })
|
|
39
|
-
return s.end(fs.readFileSync(fn, 'utf-8'))
|
|
40
|
-
}
|
|
41
|
-
if (routes[r.url]) return routes[r.url](r, s, data)
|
|
42
|
-
else s.writeHead(404).end()
|
|
43
|
-
} catch (e) {
|
|
44
|
-
console.log(e)
|
|
45
|
-
s.writeHead(404).end()
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
.listen(3000, (x) => console.log('listening on 3000'))
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import http from 'node:http'
|
|
4
|
+
import { pathToFileURL } from 'node:url'
|
|
5
|
+
import { resolve } from 'node:path'
|
|
6
|
+
import fs from 'node:fs'
|
|
7
|
+
|
|
8
|
+
const routesfile = resolve('routes.mjs')
|
|
9
|
+
|
|
10
|
+
if (!fs.existsSync(routesfile)) {
|
|
11
|
+
fs.writeFileSync(routesfile, `export default {
|
|
12
|
+
_debug: ({method, url}, s) => !console.log(method, url),
|
|
13
|
+
_example: (r, s) => console.log('returning a falsy value (above) will stop the chain'),
|
|
14
|
+
'/api': (r, s) => s.end('an example api response')
|
|
15
|
+
}`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const routesurl = pathToFileURL(routesfile).href
|
|
19
|
+
console.log(routesfile, routesurl)
|
|
20
|
+
const routes = (await import(routesurl)).default
|
|
21
|
+
|
|
22
|
+
http
|
|
23
|
+
.createServer(async (r, s) => {
|
|
24
|
+
try {
|
|
25
|
+
let data = ''
|
|
26
|
+
r.on('data', (s) => (data += s.toString()))
|
|
27
|
+
r.on('end', (x) => {
|
|
28
|
+
try {
|
|
29
|
+
data = JSON.parse(data)
|
|
30
|
+
} catch {}
|
|
31
|
+
});
|
|
32
|
+
const midware = Object.keys(routes)
|
|
33
|
+
.filter((k) => k.startsWith('_'))
|
|
34
|
+
.find((k) => routes[k](r, s, data));
|
|
35
|
+
if (r.url == '/') r.url = '/index.html'
|
|
36
|
+
const fn = `./public${r.url.replace('..', '')}`
|
|
37
|
+
if (fs.existsSync(fn)) {
|
|
38
|
+
if (fn.match(/sw\.js/)) s.writeHead(200, { 'Content-Type': 'application/javascript' })
|
|
39
|
+
return s.end(fs.readFileSync(fn, 'utf-8'))
|
|
40
|
+
}
|
|
41
|
+
if (routes[r.url]) return routes[r.url](r, s, data)
|
|
42
|
+
else s.writeHead(404).end()
|
|
43
|
+
} catch (e) {
|
|
44
|
+
console.log(e)
|
|
45
|
+
s.writeHead(404).end()
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.listen(3000, (x) => console.log('listening on 3000'))
|