@voxgig/build 4.3.0 → 4.11.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 +51 -2
- package/build.ts +20 -0
- package/dist/api/api_gen.d.ts +7 -0
- package/dist/api/api_gen.js +370 -0
- package/dist/api/api_gen.js.map +1 -0
- package/dist/build.d.ts +16 -1
- package/dist/build.js +17 -1
- package/dist/build.js.map +1 -1
- package/dist/doc/doc_gen.d.ts +8 -0
- package/dist/doc/doc_gen.js +397 -0
- package/dist/doc/doc_gen.js.map +1 -0
- package/dist/env/web/web_gen.js +159 -1
- package/dist/env/web/web_gen.js.map +1 -1
- package/dist/shape/ent.js +4 -2
- package/dist/shape/ent.js.map +1 -1
- package/env/web/web_gen.ts +174 -1
- package/package.json +6 -9
- package/tm/web/backend/env/shared/seed.ts.frag +23 -0
- package/tm/web/backend/env/web/api.ts.frag +157 -0
- package/tm/web/backend/env/web/web.ts.frag +37 -4
- package/tm/web/backend/srv/api/api-srv.ts.frag +4 -0
- package/tm/web/backend/srv/api/expose.ts.frag +33 -0
- package/tm/web/backend/srv/api/get_info.ts.frag +6 -0
- package/tm/web/backend/srv/api/on_ent.ts.frag +124 -0
- package/tm/web/backend/srv/auth/apikey_util.ts.frag +10 -0
- package/tm/web/backend/srv/auth/auth-srv.ts.frag +1 -0
- package/tm/web/backend/srv/auth/change_pass.ts.frag +12 -0
- package/tm/web/backend/srv/auth/create_apikey.ts.frag +33 -0
- package/tm/web/backend/srv/auth/get_info.ts.frag +1 -0
- package/tm/web/backend/srv/auth/list_apikey.ts.frag +15 -0
- package/tm/web/backend/srv/auth/load_auth.ts.frag +10 -1
- package/tm/web/backend/srv/auth/remind_pass.ts.frag +35 -0
- package/tm/web/backend/srv/auth/revoke_apikey.ts.frag +23 -0
- package/tm/web/backend/srv/auth/signin_user.ts.frag +12 -2
- package/tm/web/backend/srv/auth/signout_user.ts.frag +11 -1
- package/tm/web/backend/srv/auth/update_user.ts.frag +15 -0
- package/tm/web/backend/srv/auth/user_util.ts.frag +21 -0
- package/tm/web/backend/srv/auth/web_change_pass.ts.frag +16 -0
- package/tm/web/backend/srv/auth/web_create_apikey.ts.frag +15 -0
- package/tm/web/backend/srv/auth/web_list_apikey.ts.frag +11 -0
- package/tm/web/backend/srv/auth/web_load_auth.ts.frag +1 -0
- package/tm/web/backend/srv/auth/web_remind_pass.ts.frag +7 -0
- package/tm/web/backend/srv/auth/web_revoke_apikey.ts.frag +14 -0
- package/tm/web/backend/srv/auth/web_signin_user.ts.frag +1 -0
- package/tm/web/backend/srv/auth/web_signout_user.ts.frag +11 -3
- package/tm/web/backend/srv/auth/web_update_user.ts.frag +11 -0
- package/tm/web/backend/srv/ent/access.ts.frag +179 -0
- package/tm/web/backend/srv/ent/cmd_list.ts.frag +86 -0
- package/tm/web/backend/srv/ent/cmd_load.ts.frag +56 -0
- package/tm/web/backend/srv/ent/cmd_remove.ts.frag +60 -0
- package/tm/web/backend/srv/ent/cmd_save.ts.frag +141 -0
- package/tm/web/backend/srv/ent/ent-srv.ts.frag +4 -0
- package/tm/web/backend/srv/ent/get_info.ts.frag +6 -0
- package/tm/web/backend/srv/ent/web_cmd_list.ts.frag +17 -0
- package/tm/web/backend/srv/ent/web_cmd_load.ts.frag +17 -0
- package/tm/web/backend/srv/ent/web_cmd_remove.ts.frag +17 -0
- package/tm/web/backend/srv/ent/web_cmd_save.ts.frag +17 -0
- package/tm/web/backend/test/unit/env/web/api-router.test.ts.frag +315 -0
- package/tm/web/backend/test/unit/env/web/surface.test.ts.frag +109 -0
- package/tm/web/backend/test/unit/srv/api/api.setup.ts.frag +162 -0
- package/tm/web/backend/test/unit/srv/api/api.test.ts.frag +225 -0
- package/tm/web/backend/test/unit/srv/auth/apikey.test.ts.frag +152 -0
- package/tm/web/backend/test/unit/srv/auth/auth.setup.ts.frag +40 -0
- package/tm/web/backend/test/unit/srv/auth/session.test.ts.frag +189 -0
- package/tm/web/backend/test/unit/srv/ent/ent.setup.ts.frag +53 -0
- package/tm/web/backend/test/unit/srv/ent/proxy.test.ts.frag +109 -0
- package/tm/web/docs/explanation/web-architecture.md.frag +50 -0
- package/tm/web/docs/how-to/add-a-custom-entity-view.md.frag +53 -0
- package/tm/web/docs/how-to/change-the-theme.md.frag +63 -0
- package/tm/web/docs/how-to/customise-the-web-app.md.frag +68 -0
- package/tm/web/docs/how-to/use-the-api.md.frag +53 -0
- package/tm/web/docs/reference/web-app.md.frag +98 -0
- package/tm/web/web/AGENTS.md.frag +52 -0
- package/tm/web/web/e2e/smoke.spec.js.frag +13 -11
- package/tm/web/web/index.html.frag +3 -0
- package/tm/web/web/package.json.frag +4 -1
- package/tm/web/web/playwright.config.js.frag +6 -1
- package/tm/web/web/src/api.js.frag +92 -0
- package/tm/web/web/src/bus.js.frag +46 -23
- package/tm/web/web/src/cmp/admin.js.frag +292 -193
- package/tm/web/web/src/cmp/admin.md.frag +51 -0
- package/tm/web/web/src/cmp/app.js.frag +12 -15
- package/tm/web/web/src/cmp/app.md.frag +28 -0
- package/tm/web/web/src/cmp/auth.js.frag +69 -41
- package/tm/web/web/src/cmp/auth.md.frag +36 -0
- package/tm/web/web/src/cmp/public.js.frag +58 -0
- package/tm/web/web/src/cmp/public.md.frag +26 -0
- package/tm/web/web/src/cmp/settings.js.frag +178 -0
- package/tm/web/web/src/cmp/settings.md.frag +30 -0
- package/tm/web/web/src/cmp/shell.js.frag +231 -0
- package/tm/web/web/src/cmp/shell.md.frag +49 -0
- package/tm/web/web/src/cmp/view/custom-view.js.frag +47 -0
- package/tm/web/web/src/cmp/view/custom-view.md.frag +31 -0
- package/tm/web/web/src/custom.css.frag +8 -0
- package/tm/web/web/src/customise.js.frag +30 -0
- package/tm/web/web/src/hooks.js.frag +79 -0
- package/tm/web/web/src/main.js.frag +17 -4
- package/tm/web/web/src/model.js.frag +162 -0
- package/tm/web/web/src/style.css.frag +135 -21
- package/tm/web/web/src/theme.js.frag +82 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Thin client over the Seneca bus.
|
|
2
|
+
//
|
|
3
|
+
// EVERY message the browser sends is an aim:web message: that is the only
|
|
4
|
+
// namespace the backend gateway accepts (see backend/src/env/web/web.ts),
|
|
5
|
+
// and each one is a declared proxy that forwards to the real service
|
|
6
|
+
// message. Entity CRUD still lands on the ONE generic backend service, so
|
|
7
|
+
// the same four calls serve every entity in the model.
|
|
8
|
+
|
|
9
|
+
import { bus } from './bus.js'
|
|
10
|
+
|
|
11
|
+
// ---- generic entity CRUD ------------------------------------------------
|
|
12
|
+
|
|
13
|
+
async function list(ent, q) {
|
|
14
|
+
const r = await bus.post({ aim: 'web', on: 'ent', cmd: 'list', ent, q: q || {} })
|
|
15
|
+
return (r && r.ok && r.list) || []
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function load(ent, id) {
|
|
19
|
+
const r = await bus.post({ aim: 'web', on: 'ent', cmd: 'load', ent, id })
|
|
20
|
+
return r && r.ok ? r.item : null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function save(ent, item) {
|
|
24
|
+
return bus.post({ aim: 'web', on: 'ent', cmd: 'save', ent, item })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function remove(ent, id) {
|
|
28
|
+
return bus.post({ aim: 'web', on: 'ent', cmd: 'remove', ent, id })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Users, for reference pickers (read-only, public fields).
|
|
32
|
+
async function users() {
|
|
33
|
+
return list('sys/user')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ---- auth / settings ----------------------------------------------------
|
|
37
|
+
|
|
38
|
+
async function loadAuth() {
|
|
39
|
+
return bus.post('aim:web,on:auth,load:auth')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function signin(email, password) {
|
|
43
|
+
return bus.post('aim:web,on:auth,signin:user', { email, password })
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function signout() {
|
|
47
|
+
return bus.post('aim:web,on:auth,signout:user')
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function changePass(password) {
|
|
51
|
+
return bus.post({ aim: 'web', on: 'auth', change: 'pass', password })
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function updateUser(data) {
|
|
55
|
+
return bus.post({ aim: 'web', on: 'auth', update: 'user', data })
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function remindPass(email) {
|
|
59
|
+
return bus.post({ aim: 'web', on: 'auth', remind: 'pass', email })
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ---- API access keys (REST API auth; Settings & security) ---------------
|
|
63
|
+
|
|
64
|
+
async function createApikey(name) {
|
|
65
|
+
return bus.post({ aim: 'web', on: 'auth', create: 'apikey', name })
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function listApikeys() {
|
|
69
|
+
return bus.post({ aim: 'web', on: 'auth', list: 'apikey' })
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function revokeApikey(id) {
|
|
73
|
+
return bus.post({ aim: 'web', on: 'auth', revoke: 'apikey', id })
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export {
|
|
77
|
+
list,
|
|
78
|
+
load,
|
|
79
|
+
save,
|
|
80
|
+
remove,
|
|
81
|
+
users,
|
|
82
|
+
loadAuth,
|
|
83
|
+
signin,
|
|
84
|
+
signout,
|
|
85
|
+
changePass,
|
|
86
|
+
updateUser,
|
|
87
|
+
remindPass,
|
|
88
|
+
createApikey,
|
|
89
|
+
listApikeys,
|
|
90
|
+
revokeApikey,
|
|
91
|
+
}
|
|
92
|
+
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// The browser-side Seneca service bus. All component state and all
|
|
2
2
|
// backend communication flow through messages on this bus:
|
|
3
3
|
//
|
|
4
|
-
// aim
|
|
4
|
+
// aim:web,* -> the backend gateway (/seneca) via the
|
|
5
5
|
// seneca-browser fetch transport (cookie auth)
|
|
6
6
|
// cmp:* -> local component plugins (state)
|
|
7
7
|
//
|
|
8
8
|
// Cross-component notification uses the tiny `evt` plugin below:
|
|
9
9
|
// components post cmp:bus,emit:<name> and subscribe with onEvent().
|
|
10
10
|
|
|
11
|
-
/* global Seneca */
|
|
11
|
+
/* global Seneca, SenecaBrowserStore, SenecaBrowserDebug */
|
|
12
12
|
|
|
13
13
|
const bus = Seneca({
|
|
14
14
|
legacy: false,
|
|
@@ -23,34 +23,56 @@ const bus = Seneca({
|
|
|
23
23
|
},
|
|
24
24
|
})
|
|
25
25
|
.test()
|
|
26
|
-
.client({ type: 'browser', pin: 'aim
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
bus.use(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
fn(msg.data || {})
|
|
39
|
-
}
|
|
40
|
-
catch (e) {
|
|
41
|
-
console.error('evt listener failed', msg.name, e)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
reply({ ok: true, count: subs.length })
|
|
26
|
+
.client({ type: 'browser', pin: 'aim:web' })
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
// Transparent state cache (Redux-like): caches aim:web query results and
|
|
30
|
+
// invalidates on writes, so repeated reads are served without a round-trip.
|
|
31
|
+
// Registered AFTER .client() so the aim:web pin actions exist to be wrapped.
|
|
32
|
+
if ('undefined' !== typeof SenecaBrowserStore) {
|
|
33
|
+
bus.use(SenecaBrowserStore, {
|
|
34
|
+
pin: 'aim:web',
|
|
35
|
+
// Defaults plus 'revoke': aim:web,on:auth,revoke:apikey must
|
|
36
|
+
// invalidate the cached list:apikey reads.
|
|
37
|
+
write: ['save', 'remove', 'update', 'delete', 'create', 'done', 'set', 'add', 'revoke'],
|
|
45
38
|
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// In-window devtools: a resizable/hideable pop-up showing live Seneca
|
|
42
|
+
// message flows, config, and (via the store plugin above) the cache tree.
|
|
43
|
+
// aim:web messages are the remote (backend) calls. Loaded as a global script
|
|
44
|
+
// in index.html; guarded so a missing bundle never breaks the app.
|
|
45
|
+
if ('undefined' !== typeof SenecaBrowserDebug) {
|
|
46
|
+
bus.use(SenecaBrowserDebug, { remotePins: 'aim:web' })
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
// Event fanout, unified on Seneca messages: cross-component events use the
|
|
51
|
+
// bus's own sub/act. Unlike a plain `add` (single handler), `sub` allows
|
|
52
|
+
// many observers per pattern - so it IS the pub/sub primitive. A no-op sink
|
|
53
|
+
// action lets `act` resolve; observers subscribe via `sub`. This is the same
|
|
54
|
+
// mechanism reactivity uses (see @seneca/browser-store's changed:* events).
|
|
55
|
+
bus.add('cmp:evt', function (msg, reply) {
|
|
56
|
+
reply()
|
|
46
57
|
})
|
|
47
58
|
|
|
48
59
|
function onEvent(name, fn) {
|
|
49
|
-
(
|
|
60
|
+
bus.sub('cmp:evt,name:' + name, function (msg) {
|
|
61
|
+
fn(msg.data || {})
|
|
62
|
+
})
|
|
50
63
|
}
|
|
51
64
|
|
|
52
65
|
function emit(name, data) {
|
|
53
|
-
bus.
|
|
66
|
+
bus.act('cmp:evt,name:' + name, { data })
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
// Avoid cross-user staleness: drop all cached queries whenever auth changes
|
|
71
|
+
// (sign in / sign out), since cached results are principal-scoped.
|
|
72
|
+
if ('undefined' !== typeof SenecaBrowserStore) {
|
|
73
|
+
onEvent('auth', function () {
|
|
74
|
+
bus.act('sys:browser-store,clear:store', function () {})
|
|
75
|
+
})
|
|
54
76
|
}
|
|
55
77
|
|
|
56
78
|
|
|
@@ -59,3 +81,4 @@ export {
|
|
|
59
81
|
onEvent,
|
|
60
82
|
emit,
|
|
61
83
|
}
|
|
84
|
+
|