Compare commits

...

221 Commits

Author SHA1 Message Date
semantic-release-bot 58f6bd17f5 chore(release): 0.1.0-develop.68 [skip ci]
# [0.1.0-develop.68](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.67...v0.1.0-develop.68) (2023-11-17)
2023-11-17 13:49:02 +00:00
Derrick Hammer 7ed66baeab
Merge remote-tracking branch 'origin/develop' into develop 2023-11-17 08:48:09 -05:00
Derrick Hammer a450289a50
dep: update libweb 2023-11-17 08:48:04 -05:00
semantic-release-bot eb6f7b9685 chore(release): 0.1.0-develop.67 [skip ci]
# [0.1.0-develop.67](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.66...v0.1.0-develop.67) (2023-10-19)
2023-10-19 21:09:40 +00:00
Derrick Hammer fb575a0083
Merge remote-tracking branch 'origin/develop' into develop 2023-10-19 17:08:37 -04:00
Derrick Hammer f84a7e7944
dep: update libweb 2023-10-19 17:08:32 -04:00
semantic-release-bot 0c91c3a4ec chore(release): 0.1.0-develop.66 [skip ci]
# [0.1.0-develop.66](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.65...v0.1.0-develop.66) (2023-10-12)

### Bug Fixes

* always show log data ([d3259fa](d3259fa3f4))
* duplicate kernelLoadedDefer ([a4b9b46](a4b9b46a3e))
2023-10-12 07:41:44 +00:00
Derrick Hammer d3259fa3f4
fix: always show log data 2023-10-12 03:40:39 -04:00
Derrick Hammer a4b9b46a3e
fix: duplicate kernelLoadedDefer 2023-10-12 03:40:02 -04:00
semantic-release-bot 5c34946604 chore(release): 0.1.0-develop.65 [skip ci]
# [0.1.0-develop.65](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.64...v0.1.0-develop.65) (2023-10-09)

### Features

* add createNetworkClient helper ([6ecaf16](6ecaf16d4e))
2023-10-09 04:17:11 +00:00
Derrick Hammer 4693c00311
Merge remote-tracking branch 'origin/develop' into develop 2023-10-09 00:16:00 -04:00
Derrick Hammer 6ecaf16d4e
feat: add createNetworkClient helper 2023-10-09 00:15:47 -04:00
semantic-release-bot 44df5c3bee chore(release): 0.1.0-develop.64 [skip ci]
# [0.1.0-develop.64](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.63...v0.1.0-develop.64) (2023-09-20)
2023-09-20 15:00:58 +00:00
Derrick Hammer 7730140b26
Merge remote-tracking branch 'origin/develop' into develop 2023-09-20 10:59:57 -04:00
Derrick Hammer 424e219f66
dep: update libweb 2023-09-20 10:59:53 -04:00
semantic-release-bot b18fd046f0 chore(release): 0.1.0-develop.63 [skip ci]
# [0.1.0-develop.63](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.62...v0.1.0-develop.63) (2023-09-16)

### Bug Fixes

* remove checking the method for kernel -> sw messages ([6e1e244](6e1e244f0e))
2023-09-16 18:27:13 +00:00
Derrick Hammer b73e6b3b31
Merge remote-tracking branch 'origin/develop' into develop 2023-09-16 14:26:11 -04:00
Derrick Hammer 6e1e244f0e
fix: remove checking the method for kernel -> sw messages 2023-09-16 14:26:05 -04:00
semantic-release-bot e60ef84435 chore(release): 0.1.0-develop.62 [skip ci]
# [0.1.0-develop.62](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.61...v0.1.0-develop.62) (2023-09-11)
2023-09-11 18:20:31 +00:00
Derrick Hammer 34da5bdd21
Merge remote-tracking branch 'origin/develop' into develop 2023-09-11 14:19:37 -04:00
Derrick Hammer b43dac1f88
dep: use libweb 2023-09-11 14:19:30 -04:00
semantic-release-bot d7ba7da16f chore(release): 0.1.0-develop.61 [skip ci]
# [0.1.0-develop.61](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.60...v0.1.0-develop.61) (2023-09-11)

### Bug Fixes

* add service worker to check ([c2be4fe](c2be4fe886))
* use FROM_SW ([ca15414](ca15414444))
2023-09-11 13:56:24 +00:00
Derrick Hammer ca15414444
fix: use FROM_SW 2023-09-11 09:54:52 -04:00
Derrick Hammer c2be4fe886
fix: add service worker to check 2023-09-11 09:54:51 -04:00
semantic-release-bot 1952aea355 chore(release): 0.1.0-develop.60 [skip ci]
# [0.1.0-develop.60](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.59...v0.1.0-develop.60) (2023-09-11)

### Bug Fixes

* don't nest in a data property with exchangeCommunicationKeys ([d7663d0](d7663d0ff5))
2023-09-11 12:11:48 +00:00
Derrick Hammer db5e40cb9e
Merge remote-tracking branch 'origin/develop' into develop 2023-09-11 08:10:46 -04:00
Derrick Hammer d7663d0ff5
fix: don't nest in a data property with exchangeCommunicationKeys 2023-09-11 08:10:41 -04:00
semantic-release-bot 4cb47e670f chore(release): 0.1.0-develop.59 [skip ci]
# [0.1.0-develop.59](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.58...v0.1.0-develop.59) (2023-09-11)

### Bug Fixes

* newBootloaderQuery now returns an ErrTuple ([780f4fd](780f4fddf7))
* newBootloaderQuery should return a ErrTuple ([3ee446a](3ee446a9c5))
2023-09-11 11:14:50 +00:00
Derrick Hammer d0d4e53672
Merge remote-tracking branch 'origin/develop' into develop 2023-09-11 07:13:30 -04:00
Derrick Hammer 780f4fddf7
fix: newBootloaderQuery now returns an ErrTuple 2023-09-11 07:13:27 -04:00
Derrick Hammer 3ee446a9c5
fix: newBootloaderQuery should return a ErrTuple 2023-09-11 07:10:42 -04:00
semantic-release-bot 81a306ed54 chore(release): 0.1.0-develop.58 [skip ci]
# [0.1.0-develop.58](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.57...v0.1.0-develop.58) (2023-09-11)

### Bug Fixes

* need to pass nonce with query ([6fb7486](6fb7486368))
2023-09-11 11:01:38 +00:00
Derrick Hammer 2369ab7d32
Merge remote-tracking branch 'origin/develop' into develop 2023-09-11 07:00:42 -04:00
Derrick Hammer 6fb7486368
fix: need to pass nonce with query 2023-09-11 07:00:38 -04:00
semantic-release-bot 1f5b34e848 chore(release): 0.1.0-develop.57 [skip ci]
# [0.1.0-develop.57](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.56...v0.1.0-develop.57) (2023-09-11)

### Bug Fixes

* replace kernelLoadedResolve with kernelLoadedDefer ([b5d3ba4](b5d3ba46cf))
2023-09-11 10:54:29 +00:00
Derrick Hammer 9244312141
Merge remote-tracking branch 'origin/develop' into develop 2023-09-11 06:53:07 -04:00
Derrick Hammer b5d3ba46cf
fix: replace kernelLoadedResolve with kernelLoadedDefer 2023-09-11 06:52:58 -04:00
semantic-release-bot 425b478800 chore(release): 0.1.0-develop.56 [skip ci]
# [0.1.0-develop.56](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.55...v0.1.0-develop.56) (2023-09-11)

### Bug Fixes

* use newBootloaderQuery ([25d2f6b](25d2f6b1c0))

### Features

* add newBootloaderQuery method ([8561535](85615350f0))
2023-09-11 10:43:32 +00:00
Derrick Hammer 1138e45486
Merge remote-tracking branch 'origin/develop' into develop 2023-09-11 06:42:38 -04:00
Derrick Hammer 25d2f6b1c0
fix: use newBootloaderQuery 2023-09-11 06:42:32 -04:00
Derrick Hammer 85615350f0
feat: add newBootloaderQuery method 2023-09-11 06:41:17 -04:00
semantic-release-bot 7e22774163 chore(release): 0.1.0-develop.55 [skip ci]
# [0.1.0-develop.55](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.54...v0.1.0-develop.55) (2023-09-11)

### Bug Fixes

* export login and serviceWorkerReady ([cb5a617](cb5a6175f6))
2023-09-11 10:15:32 +00:00
Derrick Hammer cce4884dc3
Merge remote-tracking branch 'origin/develop' into develop 2023-09-11 06:14:36 -04:00
Derrick Hammer cb5a6175f6
fix: export login and serviceWorkerReady 2023-09-11 06:14:32 -04:00
semantic-release-bot 8c07210ec6 chore(release): 0.1.0-develop.54 [skip ci]
# [0.1.0-develop.54](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.53...v0.1.0-develop.54) (2023-09-11)

### Features

* add login function that calls exchangeCommunicationKeys and setLoginKey ([fd6c8d3](fd6c8d3b1f))
* add service worker support ([15c5960](15c59603f2))
2023-09-11 10:10:02 +00:00
Derrick Hammer 615954a1f6
Merge remote-tracking branch 'origin/develop' into develop 2023-09-11 06:09:01 -04:00
Derrick Hammer fd6c8d3b1f
feat: add login function that calls exchangeCommunicationKeys and setLoginKey 2023-09-11 06:08:41 -04:00
Derrick Hammer 17eb74483c
refactor: add getKernelIframe method 2023-09-11 05:58:48 -04:00
Derrick Hammer 15c59603f2
feat: add service worker support 2023-09-10 19:06:55 -04:00
Derrick Hammer c4e211b04c
refactor: switch to using defer's 2023-09-10 18:46:23 -04:00
semantic-release-bot d4d0d170fc chore(release): 0.1.0-develop.53 [skip ci]
# [0.1.0-develop.53](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.52...v0.1.0-develop.53) (2023-09-09)
2023-09-09 20:05:19 +00:00
Derrick Hammer 665117dfac
Merge remote-tracking branch 'origin/develop' into develop 2023-09-09 16:04:16 -04:00
Derrick Hammer b2ac3349b6
dep: update libweb 2023-09-09 16:04:08 -04:00
semantic-release-bot 955ff3793b chore(release): 0.1.0-develop.52 [skip ci]
# [0.1.0-develop.52](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.51...v0.1.0-develop.52) (2023-09-09)
2023-09-09 19:41:30 +00:00
Derrick Hammer d82460315a
Merge remote-tracking branch 'origin/develop' into develop 2023-09-09 15:40:23 -04:00
Derrick Hammer c91f93b107
dep: update libweb 2023-09-09 15:40:17 -04:00
semantic-release-bot a5f16cae41 chore(release): 0.1.0-develop.51 [skip ci]
# [0.1.0-develop.51](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.50...v0.1.0-develop.51) (2023-09-09)
2023-09-09 11:36:57 +00:00
Derrick Hammer 602a7f8f56
Merge remote-tracking branch 'origin/develop' into develop 2023-09-09 07:36:00 -04:00
Derrick Hammer 268960b800
refactor: remove localhost-only check 2023-09-09 07:35:38 -04:00
semantic-release-bot e42237b34c chore(release): 0.1.0-develop.50 [skip ci]
# [0.1.0-develop.50](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.49...v0.1.0-develop.50) (2023-09-08)
2023-09-08 17:25:56 +00:00
Derrick Hammer 602673e825
Merge remote-tracking branch 'origin/develop' into develop 2023-09-08 13:24:58 -04:00
Derrick Hammer 5051951dcd
dep: update libweb 2023-09-08 13:24:52 -04:00
semantic-release-bot a755015cca chore(release): 0.1.0-develop.49 [skip ci]
# [0.1.0-develop.49](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.48...v0.1.0-develop.49) (2023-09-08)
2023-09-08 16:58:09 +00:00
Derrick Hammer 4fd0644dd9
Merge remote-tracking branch 'origin/develop' into develop 2023-09-08 12:57:15 -04:00
Derrick Hammer 0ab4de1b2c
dep: update libweb 2023-09-08 12:57:11 -04:00
semantic-release-bot 0c701c3d21 chore(release): 0.1.0-develop.48 [skip ci]
# [0.1.0-develop.48](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.47...v0.1.0-develop.48) (2023-09-08)
2023-09-08 14:18:28 +00:00
Derrick Hammer d349555afd
Merge remote-tracking branch 'origin/develop' into develop 2023-09-08 10:17:33 -04:00
Derrick Hammer ad5ee757d2
dep: update libweb 2023-09-08 10:17:28 -04:00
semantic-release-bot d508bd6140 chore(release): 0.1.0-develop.47 [skip ci]
# [0.1.0-develop.47](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.46...v0.1.0-develop.47) (2023-09-08)
2023-09-08 13:38:37 +00:00
Derrick Hammer 4c4d5c977a
Merge remote-tracking branch 'origin/develop' into develop 2023-09-08 09:37:41 -04:00
Derrick Hammer 0d6b2c50a1
dep: update libweb 2023-09-08 09:37:38 -04:00
semantic-release-bot f36e1b26f0 chore(release): 0.1.0-develop.46 [skip ci]
# [0.1.0-develop.46](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.45...v0.1.0-develop.46) (2023-09-08)

### Bug Fixes

* export types since we are no longer storing them in libweb ([4abc3ed](4abc3ed9c4))
* update imports to be local ([631fde4](631fde4868))
* use Err from types ([bb1229e](bb1229eeb2))
* use types and util locally ([469f02b](469f02b69f))
2023-09-08 12:50:37 +00:00
Derrick Hammer 631fde4868
fix: update imports to be local 2023-09-08 08:49:41 -04:00
Derrick Hammer 469f02b69f
fix: use types and util locally 2023-09-08 08:43:46 -04:00
Derrick Hammer b46bd6048e
refactor: move b64ToBuf from libweb 2023-09-08 08:42:55 -04:00
Derrick Hammer bb1229eeb2
fix: use Err from types 2023-09-08 08:39:58 -04:00
Derrick Hammer a18e2fbe36
Merge remote-tracking branch 'origin/develop' into develop 2023-09-08 08:30:10 -04:00
Derrick Hammer 4abc3ed9c4
fix: export types since we are no longer storing them in libweb 2023-09-08 08:29:26 -04:00
Derrick Hammer da61dda507
dep: update libweb 2023-09-08 08:28:07 -04:00
Derrick Hammer 8a4e66782d
refactor: export util 2023-09-08 05:44:08 -04:00
Derrick Hammer 353f2457e8
refactor: move decodeU64 and encodeU64 from libweb 2023-09-08 05:43:56 -04:00
Derrick Hammer 44349bef9c
refactor: moving types and functions from libweb 2023-09-07 19:41:11 -04:00
semantic-release-bot 05cbe32a57 chore(release): 0.1.0-develop.45 [skip ci]
# [0.1.0-develop.45](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.44...v0.1.0-develop.45) (2023-09-04)
2023-09-04 11:43:52 +00:00
Derrick Hammer 00abaed2ed
Merge remote-tracking branch 'origin/develop' into develop 2023-09-04 07:42:54 -04:00
Derrick Hammer ac591eea3f
dep: update libweb 2023-09-04 07:42:49 -04:00
semantic-release-bot e009232076 chore(release): 0.1.0-develop.44 [skip ci]
# [0.1.0-develop.44](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.43...v0.1.0-develop.44) (2023-09-04)
2023-09-04 07:55:02 +00:00
Derrick Hammer d5a22ee6b7
Merge remote-tracking branch 'origin/develop' into develop 2023-09-04 03:53:49 -04:00
Derrick Hammer 97f384701b
dep: update libweb 2023-09-04 03:53:45 -04:00
semantic-release-bot bc7c5ee7fe chore(release): 0.1.0-develop.43 [skip ci]
# [0.1.0-develop.43](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.42...v0.1.0-develop.43) (2023-09-04)
2023-09-04 07:36:58 +00:00
Derrick Hammer 3bdaa08141
Merge remote-tracking branch 'origin/develop' into develop 2023-09-04 03:36:05 -04:00
Derrick Hammer 3b87fc5e7f
dep: update libweb 2023-09-04 03:36:01 -04:00
semantic-release-bot 4ad2304692 chore(release): 0.1.0-develop.42 [skip ci]
# [0.1.0-develop.42](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.41...v0.1.0-develop.42) (2023-09-04)
2023-09-04 01:33:06 +00:00
Derrick Hammer b078fff670
Merge remote-tracking branch 'origin/develop' into develop 2023-09-03 21:31:56 -04:00
Derrick Hammer 477d726964
dep: update libweb 2023-09-03 21:31:52 -04:00
semantic-release-bot a1e58c02d3 chore(release): 0.1.0-develop.41 [skip ci]
# [0.1.0-develop.41](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.40...v0.1.0-develop.41) (2023-09-04)
2023-09-04 01:19:00 +00:00
Derrick Hammer 9f10647c89
Merge remote-tracking branch 'origin/develop' into develop 2023-09-03 21:18:02 -04:00
Derrick Hammer 5c13bbb0a1
dep: update libweb 2023-09-03 21:17:52 -04:00
semantic-release-bot 7aebea3163 chore(release): 0.1.0-develop.40 [skip ci]
# [0.1.0-develop.40](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.39...v0.1.0-develop.40) (2023-09-04)
2023-09-04 00:49:09 +00:00
Derrick Hammer c1632cabb8
Merge remote-tracking branch 'origin/develop' into develop 2023-09-03 20:48:13 -04:00
Derrick Hammer d3cc4fbdc6
dep: update libweb 2023-09-03 20:48:09 -04:00
semantic-release-bot 7535eac63c chore(release): 0.1.0-develop.39 [skip ci]
# [0.1.0-develop.39](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.38...v0.1.0-develop.39) (2023-09-03)
2023-09-03 03:01:47 +00:00
Derrick Hammer a046dcc9ce
Merge remote-tracking branch 'origin/develop' into develop 2023-09-02 23:00:37 -04:00
Derrick Hammer 4d02a2e7d1
dep: update libweb 2023-09-02 23:00:31 -04:00
semantic-release-bot b714ec5108 chore(release): 0.1.0-develop.38 [skip ci]
# [0.1.0-develop.38](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.37...v0.1.0-develop.38) (2023-09-02)
2023-09-02 11:52:15 +00:00
Derrick Hammer 5e9fbad354
Merge remote-tracking branch 'origin/develop' into develop 2023-09-02 07:51:09 -04:00
Derrick Hammer cf51bf21bc
dep: update libweb 2023-09-02 07:51:05 -04:00
semantic-release-bot a82500aabf chore(release): 0.1.0-develop.37 [skip ci]
# [0.1.0-develop.37](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.36...v0.1.0-develop.37) (2023-09-02)
2023-09-02 11:38:17 +00:00
Derrick Hammer 10474a4018
Merge remote-tracking branch 'origin/develop' into develop 2023-09-02 07:37:12 -04:00
Derrick Hammer 88d15337dc
dep: update libweb 2023-09-02 07:37:08 -04:00
semantic-release-bot 0c05ac1f95 chore(release): 0.1.0-develop.36 [skip ci]
# [0.1.0-develop.36](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.35...v0.1.0-develop.36) (2023-08-20)
2023-08-20 06:39:33 +00:00
Derrick Hammer 0fd3547065
Merge remote-tracking branch 'origin/develop' into develop 2023-08-20 02:38:26 -04:00
Derrick Hammer b650c58bb5
dep: update libweb 2023-08-20 02:38:19 -04:00
semantic-release-bot b5b90b7522 chore(release): 0.1.0-develop.35 [skip ci]
# [0.1.0-develop.35](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.34...v0.1.0-develop.35) (2023-08-10)
2023-08-10 06:51:45 +00:00
Derrick Hammer 36a3877455
Merge remote-tracking branch 'origin/develop' into develop 2023-08-10 02:50:39 -04:00
Derrick Hammer 58a6ea2450
dep: update libweb 2023-08-10 02:50:34 -04:00
semantic-release-bot 28aa639cbf chore(release): 0.1.0-develop.34 [skip ci]
# [0.1.0-develop.34](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.33...v0.1.0-develop.34) (2023-07-29)

### Bug Fixes

* change callModule wrapper signature and correctly call callModule ([2adbddc](2adbddc769))
2023-07-29 23:49:46 +00:00
Derrick Hammer b6c56cf719
Merge remote-tracking branch 'origin/develop' into develop 2023-07-29 19:48:29 -04:00
Derrick Hammer 2adbddc769
fix: change callModule wrapper signature and correctly call callModule 2023-07-29 19:48:21 -04:00
semantic-release-bot 213d2744e0 chore(release): 0.1.0-develop.33 [skip ci]
# [0.1.0-develop.33](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.32...v0.1.0-develop.33) (2023-07-29)

### Bug Fixes

* make callModule a wrapper function that calls handleError ([73ea9ca](73ea9ca5b0))
2023-07-29 23:33:49 +00:00
Derrick Hammer 74f2b7dba3
Merge remote-tracking branch 'origin/develop' into develop 2023-07-29 19:32:51 -04:00
Derrick Hammer 73ea9ca5b0
fix: make callModule a wrapper function that calls handleError 2023-07-29 19:32:45 -04:00
semantic-release-bot 115faaacd1 chore(release): 0.1.0-develop.32 [skip ci]
# [0.1.0-develop.32](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.31...v0.1.0-develop.32) (2023-07-29)

### Bug Fixes

* add missing typeof check ([420a28c](420a28c224))
2023-07-29 20:47:29 +00:00
Derrick Hammer 6f036eae12
Merge remote-tracking branch 'origin/develop' into develop 2023-07-29 16:46:35 -04:00
Derrick Hammer 420a28c224
fix: add missing typeof check 2023-07-29 16:46:28 -04:00
semantic-release-bot 6a74429ce4 chore(release): 0.1.0-develop.31 [skip ci]
# [0.1.0-develop.31](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.30...v0.1.0-develop.31) (2023-07-29)

### Bug Fixes

* function does not need to be async ([09b691c](09b691ce0f))
* update status signature ([809e0ec](809e0ecd3b))

### Features

* add name method for api ([7affb28](7affb28081))
2023-07-29 03:49:22 +00:00
Derrick Hammer 7affb28081
feat: add name method for api 2023-07-28 23:48:24 -04:00
Derrick Hammer 809e0ecd3b
fix: update status signature 2023-07-28 23:48:07 -04:00
Derrick Hammer 1f3d59982a
Merge remote-tracking branch 'origin/develop' into develop 2023-07-27 10:44:52 -04:00
Derrick Hammer 09b691ce0f
fix: function does not need to be async 2023-07-27 10:44:44 -04:00
semantic-release-bot 3e890aebd4 chore(release): 0.1.0-develop.30 [skip ci]
# [0.1.0-develop.30](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.29...v0.1.0-develop.30) (2023-07-27)

### Bug Fixes

* make getNetworkModuleStatus not be async so we don't need to wait to get the async function if we have a callback ([a72651e](a72651e924))
2023-07-27 14:18:41 +00:00
Derrick Hammer 4b8240bcd5
Merge remote-tracking branch 'origin/develop' into develop 2023-07-27 10:17:44 -04:00
Derrick Hammer a72651e924
fix: make getNetworkModuleStatus not be async so we don't need to wait to get the async function if we have a callback 2023-07-27 10:17:35 -04:00
semantic-release-bot 090b2b830d chore(release): 0.1.0-develop.29 [skip ci]
# [0.1.0-develop.29](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.28...v0.1.0-develop.29) (2023-07-26)
2023-07-26 14:34:31 +00:00
Derrick Hammer 490291f1e0
Merge remote-tracking branch 'origin/develop' into develop 2023-07-26 10:33:34 -04:00
Derrick Hammer e3e910cfaf
refactor: add support for extension pages which need to use the bridge mode communication via runtime.connect 2023-07-26 10:33:24 -04:00
semantic-release-bot d86a48011f chore(release): 0.1.0-develop.28 [skip ci]
# [0.1.0-develop.28](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.27...v0.1.0-develop.28) (2023-07-25)

### Bug Fixes

* export getNetworkModuleStatus ([624511a](624511a041))
2023-07-25 15:43:21 +00:00
Derrick Hammer 6b00982e68
Merge remote-tracking branch 'origin/develop' into develop 2023-07-25 11:42:26 -04:00
Derrick Hammer 624511a041
fix: export getNetworkModuleStatus 2023-07-25 11:42:18 -04:00
semantic-release-bot a97d2099b0 chore(release): 0.1.0-develop.27 [skip ci]
# [0.1.0-develop.27](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.26...v0.1.0-develop.27) (2023-07-23)

### Bug Fixes

* export NetworkClient ([55b578a](55b578aace))
2023-07-23 17:37:34 +00:00
Derrick Hammer e6ee874107
Merge remote-tracking branch 'origin/develop' into develop 2023-07-23 13:36:42 -04:00
Derrick Hammer 55b578aace
fix: export NetworkClient 2023-07-23 13:36:34 -04:00
semantic-release-bot 87b9dc4ab1 chore(release): 0.1.0-develop.26 [skip ci]
# [0.1.0-develop.26](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.25...v0.1.0-develop.26) (2023-07-23)

### Features

* re-export defer from p-defer ([2ac16d2](2ac16d2c5c))
2023-07-23 17:30:27 +00:00
Derrick Hammer 9550704596
Merge remote-tracking branch 'origin/develop' into develop 2023-07-23 13:29:31 -04:00
Derrick Hammer 2ac16d2c5c
feat: re-export defer from p-defer 2023-07-23 13:29:25 -04:00
semantic-release-bot 2dcfcdfc4b chore(release): 0.1.0-develop.25 [skip ci]
# [0.1.0-develop.25](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.24...v0.1.0-develop.25) (2023-07-23)

### Features

* add getNetworkModuleStatus to fetch a network module status, either one time or continuous ([19167ac](19167acec2))
* create abstract NetworkClient with register, status, and ready methods. status calls getNetworkModuleStatus ([711b134](711b1341b8))
2023-07-23 17:29:09 +00:00
Derrick Hammer cf4774f8df
Merge remote-tracking branch 'origin/develop' into develop 2023-07-23 13:28:02 -04:00
Derrick Hammer 711b1341b8
feat: create abstract NetworkClient with register, status, and ready methods. status calls getNetworkModuleStatus 2023-07-23 13:27:56 -04:00
Derrick Hammer 19167acec2
feat: add getNetworkModuleStatus to fetch a network module status, either one time or continuous 2023-07-23 13:27:05 -04:00
Derrick Hammer b55782db8f
dep: add p-defer 2023-07-23 13:15:19 -04:00
semantic-release-bot 7f98cf47ee chore(release): 0.1.0-develop.24 [skip ci]
# [0.1.0-develop.24](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.23...v0.1.0-develop.24) (2023-07-21)

### Bug Fixes

* if we are in a webworker, automatically setup the handler so we don't ever forget ([565fb05](565fb05d85))
2023-07-21 17:21:06 +00:00
Derrick Hammer 736af0dcc6
Merge remote-tracking branch 'origin/develop' into develop 2023-07-21 13:20:06 -04:00
Derrick Hammer 565fb05d85
fix: if we are in a webworker, automatically setup the handler so we don't ever forget 2023-07-21 13:19:56 -04:00
Derrick Hammer 6c15b862cd
ci: add webworker to tsconfig lib 2023-07-21 13:19:06 -04:00
semantic-release-bot 8e768e787b chore(release): 0.1.0-develop.23 [skip ci]
# [0.1.0-develop.23](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.22...v0.1.0-develop.23) (2023-07-21)

### Bug Fixes

* add type check on window ([ceffa29](ceffa292ca))
2023-07-21 13:29:49 +00:00
Derrick Hammer c28ff21ed8
Merge remote-tracking branch 'origin/develop' into develop 2023-07-21 09:28:46 -04:00
Derrick Hammer ceffa292ca
fix: add type check on window 2023-07-21 09:28:40 -04:00
semantic-release-bot 6cb5b838e8 chore(release): 0.1.0-develop.22 [skip ci]
# [0.1.0-develop.22](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.21...v0.1.0-develop.22) (2023-07-21)
2023-07-21 13:24:29 +00:00
Derrick Hammer 9a386fed7d
Merge remote-tracking branch 'origin/develop' into develop 2023-07-21 09:23:17 -04:00
Derrick Hammer 0b4a108ca8
dep: update libweb 2023-07-21 09:23:13 -04:00
semantic-release-bot cd18679263 chore(release): 0.1.0-develop.21 [skip ci]
# [0.1.0-develop.21](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.20...v0.1.0-develop.21) (2023-07-20)
2023-07-20 16:18:51 +00:00
Derrick Hammer 6002af3ea7
Merge remote-tracking branch 'origin/develop' into develop 2023-07-20 12:17:54 -04:00
Derrick Hammer a0d1a0445c
refactor: change bootup process for when we are running from the extension background page to query the kernel version to detect that it's ready, and talk directly to the kernel, not via the bridge 2023-07-20 12:17:22 -04:00
semantic-release-bot e1d1e3418b chore(release): 0.1.0-develop.20 [skip ci]
# [0.1.0-develop.20](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.19...v0.1.0-develop.20) (2023-07-18)
2023-07-18 20:44:48 +00:00
Derrick Hammer 5506e18f59
dep: update libweb 2023-07-18 16:43:51 -04:00
semantic-release-bot e506428f90 chore(release): 0.1.0-develop.19 [skip ci]
# [0.1.0-develop.19](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.18...v0.1.0-develop.19) (2023-07-18)
2023-07-18 17:34:17 +00:00
Derrick Hammer ce69b73361
dep: update libweb 2023-07-18 13:31:04 -04:00
semantic-release-bot a1717b865c chore(release): 0.1.0-develop.18 [skip ci]
# [0.1.0-develop.18](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.17...v0.1.0-develop.18) (2023-07-18)
2023-07-18 14:28:36 +00:00
Derrick Hammer b2a4044204
Merge remote-tracking branch 'origin/develop' into develop 2023-07-18 10:27:34 -04:00
Derrick Hammer aaedabc658
dep: update libweb 2023-07-18 10:27:30 -04:00
semantic-release-bot c6b1dab3cc chore(release): 0.1.0-develop.17 [skip ci]
# [0.1.0-develop.17](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.16...v0.1.0-develop.17) (2023-07-18)
2023-07-18 13:42:26 +00:00
Derrick Hammer bf73dc7480
Merge remote-tracking branch 'origin/develop' into develop 2023-07-18 09:41:27 -04:00
Derrick Hammer 9c58a0b805
dep: update libweb 2023-07-18 09:41:19 -04:00
semantic-release-bot d48c1997ae chore(release): 0.1.0-develop.16 [skip ci]
# [0.1.0-develop.16](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.15...v0.1.0-develop.16) (2023-07-11)

### Bug Fixes

* pass event.data.err to logErr ([191c3b5](191c3b5f90))
2023-07-11 21:07:06 +00:00
Derrick Hammer c42433bf7b
Merge remote-tracking branch 'origin/develop' into develop 2023-07-11 17:06:01 -04:00
Derrick Hammer 191c3b5f90
fix: pass event.data.err to logErr 2023-07-11 17:05:55 -04:00
semantic-release-bot 8460bcae01 chore(release): 0.1.0-develop.15 [skip ci]
# [0.1.0-develop.15](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.14...v0.1.0-develop.15) (2023-07-08)
2023-07-08 08:42:36 +00:00
Derrick Hammer 7c838b2238
Merge remote-tracking branch 'origin/develop' into develop 2023-07-08 04:41:28 -04:00
Derrick Hammer e9d49c6d81
dep: update libweb 2023-07-08 04:41:20 -04:00
semantic-release-bot 68d76c5d53 chore(release): 0.1.0-develop.14 [skip ci]
# [0.1.0-develop.14](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.13...v0.1.0-develop.14) (2023-07-03)

### Bug Fixes

* export concatBytes ([c1f3daa](c1f3daae83))
2023-07-03 06:14:15 +00:00
Derrick Hammer bd6dc1b24d
Merge remote-tracking branch 'origin/develop' into develop 2023-07-03 02:13:03 -04:00
Derrick Hammer c1f3daae83
fix: export concatBytes 2023-07-03 02:12:59 -04:00
semantic-release-bot 39046f60c6 chore(release): 0.1.0-develop.13 [skip ci]
# [0.1.0-develop.13](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.12...v0.1.0-develop.13) (2023-07-02)
2023-07-02 22:13:23 +00:00
Derrick Hammer 25c2b89a7c
Merge remote-tracking branch 'origin/develop' into develop 2023-07-02 18:12:19 -04:00
Derrick Hammer 696656c9aa
dep: update node-library-preset 2023-07-02 18:12:14 -04:00
semantic-release-bot 962722be5e chore(release): 0.1.0-develop.12 [skip ci]
# [0.1.0-develop.12](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.11...v0.1.0-develop.12) (2023-07-02)

### Bug Fixes

* replace skt.us with kernel.lumeweb.com ([079bfc2](079bfc2b19))
2023-07-02 16:36:09 +00:00
Derrick Hammer a92d0c3d76
Merge remote-tracking branch 'origin/develop' into develop 2023-07-02 12:35:09 -04:00
Derrick Hammer 079bfc2b19
fix: replace skt.us with kernel.lumeweb.com 2023-07-02 12:35:05 -04:00
semantic-release-bot c7f2e0fc21 chore(release): 0.1.0-develop.11 [skip ci]
# [0.1.0-develop.11](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.10...v0.1.0-develop.11) (2023-07-02)

### Bug Fixes

* add support for a hosted kernel, but only on localhost (for debugging) ([44e2a0d](44e2a0d06d))
2023-07-02 15:23:35 +00:00
Derrick Hammer 962a79bf38
Merge remote-tracking branch 'origin/develop' into develop 2023-07-02 11:22:17 -04:00
Derrick Hammer 44e2a0d06d
fix: add support for a hosted kernel, but only on localhost (for debugging) 2023-07-02 11:22:11 -04:00
semantic-release-bot 222ac7974a chore(release): 0.1.0-develop.10 [skip ci]
# [0.1.0-develop.10](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.9...v0.1.0-develop.10) (2023-07-02)

### Bug Fixes

* export bufToHex ([9767232](976723202d))
2023-07-02 03:18:38 +00:00
Derrick Hammer 2053ca8a10
Merge remote-tracking branch 'origin/develop' into develop 2023-07-01 23:17:39 -04:00
Derrick Hammer 976723202d
fix: export bufToHex 2023-07-01 23:17:35 -04:00
Derrick Hammer 325e80f6e8
dep: update libweb 2023-07-01 23:17:24 -04:00
semantic-release-bot 4b271ce053 chore(release): 0.1.0-develop.9 [skip ci]
# [0.1.0-develop.9](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.8...v0.1.0-develop.9) (2023-07-01)
2023-07-01 19:57:23 +00:00
Derrick Hammer 2affd20bb9
Merge remote-tracking branch 'origin/develop' into develop 2023-07-01 15:56:33 -04:00
Derrick Hammer f7cc9a755e
refactor: move to emittery 2023-07-01 15:56:28 -04:00
semantic-release-bot 9c280037ed chore(release): 0.1.0-develop.8 [skip ci]
# [0.1.0-develop.8](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.7...v0.1.0-develop.8) (2023-07-01)
2023-07-01 09:09:57 +00:00
Derrick Hammer 3036ba1d5e
Merge remote-tracking branch 'origin/develop' into develop 2023-07-01 05:09:03 -04:00
Derrick Hammer 94287ce2d9
refactor: re-export several crypto, string, and binary utilities 2023-07-01 05:08:56 -04:00
semantic-release-bot 45a48ef721 chore(release): 0.1.0-develop.7 [skip ci]
# [0.1.0-develop.7](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.6...v0.1.0-develop.7) (2023-07-01)

### Bug Fixes

* export handlePresentKey ([e6a13a1](e6a13a16cc))
2023-07-01 07:04:43 +00:00
Derrick Hammer 2bbc08ede5
Merge remote-tracking branch 'origin/develop' into develop 2023-07-01 03:03:50 -04:00
Derrick Hammer e6a13a16cc
fix: export handlePresentKey 2023-07-01 03:03:44 -04:00
semantic-release-bot e664dbd245 chore(release): 0.1.0-develop.6 [skip ci]
# [0.1.0-develop.6](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.5...v0.1.0-develop.6) (2023-06-29)
2023-06-29 22:13:19 +00:00
Derrick Hammer 9c18b83c92
Merge remote-tracking branch 'origin/develop' into develop 2023-06-29 18:12:19 -04:00
Derrick Hammer ee65808fab
dep: use absolute version number for libweb 2023-06-29 18:06:31 -04:00
semantic-release-bot 4ca68f2027 chore(release): 0.1.0-develop.5 [skip ci]
# [0.1.0-develop.5](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.4...v0.1.0-develop.5) (2023-06-29)

### Bug Fixes

* need typeof ([2d7d057](2d7d057b05))
2023-06-29 06:41:49 +00:00
Derrick Hammer c955e22d02
Merge remote-tracking branch 'origin/develop' into develop 2023-06-29 02:40:53 -04:00
Derrick Hammer 2d7d057b05
fix: need typeof 2023-06-29 02:40:48 -04:00
semantic-release-bot 141090c5d3 chore(release): 0.1.0-develop.4 [skip ci]
# [0.1.0-develop.4](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.3...v0.1.0-develop.4) (2023-06-29)
2023-06-29 05:35:29 +00:00
Derrick Hammer 43c9790206
Merge remote-tracking branch 'origin/develop' into develop 2023-06-29 01:34:32 -04:00
Derrick Hammer a83209d941
dep: update libweb 2023-06-29 01:34:20 -04:00
semantic-release-bot fcfb5cf0f6 chore(release): 0.1.0-develop.3 [skip ci]
# [0.1.0-develop.3](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.2...v0.1.0-develop.3) (2023-06-28)

### Bug Fixes

* update package exports to include types ([aae4acd](aae4acd6a7))
2023-06-28 04:51:29 +00:00
Derrick Hammer ae036cd520
Merge remote-tracking branch 'origin/develop' into develop 2023-06-28 00:50:22 -04:00
Derrick Hammer aae4acd6a7
fix: update package exports to include types 2023-06-28 00:50:11 -04:00
semantic-release-bot 2be0940d36 chore(release): 0.1.0-develop.2 [skip ci]
# [0.1.0-develop.2](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.1...v0.1.0-develop.2) (2023-06-28)

### Bug Fixes

* add factory back in ([480fdf2](480fdf23e8))
2023-06-28 04:34:03 +00:00
Derrick Hammer 62ec7db738
Merge remote-tracking branch 'origin/develop' into develop 2023-06-28 00:33:09 -04:00
Derrick Hammer 480fdf23e8
fix: add factory back in 2023-06-28 00:32:59 -04:00
Derrick Hammer 021fcf424e
refactor: change how module calling works 2023-06-28 00:26:22 -04:00
semantic-release-bot 02891f2e71 chore(release): 0.1.0-develop.1 [skip ci]
# [0.1.0-develop.1](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.0.1...v0.1.0-develop.1) (2023-06-28)

### Features

* initial version ([caae937](caae937352))
2023-06-28 02:48:31 +00:00
Derrick Hammer caae937352
feat: initial version 2023-06-27 22:47:11 -04:00
26 changed files with 20731 additions and 1 deletions

13
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: Build/Publish
on:
push:
branches:
- master
- develop
- develop-*
jobs:
main:
uses: lumeweb/github-node-deploy-workflow/.github/workflows/main.yml@master
secrets: inherit

12
.presetterrc.json Normal file
View File

@ -0,0 +1,12 @@
{
"preset": [
"@lumeweb/node-library-preset"
],
"config": {
"tsconfig": {
"compilerOptions": {
"lib": ["webworker"]
}
}
}
}

319
CHANGELOG.md Normal file
View File

@ -0,0 +1,319 @@
# [0.1.0-develop.68](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.67...v0.1.0-develop.68) (2023-11-17)
# [0.1.0-develop.67](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.66...v0.1.0-develop.67) (2023-10-19)
# [0.1.0-develop.66](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.65...v0.1.0-develop.66) (2023-10-12)
### Bug Fixes
* always show log data ([d3259fa](https://git.lumeweb.com/LumeWeb/libkernel/commit/d3259fa3f4b2330031480b10b41af11d038c0dc6))
* duplicate kernelLoadedDefer ([a4b9b46](https://git.lumeweb.com/LumeWeb/libkernel/commit/a4b9b46a3e8f1d4f89dbb1ec87fa3b2f605bc91a))
# [0.1.0-develop.65](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.64...v0.1.0-develop.65) (2023-10-09)
### Features
* add createNetworkClient helper ([6ecaf16](https://git.lumeweb.com/LumeWeb/libkernel/commit/6ecaf16d4e3789d3dc1537ad84eabc6774f489ac))
# [0.1.0-develop.64](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.63...v0.1.0-develop.64) (2023-09-20)
# [0.1.0-develop.63](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.62...v0.1.0-develop.63) (2023-09-16)
### Bug Fixes
* remove checking the method for kernel -> sw messages ([6e1e244](https://git.lumeweb.com/LumeWeb/libkernel/commit/6e1e244f0e7ad607f8fd249fe38b8dbe1a6def51))
# [0.1.0-develop.62](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.61...v0.1.0-develop.62) (2023-09-11)
# [0.1.0-develop.61](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.60...v0.1.0-develop.61) (2023-09-11)
### Bug Fixes
* add service worker to check ([c2be4fe](https://git.lumeweb.com/LumeWeb/libkernel/commit/c2be4fe886cad8210aa04b6c1e55064fce93c9b5))
* use FROM_SW ([ca15414](https://git.lumeweb.com/LumeWeb/libkernel/commit/ca15414444c8a94af0db4758e6b855313c0cf332))
# [0.1.0-develop.60](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.59...v0.1.0-develop.60) (2023-09-11)
### Bug Fixes
* don't nest in a data property with exchangeCommunicationKeys ([d7663d0](https://git.lumeweb.com/LumeWeb/libkernel/commit/d7663d0ff5f1f5ef2f7535a6aa1bf5c1f2f310d2))
# [0.1.0-develop.59](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.58...v0.1.0-develop.59) (2023-09-11)
### Bug Fixes
* newBootloaderQuery now returns an ErrTuple ([780f4fd](https://git.lumeweb.com/LumeWeb/libkernel/commit/780f4fddf71fe158ef899353b0210a53b02430c6))
* newBootloaderQuery should return a ErrTuple ([3ee446a](https://git.lumeweb.com/LumeWeb/libkernel/commit/3ee446a9c5ce8adda16e16b01fab95b7dc25a547))
# [0.1.0-develop.58](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.57...v0.1.0-develop.58) (2023-09-11)
### Bug Fixes
* need to pass nonce with query ([6fb7486](https://git.lumeweb.com/LumeWeb/libkernel/commit/6fb7486368b1114c9b30ae075a31302a8dc14eb4))
# [0.1.0-develop.57](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.56...v0.1.0-develop.57) (2023-09-11)
### Bug Fixes
* replace kernelLoadedResolve with kernelLoadedDefer ([b5d3ba4](https://git.lumeweb.com/LumeWeb/libkernel/commit/b5d3ba46cf2f912652bf32769c6ae60dab40224a))
# [0.1.0-develop.56](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.55...v0.1.0-develop.56) (2023-09-11)
### Bug Fixes
* use newBootloaderQuery ([25d2f6b](https://git.lumeweb.com/LumeWeb/libkernel/commit/25d2f6b1c09e13b876419fa2262aaa9cbc20a919))
### Features
* add newBootloaderQuery method ([8561535](https://git.lumeweb.com/LumeWeb/libkernel/commit/85615350f097345ee36bc5d0bcb482a363e83291))
# [0.1.0-develop.55](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.54...v0.1.0-develop.55) (2023-09-11)
### Bug Fixes
* export login and serviceWorkerReady ([cb5a617](https://git.lumeweb.com/LumeWeb/libkernel/commit/cb5a6175f648130b2ffdb57bdeaa0af0ec3e9529))
# [0.1.0-develop.54](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.53...v0.1.0-develop.54) (2023-09-11)
### Features
* add login function that calls exchangeCommunicationKeys and setLoginKey ([fd6c8d3](https://git.lumeweb.com/LumeWeb/libkernel/commit/fd6c8d3b1f8a62e6d0d30cef112d7feb3980c36e))
* add service worker support ([15c5960](https://git.lumeweb.com/LumeWeb/libkernel/commit/15c59603f2f9b50531f82dcd36294719c7185ed6))
# [0.1.0-develop.53](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.52...v0.1.0-develop.53) (2023-09-09)
# [0.1.0-develop.52](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.51...v0.1.0-develop.52) (2023-09-09)
# [0.1.0-develop.51](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.50...v0.1.0-develop.51) (2023-09-09)
# [0.1.0-develop.50](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.49...v0.1.0-develop.50) (2023-09-08)
# [0.1.0-develop.49](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.48...v0.1.0-develop.49) (2023-09-08)
# [0.1.0-develop.48](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.47...v0.1.0-develop.48) (2023-09-08)
# [0.1.0-develop.47](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.46...v0.1.0-develop.47) (2023-09-08)
# [0.1.0-develop.46](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.45...v0.1.0-develop.46) (2023-09-08)
### Bug Fixes
* export types since we are no longer storing them in libweb ([4abc3ed](https://git.lumeweb.com/LumeWeb/libkernel/commit/4abc3ed9c4f0c6a7662d2eda4b5c71c39e8bc0fe))
* update imports to be local ([631fde4](https://git.lumeweb.com/LumeWeb/libkernel/commit/631fde4868e4fe5e0b8f7c779d8d079093a70c3b))
* use Err from types ([bb1229e](https://git.lumeweb.com/LumeWeb/libkernel/commit/bb1229eeb2429d5a71e797283116d2fcfb5eb732))
* use types and util locally ([469f02b](https://git.lumeweb.com/LumeWeb/libkernel/commit/469f02b69fc65b4caea8136587e14e095c6e6b6e))
# [0.1.0-develop.45](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.44...v0.1.0-develop.45) (2023-09-04)
# [0.1.0-develop.44](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.43...v0.1.0-develop.44) (2023-09-04)
# [0.1.0-develop.43](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.42...v0.1.0-develop.43) (2023-09-04)
# [0.1.0-develop.42](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.41...v0.1.0-develop.42) (2023-09-04)
# [0.1.0-develop.41](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.40...v0.1.0-develop.41) (2023-09-04)
# [0.1.0-develop.40](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.39...v0.1.0-develop.40) (2023-09-04)
# [0.1.0-develop.39](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.38...v0.1.0-develop.39) (2023-09-03)
# [0.1.0-develop.38](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.37...v0.1.0-develop.38) (2023-09-02)
# [0.1.0-develop.37](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.36...v0.1.0-develop.37) (2023-09-02)
# [0.1.0-develop.36](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.35...v0.1.0-develop.36) (2023-08-20)
# [0.1.0-develop.35](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.34...v0.1.0-develop.35) (2023-08-10)
# [0.1.0-develop.34](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.33...v0.1.0-develop.34) (2023-07-29)
### Bug Fixes
* change callModule wrapper signature and correctly call callModule ([2adbddc](https://git.lumeweb.com/LumeWeb/libkernel/commit/2adbddc769e00767541e27efbef3fd237eb68e2d))
# [0.1.0-develop.33](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.32...v0.1.0-develop.33) (2023-07-29)
### Bug Fixes
* make callModule a wrapper function that calls handleError ([73ea9ca](https://git.lumeweb.com/LumeWeb/libkernel/commit/73ea9ca5b08d9ef4a8b2f54ba4174a66e6e3ec2f))
# [0.1.0-develop.32](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.31...v0.1.0-develop.32) (2023-07-29)
### Bug Fixes
* add missing typeof check ([420a28c](https://git.lumeweb.com/LumeWeb/libkernel/commit/420a28c2246a696d1dea136c599f6b69f116a61f))
# [0.1.0-develop.31](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.30...v0.1.0-develop.31) (2023-07-29)
### Bug Fixes
* function does not need to be async ([09b691c](https://git.lumeweb.com/LumeWeb/libkernel/commit/09b691ce0f12ffb4541d7fde392728ed9043e3e0))
* update status signature ([809e0ec](https://git.lumeweb.com/LumeWeb/libkernel/commit/809e0ecd3b7d6fe18a3faa22516c45c916c3b89a))
### Features
* add name method for api ([7affb28](https://git.lumeweb.com/LumeWeb/libkernel/commit/7affb2808133372f2c94a63deff58f3f057f4ce8))
# [0.1.0-develop.30](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.29...v0.1.0-develop.30) (2023-07-27)
### Bug Fixes
* make getNetworkModuleStatus not be async so we don't need to wait to get the async function if we have a callback ([a72651e](https://git.lumeweb.com/LumeWeb/libkernel/commit/a72651e9246d6d0a8a9670f9ada534e5da5116e6))
# [0.1.0-develop.29](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.28...v0.1.0-develop.29) (2023-07-26)
# [0.1.0-develop.28](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.27...v0.1.0-develop.28) (2023-07-25)
### Bug Fixes
* export getNetworkModuleStatus ([624511a](https://git.lumeweb.com/LumeWeb/libkernel/commit/624511a0417531db57c93d64cae74dd7f66996b1))
# [0.1.0-develop.27](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.26...v0.1.0-develop.27) (2023-07-23)
### Bug Fixes
* export NetworkClient ([55b578a](https://git.lumeweb.com/LumeWeb/libkernel/commit/55b578aaceaea0ae92700fccbb7eca5085c6b35c))
# [0.1.0-develop.26](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.25...v0.1.0-develop.26) (2023-07-23)
### Features
* re-export defer from p-defer ([2ac16d2](https://git.lumeweb.com/LumeWeb/libkernel/commit/2ac16d2c5c6f505d4a76d41c5e9e3ad67dacb1cd))
# [0.1.0-develop.25](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.24...v0.1.0-develop.25) (2023-07-23)
### Features
* add getNetworkModuleStatus to fetch a network module status, either one time or continuous ([19167ac](https://git.lumeweb.com/LumeWeb/libkernel/commit/19167acec25fd1e9caa6023e539f10b8c0e0fb02))
* create abstract NetworkClient with register, status, and ready methods. status calls getNetworkModuleStatus ([711b134](https://git.lumeweb.com/LumeWeb/libkernel/commit/711b1341b80da16cc500ca1e6ba856a145f50037))
# [0.1.0-develop.24](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.23...v0.1.0-develop.24) (2023-07-21)
### Bug Fixes
* if we are in a webworker, automatically setup the handler so we don't ever forget ([565fb05](https://git.lumeweb.com/LumeWeb/libkernel/commit/565fb05d85073f254badb9e05ba372568da62c37))
# [0.1.0-develop.23](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.22...v0.1.0-develop.23) (2023-07-21)
### Bug Fixes
* add type check on window ([ceffa29](https://git.lumeweb.com/LumeWeb/libkernel/commit/ceffa292ca7fa12f5a53b6975d988caff5347747))
# [0.1.0-develop.22](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.21...v0.1.0-develop.22) (2023-07-21)
# [0.1.0-develop.21](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.20...v0.1.0-develop.21) (2023-07-20)
# [0.1.0-develop.20](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.19...v0.1.0-develop.20) (2023-07-18)
# [0.1.0-develop.19](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.18...v0.1.0-develop.19) (2023-07-18)
# [0.1.0-develop.18](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.17...v0.1.0-develop.18) (2023-07-18)
# [0.1.0-develop.17](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.16...v0.1.0-develop.17) (2023-07-18)
# [0.1.0-develop.16](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.15...v0.1.0-develop.16) (2023-07-11)
### Bug Fixes
* pass event.data.err to logErr ([191c3b5](https://git.lumeweb.com/LumeWeb/libkernel/commit/191c3b5f903fd057443f2a35db1a32a3e3de90ff))
# [0.1.0-develop.15](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.14...v0.1.0-develop.15) (2023-07-08)
# [0.1.0-develop.14](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.13...v0.1.0-develop.14) (2023-07-03)
### Bug Fixes
* export concatBytes ([c1f3daa](https://git.lumeweb.com/LumeWeb/libkernel/commit/c1f3daae83705ec2c90ffb976d4232be48b60c0c))
# [0.1.0-develop.13](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.12...v0.1.0-develop.13) (2023-07-02)
# [0.1.0-develop.12](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.11...v0.1.0-develop.12) (2023-07-02)
### Bug Fixes
* replace skt.us with kernel.lumeweb.com ([079bfc2](https://git.lumeweb.com/LumeWeb/libkernel/commit/079bfc2b192c267df9802536306fb453575c59d0))
# [0.1.0-develop.11](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.10...v0.1.0-develop.11) (2023-07-02)
### Bug Fixes
* add support for a hosted kernel, but only on localhost (for debugging) ([44e2a0d](https://git.lumeweb.com/LumeWeb/libkernel/commit/44e2a0d06d5c8511a505a6b5348db6cefac10a01))
# [0.1.0-develop.10](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.9...v0.1.0-develop.10) (2023-07-02)
### Bug Fixes
* export bufToHex ([9767232](https://git.lumeweb.com/LumeWeb/libkernel/commit/976723202d4e7af6288fd73b33756ba016d31999))
# [0.1.0-develop.9](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.8...v0.1.0-develop.9) (2023-07-01)
# [0.1.0-develop.8](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.7...v0.1.0-develop.8) (2023-07-01)
# [0.1.0-develop.7](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.6...v0.1.0-develop.7) (2023-07-01)
### Bug Fixes
* export handlePresentKey ([e6a13a1](https://git.lumeweb.com/LumeWeb/libkernel/commit/e6a13a16cce277f3782526ac9aef3160e8f613e4))
# [0.1.0-develop.6](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.5...v0.1.0-develop.6) (2023-06-29)
# [0.1.0-develop.5](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.4...v0.1.0-develop.5) (2023-06-29)
### Bug Fixes
* need typeof ([2d7d057](https://git.lumeweb.com/LumeWeb/libkernel/commit/2d7d057b052c55e9eaf48f38798075a138c1bac1))
# [0.1.0-develop.4](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.3...v0.1.0-develop.4) (2023-06-29)
# [0.1.0-develop.3](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.2...v0.1.0-develop.3) (2023-06-28)
### Bug Fixes
* update package exports to include types ([aae4acd](https://git.lumeweb.com/LumeWeb/libkernel/commit/aae4acd6a70724e242f0c4cfb6e75e95e448a31b))
# [0.1.0-develop.2](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.1.0-develop.1...v0.1.0-develop.2) (2023-06-28)
### Bug Fixes
* add factory back in ([480fdf2](https://git.lumeweb.com/LumeWeb/libkernel/commit/480fdf23e85ad954bc2218138c57e963a10d17dd))
# [0.1.0-develop.1](https://git.lumeweb.com/LumeWeb/libkernel/compare/v0.0.1...v0.1.0-develop.1) (2023-06-28)
### Features
* initial version ([caae937](https://git.lumeweb.com/LumeWeb/libkernel/commit/caae93735270b4ce8a656d624fcd13adab84fd97))

View File

@ -1,6 +1,7 @@
MIT License
Copyright (c) <year> <copyright holders>
Copyright (c) 2023 Hammer Technologies LLC
Copyright (c) 2022 Skynet Labs
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -1,2 +1,3 @@
# libkernel
Library is based on, and copies much of its work from https://github.com/SkynetLabs/skynet-kernel/tree/beta/libs/libkmodule and https://github.com/SkynetLabs/skynet-kernel/tree/beta/libs/libkernel

18256
npm-shrinkwrap.json generated Normal file

File diff suppressed because it is too large Load Diff

44
package.json Normal file
View File

@ -0,0 +1,44 @@
{
"name": "@lumeweb/libkernel",
"version": "0.1.0-develop.68",
"main": "lib/index.js",
"type": "module",
"types": "lib/index.d.ts",
"exports": {
".": {
"import": "./lib/index.js",
"types": "./lib/index.d.ts"
},
"./kernel": {
"import": "./lib/kernel/index.js",
"types": "./lib/kernel/index.d.ts"
},
"./module": {
"import": "./lib/module/index.js",
"types": "./lib/module/index.d.ts"
}
},
"repository": {
"type": "git",
"url": "gitea@git.lumeweb.com:LumeWeb/libkernel.git"
},
"devDependencies": {
"@lumeweb/node-library-preset": "^0.2.7",
"presetter": "*",
"prettier": "^2.8.8"
},
"readme": "ERROR: No README data found!",
"scripts": {
"prepare": "presetter bootstrap",
"build": "run build",
"semantic-release": "semantic-release"
},
"dependencies": {
"@lumeweb/libweb": "0.2.0-develop.61",
"emittery": "^1.0.1",
"p-defer": "^4.0.0"
},
"publishConfig": {
"access": "public"
}
}

63
src/api.ts Normal file
View File

@ -0,0 +1,63 @@
import {
callModule as callModuleKernel,
connectModule as connectModuleKernel,
log as logKernel,
logErr as logErrKernel,
} from "#kernel/index.js";
import {
callModule as callModuleModule,
connectModule as connectModuleModule,
log as logModule,
logErr as logErrModule,
} from "#module/index.js";
import defer, { DeferredPromise } from "p-defer";
import { connectModuleBound } from "#module/client.js";
// @ts-ignore
const kernelEnv = typeof window !== "undefined" && window?.document;
export const callModule = kernelEnv ? callModuleKernel : callModuleModule;
export const connectModule = kernelEnv
? connectModuleKernel
: connectModuleModule;
export const log = kernelEnv ? logKernel : logModule;
export const logErr = kernelEnv ? logErrKernel : logErrModule;
export function getNetworkModuleStatus(
callback?: any,
module?: string,
// @ts-ignore
CM: connectModuleBound = connectModule.bind(null, module),
): Promise<void> | (() => void) {
let recvUpdate = (data) => {
callback?.(data);
};
const [close, resp] = CM("status", null, (data) => {
recvUpdate(data);
});
if (!callback) {
return new Promise(async (resolve) => {
const d = defer();
recvUpdate = (data) => {
resolve(data);
d.resolve();
};
await d.promise;
close();
});
}
let closed = false;
return () => {
if (closed) {
return;
}
closed = true;
close();
};
}

101
src/errTracker.ts Normal file
View File

@ -0,0 +1,101 @@
// errTracker.ts defines an 'ErrTracker' type which keeps track of historical
// errors. When the number of errors gets too large, it randomly starts pruning
// errors. It always keeps 250 of the most recent errors, and then keeps up to
// 500 historic errors, where the first few errors after runtime are always
// kept, and the ones in the middle are increasingly likely to be omitted from
// the history.
import { Err } from "./types.js";
// MAX_ERRORS defines the maximum number of errors that will be held in the
// HistoricErr object.
const MAX_ERRORS = 1000;
// HistoricErr is a wrapper that adds a date to the Err type.
interface HistoricErr {
err: Err;
date: Date;
}
// ErrTracker keeps track of errors that have happened, randomly dropping
// errors to prevent the tracker from using too much memory if there happen to
// be a large number of errors.
interface ErrTracker {
recentErrs: HistoricErr[];
oldErrs: HistoricErr[];
addErr: (err: Err) => void;
viewErrs: () => HistoricErr[];
}
// newErrTracker returns an ErrTracker object that is ready to have errors
// added to it.
function newErrTracker(): ErrTracker {
const et: ErrTracker = {
recentErrs: [],
oldErrs: [],
addErr: function (err: Err): void {
addHistoricErr(et, err);
},
viewErrs: function (): HistoricErr[] {
return viewErrs(et);
},
};
return et;
}
// addHistoricErr is a function that will add an error to a set of historic
// errors. It uses randomness to prune errors once the error object is too
// large.
function addHistoricErr(et: ErrTracker, err: Err): void {
// Add this error to the set of most recent errors.
et.recentErrs.push({
err,
date: new Date(),
});
// Determine whether some of the most recent errors need to be moved into
// logTermErrs. If the length of the mostRecentErrs is not at least half of
// the MAX_ERRORS, we don't need to do anything.
if (et.recentErrs.length < MAX_ERRORS / 2) {
return;
}
// Iterate through the recentErrs. For the first half of the recentErrs, we
// will use randomness to either toss them or move them to oldErrs. The
// second half of the recentErrs will be kept as the new recentErrs array.
const newRecentErrs : HistoricErr[] = [];
for (let i = 0; i < et.recentErrs.length; i++) {
// If we are in the second half of the array, add the element to
// newRecentErrs.
if (i > et.recentErrs.length / 2) {
newRecentErrs.push(et.recentErrs[i]);
continue;
}
// We are in the first half of the array, use a random number to add the
// error oldErrs probabilistically.
const rand = Math.random();
const target = et.oldErrs.length / (MAX_ERRORS / 2);
if (rand > target || et.oldErrs.length < 25) {
et.oldErrs.push(et.recentErrs[i]);
}
}
et.recentErrs = newRecentErrs;
}
// viewErrs returns the list of errors that have been retained by the
// HistoricErr object.
function viewErrs(et: ErrTracker): HistoricErr[] {
const finalErrs: HistoricErr[] = [];
for (let i = 0; i < et.oldErrs.length; i++) {
finalErrs.push(et.oldErrs[i]);
}
for (let i = 0; i < et.recentErrs.length; i++) {
finalErrs.push(et.recentErrs[i]);
}
return finalErrs;
}
export { ErrTracker, HistoricErr, newErrTracker };

17
src/index.ts Normal file
View File

@ -0,0 +1,17 @@
export {
ed25519,
sha512,
ensureBytes,
equalBytes,
concatBytes,
utf8ToBytes,
} from "@lumeweb/libweb";
export {
callModule,
connectModule,
log,
logErr,
getNetworkModuleStatus,
} from "./api.js";
export * from "./util.js";
export * from "./types.js";

111
src/kernel/auth.ts Normal file
View File

@ -0,0 +1,111 @@
import {
getKernelIframe,
init,
kernelAuthLocation,
kernelLoadedDefer,
loginDefer,
logoutDefer,
newBootloaderQuery,
newKernelQuery,
} from "./queries.js";
import { Err } from "#types.js";
import { x25519 } from "@noble/curves/ed25519";
import { bytesToHex, hexToBytes, randomBytes } from "@lumeweb/libweb";
import { secretbox } from "@noble/ciphers/salsa";
// There are 5 stages of auth.
//
// Stage 0: Bootloader is not loaded.
// Stage 1: Bootloader is loaded, user is not logged in.
// Stage 2: Bootloader is loaded, user is logged in.
// Stage 3: Kernel is loaded, user is logged in.
// Stage 4: Kernel is loaded, user is logged out.
//
// init() will block until auth has reached stage 1. If the user is already
// logged in from a previous session, auth will immediately progress to stage
// 2.
//
// loginComplete() will block until auth has reached stage 2. The kernel is not
// ready to receive messages yet, but apps do not need to present users with a
// login dialog.
//
// kernelLoaded() will block until auth has reached stage 3. kernelLoaded()
// returns a promise that can resolve with an error. If there was an error, it
// means the kernel could not be loaded and cannot be used.
//
// logoutComplete() will block until auth has reached stage 4. libkernel does
// not support resetting the auth stages, once stage 4 has been reached the app
// needs to refresh.
// loginComplete will resolve when the user has successfully logged in.
function loginComplete(): Promise<void> {
return loginDefer.promise;
}
// kernelLoaded will resolve when the user has successfully loaded the kernel.
// If there was an error in loading the kernel, the error will be returned.
//
// NOTE: kernelLoaded will not resolve until after loginComplete has resolved.
function kernelLoaded(): Promise<Err> {
return kernelLoadedDefer.promise;
}
// logoutComplete will resolve when the user has logged out. Note that
// logoutComplete will only resolve if the user logged in first - if the user
// was not logged in to begin with, this promise will not resolve.
function logoutComplete(): Promise<void> {
return logoutDefer.promise;
}
// openAuthWindow is intended to be used as an onclick target when the user
// clicks the 'login' button on a lume application. It will block until the
// auth location is known, and then it will pop open the correct auth window
// for the user.
//
// NOTE: openAuthWindow will only open a window if the user is not already
// logged in. If the user is already logged in, this function is a no-op.
//
// NOTE: When using this function, you probably want to have your login button
// faded out or presenting the user with a spinner until init() resolves. In
// the worst case (user has no browser extension, and is on a slow internet
// connection) this could take multiple seconds.
function openAuthWindow(): void {
// openAuthWindow doesn't care what the auth status is, it's just trying to
// open the right window.
init().then(() => {
window.open(kernelAuthLocation, "_blank");
});
}
async function login(key: Uint8Array) {
let privKey = x25519.utils.randomPrivateKey();
const iframe = getKernelIframe();
if (!iframe) {
return;
}
let pubKeyRet = await newBootloaderQuery(
"exchangeCommunicationKeys",
bytesToHex(x25519.getPublicKey(privKey)),
);
if (pubKeyRet[1]) {
alert(`Failed to login: could not get communication key: ${pubKeyRet[1]}`);
return;
}
let pubKey = hexToBytes(pubKeyRet[0] as string);
const secret = x25519.getSharedSecret(privKey, pubKey);
const nonce = randomBytes(24);
const box = secretbox(secret, nonce);
const ciphertext = box.seal(key);
await newBootloaderQuery("setLoginKey", {
data: bytesToHex(ciphertext),
nonce: bytesToHex(nonce),
});
}
export { loginComplete, kernelLoaded, logoutComplete, openAuthWindow, login };

17
src/kernel/index.ts Normal file
View File

@ -0,0 +1,17 @@
export {
kernelLoaded,
loginComplete,
logoutComplete,
openAuthWindow,
login,
} from "./auth.js";
export { kernelVersion } from "./query/version.js";
export {
callModule,
connectModule,
init,
newKernelQuery,
getKernelIframe,
serviceWorkerReady,
} from "./queries.js";
export { log, logErr } from "./log.js";

13
src/kernel/log.ts Normal file
View File

@ -0,0 +1,13 @@
// log provides a wrapper for console.log that prefixes '[libkernel]' to the
// output.
function log(...inputs: any) {
console.log("[libkernel]", ...inputs);
}
// logErr provides a wrapper for console.error that prefixes '[libkernel]' to
// the output.
function logErr(...inputs: any) {
console.error("[libkernel]", ...inputs);
}
export { log, logErr };

697
src/kernel/queries.ts Normal file
View File

@ -0,0 +1,697 @@
import { log, logErr } from "./log.js";
import { DataFn, Err, ErrTuple } from "#types.js";
import { bufToB64, encodeU64 } from "#util.js";
import defer, { DeferredPromise } from "p-defer";
// queryResolve is the 'resolve' value of a promise that returns an ErrTuple.
// It gets called when a query sends a 'response' message.
type queryResolve = (er: ErrTuple) => void;
// queryMap is a hashmap that maps a nonce to an open query. 'resolve' gets
// called when a response has been provided for the query.
//
// 'receiveUpdate' is a function that gets called every time a responseUpdate
// message is sent to the query. If a responseUpdate is sent but there is no
// 'receiveUpdate' method defined, the update will be ignored.
//
// 'kernelNonceReceived' is a promise that resolves when the kernel nonce has
// been received from the kernel, which is a prerequesite for sending
// queryUpdate messages. The promise will resolve with a string that contains
// the kernel nonce.
interface queryMap {
[nonce: string]: {
resolve: queryResolve;
receiveUpdate?: DataFn;
kernelNonceReceived?: DataFn;
};
}
declare global {
interface Window {
browser: any;
}
}
declare var browser: any;
const IS_EXTENSION_BG =
typeof window !== "undefined" &&
window.location.pathname.includes("_generated_background_page.html");
const IS_EXTENSION_ENV =
typeof window !== "undefined" && window.browser?.runtime?.id;
const IS_EXTENSION =
IS_EXTENSION_ENV &&
window.location.pathname.includes("_generated_background_page.html");
const IS_EXTENSION_PAGE = IS_EXTENSION_ENV && !IS_EXTENSION_BG;
const IS_EXTENSION_ANY = IS_EXTENSION || IS_EXTENSION_PAGE;
const EXTENSION_KERNEL_ORIGIN = "http://kernel.lume";
const EXTENSION_HOSTED_ORIGIN = "https://kernel.lumeweb.com";
// Create the queryMap.
const queries: queryMap = {};
// Define the nonce handling. nonceSeed is 16 random bytes that get generated
// at init and serve as the baseline for creating random nonces. nonceCounter
// tracks which messages have been sent. We hash together the nonceSeed and the
// current nonceCounter to get a secure nonce.
//
// We need a secure nonce so that we know which messages from the kernel are
// intended for us. There could be multiple pieces of independent code talking
// to the kernel and using nonces, by having secure random nonces we can
// guarantee that the applications will not use conflicting nonces.
let nonceSeed: Uint8Array;
let nonceCounter: number;
let bgConn: any;
let serviceWorker: ServiceWorker;
let kernelIframe: HTMLIFrameElement;
function getKernelIframe() {
return kernelIframe;
}
async function serviceWorkerReady() {
const sw = await navigator.serviceWorker.ready;
navigator.serviceWorker.onmessage = (...args) => handleMessage(...args);
serviceWorker = sw.active as ServiceWorker;
}
function getServiceWorker() {
return serviceWorker;
}
function initNonce() {
nonceSeed = new Uint8Array(16);
nonceCounter = 0;
crypto.getRandomValues(nonceSeed);
}
// nextNonce will combine the nonceCounter with the nonceSeed to produce a
// unique string that can be used as the nonce with the kernel.
//
// Note: the nonce is only ever going to be visible to the kernel and to other
// code running in the same webpage, so we don't need to hash our nonceSeed. We
// just need it to be unique, not undetectable.
function nextNonce(): string {
const nonceNum = nonceCounter;
nonceCounter += 1;
const [nonceNumBytes, err] = encodeU64(BigInt(nonceNum));
if (err !== null) {
// encodeU64 only fails if nonceNum is outside the bounds of a
// uint64, which shouldn't happen ever.
logErr("encodeU64 somehow failed", err);
}
const noncePreimage = new Uint8Array(nonceNumBytes.length + nonceSeed.length);
noncePreimage.set(nonceNumBytes, 0);
noncePreimage.set(nonceSeed, nonceNumBytes.length);
return bufToB64(noncePreimage);
}
// Establish the handler for incoming messages.
function handleMessage(event: MessageEvent) {
// Ignore all messages that aren't from approved kernel sources. The two
// approved sources are skt.us and the browser extension bridge (which has
// an event.source equal to 'window')
const FROM_KERNEL =
event.source !== window &&
event.origin === EXTENSION_KERNEL_ORIGIN &&
IS_EXTENSION_ANY;
const FROM_SW = event.source === serviceWorker;
const FROM_HOSTED_KERNEL =
event.source !== window && event.origin === EXTENSION_HOSTED_ORIGIN;
if (bgConn) {
event = Object.assign({}, event);
// @ts-ignore
event.data = Object.assign({}, event);
}
if (!FROM_KERNEL && !FROM_HOSTED_KERNEL && !bgConn && !FROM_SW) {
return;
}
if (event.source === kernelIframe?.contentWindow && event.data.sw) {
delete event.data.sw;
serviceWorker?.postMessage(event.data);
return;
}
if (FROM_SW) {
if (["moduleCall", "queryUpdate", "response"].includes(event.data.method)) {
kernelIframe?.contentWindow?.postMessage(
{ ...event.data, sw: true },
"https://kernel.lumeweb.com",
);
return;
}
}
if (IS_EXTENSION && !event.data?.data) {
event.data.data = Object.assign({}, event.data);
}
// Ignore any messages that don't have a method and data field.
if (!("method" in event.data) || !("data" in event.data)) {
return;
}
// Handle logging messages.
if (event.data.method === "log" && !IS_EXTENSION) {
if (event.data.data.isErr) {
console.error(event.data.data.message);
} else {
console.log(event.data.data.message);
}
return;
}
// init is complete when the kernel sends us the auth status. If the
// user is logged in, report success, otherwise return an error
// indicating that the user is not logged in.
if (event.data.method === "kernelAuthStatus") {
// If we have received an auth status message, it means the bootloader
// at a minimum is working.
if (!initResolved) {
initResolved = true;
// We can't actually establish that init is complete until the
// kernel source has been set. This happens async and might happen
// after we receive the auth message.
sourceDefer.promise.then(() => {
initDefer.resolve();
});
}
if (IS_EXTENSION_ANY && event.data.data.kernelLoaded === "success") {
const nonce = nextNonce();
queries[nonce] = {
resolve: sourceDefer.resolve as unknown as queryResolve,
};
const kernelMessage = {
method: "version",
nonce,
data: null,
};
if (IS_EXTENSION_PAGE) {
bgConn.postMessage(kernelMessage);
} else {
kernelSource.postMessage(kernelMessage, kernelOrigin);
}
}
// If the auth status message says that login is complete, it means
// that the user is logged in.
if (!loginResolved && event.data.data.loginComplete) {
loginResolved = true;
loginDefer.resolve();
}
// If the auth status message says that the kernel loaded, it means
// that the kernel is ready to receive messages.
if (!kernelLoadedResolved && event.data.data.kernelLoaded !== "not yet") {
kernelLoadedResolved = true;
if (event.data.data.kernelLoaded === "success") {
kernelLoadedDefer.resolve(null);
} else {
kernelLoadedDefer.resolve(event.data.data.kernelLoaded);
}
}
// If we have received a message indicating that the user has logged
// out, we need to reload the page and reset the auth process.
if (event.data.data.logoutComplete) {
if (!logoutResolved) {
logoutDefer.resolve();
}
window.location.reload();
}
return;
}
// Check that the message sent has a nonce. We don't log
// on failure because the message may have come from 'window', which
// will happen if the app has other messages being sent to the window.
if (!("nonce" in event.data)) {
return;
}
// If we can't locate the nonce in the queries map, there is nothing to do.
// This can happen especially for responseUpdate messages.
if (!(event.data.nonce in queries)) {
return;
}
const query = queries[event.data.nonce];
// Handle a response. Once the response has been received, it is safe to
// delete the query from the queries map.
if (event.data.method === "response") {
queries[event.data.nonce].resolve([event.data.data, event.data.err]);
delete queries[event.data.nonce];
return;
}
// Handle a response update.
if (event.data.method === "responseUpdate") {
// If no update handler was provided, there is nothing to do.
if (typeof query.receiveUpdate === "function") {
query.receiveUpdate(event.data.data);
}
return;
}
// Handle a responseNonce.
if (event.data.method === "responseNonce") {
if (typeof query.kernelNonceReceived === "function") {
query.kernelNonceReceived(event.data.data.nonce);
}
return;
}
// Ignore any other messages as they might be from other applications.
}
function launchKernelFrame() {
kernelIframe = document.createElement("iframe");
kernelIframe.src = "https://kernel.lumeweb.com";
kernelIframe.width = "0";
kernelIframe.height = "0";
kernelIframe.style.border = "0";
kernelIframe.style.position = "absolute";
document.body.appendChild(kernelIframe);
kernelSource = <Window>kernelIframe.contentWindow;
kernelOrigin = EXTENSION_HOSTED_ORIGIN;
kernelAuthLocation = `${EXTENSION_HOSTED_ORIGIN}/auth.html`;
sourceDefer.resolve();
// Set a timer to fail the login process if the kernel doesn't load in
// time.
setTimeout(() => {
if (initResolved) {
return;
}
initResolved = true;
initDefer.resolve(
"tried to open kernel in kernelIframe, but hit a timeout" as any,
);
}, 24000);
}
// messageBridge will send a message to the bridge of the lume extension to
// see if it exists. If it does not respond or if it responds with an error,
// messageBridge will open an iframe to skt.us and use that as the kernel.
let kernelSource: Window;
let kernelOrigin: string;
let kernelAuthLocation: string;
function messageBridge() {
// Establish the function that will handle the bridge's response.
let bridgeInitComplete = false;
let bridgeResolve: queryResolve = () => {}; // Need to set bridgeResolve here to make tsc happy
const p: Promise<ErrTuple> = new Promise((resolve) => {
bridgeResolve = resolve;
});
if (IS_EXTENSION_PAGE) {
bgConn = browser.runtime.connect();
bgConn.onMessage.addListener(handleMessage);
}
p.then(([, err]) => {
// Check if the timeout already elapsed.
if (bridgeInitComplete) {
logErr("received response from bridge, but init already finished");
return;
}
bridgeInitComplete = true;
// Bridge has responded successfully, and there's no error.
if (IS_EXTENSION) {
const iframes = Array.from(
document.getElementsByTagName("iframe"),
).filter((item) => item.src === EXTENSION_KERNEL_ORIGIN + "/");
if (!iframes.length) {
logErr("could not find kernel iframe");
return;
}
kernelSource = iframes[0].contentWindow as Window;
kernelOrigin = EXTENSION_KERNEL_ORIGIN;
} else {
kernelSource = window;
kernelOrigin = window.origin;
}
kernelAuthLocation = `${EXTENSION_KERNEL_ORIGIN}/auth.html`;
log("established connection to bridge, using browser extension for kernel");
if (!IS_EXTENSION_ANY) {
sourceDefer.resolve();
}
});
if (!IS_EXTENSION_ANY) {
// Add the handler to the queries map.
const nonce = nextNonce();
queries[nonce] = {
resolve: bridgeResolve,
};
// Send a message to the bridge of the browser extension to determine
// whether the bridge exists.
window.postMessage(
{
nonce,
method: "kernelBridgeVersion",
},
window.origin,
);
// Set a timeout, if we do not hear back from the bridge in 500
// milliseconds we assume that the bridge is not available.
setTimeout(() => {
// If we've already received and processed a message from the
// bridge, there is nothing to do.
if (bridgeInitComplete) {
return;
}
bridgeInitComplete = true;
log("browser extension not found, falling back to lumeweb.com");
launchKernelFrame();
}, 500);
}
if (IS_EXTENSION_ANY) {
bridgeResolve([null, null]);
}
return initDefer;
}
// init is a function that returns a promise which will resolve when
// initialization is complete.
//
// The init / auth process has 5 stages. The first stage is that something
// somewhere needs to call init(). It is safe to call init() multiple times,
// thanks to the 'initialized' variable.
let initialized = false; // set to true once 'init()' has been called
let initResolved = false; // set to true once we know the bootloader is working
let initDefer: DeferredPromise<void>;
let loginResolved = false; // set to true once we know the user is logged in
let loginDefer: DeferredPromise<void>;
let kernelLoadedResolved = false; // set to true once the user kernel is loaded
let kernelLoadedDefer: DeferredPromise<Err>;
const logoutResolved = false; // set to true once the user is logged out
let logoutDefer: DeferredPromise<void>;
let sourceDefer: DeferredPromise<void>; // resolves when the source is known and set
function init(): Promise<void> {
// If init has already been called, just return the init promise.
if (initialized) {
return initDefer.promise;
}
initialized = true;
// Run all of the init functions.
initNonce();
window.addEventListener("message", handleMessage);
messageBridge();
// Create the promises that resolve at various stages of the auth flow.
initDefer = defer();
loginDefer = defer();
kernelLoadedDefer = defer();
logoutDefer = defer();
sourceDefer = defer();
// Return the initDefer, which will resolve when bootloader init is
// complete.
return initDefer.promise;
}
// callModule is a generic function to call a module. The first input is the
// module identifier (typically a skylink), the second input is the method
// being called on the module, and the final input is optional and contains
// input data to be passed to the module. The input data will depend on the
// module and the method that is being called. The return value is an ErrTuple
// that contains the module's response. The format of the response is an
// arbitrary object whose fields depend on the module and method being called.
//
// callModule can only be used for query-response communication, there is no
// support for sending or receiving updates.
function callModule(
module: string,
method: string,
data?: any,
): Promise<ErrTuple> {
const moduleCallData = {
module,
method,
data,
};
const [, query] = newKernelQuery("moduleCall", moduleCallData, false);
return query;
}
// connectModule is the standard function to send a query to a module that can
// optionally send and optionally receive updates. The first three inputs match
// the inputs of 'callModule', and the fourth input is a function that will be
// called any time that the module sends a responseUpdate. The receiveUpdate
// function should have the following signature:
//
// `function receiveUpdate(data: any)`
//
// The structure of the data will depend on the module and method that was
// queried.
//
// The first return value is a 'sendUpdate' function that can be called to send
// a queryUpdate to the module. The sendUpdate function has the same signature
// as the receiveUpdate function, it's an arbitrary object whose fields depend
// on the module and method being queried.
//
// The second return value is a promise that returns an ErrTuple. It will
// resolve when the module sends a response message, and works the same as the
// return value of callModule.
function connectModule(
module: string,
method: string,
data: any,
receiveUpdate: DataFn,
): [sendUpdate: DataFn, response: Promise<ErrTuple>] {
const moduleCallData = {
module,
method,
data,
};
return newKernelQuery("moduleCall", moduleCallData, true, receiveUpdate);
}
// newKernelQuery opens a query to the kernel. Details like postMessage
// communication and nonce handling are all abstracted away by newKernelQuery.
//
// The first arg is the method that is being called on the kernel, and the
// second arg is the data that will be sent to the kernel as input to the
// method.
//
// The thrid arg is an optional function that can be passed in to receive
// responseUpdates to the query. Not every query will send responseUpdates, and
// most responseUpdates can be ignored, but sometimes contain useful
// information like download progress.
//
// The first output is a 'sendUpdate' function that can be called to send a
// queryUpdate. The second output is a promise that will resolve when the query
// receives a response message. Once the response message has been received, no
// more updates can be sent or received.
function newKernelQuery(
method: string,
data: any,
sendUpdates: boolean,
receiveUpdate?: DataFn,
): [sendUpdate: DataFn, response: Promise<ErrTuple>] {
// NOTE: The implementation here is gnarly, because I didn't want to use
// async/await (that decision should be left to the caller) and I also
// wanted this function to work correctly even if init() had not been
// called yet.
//
// This function returns a sendUpdate function along with a promise, so we
// can't simply wrap everything in a basic promise. The sendUpdate function
// has to block internally until all of the setup is complete, and then we
// can't send a query until all of the setup is complete, and the setup
// cylce has multiple dependencies and therefore we get a few promises that
// all depend on each other.
//
// Using async/await here actually breaks certain usage patterns (or at
// least makes them much more difficult to use correctly). The standard way
// to establish duplex communication using connectModule is to define a
// variable 'sendUpdate' before defining the function 'receiveUpdate', and
// then setting 'sendUpdate' equal to the first return value of
// 'connectModue'. It looks like this:
//
// let sendUpdate;
// let receiveUpdate = function(data: any) {
// if (data.needsUpdate) {
// sendUpdate(someUpdate)
// }
// }
// let [sendUpdateFn, response] = connectModule(x, y, z, receiveUpdate)
// sendUpdate = sendUpdateFn
//
// If we use async/await, it's not safe to set sendUpdate after
// connectModule returns because 'receiveUpdate' may be called before
// 'sendUpdate' is set. You can fix that by using a promise, but it's a
// complicated fix and we want this library to be usable by less
// experienced developers.
//
// Therefore, we make an implementation tradeoff here and avoid async/await
// at the cost of having a bunch of complicated promise chaining.
// Create a promise that will resolve once the nonce is available. We
// cannot get the nonce until init() is complete. getNonce therefore
// implies that init is complete.
const getNonce: Promise<string> = new Promise((resolve) => {
init().then(() => {
kernelLoadedDefer.promise.then(() => {
resolve(nextNonce());
});
});
});
// Two promises are being created at once here. Once is 'p', which will be
// returned to the caller of newKernelQuery and will be resolved when the
// kernel provides a 'response' message. The other is for internal use and
// will resolve once the query has been created.
let p!: Promise<ErrTuple>;
const haveQueryCreated: Promise<string> = new Promise(
(queryCreatedResolve) => {
p = new Promise((resolve) => {
getNonce.then((nonce: string) => {
queries[nonce] = { resolve };
if (receiveUpdate !== null && receiveUpdate !== undefined) {
queries[nonce]["receiveUpdate"] = receiveUpdate;
}
queryCreatedResolve(nonce);
});
});
},
);
// Create a promise that will be resolved once we are ready to receive the
// kernelNonce. We won't be ready to receive the kernel nonce until after
// the queries[nonce] object has been created.
let readyForKernelNonce!: DataFn;
const getReadyForKernelNonce: Promise<void> = new Promise((resolve) => {
readyForKernelNonce = resolve;
});
// Create the sendUpdate function. It defaults to doing nothing. After the
// sendUpdate function is ready to receive the kernelNonce, resolve the
// promise that blocks until the sendUpdate function is ready to receive
// the kernel nonce.
let sendUpdate: DataFn;
if (!sendUpdates) {
sendUpdate = () => {};
readyForKernelNonce(); // We won't get a kernel nonce, no reason to block.
} else {
// sendUpdate will send an update to the kernel. The update can't be
// sent until the kernel nonce is known. Create a promise that will
// resolve when the kernel nonce is known.
//
// This promise cannot itself be created until the queries[nonce]
// object has been created, so block for the query to be created.
const blockForKernelNonce: Promise<string> = new Promise((resolve) => {
haveQueryCreated.then((nonce: string) => {
queries[nonce]["kernelNonceReceived"] = resolve;
readyForKernelNonce();
});
});
// The sendUpdate function needs both the local nonce and also the
// kernel nonce. Block for both. Having the kernel nonce implies that
// the local nonce is ready, therefore start by blocking for the kernel
// nonce.
sendUpdate = function (updateData: any) {
blockForKernelNonce.then((nonce: string) => {
kernelSource.postMessage(
{
method: "queryUpdate",
nonce,
data: updateData,
},
kernelOrigin,
);
});
};
}
// Prepare to send the query to the kernel. The query cannot be sent until
// the queries object is created and also we are ready to receive the
// kernel nonce.
haveQueryCreated.then((nonce: string) => {
getReadyForKernelNonce.then(() => {
// There are two types of messages we can send depending on whether
// we are talking to skt.us or the background script.
const kernelMessage = {
method,
nonce,
data,
sendKernelNonce: sendUpdates,
} as any;
const backgroundMessage = {
method: "newKernelQuery",
nonce,
data: kernelMessage,
};
// The message structure needs to adjust based on whether we are
// talking directly to the kernel or whether we are talking to the
// background page.
if (kernelOrigin === "https://kernel.lumeweb.com" || IS_EXTENSION) {
if (IS_EXTENSION) {
kernelMessage.domain = window.origin;
}
kernelSource.postMessage(kernelMessage, kernelOrigin);
} else if (IS_EXTENSION_PAGE) {
bgConn.postMessage(kernelMessage);
} else {
kernelSource.postMessage(backgroundMessage, kernelOrigin);
}
});
});
// Return sendUpdate and the promise. sendUpdate is already set to block
// until all the necessary prereqs are complete.
return [sendUpdate, p];
}
function newBootloaderQuery(method: string, data: any): Promise<ErrTuple> {
return new Promise((resolve) => {
initDefer.promise.then(() => {
if (getKernelIframe().contentWindow === null) {
console.error(
"kernelFrame.contentWindow was null, cannot send message!",
);
return;
}
let nonce = nextNonce();
queries[nonce] = { resolve };
getKernelIframe().contentWindow?.postMessage(
{ method, data, nonce },
kernelOrigin,
);
});
});
}
export {
callModule,
connectModule,
init,
kernelAuthLocation,
kernelLoadedDefer,
loginDefer,
logoutDefer,
newKernelQuery,
serviceWorkerReady,
getKernelIframe,
newBootloaderQuery,
};

View File

@ -0,0 +1,21 @@
import { newKernelQuery } from "../queries.js";
import { Err } from "#types.js";
// kernelVersion will fetch the version number of the kernel. If successful,
// the returned value will be an object containing a field 'version' with a
// version string, and a 'distribtion' field with a string that states the
// distribution of the kernel".
function kernelVersion(): Promise<[string, string, Err]> {
return new Promise((resolve) => {
const [, query] = newKernelQuery("version", {}, false);
query.then(([result, err]) => {
if (err !== null) {
resolve(["", "", err]);
return;
}
resolve([result.version, result.distribution, err]);
});
});
}
export { kernelVersion };

79
src/module/client.ts Normal file
View File

@ -0,0 +1,79 @@
import Emittery from "emittery";
import { callModule, connectModule, log, logErr } from "../api.js";
import { DataFn, ErrTuple } from "#types.js";
export type callModuleBound = (method: string, data?: any) => Promise<ErrTuple>;
export type connectModuleBound = (
method: string,
data: any,
receiveUpdate: DataFn,
) => [sendUpdate: DataFn, response: Promise<ErrTuple>];
interface ModuleBag {
callModule: typeof callModule;
connectModule: typeof connectModule;
log: typeof log;
logErr: typeof logErr;
}
interface ModuleBagBound extends ModuleBag {
callModule: callModuleBound;
connectModule: connectModuleBound;
}
export abstract class Client extends Emittery {
private _module: string;
constructor(module: string) {
super();
this._module = module;
}
get callModule(): callModuleBound {
return this.getBound(this._module).callModule;
}
get connectModule(): connectModuleBound {
return this.getBound(this._module).connectModule;
}
public getBound(module: string): ModuleBagBound {
return {
callModule: async (method: string, data?: any) => {
const ret = await callModule(module, method, data);
this.handleError(ret);
return ret;
},
connectModule: connectModule.bind(undefined, module),
} as ModuleBagBound;
}
protected handleError(ret: ErrTuple): void {
if (ret[1]) {
throw new Error(ret[1]);
}
}
protected handleErrorOrReturn(ret: ErrTuple): any {
this.handleError(ret);
return ret[0];
}
protected async callModuleReturn(method: string, data?: any): Promise<any> {
const ret = await this.callModule(method, data);
return ret[0];
}
}
type ClientConstructor<U> = new (module: string, ...args: any[]) => U;
export const factory = function <T extends Client = Client>(
type: ClientConstructor<T>,
module: string,
) {
return function (...args: any): T {
return new type(module, ...args);
};
};

View File

@ -0,0 +1,20 @@
import { Client } from "../client.js";
import { getNetworkModuleStatus } from "#api.js";
export default abstract class NetworkClient extends Client {
public async register() {
return this.callModuleReturn("register");
}
public status(callback?: any): Promise<void> | (() => void) {
return getNetworkModuleStatus(callback, undefined, this.connectModule);
}
public async name() {
return this.callModuleReturn("name");
}
public async ready() {
return this.callModuleReturn("ready");
}
}

22
src/module/index.ts Normal file
View File

@ -0,0 +1,22 @@
import defer from "p-defer";
export { defer };
export { log, logErr } from "./log.js";
export { ActiveQuery, addHandler, handleMessage } from "./messages.js";
export { callModule, connectModule, newKernelQuery } from "./queries.js";
export { getDataFromKernel, getKey, handlePresentKey } from "./key.js";
export { moduleQuery, presentKeyData } from "./types.js";
export { Client, factory } from "./client.js";
import NetworkClient from "./clients/network.js";
export { NetworkClient };
import { factory } from "./client.js";
class GenericNetworkClient extends NetworkClient {}
export function createNetworkClient(module: string): GenericNetworkClient {
return factory<GenericNetworkClient>(GenericNetworkClient, module)();
}

38
src/module/key.ts Normal file
View File

@ -0,0 +1,38 @@
import { ActiveQuery, DataFn } from "./messages.js";
// Define a set of helper variables that track whether the key has been
// received by the kernel yet.
let resolveKey: DataFn;
const keyPromise: Promise<Uint8Array> = new Promise((resolve) => {
resolveKey = resolve;
});
// dataFromKernel will hold any data that is sent by the kernel in the
// 'presentKey' call that happens at startup.
//
// dataFromKernel should not be accessed until 'keyPromise' has been resolved.
let dataFromKernel: any;
// getKey will return a promise that resolves when the key is available.
function getKey(): Promise<Uint8Array> {
return keyPromise;
}
// getDataFromKernel will resolve with the data that was provided by the kernel
// in 'presentKey' once that data is available.
function getDataFromKernel(): Promise<any> {
return new Promise((resolve) => {
keyPromise.then(() => {
resolve(dataFromKernel);
});
});
}
// handlePresentKey will accept a key from the kernel and unblock any method
// that is waiting for the key.
function handlePresentKey(aq: ActiveQuery) {
dataFromKernel = aq.callerInput;
resolveKey(aq.callerInput.key);
}
export { getDataFromKernel, getKey, handlePresentKey };

42
src/module/log.ts Normal file
View File

@ -0,0 +1,42 @@
import { objAsString } from "#util.js";
// logHelper is a helper function that runs the code for both log and logErr.
// It takes a boolean indiciating whether the log should be an error, and then
// it stringifies all of the reamining inputs and sends them to the kernel in a
// log message.
function logHelper(isErr: boolean, ...inputs: any) {
let message = "";
for (let i = 0; i < inputs.length; i++) {
if (i !== 0) {
message += "\n";
}
message += objAsString(inputs[i]);
}
postMessage({
method: "log",
data: {
isErr,
message,
},
});
}
// log is a helper function to send a bunch of inputs to the kernel serialized
// as a log message. Note that any inputs which cannot be stringified using
// JSON.stringify will be substituted with a placeholder string indicating that
// the input could not be stringified.
function log(...inputs: any) {
console.log(...inputs);
logHelper(false, ...inputs);
}
// logErr is a helper function to send a bunch of inputs to the kernel
// serialized as an error log message. Note that any inputs which cannot be
// stringified using JSON.stringify will be substituted with a placeholder
// string indicating that the input could not be stringified.
function logErr(...inputs: any) {
console.error(...inputs);
logHelper(true, ...inputs);
}
export { log, logErr };

260
src/module/messages.ts Normal file
View File

@ -0,0 +1,260 @@
import { logErr } from "./log.js";
import { handleNoOp } from "./messages/no-op.js";
import {
clearIncomingQuery,
getSetReceiveUpdate,
handleQueryUpdate,
handleResponse,
handleResponseNonce,
handleResponseUpdate,
} from "./queries.js";
import { handlePresentKey } from "./key.js";
import type { DataFn, ErrFn } from "#types.js";
import { addContextToErr, objAsString } from "#util.js";
// handlerFn takes an ActiveQuery as input and has no return value. The return
// is expected to come in the form of calling aq.accept or aq.reject.
type handlerFn = (aq: ActiveQuery) => void;
// ActiveQuery is an object that gets provided to the handler of a query and
// contains all necessary elements for interacting with the query.
interface ActiveQuery {
// callerInput is arbitrary input provided by the caller that is not
// checked by the kernel. Modules should verify the callerInput before
// using any fields.
callerInput: any;
// accept and reject are functions that will send response messages
// that close out the query. accept can take an arbitrary object as
// input, reject should always be a string.
respond: DataFn;
reject: ErrFn;
// domain is a field provided by the kernel that informs the module who
// the caller is. The module can use the domain to make access control
// decisions, and determine if a particular caller should be allowed to
// use a particular API.
domain: string;
// sendUpdate is used for sending responseUpdate messages to the
// caller. These messages can contain arbitrary information.
sendUpdate: DataFn;
// setReceiveUpdate is part of a handshake that needs to be performed
// to receive queryUpdates from the caller. It is a function that takes
// another function as input. The function provided as input is the
// function that will be called to process incoming queryUpdates.
setReceiveUpdate?: (receiveUpdate: DataFn) => void;
}
// addHandlerOptions defines the set of possible options that can be provided
// to the addHandler function.
//
// The 'receiveUpdates' option indicates whether the handler can receive
// updates and defaults to false. If it is set to false, any queryUpdate
// messages that get sent will be discarded. If it is set to 'true', any
// queryUpdate messages that get sent will be held until the handler provides a
// 'receiveUpdate' function to the ActiveQuery object using the
// ActiveQuery.setReceiveUpdate function.
interface addHandlerOptions {
receiveUpdates?: boolean;
}
// queryRouter defines the hashmap that is used to route queries to their
// respective handlers. The 'handler' field is the function that will be called
// to process the query, and 'receiveUpdates' is a flag that indicates whether
// or not queryUpdate messages should be processed.
interface queryRouter {
[method: string]: {
handler: handlerFn;
receiveUpdates: boolean;
};
}
// Set the default handler options so that they can be imported and used by
// modules. This is syntactic sugar.
const addHandlerDefaultOptions = {
receiveUpdates: false,
};
// Create a router which will route methods to their handlers. New handlers can
// be added to the router by calling 'addHandler'.
//
// Currently, there are two default handlers provided by libkmodule. The first
// is a handler for 'presentKey', which accepts keys provided by the kernel.
// The second is 'no-op', which allows a caller to make a no-op query on the
// module, which can be useful both for debugging, and also for 'warming up'
// the module so that it's in the kernel cache already the first time that a
// user tries to use the module.
//
// handleMessage implicitly handles 'queryUpdate' and 'responseUpdate' and
// 'response' methods as well, but those don't go through the router because
// special handling is required for those methods.
const router: queryRouter = {};
router["presentKey"] = { handler: handlePresentKey, receiveUpdates: false };
router["no-op"] = { handler: handleNoOp, receiveUpdates: false };
// addHandler will add a new handler to the router to process specific methods.
//
// NOTE: The 'queryUpdate', 'response', and 'responseUpdate' messages are all
// handled before the router is considered, and therefore they cannot be
// overwritten by calling 'addHandler'.
function addHandler(
method: string,
handler: handlerFn,
options?: addHandlerOptions,
) {
// If options is undefined, use the default options.
if (options === undefined) {
options = addHandlerDefaultOptions;
}
// Don't set the 'receiveUpdates' flag in the router if the provided
// options haven't enabled them.
//
// NOTE: options.receiveUpdates may be undefined, that's why we
// explicitly set it to talse here.
if (options.receiveUpdates !== true) {
router[method] = { handler, receiveUpdates: false };
return;
}
router[method] = { handler, receiveUpdates: true };
}
// handleMessage is the standard handler for messages. It has special handling
// for the 'queryUpdate', 'response', and 'responseUpdate' messages. Otherwise,
// it will use the router to connect moduleCalls to the appropriate handler.
//
// When passing a call off to a handler, it will create an 'ActiveQuery' object
// that the handler can work with.
function handleMessage(event: MessageEvent) {
// Special handling for "response" messages.
if (event.data.method === "queryUpdate") {
handleQueryUpdate(event);
return;
}
if (event.data.method === "response") {
handleResponse(event);
return;
}
if (event.data.method === "responseNonce") {
handleResponseNonce(event);
return;
}
if (event.data.method === "responseUpdate") {
handleResponseUpdate(event);
return;
}
// Make sure we have a handler for this object.
if (!Object.prototype.hasOwnProperty.call(router, event.data.method)) {
respondErr(event, "unrecognized method '" + event.data.method + "'");
return;
}
// Set up the accept and reject functions. They use the 'responded'
// variable to ensure that only one response is ever sent.
let responded = false;
const respond = function (data: any) {
// Check if a response was already sent.
if (responded) {
const str = objAsString(data);
logErr("accept called after response already sent: " + str);
return;
}
// Send a response.
responded = true;
postMessage({
nonce: event.data.nonce,
method: "response",
err: null,
data,
});
// Clear this query from the set of incomingQueries.
clearIncomingQuery(event.data.nonce);
};
const reject = function (err: string) {
// Check if a response was already sent.
if (responded) {
const str = objAsString(err);
logErr("reject called after response already sent: " + str);
return;
}
// Send the response as an error.
responded = true;
respondErr(event, err);
};
// Define the function that will allow the handler to send an update.
const sendUpdate = function (updateData: any) {
if (responded) {
const str = objAsString(updateData);
logErr("sendUpdate called after response already sent: " + str);
return;
}
postMessage({
method: "responseUpdate",
nonce: event.data.nonce,
data: updateData,
});
};
// Try to handle the message. If an exception is thrown by the handler,
// catch the error and respond with that error.
//
// NOTE: Throwing exceptions is considered bad practice, this code is only
// here because the practice is so common throughout javascript and we want
// to make sure developer code works without developers getting too
// frustrated.
//
// NOTE: The final argument contains a set of extra fields about the call,
// for example providing the domain of the caller. We used an object for
// this final field so that it could be extended later.
try {
const activeQuery: ActiveQuery = {
callerInput: event.data.data,
respond,
reject,
sendUpdate,
domain: event.data.domain,
};
if (router[event.data.method].receiveUpdates) {
activeQuery.setReceiveUpdate = getSetReceiveUpdate(event);
}
router[event.data.method].handler(activeQuery);
} catch (err: any) {
// Convert the thrown error and log it. We know that strErr is a string
// because objAsString must return a string, and addContextToErr only
// returns null if strErr is null.
const strErr = objAsString(err);
const finalErr = <string>addContextToErr(strErr, "module threw an error");
logErr(finalErr);
// Only send a response if a response was not already sent.
if (responded) {
return;
}
respondErr(event, finalErr);
}
}
// respondErr will send an error to the kernel as a response to a moduleCall.
function respondErr(event: MessageEvent, err: string) {
const strErr = objAsString(err);
postMessage({
nonce: event.data.nonce,
method: "response",
err: strErr,
data: null,
});
clearIncomingQuery(event.data.nonce);
}
if (typeof importScripts === "function") {
onmessage = handleMessage;
}
export { ActiveQuery, addHandler, DataFn, handleMessage };

View File

@ -0,0 +1,10 @@
import { ActiveQuery } from "../messages.js";
// handleNoOp create a no-op function for the module that allows the module to
// be "warmed up", meaning the kernel will stick the module into the cache so
// that it loads faster when a user actually needs the module.
function handleNoOp(aq: ActiveQuery) {
aq.respond({ success: true });
}
export { handleNoOp };

323
src/module/queries.ts Normal file
View File

@ -0,0 +1,323 @@
import { log, logErr } from "./log.js";
import type { DataFn, ErrTuple } from "#types.js";
import { objAsString } from "#util.js";
// queryResolve defines the function that gets called to resolve a query. It's
// the 'resolve' field of a promise that returns a tuple containing some data
// and an err.
type queryResolve = (et: ErrTuple) => void;
// queryMap defines the type for the queries map, which maps a nonce to the
// outgoing query that the module made.
interface queryMap {
[nonce: number]: {
resolve: queryResolve;
receiveUpdate?: DataFn;
kernelNonce?: number;
kernelNonceReceived?: DataFn;
};
}
// incomingQueryMap defines the type for mapping incoming queries to the method
// that can receive queryUpdates. To allow queryUpdate messages to be processed
// in the same scope as the original query, we put a 'setReceiveUpdate'
// function in the activeQuery object.
//
// blockForReceiveUpdate is a promise that will be resolved once the
// receiveUpdate function has been set.
interface incomingQueryMap {
[nonce: string]: Promise<DataFn>;
}
// queries is an object that tracks outgoing queries to the kernel. When making
// a query, we assign a nonce to that query. All response and responseUpdate
// messages for that query will make use of the nonce assigned here. When we
// receive a response or responseUpdate message, we will use this map to locate
// the original query that is associated with the response.
//
// The kernel provides security guarantees that all incoming response and
// responseUpdate messages have nonces that are associated with the correct
// query.
//
// queries is a hashmap where the nonce is the key and various query state
// items are the values.
//
// NOTE: When sending out queryUpdate messages, the queries need to use the
// nonce assigned by the kernel. The nonces in the 'queries' map will not work.
let queriesNonce = 0;
const queries: queryMap = {};
// incomingQueries is an object
// set of information needed to process queryUpdate messages.
const incomingQueries: incomingQueryMap = {};
// clearIncomingQuery will clear a query with the provided nonce from the set
// of incomingQueries. This method gets called when the response is either
// accepted or rejected.
function clearIncomingQuery(nonce: number) {
delete incomingQueries[nonce];
}
// getSetReceiveUpdate returns a function called 'setReceiveUpdate' which can
// be called to set the receiveUpdate function for the current query. All
// queryUpdate messages that get received will block until setReceiveUpdate has
// been called.
function getSetReceiveUpdate(
event: MessageEvent,
): (receiveUpdate: DataFn) => void {
// Create the promise that allows us to block until the handler has
// provided us its receiveUpdate function.
let updateReceived: DataFn;
// Add the blockForReceiveUpdate object to the queryUpdateRouter.
incomingQueries[event.data.nonce] = new Promise((resolve) => {
updateReceived = resolve;
});
return function (receiveUpdate: DataFn) {
updateReceived(receiveUpdate);
};
}
// handleQueryUpdate currently discards all queryUpdates.
async function handleQueryUpdate(event: MessageEvent) {
// Check whether the handler for this query wants to process
// receiveUpdate messages. This lookup may also fail if no handler
// exists for this nonce, which can happen if the queryUpdate message
// created concurrently with a response (which is not considered a bug
// or error).
if (!(event.data.nonce in incomingQueries)) {
return;
}
// Block until the handler has provided a receiveUpdate function, than
// call receiveUpdate.
const receiveUpdate = await incomingQueries[event.data.nonce];
receiveUpdate(event.data.data);
}
// handleResponse will take a response and match it to the correct query.
//
// NOTE: The kernel guarantees that an err field and a data field and a nonce
// field will be present in any message that gets sent using the "response"
// method.
function handleResponse(event: MessageEvent) {
// Look for the query with the corresponding nonce.
if (!(event.data.nonce in queries)) {
logErr(
"no open query found for provided nonce: " + objAsString(event.data.data),
);
return;
}
// Check if the response is an error.
if (event.data.err !== null) {
logErr("there's an error in the data", event.data.err);
queries[event.data.nonce].resolve([{}, event.data.err]);
delete queries[event.data.nonce];
return;
}
// Call the handler function using the provided data, then delete the query
// from the query map.
queries[event.data.nonce].resolve([event.data.data, null]);
delete queries[event.data.nonce];
}
// handleResponseNonce will handle a message with the method 'responseNonce'.
// This is a message from the kernel which is telling us what nonce we should
// use when we send queryUpdate messages to the kernel for a particular query.
function handleResponseNonce(event: MessageEvent) {
// Check if the query exists. If it does not exist, it's possible that the
// messages just arrived out of order and nothing is going wrong.
if (!(event.data.nonce in queries)) {
logErr("temp err: nonce could not be found");
return;
}
const query = queries[event.data.nonce];
if ("kernelNonce" in query) {
logErr("received two responseNonce messages for the same query nonce");
return;
}
if (typeof query["kernelNonceReceived"] !== "function") {
// We got a nonce even though one wasn't requested.
log("received nonce even though none was requested");
return;
}
query["kernelNonce"] = event.data.data.nonce;
query.kernelNonceReceived();
return;
}
// handleResponseUpdate attempts to find the corresponding query using the
// nonce and then calls the corresponding receiveUpdate function.
//
// Because response and responseUpdate messages are sent asynchronously, it's
// completely possible that a responseUpdate is received after the query has
// been closed out by a response. We therefore just ignore any messages that
// can't be matched to a nonce.
function handleResponseUpdate(event: MessageEvent) {
// Ignore this message if there is no corresponding query, the query may
// have been closed out and this message was just processed late.
if (!(event.data.nonce in queries)) {
return;
}
// Check whether a receiveUpdate function was set, and if so pass the
// update along. To prevent typescript
const query = queries[event.data.nonce];
if (typeof query["receiveUpdate"] === "function") {
query.receiveUpdate(event.data.data);
}
}
// callModule is a generic function to call a module. It will return whatever
// response is provided by the module.
//
// callModule can only be used for query-response communications, there is no
// support for handling queryUpdate or responseUpdate messages - they will be
// ignored if received. If you need those messages, use 'connectModule'
// instead.
function callModule(
module: string,
method: string,
data?: any,
): Promise<ErrTuple> {
const moduleCallData = {
module,
method,
data,
};
const [, query] = newKernelQuery("moduleCall", moduleCallData, false);
return query;
}
// connectModule is a generic function to connect to a module. It is similar to
// callModule, except that it also supports sending and receiving updates in
// the middule of the call. If the module being called sends and update, the
// updated will be passed to the caller through the 'receiveUpdate' function.
// If the caller wishes to send an update to the module, it can use the
// provided 'sendUpdate' function.
//
// The call signature is a bit messy, so let's disect it a bit. The input
// values are the same as callModule, except there's a fourth input for
// providing a 'receiveUpdate' function. It is okay to provide 'null' or
// 'undefined' as the function to receive updates if you do not care to receive
// or process any updates sent by the module. If you do want to receive
// updates, the receiveUpdate function should have the following function
// signature:
//
// `function receiveUpdate(data: any)`
//
// The data that gets sent is at the full discretion of the module, and will
// depend on which method was called in the original query.
//
// The return value is a tuple of a 'sendUpdate' function and a promise. The
// promise itself resolves to a tuple which matches the tuple in the
// 'callModule' function - the first value is the response data, and the second
// value is an error. When the promise resolves, it means the query has
// completed and no more updates will be processed. Therefore, 'sendUpdate' is
// only valid until the promise resolves.
//
// sendUpdate has the following function signature:
//
// `function sendUpdate(data: any)`
//
// Like 'receiveUpdate', the data that should be sent when sending an update to
// the module is entirely determined by the module and will vary based on what
// method was called in the original query.
function connectModule(
module: string,
method: string,
data: any,
receiveUpdate: DataFn,
): [sendUpdate: DataFn, response: Promise<ErrTuple>] {
const moduleCallData = {
module,
method,
data,
};
// We omit the 'receiveUpdate' function because this is a no-op. If the
// value is not defined, newKernelQuery will place in a no-op for us.
return newKernelQuery("moduleCall", moduleCallData, true, receiveUpdate);
}
// newKernelQuery creates a query to send to the kernel. It automatically
// handles details like the nonces and the postMessage communicaations.
//
// The first input is the method being called on the kernel, and the second
// input is the data being provided as input to the method.
//
// The third input is a boolean indicating whether or not you want to send
// queryUpdates. There is a small amount of performance overhead associated
// with sending updates (slightly under one millisecond) so we only set up the
// ability to send updates if it is requested.
//
// The final input is an optional function that gets called when a
// responseUpdate is received. If no fourth input is provided, responseUpdates
// will be ignored.
//
// NOTE: Typically developers should not use this function. Instead use
// 'callModule' or 'connectModule'.
function newKernelQuery(
method: string,
data: any,
sendUpdates: boolean,
receiveUpdate?: DataFn,
): [sendUpdate: DataFn, response: Promise<ErrTuple>] {
// Get the nonce for the query.
const nonce = queriesNonce;
queriesNonce += 1;
// Create the sendUpdate function, which allows the caller to send a
// queryUpdate. The update cannot actually be sent until the kernel has told us the responseNonce
let sendUpdate: DataFn = () => {};
// Establish the query in the queries map and then send the query to the
// kernel.
const p: Promise<ErrTuple> = new Promise((resolve) => {
queries[nonce] = { resolve };
});
if (receiveUpdate !== null && receiveUpdate !== undefined) {
queries[nonce]["receiveUpdate"] = receiveUpdate;
}
if (sendUpdates) {
// Set up the promise that resovles when we have received the responseNonce
// from the kernel.
const blockForKernelNonce = new Promise((resolve) => {
queries[nonce]["kernelNonceReceived"] = resolve;
});
sendUpdate = function (updateData: any) {
blockForKernelNonce.then(() => {
// It's possible that the query was already closed and deleted from
// the queries map, so we need an existence check before completing
// the postMessage call.
if (!(nonce in queries)) {
return;
}
postMessage({
method: "queryUpdate",
nonce: queries[nonce].kernelNonce,
data: updateData,
});
});
};
}
postMessage({
method,
nonce,
data,
sendKernelNonce: sendUpdates,
});
return [sendUpdate, p];
}
export {
callModule,
clearIncomingQuery,
connectModule,
getSetReceiveUpdate,
handleQueryUpdate,
handleResponse,
handleResponseNonce,
handleResponseUpdate,
newKernelQuery,
};

40
src/module/types.ts Normal file
View File

@ -0,0 +1,40 @@
// moduleQuery defines a query that can be sent to a module. The method is used
// to tell the module what query is being made. The domain is set by the
// kernel, and is guaranteed to match the domain of the caller. The module can
// use the 'domain' to enforce access control policies. The 'data' can be any
// arbitrary object, and will depend on the method. The module developer is
// ultimately the one who decides what data should be provided as input to each
// method call.
//
// NOTE: While the kernel does do verification for the method and domain, the
// kernel does not do any verification for the data field. The module itself is
// responsible for verifying all inputs provided in the data field.
interface moduleQuery {
method: string;
domain: string;
data: any;
}
// presentKeyData contains the data that gets sent in a 'presentKey' call
// from the kernel. 'presentKey' is called on the module immediately after the
// module starts up.
//
// The 'key' is a unique key dervied by the kernel for the module based on
// the module's domain and the key of the user. Modules in different domains
// will have different keys, and have no way to guess what the keys of other
// modules are.
//
// It is safe to use the 'key' for things like blockchain wallets.
//
// If the module has been given access to the root private key,
// presentKeyData will include the rootPrivateKey. If the module does not
// have access to the root private key, the field will not be included. A
// module that receives the root private key has full read and write access
// to all of the user's data.
//
interface presentKeyData {
key: Uint8Array;
rootPrivateKey?: Uint8Array;
}
export { moduleQuery, presentKeyData };

87
src/types.ts Normal file
View File

@ -0,0 +1,87 @@
// DataFn can take any object as input and has no return value. The input is
// allowed to be undefined.
type DataFn = (data?: any) => void;
// Err is an error type that is either a string or a null. If the value is
// null, that indicates that there was no error. If the value is a string, it
// indicates that there was an error and the string contains the error message.
//
// The skynet libraries prefer this error type to the standard Error type
// because many times skynet libraries need to pass errors over postMessage,
// and the 'Error' type is not able to be sent over postMessage.
type Err = string | null;
// ErrFn must take an error message as input. The input is not allowed to be
// undefined or null, there must be an error.
type ErrFn = (errMsg: string) => void;
// ErrTuple is a type that pairs a 'data' field with an 'err' field. Skynet
// libraries typically prefer returning ErrTuples to throwing or rejecting,
// because it allows upstream code to avoid the try/catch/throw pattern. Though
// the pattern is much celebrated in javascript, it encourages relaxed error
// handling, and often makes error handling much more difficult because the try
// and the catch are in different scopes.
//
// Most of the Skynet core libraries do not have any `throws` anywhere in their
// API.
//
// Typically, an ErrTuple will have only one field filled out. If data is
// returned, the err should be 'null'. If an error is returned, the data field
// should generally be empty. Callers are expected to check the error before
// they access any part of the data field.
type ErrTuple<T = any> = [data: T, err: Err];
// KernelAuthStatus is the structure of a message that gets sent by the kernel
// containing its auth status. Auth occurs in 5 stages.
//
// Stage 0; no auth updates
// Stage 1: bootloader is loaded, user is not yet logged in
// Stage 2: bootloader is loaded, user is logged in
// Stage 3: kernel is loaded, user is logged in
// Stage 4: kernel is loaded, user is logging out (refresh iminent)
//
// 'kernelLoaded' is initially set to "not yet" and will be updated when the
// kernel has loaded. If it is set to "success", it means the kernel loaded
// without issues. If it is set to anything else, it means that there was an
// error, and the new value is the error.
//
// 'kernelLoaded' will not be changed until 'loginComplete' has been set to
// true. 'loginComplete' can be set to true immediately if the user is already
// logged in.
//
// 'logoutComplete' can be set to 'true' at any point, which indicates that the
// auth cycle needs to reset.
interface KernelAuthStatus {
loginComplete: boolean;
kernelLoaded: "not yet" | "success" | string;
logoutComplete: boolean;
}
interface Portal {
id: string;
name: string;
url: string;
}
// RequestOverrideResponse defines the type that the kernel returns as a
// response to a requestOverride call.
interface RequestOverrideResponse {
override: boolean;
headers?: any; // TODO: I don't know how to do an array of types.
body?: Uint8Array;
}
export interface KeyPair {
publicKey: Uint8Array;
privateKey: Uint8Array;
}
export {
DataFn,
ErrFn,
Err,
ErrTuple,
KernelAuthStatus,
RequestOverrideResponse,
Portal,
};

123
src/util.ts Normal file
View File

@ -0,0 +1,123 @@
// addContextToErr is a helper function that standardizes the formatting of
// adding context to an error.
//
// NOTE: To protect against accidental situations where an Error type or some
// other type is provided instead of a string, we wrap both of the inputs with
// objAsString before returning them. This prevents runtime failures.
import { Err } from "#types.js";
const MAX_UINT_64 = 18446744073709551615n;
function addContextToErr(err: any, context: string): string {
if (err === null || err === undefined) {
err = "[no error provided]";
}
return objAsString(context) + ": " + objAsString(err);
}
// objAsString will try to return the provided object as a string. If the
// object is already a string, it will be returned without modification. If the
// object is an 'Error', the message of the error will be returned. If the object
// has a toString method, the toString method will be called and the result
// will be returned. If the object is null or undefined, a special string will
// be returned indicating that the undefined/null object cannot be converted to
// a string. In all other cases, JSON.stringify is used. If JSON.stringify
// throws an exception, a message "[could not provide object as string]" will
// be returned.
//
// NOTE: objAsString is intended to produce human readable output. It is lossy,
// and it is not intended to be used for serialization.
function objAsString(obj: any): string {
// Check for undefined input.
if (obj === undefined) {
return "[cannot convert undefined to string]";
}
if (obj === null) {
return "[cannot convert null to string]";
}
// Parse the error into a string.
if (typeof obj === "string") {
return obj;
}
// Check if the object is an error, and return the message of the error if
// so.
if (obj instanceof Error) {
return obj.message;
}
// Check if the object has a 'toString' method defined on it. To ensure
// that we don't crash or throw, check that the toString is a function, and
// also that the return value of toString is a string.
if (Object.prototype.hasOwnProperty.call(obj, "toString")) {
if (typeof obj.toString === "function") {
const str = obj.toString();
if (typeof str === "string") {
return str;
}
}
}
// If the object does not have a custom toString, attempt to perform a
// JSON.stringify. We use a lot of bigints in libskynet, and calling
// JSON.stringify on an object with a bigint will cause a throw, so we add
// some custom handling to allow bigint objects to still be encoded.
try {
return JSON.stringify(obj, (_, v) => {
if (typeof v === "bigint") {
return v.toString();
}
return v;
});
} catch (err: any) {
if (err !== undefined && typeof err.message === "string") {
return `[stringify failed]: ${err.message}`;
}
return "[stringify failed]";
}
}
// decodeU64 is the opposite of encodeU64, it takes a uint64 encoded as 8 bytes
// and decodes them into a BigInt.
function decodeU64(u8: Uint8Array): [bigint, Err] {
// Check the input.
if (u8.length !== 8) {
return [0n, "input should be 8 bytes"];
}
// Process the input.
let num = 0n;
for (let i = u8.length - 1; i >= 0; i--) {
num *= 256n;
num += BigInt(u8[i]);
}
return [num, null];
}
// encodeU64 will encode a bigint in the range of a uint64 to an 8 byte
// Uint8Array.
function encodeU64(num: bigint): [Uint8Array, Err] {
// Check the bounds on the bigint.
if (num < 0) {
return [new Uint8Array(0), "expected a positive integer"];
}
if (num > MAX_UINT_64) {
return [new Uint8Array(0), "expected a number no larger than a uint64"];
}
// Encode the bigint into a Uint8Array.
const encoded = new Uint8Array(8);
for (let i = 0; i < encoded.length; i++) {
encoded[i] = Number(num & 0xffn);
num = num >> 8n;
}
return [encoded, null];
}
function bufToB64(buf: Uint8Array): string {
const b64Str = btoa(String.fromCharCode(...buf));
return b64Str.replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
}
export { objAsString, addContextToErr, encodeU64, decodeU64, bufToB64 };