@juspay/shooter 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/notifier.cjs +117 -33
- package/.claude/settings.json +14 -14
- package/README.md +116 -84
- package/bin/shooter.cjs +471 -102
- package/build/client/_app/immutable/assets/{0.CM9Hl6d-.css → 0.BhZOCxO4.css} +1 -1
- package/build/client/_app/immutable/assets/0.BhZOCxO4.css.br +0 -0
- package/build/client/_app/immutable/assets/0.BhZOCxO4.css.gz +0 -0
- package/build/client/_app/immutable/assets/1.BYutk3aU.css +1 -0
- package/build/client/_app/immutable/assets/1.BYutk3aU.css.br +0 -0
- package/build/client/_app/immutable/assets/1.BYutk3aU.css.gz +0 -0
- package/build/client/_app/immutable/assets/2.CAShZ7lQ.css.gz +0 -0
- package/build/client/_app/immutable/assets/3.DGDHCVnW.css +1 -0
- package/build/client/_app/immutable/assets/3.DGDHCVnW.css.br +0 -0
- package/build/client/_app/immutable/assets/3.DGDHCVnW.css.gz +0 -0
- package/build/client/_app/immutable/assets/4.BFUut--w.css +1 -0
- package/build/client/_app/immutable/assets/4.BFUut--w.css.br +0 -0
- package/build/client/_app/immutable/assets/4.BFUut--w.css.gz +0 -0
- package/build/client/_app/immutable/assets/5.BTOx7yt7.css +1 -0
- package/build/client/_app/immutable/assets/5.BTOx7yt7.css.br +0 -0
- package/build/client/_app/immutable/assets/5.BTOx7yt7.css.gz +0 -0
- package/build/client/_app/immutable/assets/6.eZGZN-BF.css +1 -0
- package/build/client/_app/immutable/assets/6.eZGZN-BF.css.br +0 -0
- package/build/client/_app/immutable/assets/6.eZGZN-BF.css.gz +0 -0
- package/build/client/_app/immutable/assets/7.DwS5ZHBh.css +1 -0
- package/build/client/_app/immutable/assets/7.DwS5ZHBh.css.br +0 -0
- package/build/client/_app/immutable/assets/7.DwS5ZHBh.css.gz +0 -0
- package/build/client/_app/immutable/assets/ChatView.CwWbzIL-.css +1 -0
- package/build/client/_app/immutable/assets/ChatView.CwWbzIL-.css.br +0 -0
- package/build/client/_app/immutable/assets/ChatView.CwWbzIL-.css.gz +0 -0
- package/build/client/_app/immutable/assets/Phone.FQEfwCX2.css +1 -0
- package/build/client/_app/immutable/assets/Phone.FQEfwCX2.css.br +0 -0
- package/build/client/_app/immutable/assets/Phone.FQEfwCX2.css.gz +0 -0
- package/build/client/_app/immutable/assets/markdown.Dc-OSJWY.css +1 -0
- package/build/client/_app/immutable/assets/markdown.Dc-OSJWY.css.br +0 -0
- package/build/client/_app/immutable/assets/markdown.Dc-OSJWY.css.gz +0 -0
- package/build/client/_app/immutable/assets/xterm.DFuMZ0ql.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B-K5Sh65.js +1 -0
- package/build/client/_app/immutable/chunks/B-K5Sh65.js.br +0 -0
- package/build/client/_app/immutable/chunks/B-K5Sh65.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B5NAKyil.js +20 -0
- package/build/client/_app/immutable/chunks/B5NAKyil.js.br +0 -0
- package/build/client/_app/immutable/chunks/B5NAKyil.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B8XegpSE.js +1 -0
- package/build/client/_app/immutable/chunks/B8XegpSE.js.br +0 -0
- package/build/client/_app/immutable/chunks/B8XegpSE.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B8zoBsv3.js +6 -0
- package/build/client/_app/immutable/chunks/B8zoBsv3.js.br +0 -0
- package/build/client/_app/immutable/chunks/B8zoBsv3.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BLszSzTT.js +1 -0
- package/build/client/_app/immutable/chunks/BLszSzTT.js.br +0 -0
- package/build/client/_app/immutable/chunks/BLszSzTT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BOYo8yTr.js +1 -0
- package/build/client/_app/immutable/chunks/BOYo8yTr.js.br +0 -0
- package/build/client/_app/immutable/chunks/BOYo8yTr.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BTGVxaYV.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BYqGCrTe.js +1 -0
- package/build/client/_app/immutable/chunks/BYqGCrTe.js.br +0 -0
- package/build/client/_app/immutable/chunks/BYqGCrTe.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BlxrFPDK.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bu1aqm5j.js +1 -0
- package/build/client/_app/immutable/chunks/Bu1aqm5j.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bu1aqm5j.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C4mLaWWx.js +1 -0
- package/build/client/_app/immutable/chunks/C4mLaWWx.js.br +0 -0
- package/build/client/_app/immutable/chunks/C4mLaWWx.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CQjSATpv.js +61 -0
- package/build/client/_app/immutable/chunks/CQjSATpv.js.br +0 -0
- package/build/client/_app/immutable/chunks/CQjSATpv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CSoRdFvv.js +1 -0
- package/build/client/_app/immutable/chunks/CSoRdFvv.js.br +0 -0
- package/build/client/_app/immutable/chunks/CSoRdFvv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CZHsSL_X.js +1 -0
- package/build/client/_app/immutable/chunks/CZHsSL_X.js.br +0 -0
- package/build/client/_app/immutable/chunks/CZHsSL_X.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DLu6yJIZ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DSU1n5N_.js +1 -0
- package/build/client/_app/immutable/chunks/DSU1n5N_.js.br +0 -0
- package/build/client/_app/immutable/chunks/DSU1n5N_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DVkn4r72.js +1 -0
- package/build/client/_app/immutable/chunks/DVkn4r72.js.br +0 -0
- package/build/client/_app/immutable/chunks/DVkn4r72.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DjsDGxCa.js +41 -0
- package/build/client/_app/immutable/chunks/DjsDGxCa.js.br +0 -0
- package/build/client/_app/immutable/chunks/DjsDGxCa.js.gz +0 -0
- package/build/client/_app/immutable/chunks/PPVm8Dsz.js.gz +0 -0
- package/build/client/_app/immutable/chunks/UJOiqIYE.js +1 -0
- package/build/client/_app/immutable/chunks/UJOiqIYE.js.br +0 -0
- package/build/client/_app/immutable/chunks/UJOiqIYE.js.gz +0 -0
- package/build/client/_app/immutable/chunks/r0JawsZc.js +2 -0
- package/build/client/_app/immutable/chunks/r0JawsZc.js.br +0 -0
- package/build/client/_app/immutable/chunks/r0JawsZc.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.Z3zMnuSx.js +2 -0
- package/build/client/_app/immutable/entry/app.Z3zMnuSx.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Z3zMnuSx.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.Dd-gIP4y.js +1 -0
- package/build/client/_app/immutable/entry/start.Dd-gIP4y.js.br +2 -0
- package/build/client/_app/immutable/entry/start.Dd-gIP4y.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.D2YR8tTD.js +1 -0
- package/build/client/_app/immutable/nodes/0.D2YR8tTD.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.D2YR8tTD.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.B3m6rO4C.js +1 -0
- package/build/client/_app/immutable/nodes/1.B3m6rO4C.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.B3m6rO4C.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.CyRB2euU.js +1 -0
- package/build/client/_app/immutable/nodes/2.CyRB2euU.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CyRB2euU.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.3yohCM25.js +3 -0
- package/build/client/_app/immutable/nodes/3.3yohCM25.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.3yohCM25.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.DEAcwl7l.js +1 -0
- package/build/client/_app/immutable/nodes/4.DEAcwl7l.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.DEAcwl7l.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.C6bLGWQR.js +4 -0
- package/build/client/_app/immutable/nodes/5.C6bLGWQR.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.C6bLGWQR.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.ByTzlA2D.js +2 -0
- package/build/client/_app/immutable/nodes/6.ByTzlA2D.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.ByTzlA2D.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.BPMfwzd2.js +2 -0
- package/build/client/_app/immutable/nodes/7.BPMfwzd2.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.BPMfwzd2.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/client/favicon.svg.gz +0 -0
- package/build/client/manifest.json +13 -0
- package/build/client/manifest.json.br +0 -0
- package/build/client/manifest.json.gz +0 -0
- package/build/pty-holder.cjs +37 -8
- package/build/server/chunks/0-Vk38tI2J.js +9 -0
- package/build/server/chunks/0-Vk38tI2J.js.map +1 -0
- package/build/server/chunks/1-BvYQX5MR.js +9 -0
- package/build/server/chunks/1-BvYQX5MR.js.map +1 -0
- package/build/server/chunks/2-Cl7R4Qk2.js +9 -0
- package/build/server/chunks/2-Cl7R4Qk2.js.map +1 -0
- package/build/server/chunks/3-Ck7ewhOX.js +9 -0
- package/build/server/chunks/3-Ck7ewhOX.js.map +1 -0
- package/build/server/chunks/4-CnDeRm2Z.js +9 -0
- package/build/server/chunks/4-CnDeRm2Z.js.map +1 -0
- package/build/server/chunks/5-IxitzEvN.js +9 -0
- package/build/server/chunks/5-IxitzEvN.js.map +1 -0
- package/build/server/chunks/6-CyZ3r1iS.js +9 -0
- package/build/server/chunks/6-CyZ3r1iS.js.map +1 -0
- package/build/server/chunks/7-BmI7du46.js +9 -0
- package/build/server/chunks/7-BmI7du46.js.map +1 -0
- package/build/server/chunks/Button-Cs1aE6ka.js +80 -0
- package/build/server/chunks/Button-Cs1aE6ka.js.map +1 -0
- package/build/server/chunks/EmptyState-DDFH1K8g.js +26 -0
- package/build/server/chunks/EmptyState-DDFH1K8g.js.map +1 -0
- package/build/server/chunks/Icon-CEUrotA6.js +36 -0
- package/build/server/chunks/Icon-CEUrotA6.js.map +1 -0
- package/build/server/chunks/Shimmer-DB8W1zt6.js +10 -0
- package/build/server/chunks/Shimmer-DB8W1zt6.js.map +1 -0
- package/build/server/chunks/_error.svelte-uCOJNxvr.js +39 -0
- package/build/server/chunks/_error.svelte-uCOJNxvr.js.map +1 -0
- package/build/server/chunks/_layout.svelte-CtWmEJwe.js +56 -0
- package/build/server/chunks/_layout.svelte-CtWmEJwe.js.map +1 -0
- package/build/server/chunks/_page.svelte-BcZaKdX9.js +45 -0
- package/build/server/chunks/_page.svelte-BcZaKdX9.js.map +1 -0
- package/build/server/chunks/_page.svelte-BdYynOck.js +85 -0
- package/build/server/chunks/_page.svelte-BdYynOck.js.map +1 -0
- package/build/server/chunks/_page.svelte-BgevQjq1.js +101 -0
- package/build/server/chunks/_page.svelte-BgevQjq1.js.map +1 -0
- package/build/server/chunks/_page.svelte-CVq6tRb3.js +550 -0
- package/build/server/chunks/_page.svelte-CVq6tRb3.js.map +1 -0
- package/build/server/chunks/_page.svelte-CxWcQ0Am.js +651 -0
- package/build/server/chunks/_page.svelte-CxWcQ0Am.js.map +1 -0
- package/build/server/chunks/_page.svelte-DO4oa_LY.js +44 -0
- package/build/server/chunks/_page.svelte-DO4oa_LY.js.map +1 -0
- package/build/server/chunks/{_server.ts-CbDRDIoP.js → _server.ts-BStnNIcq.js} +9 -11
- package/build/server/chunks/_server.ts-BStnNIcq.js.map +1 -0
- package/build/server/chunks/{_server.ts-DRVbgm6k.js → _server.ts-CAxsWKvS.js} +22 -25
- package/build/server/chunks/_server.ts-CAxsWKvS.js.map +1 -0
- package/build/server/chunks/{_server.ts-CPa6DgIt.js → _server.ts-COu0vNpd.js} +6 -6
- package/build/server/chunks/_server.ts-COu0vNpd.js.map +1 -0
- package/build/server/chunks/{_server.ts-C29xzfaw.js → _server.ts-CTpcLUH8.js} +10 -10
- package/build/server/chunks/_server.ts-CTpcLUH8.js.map +1 -0
- package/build/server/chunks/{_server.ts-D4MNi4cD.js → _server.ts-Cf84YIaW.js} +3 -3
- package/build/server/chunks/{_server.ts-D4MNi4cD.js.map → _server.ts-Cf84YIaW.js.map} +1 -1
- package/build/server/chunks/{_server.ts-BL2FGb5Z.js → _server.ts-Ch-6iOHp.js} +99 -53
- package/build/server/chunks/_server.ts-Ch-6iOHp.js.map +1 -0
- package/build/server/chunks/_server.ts-CtH0dhUp.js +71 -0
- package/build/server/chunks/_server.ts-CtH0dhUp.js.map +1 -0
- package/build/server/chunks/_server.ts-DB_Kg97c.js +73 -0
- package/build/server/chunks/_server.ts-DB_Kg97c.js.map +1 -0
- package/build/server/chunks/{_server.ts-DfajWaqh.js → _server.ts-DV8zTCF9.js} +7 -9
- package/build/server/chunks/_server.ts-DV8zTCF9.js.map +1 -0
- package/build/server/chunks/_server.ts-DYpJImqd.js +99 -0
- package/build/server/chunks/_server.ts-DYpJImqd.js.map +1 -0
- package/build/server/chunks/{_server.ts-ColfDHW8.js → _server.ts-DYvb9ijZ.js} +21 -10
- package/build/server/chunks/_server.ts-DYvb9ijZ.js.map +1 -0
- package/build/server/chunks/{_server.ts-Cv_OrRuL.js → _server.ts-Deok2y88.js} +209 -34
- package/build/server/chunks/_server.ts-Deok2y88.js.map +1 -0
- package/build/server/chunks/{_server.ts-y9-WYDMa.js → _server.ts-WhTJBEJy.js} +5 -4
- package/build/server/chunks/{_server.ts-y9-WYDMa.js.map → _server.ts-WhTJBEJy.js.map} +1 -1
- package/build/server/chunks/{_server.ts-BjOJsoy4.js → _server.ts-XzT2UHM1.js} +6 -5
- package/build/server/chunks/_server.ts-XzT2UHM1.js.map +1 -0
- package/build/server/chunks/{_server.ts-BgdjBZco.js → _server.ts-tSpgyl1D.js} +7 -5
- package/build/server/chunks/_server.ts-tSpgyl1D.js.map +1 -0
- package/build/server/chunks/{_server.ts-BihKSdj_.js → _server.ts-vekTmWAx.js} +8 -8
- package/build/server/chunks/_server.ts-vekTmWAx.js.map +1 -0
- package/build/server/chunks/{auth-CEgFis71.js → auth-DeCdZ83n.js} +2 -2
- package/build/server/chunks/{auth-CEgFis71.js.map → auth-DeCdZ83n.js.map} +1 -1
- package/build/server/chunks/client-BdGHe_hY.js +25 -0
- package/build/server/chunks/client-BdGHe_hY.js.map +1 -0
- package/build/server/chunks/client2-CCBGA-2V.js +7 -0
- package/build/server/chunks/client2-CCBGA-2V.js.map +1 -0
- package/build/server/chunks/error-DDXB3duW.js +12 -0
- package/build/server/chunks/error-DDXB3duW.js.map +1 -0
- package/build/server/chunks/{exports-CJ0Q5XmL.js → index-DwaY1cAm.js} +1111 -1634
- package/build/server/chunks/index-DwaY1cAm.js.map +1 -0
- package/build/server/chunks/index-server-CrDaL06Y.js +9 -0
- package/build/server/chunks/index-server-CrDaL06Y.js.map +1 -0
- package/build/server/chunks/index2-CgclKpUj.js +58 -0
- package/build/server/chunks/index2-CgclKpUj.js.map +1 -0
- package/build/server/chunks/{library-apns-BHxLmuIx.js → library-apns-BqJbvSKh.js} +4 -4
- package/build/server/chunks/library-apns-BqJbvSKh.js.map +1 -0
- package/build/server/chunks/markdown-W_mTBct0.js +8 -0
- package/build/server/chunks/markdown-W_mTBct0.js.map +1 -0
- package/build/server/chunks/opencode-db-path-DcfhJtJy.js +15 -0
- package/build/server/chunks/opencode-db-path-DcfhJtJy.js.map +1 -0
- package/build/server/chunks/{pty-manager-C0FhBiVq.js → pty-manager-BQVB7IVj.js} +155 -326
- package/build/server/chunks/pty-manager-BQVB7IVj.js.map +1 -0
- package/build/server/chunks/root-DDSnEAZv.js +1171 -0
- package/build/server/chunks/root-DDSnEAZv.js.map +1 -0
- package/build/server/chunks/{shared-server-BDY8jh20.js → shared-server-sSGG17Df.js} +2 -3
- package/build/server/chunks/{shared-server-BDY8jh20.js.map → shared-server-sSGG17Df.js.map} +1 -1
- package/build/server/chunks/state.svelte-hBbXlUak.js +11 -0
- package/build/server/chunks/state.svelte-hBbXlUak.js.map +1 -0
- package/build/server/chunks/stores-DHNzYNpX.js +28 -0
- package/build/server/chunks/stores-DHNzYNpX.js.map +1 -0
- package/build/server/index.js +1085 -2242
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +39 -25
- package/build/server/manifest.js.map +1 -1
- package/package.json +32 -9
- package/scripts/fix-generated-types.sh +37 -0
- package/scripts/homebrew/shooter.rb +51 -0
- package/scripts/install.sh +348 -186
- package/scripts/setup.cjs +215 -45
- package/server.ts +114 -71
- package/src/app.css +12 -3
- package/src/app.d.ts +13 -20
- package/src/app.html +3 -2
- package/src/generated/types/API.ts +280 -0
- package/src/generated/types/APN.ts +186 -203
- package/src/generated/types/CLI.ts +18 -25
- package/src/generated/types/Client.ts +589 -0
- package/src/generated/types/Config.ts +53 -0
- package/src/generated/types/Holder.ts +638 -0
- package/src/generated/types/JWT.ts +39 -50
- package/src/generated/types/Notification.ts +426 -0
- package/src/generated/types/OpenCode.ts +356 -0
- package/src/generated/types/Sessions.ts +570 -0
- package/src/generated/types/Terminal.ts +2184 -2071
- package/src/generated/types/WsProtocol.ts +2004 -0
- package/src/generated/types/index.ts +9 -3
- package/src/lib/env.ts +29 -0
- package/src/lib/modules/client/common/cache.ts +10 -2
- package/src/lib/modules/client/common/config-guard.ts +37 -5
- package/src/lib/modules/client/common/error.ts +10 -0
- package/src/lib/modules/client/common/index.ts +6 -5
- package/src/lib/modules/client/common/markdown.ts +22 -1
- package/src/lib/modules/client/common/native-bridge.ts +28 -20
- package/src/lib/modules/client/common/time.ts +13 -11
- package/src/lib/modules/client/terminal/ChatView.svelte +354 -74
- package/src/lib/modules/client/terminal/CommandPalette.svelte +3 -2
- package/src/lib/modules/client/terminal/ConnectionStatus.svelte +7 -1
- package/src/lib/modules/client/terminal/LaunchSheet.svelte +147 -84
- package/src/lib/modules/client/terminal/QuickKeys.svelte +3 -1
- package/src/lib/modules/client/terminal/ShortcutsHelp.svelte +2 -5
- package/src/lib/modules/client/terminal/keyboard-shortcuts.ts +27 -24
- package/src/lib/modules/client/terminal/xterm-wrapper.ts +74 -45
- package/src/lib/modules/server/apn/library-apns.ts +3 -2
- package/src/lib/modules/server/apn/notification-history.ts +2 -13
- package/src/lib/modules/server/apn/notification-sessions.ts +3 -13
- package/src/lib/modules/server/apn/pending-requests.ts +3 -8
- package/src/lib/modules/server/apn/types.ts +5 -4
- package/src/lib/modules/server/cli/index.ts +3 -2
- package/src/lib/modules/server/fcm/fcm-service.ts +8 -6
- package/src/lib/modules/server/sessions/jsonl-parser.ts +3 -3
- package/src/lib/modules/server/sessions/jsonl-reader.ts +86 -26
- package/src/lib/modules/server/sessions/opencode-db-path.ts +26 -0
- package/src/lib/modules/server/sessions/opencode-reader.ts +13 -15
- package/src/lib/modules/server/sessions/process-detector.ts +103 -0
- package/src/lib/modules/server/sessions/types.ts +11 -22
- package/src/lib/modules/server/terminal/holder-client.ts +272 -248
- package/src/lib/modules/server/terminal/opencode-watcher.ts +547 -556
- package/src/lib/modules/server/terminal/pty-holder.cjs +37 -8
- package/src/lib/modules/server/terminal/pty-manager.ts +157 -115
- package/src/lib/modules/server/terminal/session-watcher.ts +6 -4
- package/src/lib/modules/server/terminal/terminal-store.ts +131 -128
- package/src/lib/modules/server/utils/error.ts +9 -0
- package/src/lib/modules/server/ws/events-handler.ts +12 -6
- package/src/lib/modules/server/ws/keepalive.ts +86 -69
- package/src/lib/modules/server/ws/server.ts +43 -37
- package/src/lib/modules/server/ws/session-handler.ts +332 -147
- package/src/lib/modules/server/ws/terminal-handler.ts +29 -17
- package/src/lib/modules/server/ws/ticket-store.ts +29 -26
- package/src/lib/theme.css +30 -0
- package/src/lib/types/config.ts +1 -6
- package/src/routes/+error.svelte +94 -0
- package/src/routes/+layout.svelte +66 -31
- package/src/routes/+page.svelte +25 -22
- package/src/routes/api/debug/+server.ts +3 -1
- package/src/routes/api/device-token/+server.ts +60 -60
- package/src/routes/api/health/+server.ts +81 -73
- package/src/routes/api/notify/+server.ts +115 -68
- package/src/routes/api/qr-config/+server.ts +30 -32
- package/src/routes/api/response/+server.ts +9 -4
- package/src/routes/api/sessions/+server.ts +15 -5
- package/src/routes/api/sessions/connect/+server.ts +125 -0
- package/src/routes/api/sessions/detect/+server.ts +27 -0
- package/src/routes/api/terminals/+server.ts +26 -24
- package/src/routes/api/terminals/[id]/+server.ts +13 -7
- package/src/routes/api/terminals/[id]/paste-image/+server.ts +54 -52
- package/src/routes/api/terminals/[id]/resize/+server.ts +6 -3
- package/src/routes/api/webhook/+server.ts +8 -10
- package/src/routes/api/ws-status/+server.ts +7 -5
- package/src/routes/api/ws-ticket/+server.ts +42 -41
- package/src/routes/config/+page.svelte +149 -75
- package/src/routes/project/+page.svelte +165 -35
- package/src/routes/session/[id]/+page.svelte +479 -283
- package/src/routes/terminals/+page.svelte +58 -45
- package/src/routes/terminals/[id]/+page.svelte +223 -91
- package/build/client/_app/immutable/assets/0.CM9Hl6d-.css.br +0 -0
- package/build/client/_app/immutable/assets/0.CM9Hl6d-.css.gz +0 -0
- package/build/client/_app/immutable/assets/3.C0uFg0IS.css +0 -1
- package/build/client/_app/immutable/assets/3.C0uFg0IS.css.br +0 -0
- package/build/client/_app/immutable/assets/3.C0uFg0IS.css.gz +0 -0
- package/build/client/_app/immutable/assets/4.cJuCkJKZ.css +0 -1
- package/build/client/_app/immutable/assets/4.cJuCkJKZ.css.br +0 -0
- package/build/client/_app/immutable/assets/4.cJuCkJKZ.css.gz +0 -0
- package/build/client/_app/immutable/assets/5.DRjApZQW.css +0 -1
- package/build/client/_app/immutable/assets/5.DRjApZQW.css.br +0 -0
- package/build/client/_app/immutable/assets/5.DRjApZQW.css.gz +0 -0
- package/build/client/_app/immutable/assets/6.AraZrY8I.css +0 -1
- package/build/client/_app/immutable/assets/6.AraZrY8I.css.br +0 -0
- package/build/client/_app/immutable/assets/6.AraZrY8I.css.gz +0 -0
- package/build/client/_app/immutable/assets/7.BCJ1IuMx.css +0 -1
- package/build/client/_app/immutable/assets/7.BCJ1IuMx.css.br +0 -0
- package/build/client/_app/immutable/assets/7.BCJ1IuMx.css.gz +0 -0
- package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css +0 -1
- package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css.br +0 -0
- package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css.gz +0 -0
- package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css +0 -1
- package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css.br +0 -0
- package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css.gz +0 -0
- package/build/client/_app/immutable/chunks/BNJphC1q.js +0 -56
- package/build/client/_app/immutable/chunks/BNJphC1q.js.br +0 -0
- package/build/client/_app/immutable/chunks/BNJphC1q.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bvk7mfPM.js +0 -1
- package/build/client/_app/immutable/chunks/Bvk7mfPM.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bvk7mfPM.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CAokzuPQ.js +0 -1
- package/build/client/_app/immutable/chunks/CAokzuPQ.js.br +0 -0
- package/build/client/_app/immutable/chunks/CAokzuPQ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CGLrx-H5.js +0 -1
- package/build/client/_app/immutable/chunks/CGLrx-H5.js.br +0 -0
- package/build/client/_app/immutable/chunks/CGLrx-H5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CgCpWzEA.js +0 -1
- package/build/client/_app/immutable/chunks/CgCpWzEA.js.br +0 -0
- package/build/client/_app/immutable/chunks/CgCpWzEA.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Cjwk_cGO.js +0 -6
- package/build/client/_app/immutable/chunks/Cjwk_cGO.js.br +0 -0
- package/build/client/_app/immutable/chunks/Cjwk_cGO.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CtQ8EED1.js +0 -11
- package/build/client/_app/immutable/chunks/CtQ8EED1.js.br +0 -0
- package/build/client/_app/immutable/chunks/CtQ8EED1.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DERQCisl.js +0 -1
- package/build/client/_app/immutable/chunks/DERQCisl.js.br +0 -0
- package/build/client/_app/immutable/chunks/DERQCisl.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DKrg8TQs.js +0 -1
- package/build/client/_app/immutable/chunks/DKrg8TQs.js.br +0 -0
- package/build/client/_app/immutable/chunks/DKrg8TQs.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dkkpz_4D.js +0 -126
- package/build/client/_app/immutable/chunks/Dkkpz_4D.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dkkpz_4D.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DoczjQhA.js +0 -1
- package/build/client/_app/immutable/chunks/DoczjQhA.js.br +0 -0
- package/build/client/_app/immutable/chunks/DoczjQhA.js.gz +0 -0
- package/build/client/_app/immutable/chunks/RpcNruLP.js +0 -2
- package/build/client/_app/immutable/chunks/RpcNruLP.js.br +0 -0
- package/build/client/_app/immutable/chunks/RpcNruLP.js.gz +0 -0
- package/build/client/_app/immutable/chunks/a-St0Zwo.js +0 -1
- package/build/client/_app/immutable/chunks/a-St0Zwo.js.br +0 -0
- package/build/client/_app/immutable/chunks/a-St0Zwo.js.gz +0 -0
- package/build/client/_app/immutable/chunks/bo70OQUZ.js +0 -1
- package/build/client/_app/immutable/chunks/bo70OQUZ.js.br +0 -0
- package/build/client/_app/immutable/chunks/bo70OQUZ.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.QvGgdvTI.js +0 -2
- package/build/client/_app/immutable/entry/app.QvGgdvTI.js.br +0 -0
- package/build/client/_app/immutable/entry/app.QvGgdvTI.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BntDNRMC.js +0 -1
- package/build/client/_app/immutable/entry/start.BntDNRMC.js.br +0 -0
- package/build/client/_app/immutable/entry/start.BntDNRMC.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js +0 -1
- package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.MG1QhfrI.js +0 -1
- package/build/client/_app/immutable/nodes/1.MG1QhfrI.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.MG1QhfrI.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.B4MlOSh6.js +0 -1
- package/build/client/_app/immutable/nodes/2.B4MlOSh6.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.B4MlOSh6.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.DIwYkjDn.js +0 -3
- package/build/client/_app/immutable/nodes/3.DIwYkjDn.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.DIwYkjDn.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.D-cIe70D.js +0 -1
- package/build/client/_app/immutable/nodes/4.D-cIe70D.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.D-cIe70D.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.D7zPRe3L.js +0 -1
- package/build/client/_app/immutable/nodes/5.D7zPRe3L.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.D7zPRe3L.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.BB7QE48r.js +0 -2
- package/build/client/_app/immutable/nodes/6.BB7QE48r.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.BB7QE48r.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.D8mqsrZG.js +0 -2
- package/build/client/_app/immutable/nodes/7.D8mqsrZG.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.D8mqsrZG.js.gz +0 -0
- package/build/client/manifest.webmanifest +0 -1
- package/build/client/registerSW.js +0 -1
- package/build/client/registerSW.js.br +0 -0
- package/build/client/registerSW.js.gz +0 -0
- package/build/client/sw.js +0 -222
- package/build/client/sw.js.br +0 -0
- package/build/client/sw.js.gz +0 -0
- package/build/client/workbox-5119daf5.js +0 -3395
- package/build/client/workbox-5119daf5.js.br +0 -0
- package/build/client/workbox-5119daf5.js.gz +0 -0
- package/build/server/chunks/0-q2IUp76Y.js +0 -9
- package/build/server/chunks/0-q2IUp76Y.js.map +0 -1
- package/build/server/chunks/1-CU50G5wZ.js +0 -9
- package/build/server/chunks/1-CU50G5wZ.js.map +0 -1
- package/build/server/chunks/2-D01t9s8T.js +0 -9
- package/build/server/chunks/2-D01t9s8T.js.map +0 -1
- package/build/server/chunks/3-5PUQ04wC.js +0 -9
- package/build/server/chunks/3-5PUQ04wC.js.map +0 -1
- package/build/server/chunks/4-e7gywnSG.js +0 -9
- package/build/server/chunks/4-e7gywnSG.js.map +0 -1
- package/build/server/chunks/5-CA1SA6KZ.js +0 -9
- package/build/server/chunks/5-CA1SA6KZ.js.map +0 -1
- package/build/server/chunks/6-71H221sV.js +0 -9
- package/build/server/chunks/6-71H221sV.js.map +0 -1
- package/build/server/chunks/7-Bo-vmdyz.js +0 -9
- package/build/server/chunks/7-Bo-vmdyz.js.map +0 -1
- package/build/server/chunks/_layout.svelte-SFHOxs74.js +0 -132
- package/build/server/chunks/_layout.svelte-SFHOxs74.js.map +0 -1
- package/build/server/chunks/_page.svelte-B4w-2wD-.js +0 -120
- package/build/server/chunks/_page.svelte-B4w-2wD-.js.map +0 -1
- package/build/server/chunks/_page.svelte-B_qAXjkh.js +0 -213
- package/build/server/chunks/_page.svelte-B_qAXjkh.js.map +0 -1
- package/build/server/chunks/_page.svelte-CsF1_TRG.js +0 -50
- package/build/server/chunks/_page.svelte-CsF1_TRG.js.map +0 -1
- package/build/server/chunks/_page.svelte-DJC6U-P0.js +0 -68
- package/build/server/chunks/_page.svelte-DJC6U-P0.js.map +0 -1
- package/build/server/chunks/_page.svelte-DQ6HBtsz.js +0 -407
- package/build/server/chunks/_page.svelte-DQ6HBtsz.js.map +0 -1
- package/build/server/chunks/_page.svelte-LbhhjP21.js +0 -148
- package/build/server/chunks/_page.svelte-LbhhjP21.js.map +0 -1
- package/build/server/chunks/_server.ts-BL2FGb5Z.js.map +0 -1
- package/build/server/chunks/_server.ts-BgdjBZco.js.map +0 -1
- package/build/server/chunks/_server.ts-BihKSdj_.js.map +0 -1
- package/build/server/chunks/_server.ts-BjOJsoy4.js.map +0 -1
- package/build/server/chunks/_server.ts-C29xzfaw.js.map +0 -1
- package/build/server/chunks/_server.ts-CPa6DgIt.js.map +0 -1
- package/build/server/chunks/_server.ts-CbDRDIoP.js.map +0 -1
- package/build/server/chunks/_server.ts-Cl1OEWL4.js +0 -54
- package/build/server/chunks/_server.ts-Cl1OEWL4.js.map +0 -1
- package/build/server/chunks/_server.ts-ColfDHW8.js.map +0 -1
- package/build/server/chunks/_server.ts-Cv_OrRuL.js.map +0 -1
- package/build/server/chunks/_server.ts-DRVbgm6k.js.map +0 -1
- package/build/server/chunks/_server.ts-DfajWaqh.js.map +0 -1
- package/build/server/chunks/client-CxCatAKr.js +0 -255
- package/build/server/chunks/client-CxCatAKr.js.map +0 -1
- package/build/server/chunks/error.svelte-BqdwMWdK.js +0 -26
- package/build/server/chunks/error.svelte-BqdwMWdK.js.map +0 -1
- package/build/server/chunks/exports-CJ0Q5XmL.js.map +0 -1
- package/build/server/chunks/index2-DAxIoAO-.js +0 -36
- package/build/server/chunks/index2-DAxIoAO-.js.map +0 -1
- package/build/server/chunks/jsonl-parser-dmZU_Hyu.js +0 -137
- package/build/server/chunks/jsonl-parser-dmZU_Hyu.js.map +0 -1
- package/build/server/chunks/library-apns-BHxLmuIx.js.map +0 -1
- package/build/server/chunks/markdown-Bxrl3cCF.js +0 -1241
- package/build/server/chunks/markdown-Bxrl3cCF.js.map +0 -1
- package/build/server/chunks/pty-manager-C0FhBiVq.js.map +0 -1
- package/build/server/chunks/stores-D0HorpgL.js +0 -36
- package/build/server/chunks/stores-D0HorpgL.js.map +0 -1
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
2
|
+
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
2
3
|
import { json } from '@sveltejs/kit';
|
|
3
4
|
|
|
4
5
|
import type { RequestHandler } from './$types';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
// TODO: Add HMAC signature validation for webhook payloads.
|
|
8
|
+
// This is currently a stub endpoint — no signature verification is performed.
|
|
8
9
|
export const POST: RequestHandler = async ({ request }) => {
|
|
9
10
|
try {
|
|
10
11
|
const authError = validateAuth(request);
|
|
11
|
-
if (authError)
|
|
12
|
+
if (authError) {
|
|
13
|
+
return authError;
|
|
14
|
+
}
|
|
12
15
|
|
|
13
|
-
const body = (await request.json()) as
|
|
16
|
+
const body = (await request.json()) as Record<string, unknown>;
|
|
14
17
|
|
|
15
18
|
console.log('Webhook received:', {
|
|
16
19
|
body,
|
|
17
|
-
headers: Object.fromEntries(request.headers.entries()),
|
|
18
20
|
timestamp: new Date().toISOString(),
|
|
19
21
|
});
|
|
20
22
|
|
|
@@ -22,19 +24,15 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
22
24
|
// For now, just log and acknowledge
|
|
23
25
|
|
|
24
26
|
return json({
|
|
25
|
-
data: body,
|
|
26
27
|
message: 'Webhook received successfully',
|
|
27
28
|
success: true,
|
|
28
29
|
timestamp: new Date().toISOString(),
|
|
29
30
|
});
|
|
30
31
|
} catch (error) {
|
|
31
|
-
|
|
32
|
-
console.error('Webhook error:', err);
|
|
32
|
+
console.error('[webhook] Failed to process webhook:', toErrorMessage(error));
|
|
33
33
|
return json(
|
|
34
34
|
{
|
|
35
|
-
details: err.message,
|
|
36
35
|
error: 'Failed to process webhook',
|
|
37
|
-
timestamp: new Date().toISOString(),
|
|
38
36
|
},
|
|
39
37
|
{ status: 500 }
|
|
40
38
|
);
|
|
@@ -14,10 +14,12 @@ import type { RequestHandler } from './$types';
|
|
|
14
14
|
// ── Endpoint ────────────────────────────────────────────────────────
|
|
15
15
|
|
|
16
16
|
export const GET: RequestHandler = ({ request }) => {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const authError = validateAuth(request);
|
|
18
|
+
if (authError) {
|
|
19
|
+
return authError;
|
|
20
|
+
}
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
return json({
|
|
23
|
+
connectedClients: getConnectedClientCount(),
|
|
24
|
+
});
|
|
23
25
|
};
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
//
|
|
8
8
|
// Rate limited to 10 requests per minute per API key.
|
|
9
9
|
|
|
10
|
-
import { env } from '$env/dynamic/private';
|
|
11
10
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
12
11
|
import { generateTicket } from '$lib/modules/server/ws/ticket-store';
|
|
13
12
|
import { json } from '@sveltejs/kit';
|
|
@@ -27,60 +26,62 @@ const rateLimitMap = new Map<string, number[]>();
|
|
|
27
26
|
* Returns true if the request is within the rate limit, false if exceeded.
|
|
28
27
|
*/
|
|
29
28
|
function checkRateLimit(apiKey: string): boolean {
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
const cutoff = now - RATE_LIMIT_WINDOW_MS;
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
let timestamps = rateLimitMap.get(apiKey);
|
|
33
|
+
if (!timestamps) {
|
|
34
|
+
timestamps = [];
|
|
35
|
+
rateLimitMap.set(apiKey, timestamps);
|
|
36
|
+
}
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
// Prune timestamps outside the window
|
|
39
|
+
const recent = timestamps.filter((t) => t > cutoff);
|
|
40
|
+
rateLimitMap.set(apiKey, recent);
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
if (recent.length >= RATE_LIMIT_MAX) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
recent.push(now);
|
|
47
|
+
return true;
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
// Cleanup stale rate limit entries every 5 minutes
|
|
52
51
|
setInterval(() => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
const cutoff = Date.now() - RATE_LIMIT_WINDOW_MS;
|
|
53
|
+
for (const [key, timestamps] of rateLimitMap) {
|
|
54
|
+
const recent = timestamps.filter((t) => t > cutoff);
|
|
55
|
+
if (recent.length === 0) {
|
|
56
|
+
rateLimitMap.delete(key);
|
|
57
|
+
} else {
|
|
58
|
+
rateLimitMap.set(key, recent);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
62
61
|
}, 300_000).unref();
|
|
63
62
|
|
|
64
63
|
// ── Endpoint ────────────────────────────────────────────────────────
|
|
65
64
|
|
|
66
|
-
export const POST: RequestHandler =
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
export const POST: RequestHandler = ({ request }) => {
|
|
66
|
+
const authError = validateAuth(request);
|
|
67
|
+
if (authError) {
|
|
68
|
+
return authError;
|
|
69
|
+
}
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
// Extract the API key for rate limiting
|
|
72
|
+
const apiKey = request.headers.get('authorization')!.substring(7);
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
if (!checkRateLimit(apiKey)) {
|
|
75
|
+
return json(
|
|
76
|
+
{ error: 'Rate limit exceeded. Maximum 10 ticket requests per minute.' },
|
|
77
|
+
{ status: 429 }
|
|
78
|
+
);
|
|
79
|
+
}
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
const ticket = generateTicket();
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
return json({
|
|
84
|
+
expiresIn: 30,
|
|
85
|
+
ticket,
|
|
86
|
+
});
|
|
86
87
|
};
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { NativeBridgeConfig } from '$generated/types';
|
|
2
3
|
import type { ShooterConfig } from '$lib/types/config';
|
|
3
4
|
|
|
4
5
|
import { browser } from '$app/environment';
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
Card,
|
|
8
|
+
hasScanner,
|
|
9
|
+
Icon,
|
|
10
|
+
isShooterConfig,
|
|
11
|
+
scanQR,
|
|
12
|
+
toErrorMessage,
|
|
13
|
+
} from '$lib/modules/client/common';
|
|
6
14
|
import { Banner, Button, Input, Stepper } from '@juspay/svelte-ui-components';
|
|
7
|
-
import { Card, hasScanner, Icon, isShooterConfig, scanQR } from '$lib/modules/client/common';
|
|
8
15
|
import { onMount } from 'svelte';
|
|
9
16
|
|
|
10
17
|
let serverUrl = $state('');
|
|
@@ -19,7 +26,8 @@
|
|
|
19
26
|
let qrLoading = $state(false);
|
|
20
27
|
let qrError = $state('');
|
|
21
28
|
let canScan = $state(false);
|
|
22
|
-
let
|
|
29
|
+
let _bridgeCheckDone = $state(false);
|
|
30
|
+
let bridgeHydrated = false;
|
|
23
31
|
let scanLoading = $state(false);
|
|
24
32
|
|
|
25
33
|
async function fetchQrCode(): Promise<void> {
|
|
@@ -30,6 +38,8 @@
|
|
|
30
38
|
|
|
31
39
|
qrLoading = true;
|
|
32
40
|
qrError = '';
|
|
41
|
+
qrDataUrl = '';
|
|
42
|
+
qrServerUrl = '';
|
|
33
43
|
|
|
34
44
|
try {
|
|
35
45
|
const response = await fetch('/api/qr-config', {
|
|
@@ -46,8 +56,7 @@
|
|
|
46
56
|
qrDataUrl = data.dataUrl;
|
|
47
57
|
qrServerUrl = data.serverUrl;
|
|
48
58
|
} catch (error) {
|
|
49
|
-
|
|
50
|
-
qrError = `Network error: ${err.message}`;
|
|
59
|
+
qrError = `Network error: ${toErrorMessage(error)}`;
|
|
51
60
|
} finally {
|
|
52
61
|
qrLoading = false;
|
|
53
62
|
}
|
|
@@ -71,16 +80,20 @@
|
|
|
71
80
|
apiKey = config.apiKey;
|
|
72
81
|
}
|
|
73
82
|
await saveConfiguration();
|
|
74
|
-
|
|
75
|
-
|
|
83
|
+
// Only show QR success if saveConfiguration() didn't set an error/warning
|
|
84
|
+
const savedStatus: string = statusType;
|
|
85
|
+
if (savedStatus !== 'error' && savedStatus !== 'warning') {
|
|
86
|
+
result = 'Configuration updated from QR code';
|
|
87
|
+
statusType = 'success';
|
|
88
|
+
}
|
|
76
89
|
} catch {
|
|
77
90
|
result = 'Invalid QR code data';
|
|
78
91
|
statusType = 'error';
|
|
79
92
|
}
|
|
80
93
|
} catch (error) {
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
83
|
-
result = `Scanner error: ${
|
|
94
|
+
const msg = toErrorMessage(error);
|
|
95
|
+
if (msg !== 'cancelled') {
|
|
96
|
+
result = `Scanner error: ${msg}`;
|
|
84
97
|
statusType = 'error';
|
|
85
98
|
}
|
|
86
99
|
} finally {
|
|
@@ -88,19 +101,16 @@
|
|
|
88
101
|
}
|
|
89
102
|
}
|
|
90
103
|
|
|
91
|
-
function getNativeBridge(): {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
getFcmToken(): string;
|
|
102
|
-
getPlatform(): string;
|
|
103
|
-
};
|
|
104
|
+
function getNativeBridge(): null | typeof window.ShooterBridge {
|
|
105
|
+
if (typeof window === 'undefined') {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
// iOS injects window.ShooterBridge, Android injects window.ShooterNativeBridge
|
|
109
|
+
if (window.ShooterBridge) {
|
|
110
|
+
return window.ShooterBridge;
|
|
111
|
+
}
|
|
112
|
+
if (window.ShooterNativeBridge) {
|
|
113
|
+
return window.ShooterNativeBridge;
|
|
104
114
|
}
|
|
105
115
|
return null;
|
|
106
116
|
}
|
|
@@ -109,10 +119,45 @@
|
|
|
109
119
|
return window.location.origin;
|
|
110
120
|
}
|
|
111
121
|
|
|
122
|
+
/** Attempt to read config from the native bridge and hydrate state.
|
|
123
|
+
* Only performs the full hydration (overwriting form fields) once.
|
|
124
|
+
* Subsequent calls only refresh the `canScan` flag so re-polling
|
|
125
|
+
* for a late-injected bridge does not clobber user edits. */
|
|
126
|
+
function hydrateBridge(): void {
|
|
127
|
+
const bridge = getNativeBridge();
|
|
128
|
+
if (bridge && !bridgeHydrated) {
|
|
129
|
+
isNativeApp = true;
|
|
130
|
+
try {
|
|
131
|
+
const nativeConfig = JSON.parse(
|
|
132
|
+
bridge.getConfig?.() ?? '{}'
|
|
133
|
+
) as Partial<NativeBridgeConfig>;
|
|
134
|
+
// If native has config, use it (native is source of truth for credentials).
|
|
135
|
+
// Native serverUrl always overrides — it is set before the browser
|
|
136
|
+
// fallback (window.location.origin) so the native value wins.
|
|
137
|
+
if (nativeConfig.serverUrl) {
|
|
138
|
+
serverUrl = nativeConfig.serverUrl;
|
|
139
|
+
}
|
|
140
|
+
if (nativeConfig.apiKey) {
|
|
141
|
+
apiKey = nativeConfig.apiKey;
|
|
142
|
+
}
|
|
143
|
+
// Auto-populate device token with FCM token
|
|
144
|
+
const fcmToken = bridge.getFcmToken?.();
|
|
145
|
+
if (fcmToken) {
|
|
146
|
+
deviceToken = fcmToken;
|
|
147
|
+
}
|
|
148
|
+
// Mark hydrated only after native reads succeeded
|
|
149
|
+
bridgeHydrated = true;
|
|
150
|
+
} catch {
|
|
151
|
+
// Bridge communication failed — leave bridgeHydrated false so
|
|
152
|
+
// a subsequent poll can retry once the bridge is ready.
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
canScan = hasScanner();
|
|
156
|
+
}
|
|
157
|
+
|
|
112
158
|
onMount(() => {
|
|
113
159
|
if (browser) {
|
|
114
160
|
try {
|
|
115
|
-
serverUrl = getDefaultServerUrl();
|
|
116
161
|
const saved = localStorage.getItem('shooter_config');
|
|
117
162
|
if (saved) {
|
|
118
163
|
const parsed: unknown = JSON.parse(saved);
|
|
@@ -134,42 +179,28 @@
|
|
|
134
179
|
// No saved configuration — expected on first visit
|
|
135
180
|
}
|
|
136
181
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (nativeConfig.serverUrl && !serverUrl) {
|
|
144
|
-
serverUrl = nativeConfig.serverUrl;
|
|
145
|
-
}
|
|
146
|
-
if (nativeConfig.apiKey) {
|
|
147
|
-
apiKey = nativeConfig.apiKey;
|
|
148
|
-
}
|
|
149
|
-
// Auto-populate device token with FCM token
|
|
150
|
-
const fcmToken = bridge.getFcmToken();
|
|
151
|
-
if (fcmToken) {
|
|
152
|
-
deviceToken = fcmToken;
|
|
153
|
-
}
|
|
154
|
-
} catch {
|
|
155
|
-
// Bridge communication failed
|
|
156
|
-
}
|
|
182
|
+
// Hydrate from native bridge BEFORE applying the browser default.
|
|
183
|
+
// This lets native-provided serverUrl take precedence over
|
|
184
|
+
// window.location.origin.
|
|
185
|
+
hydrateBridge();
|
|
186
|
+
if (!serverUrl) {
|
|
187
|
+
serverUrl = getDefaultServerUrl();
|
|
157
188
|
}
|
|
158
|
-
|
|
159
|
-
canScan = hasScanner();
|
|
160
|
-
bridgeCheckDone = true;
|
|
189
|
+
_bridgeCheckDone = true;
|
|
161
190
|
|
|
162
191
|
// The native bridge may be injected after SvelteKit hydration.
|
|
163
192
|
// Re-check periodically for a short window to catch late injection.
|
|
164
193
|
if (!canScan) {
|
|
165
194
|
const recheckInterval = setInterval(() => {
|
|
166
|
-
|
|
195
|
+
hydrateBridge();
|
|
167
196
|
if (canScan) {
|
|
168
197
|
clearInterval(recheckInterval);
|
|
169
198
|
}
|
|
170
199
|
}, 200);
|
|
171
200
|
// Stop checking after 3 seconds
|
|
172
|
-
setTimeout(() =>
|
|
201
|
+
setTimeout(() => {
|
|
202
|
+
clearInterval(recheckInterval);
|
|
203
|
+
}, 3000);
|
|
173
204
|
}
|
|
174
205
|
}
|
|
175
206
|
});
|
|
@@ -193,10 +224,10 @@
|
|
|
193
224
|
|
|
194
225
|
const bridge = getNativeBridge();
|
|
195
226
|
if (bridge) {
|
|
196
|
-
bridge.saveConfig(
|
|
227
|
+
bridge.saveConfig?.(
|
|
197
228
|
JSON.stringify({
|
|
198
|
-
serverUrl: trimmedUrl || getDefaultServerUrl(),
|
|
199
229
|
apiKey: apiKey.trim(),
|
|
230
|
+
serverUrl: trimmedUrl || getDefaultServerUrl(),
|
|
200
231
|
})
|
|
201
232
|
);
|
|
202
233
|
}
|
|
@@ -211,8 +242,7 @@
|
|
|
211
242
|
statusType = 'warning';
|
|
212
243
|
}
|
|
213
244
|
} catch (error) {
|
|
214
|
-
|
|
215
|
-
result = `Configuration failed: ${err.message}`;
|
|
245
|
+
result = `Configuration failed: ${toErrorMessage(error)}`;
|
|
216
246
|
statusType = 'error';
|
|
217
247
|
}
|
|
218
248
|
|
|
@@ -265,8 +295,7 @@
|
|
|
265
295
|
statusType = 'error';
|
|
266
296
|
}
|
|
267
297
|
} catch (error) {
|
|
268
|
-
|
|
269
|
-
result = `Network error: ${err.message}`;
|
|
298
|
+
result = `Network error: ${toErrorMessage(error)}`;
|
|
270
299
|
statusType = 'error';
|
|
271
300
|
}
|
|
272
301
|
|
|
@@ -284,7 +313,7 @@
|
|
|
284
313
|
|
|
285
314
|
const bridge = getNativeBridge();
|
|
286
315
|
if (bridge) {
|
|
287
|
-
bridge.saveConfig(JSON.stringify({
|
|
316
|
+
bridge.saveConfig?.(JSON.stringify({ apiKey: '', serverUrl: '' }));
|
|
288
317
|
}
|
|
289
318
|
}
|
|
290
319
|
}
|
|
@@ -297,6 +326,9 @@
|
|
|
297
326
|
|
|
298
327
|
<main class="main">
|
|
299
328
|
<div class="settings-container">
|
|
329
|
+
<div style="margin-bottom: var(--space-4);">
|
|
330
|
+
<a href="/" class="back-link">← Back to Projects</a>
|
|
331
|
+
</div>
|
|
300
332
|
<div class="page-header">
|
|
301
333
|
<h1 class="page-title">Settings</h1>
|
|
302
334
|
<p class="page-description">Configure your API credentials and notification preferences</p>
|
|
@@ -304,7 +336,10 @@
|
|
|
304
336
|
|
|
305
337
|
<div class="settings-grid">
|
|
306
338
|
<section class="settings-section">
|
|
307
|
-
<Card
|
|
339
|
+
<Card
|
|
340
|
+
title="Server Configuration"
|
|
341
|
+
description="Configure server connection and credentials"
|
|
342
|
+
>
|
|
308
343
|
<Input
|
|
309
344
|
name="serverUrl"
|
|
310
345
|
label="Server URL"
|
|
@@ -322,6 +357,9 @@
|
|
|
322
357
|
placeholder="Enter your API key"
|
|
323
358
|
infoMessage="Required for sending notifications"
|
|
324
359
|
/>
|
|
360
|
+
<p class="input-help">
|
|
361
|
+
Find this in your <code>~/.shooter/.env</code> file. Run <code>shooter setup</code> to generate one.
|
|
362
|
+
</p>
|
|
325
363
|
|
|
326
364
|
<Input
|
|
327
365
|
name="deviceToken"
|
|
@@ -329,13 +367,21 @@
|
|
|
329
367
|
bind:value={deviceToken}
|
|
330
368
|
dataType="text"
|
|
331
369
|
placeholder={isNativeApp ? 'Waiting for token...' : '64-character hex string'}
|
|
332
|
-
infoMessage={isNativeApp && deviceToken
|
|
370
|
+
infoMessage={isNativeApp && deviceToken
|
|
371
|
+
? 'Auto-detected from app'
|
|
372
|
+
: 'Device token from app registration'}
|
|
333
373
|
classes="input-mono"
|
|
334
374
|
/>
|
|
375
|
+
<p class="input-help">Optional — only needed for iOS/Android push notifications.</p>
|
|
335
376
|
</Card>
|
|
336
377
|
|
|
337
378
|
{#if result}
|
|
338
|
-
{@const bannerIcon =
|
|
379
|
+
{@const bannerIcon =
|
|
380
|
+
statusType === 'success'
|
|
381
|
+
? 'check-circle'
|
|
382
|
+
: statusType === 'error'
|
|
383
|
+
? 'x-circle'
|
|
384
|
+
: 'alert-triangle'}
|
|
339
385
|
<Banner text={result} classes="banner-{statusType || 'info'}">
|
|
340
386
|
{#snippet icon()}
|
|
341
387
|
<Icon name={bannerIcon} size={16} />
|
|
@@ -349,12 +395,10 @@
|
|
|
349
395
|
onclick={testConfiguration}
|
|
350
396
|
disabled={loading || !apiKey.trim()}
|
|
351
397
|
>
|
|
352
|
-
{#
|
|
353
|
-
{
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
Test Connection
|
|
357
|
-
{/snippet}
|
|
398
|
+
{#if !loading}
|
|
399
|
+
<Icon name="play" size={14} />
|
|
400
|
+
{/if}
|
|
401
|
+
Test Connection
|
|
358
402
|
</Button>
|
|
359
403
|
<Button
|
|
360
404
|
classes="btn-primary"
|
|
@@ -379,14 +423,20 @@
|
|
|
379
423
|
/>
|
|
380
424
|
</Card>
|
|
381
425
|
|
|
382
|
-
<Card
|
|
426
|
+
<Card
|
|
427
|
+
title="Mobile App Setup"
|
|
428
|
+
description={canScan ? 'Scan a QR code to connect' : 'Scan to connect your mobile app'}
|
|
429
|
+
>
|
|
383
430
|
<div class="qr-section">
|
|
384
431
|
{#if canScan}
|
|
385
432
|
<p class="qr-description">
|
|
386
|
-
Scan the QR code shown on your server's settings page to auto-configure
|
|
387
|
-
|
|
433
|
+
Scan the QR code shown on your server's settings page to auto-configure the
|
|
434
|
+
connection.
|
|
388
435
|
</p>
|
|
389
|
-
<Button
|
|
436
|
+
<Button
|
|
437
|
+
classes="btn-secondary btn-sm"
|
|
438
|
+
onclick={handleScanQR}
|
|
439
|
+
disabled={scanLoading}
|
|
390
440
|
text={scanLoading ? 'Scanning...' : 'Scan QR Code'}
|
|
391
441
|
/>
|
|
392
442
|
{:else}
|
|
@@ -410,11 +460,14 @@
|
|
|
410
460
|
<p class="qr-error">{qrError}</p>
|
|
411
461
|
{:else}
|
|
412
462
|
<p class="qr-description">
|
|
413
|
-
Generate a QR code containing your server URL and API key. Your mobile app can
|
|
414
|
-
it to auto-configure the connection.
|
|
463
|
+
Generate a QR code containing your server URL and API key. Your mobile app can
|
|
464
|
+
scan it to auto-configure the connection.
|
|
415
465
|
</p>
|
|
416
466
|
{/if}
|
|
417
|
-
<Button
|
|
467
|
+
<Button
|
|
468
|
+
classes="btn-secondary btn-sm"
|
|
469
|
+
onclick={fetchQrCode}
|
|
470
|
+
disabled={qrLoading || !apiKey.trim()}
|
|
418
471
|
text={qrDataUrl ? 'Regenerate QR Code' : 'Generate QR Code'}
|
|
419
472
|
/>
|
|
420
473
|
{/if}
|
|
@@ -423,7 +476,9 @@
|
|
|
423
476
|
|
|
424
477
|
<Card title="Danger Zone">
|
|
425
478
|
<p class="danger-description">Clear all saved configuration data from this device.</p>
|
|
426
|
-
<Button
|
|
479
|
+
<Button
|
|
480
|
+
classes="btn-danger btn-sm"
|
|
481
|
+
onclick={clearConfiguration}
|
|
427
482
|
text="Clear Configuration"
|
|
428
483
|
/>
|
|
429
484
|
</Card>
|
|
@@ -436,7 +491,7 @@
|
|
|
436
491
|
.settings-container {
|
|
437
492
|
max-width: 900px;
|
|
438
493
|
margin: 0 auto;
|
|
439
|
-
padding-bottom:
|
|
494
|
+
padding-bottom: var(--space-6);
|
|
440
495
|
}
|
|
441
496
|
|
|
442
497
|
.page-header {
|
|
@@ -491,11 +546,12 @@
|
|
|
491
546
|
--step-text-margin: 0 0 0 var(--space-3);
|
|
492
547
|
--separator-display: none;
|
|
493
548
|
--step-text-active-color: var(--text-primary);
|
|
494
|
-
--step-text-completed-color: var(--ds-green-
|
|
549
|
+
--step-text-completed-color: var(--ds-green-900);
|
|
495
550
|
--step-index-container-active-background-color: var(--component-bg-active);
|
|
496
551
|
--step-index-container-completed-background-color: var(--ds-green-700);
|
|
497
552
|
--step-index-container-background-color: var(--component-bg-active);
|
|
498
553
|
--step-index-color: var(--text-secondary);
|
|
554
|
+
align-items: flex-start;
|
|
499
555
|
gap: var(--space-3);
|
|
500
556
|
}
|
|
501
557
|
|
|
@@ -505,6 +561,10 @@
|
|
|
505
561
|
gap: var(--space-3);
|
|
506
562
|
}
|
|
507
563
|
|
|
564
|
+
.qr-section :global(.button-container) {
|
|
565
|
+
align-self: center;
|
|
566
|
+
}
|
|
567
|
+
|
|
508
568
|
.qr-container {
|
|
509
569
|
display: flex;
|
|
510
570
|
justify-content: center;
|
|
@@ -583,6 +643,20 @@
|
|
|
583
643
|
border-left: 3px solid rgba(217, 48, 54, 0.5);
|
|
584
644
|
}
|
|
585
645
|
|
|
646
|
+
.input-help {
|
|
647
|
+
font-size: var(--text-xs);
|
|
648
|
+
color: var(--color-text-tertiary, #888);
|
|
649
|
+
margin-top: var(--space-1);
|
|
650
|
+
margin-bottom: 0;
|
|
651
|
+
}
|
|
652
|
+
.input-help code {
|
|
653
|
+
background: var(--ds-gray-200, #1a1a1a);
|
|
654
|
+
padding: 1px 4px;
|
|
655
|
+
border-radius: var(--radius-sm);
|
|
656
|
+
font-family: var(--font-mono);
|
|
657
|
+
font-size: var(--text-xs);
|
|
658
|
+
}
|
|
659
|
+
|
|
586
660
|
@media (max-width: 768px) {
|
|
587
661
|
.settings-grid {
|
|
588
662
|
grid-template-columns: 1fr;
|