instaserve 0.0.30 → 0.0.41
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 -0
- package/{db.json → data/db.json} +10 -10
- package/package.json +5 -5
- package/public/enigmatic.js +150 -0
- package/public/index.html +7 -0
- package/public/sw.js +18 -0
- package/routes.mjs +19 -0
- package/server.mjs +37 -0
- package/vastdb.mjs +5 -6
- package/index.mjs +0 -64
- package/test.mjs +0 -22
package/README.md
ADDED
package/{db.json → data/db.json}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
[
|
|
2
|
-
[
|
|
3
|
-
"user:admin",
|
|
4
|
-
{
|
|
5
|
-
"type": "user",
|
|
6
|
-
"name": "admin",
|
|
7
|
-
"pass": "01b613da484bee91c3f3806b52a6f40fd61ade874b5ffc0f62a2091cce38158b",
|
|
8
|
-
"id": "user:admin"
|
|
9
|
-
}
|
|
10
|
-
]
|
|
1
|
+
[
|
|
2
|
+
[
|
|
3
|
+
"user:admin",
|
|
4
|
+
{
|
|
5
|
+
"type": "user",
|
|
6
|
+
"name": "admin",
|
|
7
|
+
"pass": "01b613da484bee91c3f3806b52a6f40fd61ade874b5ffc0f62a2091cce38158b",
|
|
8
|
+
"id": "user:admin"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
11
|
]
|
package/package.json
CHANGED
|
@@ -0,0 +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()
|
|
150
|
+
})()
|
package/public/sw.js
ADDED
|
@@ -0,0 +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
|
+
})
|
|
18
|
+
})
|
package/routes.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*
|
|
2
|
+
routes.mjs
|
|
3
|
+
Unders
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import FS from 'node:fs'
|
|
7
|
+
export default {
|
|
8
|
+
_debug: ({ r, s, db }) => console.log(r.url, r.method),
|
|
9
|
+
_static: ({r, s}) => {
|
|
10
|
+
if(r.url == '/') r.url = '/index.html'
|
|
11
|
+
const fn = `./public${r.url.replace('..', '')}`
|
|
12
|
+
if(FS.existsSync(fn)) {
|
|
13
|
+
if (fn.match(/sw\.js/)) s.writeHead(200, { 'Content-Type': 'application/javascript' })
|
|
14
|
+
return !s.end(FS.readFileSync(fn, 'utf-8'))
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
'/api': ({s})=>s.end('example of an api response'),
|
|
19
|
+
}
|
package/server.mjs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
|
|
7
|
+
const routesfile = resolve('routes.mjs');
|
|
8
|
+
const routesurl = pathToFileURL(routesfile).href;
|
|
9
|
+
console.log(routesfile, routesurl);
|
|
10
|
+
|
|
11
|
+
const routes = (await import(routesurl)).default;
|
|
12
|
+
const VastDB = (await import(`./vastdb.mjs`)).default;
|
|
13
|
+
const db = new VastDB(routes);
|
|
14
|
+
console.log(db.filename, routes);
|
|
15
|
+
|
|
16
|
+
http
|
|
17
|
+
.createServer(async (r, s) => {
|
|
18
|
+
try {
|
|
19
|
+
let data = '';
|
|
20
|
+
r.on('data', (s) => (data += s.toString()));
|
|
21
|
+
r.on('end', (x) => {
|
|
22
|
+
try {
|
|
23
|
+
data = JSON.parse(data);
|
|
24
|
+
} catch {}
|
|
25
|
+
});
|
|
26
|
+
s.endJSON = (o) => s.end(JSON.stringify(o));
|
|
27
|
+
const midware = Object.keys(routes)
|
|
28
|
+
.filter((k) => k.startsWith('_'))
|
|
29
|
+
.find((k) => routes[k]({ r, s, data, db }));
|
|
30
|
+
if (routes[r.url]) return routes[r.url]({ r, s, data, db });
|
|
31
|
+
else s.writeHead(404).end();
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.log(e);
|
|
34
|
+
s.writeHead(404).end();
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
.listen(3000, (x) => console.log('listening on 3000'));
|
package/vastdb.mjs
CHANGED
|
@@ -2,9 +2,8 @@ import fs from 'node:fs'
|
|
|
2
2
|
export default class VastDB extends Map {
|
|
3
3
|
constructor(v) {
|
|
4
4
|
super();
|
|
5
|
-
this.filename = `${process.cwd()}/db.json`;
|
|
5
|
+
this.filename = `${process.cwd()}/data/db.json`;
|
|
6
6
|
this.views = v
|
|
7
|
-
this.triggers = []
|
|
8
7
|
if (!fs.existsSync(this.filename)) {
|
|
9
8
|
this.set({
|
|
10
9
|
type: 'user',
|
|
@@ -23,18 +22,18 @@ export default class VastDB extends Map {
|
|
|
23
22
|
query(q = () => false) {
|
|
24
23
|
return [...this].filter(q).map(([k, v]) => v)
|
|
25
24
|
}
|
|
26
|
-
getView(name) {
|
|
27
|
-
|
|
28
|
-
return
|
|
25
|
+
getView(name, param) {
|
|
26
|
+
const res = [...this].filter(this.views[name](param));
|
|
27
|
+
return res.map(([k, v]) => v);
|
|
29
28
|
}
|
|
30
29
|
set(arr) {
|
|
31
30
|
if (!arr.push) arr = [arr];
|
|
32
31
|
for (const o of arr) {
|
|
33
32
|
if (!o.name || !o.type) return false;
|
|
34
33
|
if (!o.id) o.id = o.type + ':' + o.name;
|
|
35
|
-
this.triggers.map(t => o = t(o))
|
|
36
34
|
}
|
|
37
35
|
arr.map((o) => super.set(o.id, o));
|
|
36
|
+
if(this.event) this.event(arr)
|
|
38
37
|
this.save();
|
|
39
38
|
}
|
|
40
39
|
save() {
|
package/index.mjs
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import http from 'node:http'
|
|
3
|
-
import fs from 'node:fs'
|
|
4
|
-
import {pathToFileURL} from 'node:url'
|
|
5
|
-
import { resolve } from 'node:path'
|
|
6
|
-
|
|
7
|
-
const routesfile = resolve('routes.mjs')
|
|
8
|
-
const routesurl = pathToFileURL(routesfile).href
|
|
9
|
-
const indexfile = resolve('index.html')
|
|
10
|
-
|
|
11
|
-
console.log(routesfile, routesurl)
|
|
12
|
-
|
|
13
|
-
if (!fs.existsSync(routesfile)) {
|
|
14
|
-
fs.writeFileSync(routesfile, `import fs from 'node:fs'
|
|
15
|
-
export default {
|
|
16
|
-
_debug: ({ r, s, db }) => console.log(r.url, r.method),
|
|
17
|
-
'/': e => e.s.end(fs.readFileSync('index.html', 'utf-8')),
|
|
18
|
-
'/post': ({ e, body }) => db.set(body),
|
|
19
|
-
'/tables': ({s}) => s.endJSON(db.getView('tables')),
|
|
20
|
-
'tables': name => ([k, v]) => k.match(name + ':')
|
|
21
|
-
}`)
|
|
22
|
-
}
|
|
23
|
-
if (!fs.existsSync(indexfile)) {
|
|
24
|
-
fs.writeFileSync(indexfile, `<!DOCTYPE html>
|
|
25
|
-
<link rel="icon" href="data:,">
|
|
26
|
-
<script>navigator.serviceWorker.register('sw.js')</script>
|
|
27
|
-
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css'>
|
|
28
|
-
<script src='https://unpkg.com/enigmatic/enigmatic.js'></script>
|
|
29
|
-
|
|
30
|
-
<div class='bg-yellow-200'>hello</div>`)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const routes = (await import(routesurl)).default
|
|
34
|
-
routes['/sw.js'] = e => {
|
|
35
|
-
e.s.writeHead(201, { 'Content-Type': 'application/javascript' })
|
|
36
|
-
e.s.end('self.addEventListener("fetch",e=>{e.respondWith(caches.open("e").then(function(t){return t.match(e.request).then(function(n){return n||fetch(e.request).then(function(n){return e.request.url.match(/\.js$|\.css$/)&&t.put(e.request,n.clone()),n})})}))});')
|
|
37
|
-
}
|
|
38
|
-
const VastDB = (await import(`./vastdb.mjs`)).default
|
|
39
|
-
const db = new VastDB(routes)
|
|
40
|
-
console.log(db.filename, routes)
|
|
41
|
-
|
|
42
|
-
http
|
|
43
|
-
.createServer(async (r, s) => {
|
|
44
|
-
try {
|
|
45
|
-
let data = '';
|
|
46
|
-
r.on('data', (s) => (data += s.toString()));
|
|
47
|
-
r.on('end', (x) => {
|
|
48
|
-
try {
|
|
49
|
-
data = JSON.parse(data);
|
|
50
|
-
} catch { }
|
|
51
|
-
});
|
|
52
|
-
s.endJSON = o => s.end(JSON.stringify(o))
|
|
53
|
-
const midware = Object.keys(routes)
|
|
54
|
-
.filter((k) => k.startsWith('_'))
|
|
55
|
-
.map((k) => routes[k]({ r, s, data, db }));
|
|
56
|
-
if (midware.includes(true)) return;
|
|
57
|
-
if (routes[r.url]) return routes[r.url]({ r, s, data, db });
|
|
58
|
-
else s.writeHead(404).end()
|
|
59
|
-
} catch (e) {
|
|
60
|
-
console.log(e);
|
|
61
|
-
s.writeHead(404).end();
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
.listen(3000, (x) => console.log('listening on 3000'));
|
package/test.mjs
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import Vast from './vastdb.mjs'
|
|
2
|
-
const db = new Vast()
|
|
3
|
-
|
|
4
|
-
db.views = {
|
|
5
|
-
tables: ([k, v]) => k.match('user')
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
db.triggers = {
|
|
9
|
-
test_trigger: record => record.value = 100
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
db.workflows = {
|
|
13
|
-
'testwf' : {
|
|
14
|
-
start: db => 'wait_two_sec',
|
|
15
|
-
wait_two_sec: db => new Promise(r => setTimeout(r('end'), 2000)),
|
|
16
|
-
end: db => console.log('done')
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
//console.log(db.getView('tables'))
|
|
21
|
-
db.set({name: 'testrec', value: 0})
|
|
22
|
-
console.log(db)
|