@ignix-social/editor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/NOTICE +54 -0
- package/README.md +23 -0
- package/bin/ignix-editor.mjs +8 -0
- package/package.json +53 -0
- package/patches/index.mjs +53 -0
- package/scripts/build-ffmpeg-macos.sh +35 -0
- package/scripts/build-whisper-macos.sh +21 -0
- package/scripts/vendor.mjs +41 -0
- package/skills/ignix-editor/SKILL.md +132 -0
- package/src/audio.mjs +31 -0
- package/src/binaries.json +46 -0
- package/src/binaries.mjs +83 -0
- package/src/cli.mjs +254 -0
- package/src/prepare.mjs +74 -0
- package/src/runtime/ignix-frame.js +92 -0
- package/src/transcribe.mjs +71 -0
- package/src/validate.mjs +71 -0
- package/templates/blank/index.html +41 -0
- package/vendor/hyperframes/README.md +181 -0
- package/vendor/hyperframes/UPSTREAM.json +12 -0
- package/vendor/hyperframes/bin/hyperframes-localize-fonts.mjs +12 -0
- package/vendor/hyperframes/bin/hyperframes.mjs +11 -0
- package/vendor/hyperframes/dist/add-LR3ZR2A5.js +79 -0
- package/vendor/hyperframes/dist/agentPromptGenerator-VIIPZCJ3.js +143 -0
- package/vendor/hyperframes/dist/animatedGifPrep-P2T6YM7Z.js +34 -0
- package/vendor/hyperframes/dist/asset-BE2DOV72.js +26 -0
- package/vendor/hyperframes/dist/assetCataloger-VBLPHX24.js +340 -0
- package/vendor/hyperframes/dist/auth-RCQB2ZT7.js +60 -0
- package/vendor/hyperframes/dist/autoUpdate-RJAX3DAZ.js +268 -0
- package/vendor/hyperframes/dist/backgroundChecks-H2LCUIMJ.js +61 -0
- package/vendor/hyperframes/dist/backgroundChecksWorker.js +26 -0
- package/vendor/hyperframes/dist/batchRender-FT7AP7XH.js +355 -0
- package/vendor/hyperframes/dist/beat-analyzer.global.js +338 -0
- package/vendor/hyperframes/dist/beats-Y2EOP72P.js +309 -0
- package/vendor/hyperframes/dist/benchmark-MZ7GY3JW.js +231 -0
- package/vendor/hyperframes/dist/browser-HUTAMRQE.js +237 -0
- package/vendor/hyperframes/dist/bundleWithLocalizedFonts-5QOPOB5D.js +52 -0
- package/vendor/hyperframes/dist/capture-RLZA6EMR.js +4079 -0
- package/vendor/hyperframes/dist/capture-SZZ4IYJK.js +290 -0
- package/vendor/hyperframes/dist/captureFile-LYOJOUIE.js +15 -0
- package/vendor/hyperframes/dist/captureTimeout-PA4FYWT5.js +27 -0
- package/vendor/hyperframes/dist/catalog-KYU55EWR.js +1001 -0
- package/vendor/hyperframes/dist/check-TCG4PXLR.js +1697 -0
- package/vendor/hyperframes/dist/checkBrowser-RPMO4OW5.js +1032 -0
- package/vendor/hyperframes/dist/chunk-2EAXUCCE.js +88 -0
- package/vendor/hyperframes/dist/chunk-2EGFTPWD.js +1077 -0
- package/vendor/hyperframes/dist/chunk-2PSPARWP.js +6058 -0
- package/vendor/hyperframes/dist/chunk-2YN64IN5.js +5747 -0
- package/vendor/hyperframes/dist/chunk-3GXQPCJC.js +682 -0
- package/vendor/hyperframes/dist/chunk-3ZP5DXE7.js +15 -0
- package/vendor/hyperframes/dist/chunk-4NWOGZZS.js +1990 -0
- package/vendor/hyperframes/dist/chunk-4PFZPP2N.js +587 -0
- package/vendor/hyperframes/dist/chunk-4THIAPBL.js +128 -0
- package/vendor/hyperframes/dist/chunk-4YYJOFKS.js +28 -0
- package/vendor/hyperframes/dist/chunk-54HJ63Q2.js +29 -0
- package/vendor/hyperframes/dist/chunk-5ETJX6WM.js +89 -0
- package/vendor/hyperframes/dist/chunk-5IAKAQA7.js +389 -0
- package/vendor/hyperframes/dist/chunk-5Z63TBTX.js +37 -0
- package/vendor/hyperframes/dist/chunk-6BEFEWFB.js +25 -0
- package/vendor/hyperframes/dist/chunk-6CSYCFQV.js +68 -0
- package/vendor/hyperframes/dist/chunk-6CTIGJY7.js +154 -0
- package/vendor/hyperframes/dist/chunk-7HG4BFIN.js +93 -0
- package/vendor/hyperframes/dist/chunk-7JZ4FXP2.js +118 -0
- package/vendor/hyperframes/dist/chunk-A2Z4Z4VL.js +2961 -0
- package/vendor/hyperframes/dist/chunk-AMKC3AXA.js +25 -0
- package/vendor/hyperframes/dist/chunk-AVUUN2XD.js +4847 -0
- package/vendor/hyperframes/dist/chunk-AWDFDFI3.js +46 -0
- package/vendor/hyperframes/dist/chunk-AWNBM3MZ.js +94 -0
- package/vendor/hyperframes/dist/chunk-BXCMXMJQ.js +73 -0
- package/vendor/hyperframes/dist/chunk-BZ56MTDX.js +6 -0
- package/vendor/hyperframes/dist/chunk-CFKU7HTK.js +171 -0
- package/vendor/hyperframes/dist/chunk-CWPVM2QV.js +308 -0
- package/vendor/hyperframes/dist/chunk-DPVXBVLL.js +31292 -0
- package/vendor/hyperframes/dist/chunk-DQBY7FRR.js +397 -0
- package/vendor/hyperframes/dist/chunk-E6RPWJVC.js +213 -0
- package/vendor/hyperframes/dist/chunk-EISRN4E6.js +294 -0
- package/vendor/hyperframes/dist/chunk-EOVYQ3IG.js +143 -0
- package/vendor/hyperframes/dist/chunk-F3WZGU7C.js +479 -0
- package/vendor/hyperframes/dist/chunk-FCSIGXXP.js +366 -0
- package/vendor/hyperframes/dist/chunk-FI4I7CME.js +56 -0
- package/vendor/hyperframes/dist/chunk-FLWXXDNS.js +15 -0
- package/vendor/hyperframes/dist/chunk-GK4AIFIH.js +11171 -0
- package/vendor/hyperframes/dist/chunk-GMECXFAN.js +57 -0
- package/vendor/hyperframes/dist/chunk-GULOKZLI.js +155 -0
- package/vendor/hyperframes/dist/chunk-H4YZZ2VQ.js +68 -0
- package/vendor/hyperframes/dist/chunk-H6QMKUYA.js +477 -0
- package/vendor/hyperframes/dist/chunk-HBBJFK6I.js +273 -0
- package/vendor/hyperframes/dist/chunk-HRUGC23L.js +212 -0
- package/vendor/hyperframes/dist/chunk-HVW7ABXD.js +19 -0
- package/vendor/hyperframes/dist/chunk-HW6OYASV.js +344 -0
- package/vendor/hyperframes/dist/chunk-HWKCIWQT.js +3578 -0
- package/vendor/hyperframes/dist/chunk-I465DBM6.js +1214 -0
- package/vendor/hyperframes/dist/chunk-IGLEPPTN.js +24 -0
- package/vendor/hyperframes/dist/chunk-IGNAAHS3.js +433 -0
- package/vendor/hyperframes/dist/chunk-IHFUKJOR.js +85 -0
- package/vendor/hyperframes/dist/chunk-IQ3OUQ5Z.js +213 -0
- package/vendor/hyperframes/dist/chunk-ISN5GRYI.js +20 -0
- package/vendor/hyperframes/dist/chunk-IUZFXWSV.js +446 -0
- package/vendor/hyperframes/dist/chunk-JH556Q42.js +647 -0
- package/vendor/hyperframes/dist/chunk-JTHMTOMQ.js +601 -0
- package/vendor/hyperframes/dist/chunk-K2EQN4VU.js +405 -0
- package/vendor/hyperframes/dist/chunk-K2FTXJYH.js +16044 -0
- package/vendor/hyperframes/dist/chunk-K4WIOZFP.js +32 -0
- package/vendor/hyperframes/dist/chunk-K4WKGXRC.js +18 -0
- package/vendor/hyperframes/dist/chunk-KBJUXVOJ.js +172 -0
- package/vendor/hyperframes/dist/chunk-KC5XXX3X.js +590 -0
- package/vendor/hyperframes/dist/chunk-KNU5COPB.js +29 -0
- package/vendor/hyperframes/dist/chunk-KZI44OPA.js +185 -0
- package/vendor/hyperframes/dist/chunk-L3YOGIPG.js +48 -0
- package/vendor/hyperframes/dist/chunk-LAOCA3MQ.js +189 -0
- package/vendor/hyperframes/dist/chunk-LCSMOLGX.js +312 -0
- package/vendor/hyperframes/dist/chunk-LFGJWOVA.js +61 -0
- package/vendor/hyperframes/dist/chunk-LHSR3M4M.js +498 -0
- package/vendor/hyperframes/dist/chunk-LYNI3FOL.js +123 -0
- package/vendor/hyperframes/dist/chunk-M2WBOQ2Q.js +54 -0
- package/vendor/hyperframes/dist/chunk-MRF4AMKD.js +104 -0
- package/vendor/hyperframes/dist/chunk-MWB3ZIFM.js +852 -0
- package/vendor/hyperframes/dist/chunk-NGKM64BP.js +39 -0
- package/vendor/hyperframes/dist/chunk-NXMYHJAL.js +43 -0
- package/vendor/hyperframes/dist/chunk-OAF4XJOW.js +192 -0
- package/vendor/hyperframes/dist/chunk-OFQWTKPW.js +117 -0
- package/vendor/hyperframes/dist/chunk-P6LJ4Y32.js +4662 -0
- package/vendor/hyperframes/dist/chunk-PBN6GBJE.js +108 -0
- package/vendor/hyperframes/dist/chunk-PDAMK4Q5.js +28 -0
- package/vendor/hyperframes/dist/chunk-PFCFR3KZ.js +20 -0
- package/vendor/hyperframes/dist/chunk-PJ3HDUCY.js +108 -0
- package/vendor/hyperframes/dist/chunk-PMRBLBUP.js +152 -0
- package/vendor/hyperframes/dist/chunk-PPQUYWTW.js +240 -0
- package/vendor/hyperframes/dist/chunk-Q5X2B5WT.js +29 -0
- package/vendor/hyperframes/dist/chunk-Q7IU7MOR.js +351 -0
- package/vendor/hyperframes/dist/chunk-QC4FJVLM.js +371 -0
- package/vendor/hyperframes/dist/chunk-QNYYOUU3.js +1318 -0
- package/vendor/hyperframes/dist/chunk-RDNNAKEP.js +161 -0
- package/vendor/hyperframes/dist/chunk-RMHUQGRK.js +657 -0
- package/vendor/hyperframes/dist/chunk-RQVDTPGD.js +6 -0
- package/vendor/hyperframes/dist/chunk-RVCWIIZ7.js +68 -0
- package/vendor/hyperframes/dist/chunk-S3D6GE5W.js +72 -0
- package/vendor/hyperframes/dist/chunk-S3S4TGEH.js +424 -0
- package/vendor/hyperframes/dist/chunk-S7NPLFWV.js +11395 -0
- package/vendor/hyperframes/dist/chunk-SHB5VDMH.js +51 -0
- package/vendor/hyperframes/dist/chunk-TCLGPL65.js +860 -0
- package/vendor/hyperframes/dist/chunk-THXFSPLV.js +40 -0
- package/vendor/hyperframes/dist/chunk-TJSTGSAW.js +354 -0
- package/vendor/hyperframes/dist/chunk-TQFG7HTI.js +1024 -0
- package/vendor/hyperframes/dist/chunk-TVCRUG2S.js +265 -0
- package/vendor/hyperframes/dist/chunk-TWWSYAKJ.js +24 -0
- package/vendor/hyperframes/dist/chunk-U7CZBDMV.js +27 -0
- package/vendor/hyperframes/dist/chunk-UEZXMWG3.js +139 -0
- package/vendor/hyperframes/dist/chunk-UYEZTK4U.js +61 -0
- package/vendor/hyperframes/dist/chunk-VC76R6W2.js +27 -0
- package/vendor/hyperframes/dist/chunk-VFCKXTBB.js +159 -0
- package/vendor/hyperframes/dist/chunk-VWG7OQKU.js +22 -0
- package/vendor/hyperframes/dist/chunk-VXVRPIJA.js +105 -0
- package/vendor/hyperframes/dist/chunk-WBLXWOYK.js +15 -0
- package/vendor/hyperframes/dist/chunk-WERLJGIC.js +20 -0
- package/vendor/hyperframes/dist/chunk-WMQNIQDJ.js +2057 -0
- package/vendor/hyperframes/dist/chunk-WPHMNO44.js +4528 -0
- package/vendor/hyperframes/dist/chunk-X5HWXQPU.js +113 -0
- package/vendor/hyperframes/dist/chunk-X7MTZ4T2.js +6 -0
- package/vendor/hyperframes/dist/chunk-XH4DSOS5.js +59 -0
- package/vendor/hyperframes/dist/chunk-XS4EJSKU.js +23 -0
- package/vendor/hyperframes/dist/chunk-XT5P4QMO.js +181 -0
- package/vendor/hyperframes/dist/chunk-XT7X6QCP.js +6 -0
- package/vendor/hyperframes/dist/chunk-XUHOIDKG.js +6 -0
- package/vendor/hyperframes/dist/chunk-XUXGIA7H.js +485 -0
- package/vendor/hyperframes/dist/chunk-XZABUQTX.js +113 -0
- package/vendor/hyperframes/dist/chunk-Y6W4DVPS.js +356 -0
- package/vendor/hyperframes/dist/chunk-YEIFI443.js +44 -0
- package/vendor/hyperframes/dist/chunk-YQZNILVH.js +375 -0
- package/vendor/hyperframes/dist/chunk-Z27A7NUB.js +65 -0
- package/vendor/hyperframes/dist/chunk-Z6B37SNM.js +3081 -0
- package/vendor/hyperframes/dist/chunk-ZJUKFZ2P.js +10954 -0
- package/vendor/hyperframes/dist/chunk-ZKDMAOFU.js +32 -0
- package/vendor/hyperframes/dist/chunk-ZMXUQLI2.js +17219 -0
- package/vendor/hyperframes/dist/chunk-ZTZ7NCJT.js +58 -0
- package/vendor/hyperframes/dist/chunk-ZTZA4UWZ.js +108 -0
- package/vendor/hyperframes/dist/clean-W57E5YQ3.js +293 -0
- package/vendor/hyperframes/dist/cli.js +495 -0
- package/vendor/hyperframes/dist/cloud-FFTJGZ24.js +70 -0
- package/vendor/hyperframes/dist/cloudrun-AJUTHUEA.js +763 -0
- package/vendor/hyperframes/dist/colors-HKWSZCGK.js +15 -0
- package/vendor/hyperframes/dist/commands/contrast-audit.browser.js +459 -0
- package/vendor/hyperframes/dist/commands/layout-audit.browser.js +2102 -0
- package/vendor/hyperframes/dist/commands/motion-sample.browser.js +74 -0
- package/vendor/hyperframes/dist/commands/motion-signature.browser.js +374 -0
- package/vendor/hyperframes/dist/compare-AYCTT55F.js +421 -0
- package/vendor/hyperframes/dist/compiler-QO36EXLS.js +121 -0
- package/vendor/hyperframes/dist/component-VFFR2O7T.js +176 -0
- package/vendor/hyperframes/dist/compositions-QTVN3U2A.js +228 -0
- package/vendor/hyperframes/dist/contactSheet-27SRU7A4.js +22 -0
- package/vendor/hyperframes/dist/delete-ZAKYCB7I.js +114 -0
- package/vendor/hyperframes/dist/deploy-MX76RZ36.js +101 -0
- package/vendor/hyperframes/dist/destroy-H2TZBYHH.js +42 -0
- package/vendor/hyperframes/dist/deterministicFonts-HAEMV4TM.js +50 -0
- package/vendor/hyperframes/dist/dist-EWXJGN63.js +129 -0
- package/vendor/hyperframes/dist/dist-FNNGCKFS.js +29 -0
- package/vendor/hyperframes/dist/dist-S3PJNPXQ.js +392 -0
- package/vendor/hyperframes/dist/docker/Dockerfile.render +65 -0
- package/vendor/hyperframes/dist/docs/compositions.md +67 -0
- package/vendor/hyperframes/dist/docs/data-attributes.md +27 -0
- package/vendor/hyperframes/dist/docs/examples.md +19 -0
- package/vendor/hyperframes/dist/docs/gsap.md +26 -0
- package/vendor/hyperframes/dist/docs/rendering.md +35 -0
- package/vendor/hyperframes/dist/docs/troubleshooting.md +29 -0
- package/vendor/hyperframes/dist/docs-QAPJEGLS.js +131 -0
- package/vendor/hyperframes/dist/doctor-AI7C3FON.js +67 -0
- package/vendor/hyperframes/dist/dom-IROKGVJI.js +14 -0
- package/vendor/hyperframes/dist/dotEnv-AECLXQSO.js +14 -0
- package/vendor/hyperframes/dist/events-7LALYNKZ.js +92 -0
- package/vendor/hyperframes/dist/events-FQY3HGKZ.js +88 -0
- package/vendor/hyperframes/dist/feedback-WCMDMSTK.js +472 -0
- package/vendor/hyperframes/dist/ffmpeg-QIUFEFTY.js +35 -0
- package/vendor/hyperframes/dist/figma-64WY462P.js +63 -0
- package/vendor/hyperframes/dist/fontData.generated-NXAOI4GH.js +13 -0
- package/vendor/hyperframes/dist/fontLocalizeCli.js +132 -0
- package/vendor/hyperframes/dist/get-FPOMJMZB.js +103 -0
- package/vendor/hyperframes/dist/gpuPolicy-2ZUZE5D6.js +38 -0
- package/vendor/hyperframes/dist/grade-compare-E2CKPST4.js +647 -0
- package/vendor/hyperframes/dist/gsapParser-DIYYX6JT.js +2846 -0
- package/vendor/hyperframes/dist/gsapParserAcorn-E3GEIRZB.js +28 -0
- package/vendor/hyperframes/dist/help-YRQIDDML.js +197 -0
- package/vendor/hyperframes/dist/history-PP5NDRV3.js +571 -0
- package/vendor/hyperframes/dist/hyperframe-runtime.js +1081 -0
- package/vendor/hyperframes/dist/hyperframe.manifest.json +22 -0
- package/vendor/hyperframes/dist/hyperframe.runtime.iife.js +1081 -0
- package/vendor/hyperframes/dist/hyperframes-player.global.js +474 -0
- package/vendor/hyperframes/dist/hyperframes-slideshow.global.js +149 -0
- package/vendor/hyperframes/dist/info-SEX3B7JL.js +153 -0
- package/vendor/hyperframes/dist/init-U3AKHO5B.js +1147 -0
- package/vendor/hyperframes/dist/inspect-Q3K6EDEK.js +97 -0
- package/vendor/hyperframes/dist/installer-K6O5WF44.js +37 -0
- package/vendor/hyperframes/dist/keyframes-DC64JCI3.js +2602 -0
- package/vendor/hyperframes/dist/lambda-D7UMN4DJ.js +451 -0
- package/vendor/hyperframes/dist/layout-XSPPDHOO.js +86 -0
- package/vendor/hyperframes/dist/lib-TPG2ZMAX.js +128 -0
- package/vendor/hyperframes/dist/lint-7DQZE7L3.js +164 -0
- package/vendor/hyperframes/dist/lintProject-OHBBM3DJ.js +27 -0
- package/vendor/hyperframes/dist/list-4K5MVDQX.js +162 -0
- package/vendor/hyperframes/dist/login-NTX4OWXL.js +377 -0
- package/vendor/hyperframes/dist/logout-Q654A3SI.js +100 -0
- package/vendor/hyperframes/dist/manager-67P2XFXQ.js +34 -0
- package/vendor/hyperframes/dist/manager-CT3D67CG.js +38 -0
- package/vendor/hyperframes/dist/manager-GFN75DM4.js +30 -0
- package/vendor/hyperframes/dist/media-treatment-5FYAOPNL.js +972 -0
- package/vendor/hyperframes/dist/media-use-4XXGABIL.js +113 -0
- package/vendor/hyperframes/dist/models-C4E4IWJD.js +137 -0
- package/vendor/hyperframes/dist/motionShot-S4MIGMT5.js +614 -0
- package/vendor/hyperframes/dist/normalize-O76AC4HE.js +333 -0
- package/vendor/hyperframes/dist/normalize-audio-CSFTXLXD.js +276 -0
- package/vendor/hyperframes/dist/open-2ZD6BHZG.js +115 -0
- package/vendor/hyperframes/dist/pipeline-TNGWUZQC.js +54 -0
- package/vendor/hyperframes/dist/play-CTMUXX6E.js +349 -0
- package/vendor/hyperframes/dist/policies-FSDZVS2E.js +292 -0
- package/vendor/hyperframes/dist/preflight-SMNV6RW2.js +45 -0
- package/vendor/hyperframes/dist/present-WQVHV5CR.js +350 -0
- package/vendor/hyperframes/dist/preview-JOJXTH75.js +1820 -0
- package/vendor/hyperframes/dist/producer-ECLEN5RP.js +13 -0
- package/vendor/hyperframes/dist/progress-FBIEEB7Y.js +73 -0
- package/vendor/hyperframes/dist/projectConfig-HYJMJ5BY.js +56 -0
- package/vendor/hyperframes/dist/publication-HQ5Y3KBM.js +29 -0
- package/vendor/hyperframes/dist/publish-VHDYQASC.js +430 -0
- package/vendor/hyperframes/dist/refresh-K24ETHMA.js +53 -0
- package/vendor/hyperframes/dist/remove-background-W2YX2NVH.js +253 -0
- package/vendor/hyperframes/dist/render-AO5VX3YI.js +177 -0
- package/vendor/hyperframes/dist/render-LNO62LEL.js +2367 -0
- package/vendor/hyperframes/dist/render-TTQI7TGN.js +796 -0
- package/vendor/hyperframes/dist/render-batch-YH7CTWNY.js +284 -0
- package/vendor/hyperframes/dist/renderCancellation-JPIHE47X.js +35 -0
- package/vendor/hyperframes/dist/renderSetupWorker.js +79 -0
- package/vendor/hyperframes/dist/resolver-IZ647GBZ.js +38 -0
- package/vendor/hyperframes/dist/runtimeVersion.js +18 -0
- package/vendor/hyperframes/dist/screenshotCapture-ECBTLCU6.js +179 -0
- package/vendor/hyperframes/dist/shaderTransitionWorker.js +44 -0
- package/vendor/hyperframes/dist/sherpa-KKLNW6U2.js +314 -0
- package/vendor/hyperframes/dist/sherpaWorker.js +77 -0
- package/vendor/hyperframes/dist/sites-TNVKZS73.js +52 -0
- package/vendor/hyperframes/dist/skill-ZHVLH7KX.js +15 -0
- package/vendor/hyperframes/dist/skills/hyperframes/SKILL.md +152 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/brief-contract.md +108 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/brief-format.md +72 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/capability-menu.md +47 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/frame-worker-core.md +80 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/intent-interview.md +73 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/pitch-round.md +40 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/plugin-installation.md +43 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/production-loop.md +26 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/review-loop.md +37 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/route-briefs.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/embedded-captions.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/faceless-explainer.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/general-video.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/motion-graphics.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/music-to-video.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/pr-to-video.md +28 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/product-launch-video.md +13 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/remotion-to-hyperframes.md +9 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/slideshow.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/talking-head-recut.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/script-format.md +52 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/skill-lifecycle.md +35 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/storyboard-format.md +99 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/subagent-dispatch.md +35 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/workflow-catalog.md +10 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +194 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/plugin-cli.mjs +88 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/plugin-cli.test.mjs +117 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/SKILL.md +189 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/beats.md +19 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/cloud.md +163 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/cloudrun.md +62 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/compare-and-batch.md +105 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/doctor-browser.md +57 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/init-and-scaffold.md +74 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/lambda.md +185 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +132 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/preview-render.md +193 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/upgrade-info-misc.md +134 -0
- package/vendor/hyperframes/dist/skills/media-use/SKILL.md +100 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/CREDITS.md +35 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/chime.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/click-soft.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/click.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/error.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-1.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-2.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-3.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/impact-bass-1.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/impact-bass-2.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/key-press.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/manifest.json +97 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/notification.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/ping.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/pop.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/riser.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/sparkle.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/typing.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh-cinematic.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh-short.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/bgm.md +76 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/authoring.md +163 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/motion.md +87 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/transcript-handling.md +97 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/remove-background.md +143 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/requirements.md +29 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/sfx.md +42 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/transcribe.md +52 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/tts-to-captions.md +35 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/tts.md +260 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/audio.mjs +311 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/audio.test.mjs +159 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/gemini-pipeline.test.mjs +131 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-tts.mjs +122 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-tts.test.mjs +38 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-voice.mjs +98 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-voice.test.mjs +233 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/audio-meta.mjs +39 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/audio-meta.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm.mjs +257 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm.test.mjs +74 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/concurrency.mjs +14 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/concurrency.test.mjs +41 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.mjs +43 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.py +52 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.test.mjs +86 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth_test.py +90 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-tts.mjs +122 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-tts.test.mjs +243 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/heygen.mjs +197 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/heygen.test.mjs +185 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/media-record.mjs +114 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/media-record.test.mjs +205 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/python.mjs +77 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/python.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/sfx.mjs +165 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/sfx.test.mjs +121 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.mjs +389 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.spawn.test.mjs +158 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.test.mjs +230 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lyria-recipe.py +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/wait-bgm.mjs +175 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/wait-bgm.test.mjs +108 -0
- package/vendor/hyperframes/dist/skills/media-use/luts/README.md +28 -0
- package/vendor/hyperframes/dist/skills/media-use/luts/index.json +57 -0
- package/vendor/hyperframes/dist/skills/media-use/references/audio.md +20 -0
- package/vendor/hyperframes/dist/skills/media-use/references/grading.md +160 -0
- package/vendor/hyperframes/dist/skills/media-use/references/media-treatment-recipes.md +929 -0
- package/vendor/hyperframes/dist/skills/media-use/references/media-treatments.md +202 -0
- package/vendor/hyperframes/dist/skills/media-use/references/memory.md +37 -0
- package/vendor/hyperframes/dist/skills/media-use/references/meta.md +61 -0
- package/vendor/hyperframes/dist/skills/media-use/references/operations.md +327 -0
- package/vendor/hyperframes/dist/skills/media-use/references/resolve.md +150 -0
- package/vendor/hyperframes/dist/skills/media-use/references/setup-providers.md +80 -0
- package/vendor/hyperframes/dist/skills/media-use/references/telemetry-dashboard.md +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/audio-duck.mjs +113 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/compatibility.test.mjs +96 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/dither.mjs +328 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/dither.test.mjs +176 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/eval.mjs +369 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/adopt.mjs +128 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/adopt.test.mjs +95 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bgm-provider.mjs +20 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/brand-provider.mjs +59 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bundled-sfx-provider.mjs +119 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bundled-sfx-provider.test.mjs +139 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cache.mjs +148 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/candidates.mjs +91 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/candidates.test.mjs +155 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/codex-provider.mjs +161 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/codex-provider.test.mjs +34 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.d.mts +3 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.mjs +45 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.test.mjs +79 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/coverage.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-build.mjs +181 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-build.test.mjs +80 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-validate.mjs +198 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-validate.test.mjs +125 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cutlist.mjs +184 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cutlist.test.mjs +162 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/duck.mjs +95 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/duck.test.mjs +153 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/error-diffusion.mjs +230 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/error-diffusion.test.mjs +102 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ff-binaries.mjs +37 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/freeze.mjs +72 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/freeze.test.mjs +138 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/grade-analyzer.mjs +265 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/grade-analyzer.test.mjs +285 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-cli.mjs +191 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-cli.test.mjs +301 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-search.mjs +45 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-search.test.mjs +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-video-provider.mjs +138 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-video-provider.test.mjs +435 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/image-provider.mjs +44 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/index-gen.mjs +63 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-media-search.mjs +32 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-models.mjs +318 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-models.test.mjs +220 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-run.mjs +78 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-run.test.mjs +121 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/logo-provider.mjs +244 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/logo-provider.test.mjs +298 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ltx-video-provider.mjs +94 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ltx-video-provider.test.mjs +316 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/lut-preset-provider.mjs +271 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/lut-preset-provider.test.mjs +199 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.d.mts +19 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.mjs +279 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.test.mjs +397 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/match.mjs +47 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-fetch.mjs +85 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-fetch.test.mjs +197 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-home.mjs +20 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-home.test.mjs +61 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-search.d.mts +9 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-search.mjs +107 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/mflux-provider.mjs +128 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/mflux-provider.test.mjs +174 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/misses.mjs +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/misses.test.mjs +89 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/npx-sync.mjs +31 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/npx-sync.test.mjs +50 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/parakeet-words.mjs +27 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/parakeet-words.test.mjs +44 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/prefs-store.mjs +180 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/prefs-store.test.mjs +189 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/probe.mjs +41 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/probe.test.mjs +148 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/providers.mjs +5 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/recipe-store.mjs +367 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/recipe-store.test.mjs +367 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/registry.mjs +212 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/registry.test.mjs +262 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/search.mjs +24 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/search.test.mjs +32 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/sfx-provider.mjs +23 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/specs.mjs +132 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/specs.test.mjs +157 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/stats.mjs +117 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/stats.test.mjs +165 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/svg-sanitize.mjs +21 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/telemetry.mjs +210 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/telemetry.test.mjs +437 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/test-home.test.mjs +10 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/transcriptCutFade.mjs +21 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/transcriptCutFade.test.mjs +33 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/tts-local-provider.mjs +94 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/tts-local-provider.test.mjs +72 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/usage.mjs +57 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/usage.test.mjs +54 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/voice-provider.mjs +57 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/voice-provider.test.mjs +46 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/words.mjs +18 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/prefs.mjs +70 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/recipe.mjs +103 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/resolve-plugin.test.mjs +62 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/resolve.mjs +1369 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcribe.mjs +194 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcribe.test.mjs +112 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcript-cut.mjs +270 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcript-cut.test.mjs +117 -0
- package/vendor/hyperframes/dist/skills-MJ2J4GEM.js +808 -0
- package/vendor/hyperframes/dist/skillsUpdateCheck-TKTYQN5R.js +26 -0
- package/vendor/hyperframes/dist/slideshow-EJ4IMY6P.js +24 -0
- package/vendor/hyperframes/dist/snapshot-KIVDUUMN.js +875 -0
- package/vendor/hyperframes/dist/src-6YQBJGWR.js +202 -0
- package/vendor/hyperframes/dist/src-PVYUYV3M.js +471 -0
- package/vendor/hyperframes/dist/state-KAXGHF77.js +26 -0
- package/vendor/hyperframes/dist/staticProjectServer-7EU666GS.js +49 -0
- package/vendor/hyperframes/dist/status-YM52BQ6S.js +311 -0
- package/vendor/hyperframes/dist/studio/assets/hyperframes-player-Cp8e_Zst.js +473 -0
- package/vendor/hyperframes/dist/studio/assets/index-BX3KHhGX.js +71 -0
- package/vendor/hyperframes/dist/studio/assets/index-CASEBNy2.js +1 -0
- package/vendor/hyperframes/dist/studio/assets/index-D11atkBt.css +1 -0
- package/vendor/hyperframes/dist/studio/assets/index-DMTt9nTf.js +531 -0
- package/vendor/hyperframes/dist/studio/assets/index-oE1pOdAy.js +399 -0
- package/vendor/hyperframes/dist/studio/chunk-5VSXRGIX.js +948 -0
- package/vendor/hyperframes/dist/studio/chunk-5VSXRGIX.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-7UQWVN52.js +938 -0
- package/vendor/hyperframes/dist/studio/chunk-7UQWVN52.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-EEXSYY5F.js +190 -0
- package/vendor/hyperframes/dist/studio/chunk-EEXSYY5F.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-FOEID72M.js +1441 -0
- package/vendor/hyperframes/dist/studio/chunk-FOEID72M.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-PZ5AY32C.js +10 -0
- package/vendor/hyperframes/dist/studio/chunk-PZ5AY32C.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-TDWGXBUT.js +1103 -0
- package/vendor/hyperframes/dist/studio/chunk-TDWGXBUT.js.map +1 -0
- package/vendor/hyperframes/dist/studio/domEditingLayers-IEVLO54Z.js +47 -0
- package/vendor/hyperframes/dist/studio/domEditingLayers-IEVLO54Z.js.map +1 -0
- package/vendor/hyperframes/dist/studio/favicon.svg +14 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/audio.svg +7 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/captions.svg +5 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/composition.svg +12 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/image.svg +18 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/music.svg +10 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/text.svg +3 -0
- package/vendor/hyperframes/dist/studio/index.css +165 -0
- package/vendor/hyperframes/dist/studio/index.css.map +1 -0
- package/vendor/hyperframes/dist/studio/index.d.ts +4296 -0
- package/vendor/hyperframes/dist/studio/index.html +23 -0
- package/vendor/hyperframes/dist/studio/index.js +99693 -0
- package/vendor/hyperframes/dist/studio/index.js.map +1 -0
- package/vendor/hyperframes/dist/studio/player.d.ts +30 -0
- package/vendor/hyperframes/dist/studio/player.js +10 -0
- package/vendor/hyperframes/dist/studio/player.js.map +1 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.d.ts +39 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.js +50 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.js.map +1 -0
- package/vendor/hyperframes/dist/studio/styles.css +1 -0
- package/vendor/hyperframes/dist/studio/ui.d.ts +296 -0
- package/vendor/hyperframes/dist/studio/ui.js +66 -0
- package/vendor/hyperframes/dist/studio/ui.js.map +1 -0
- package/vendor/hyperframes/dist/studio-api-PNQZRPX5.js +136 -0
- package/vendor/hyperframes/dist/studioSelectionClient-IUUPKUHZ.js +25 -0
- package/vendor/hyperframes/dist/studioServer-UWRBPIOJ.js +1457 -0
- package/vendor/hyperframes/dist/synthesize-K62TIZWI.js +182 -0
- package/vendor/hyperframes/dist/system-EZYZNUFD.js +44 -0
- package/vendor/hyperframes/dist/telemetry-2YC4SGQU.js +144 -0
- package/vendor/hyperframes/dist/telemetry-QMYM4WME.js +95 -0
- package/vendor/hyperframes/dist/templates/_shared/AGENTS.md +107 -0
- package/vendor/hyperframes/dist/templates/_shared/CLAUDE.md +107 -0
- package/vendor/hyperframes/dist/templates/blank/index.html +55 -0
- package/vendor/hyperframes/dist/templates/from-file/index.html +75 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/captions.html +154 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/graphics.html +162 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/intro.html +87 -0
- package/vendor/hyperframes/dist/templates/warm-grain/index.html +264 -0
- package/vendor/hyperframes/dist/templates/warm-grain/registry-item.json +34 -0
- package/vendor/hyperframes/dist/timeline-77Z3BBQM.js +1377 -0
- package/vendor/hyperframes/dist/tokens-OBGTYE4Z.js +92 -0
- package/vendor/hyperframes/dist/transcribe-7NVFHCGA.js +387 -0
- package/vendor/hyperframes/dist/transcribe-BNSJRR4M.js +62 -0
- package/vendor/hyperframes/dist/tts-P3LIPIL5.js +234 -0
- package/vendor/hyperframes/dist/updateCheck-UDWIJ4ZQ.js +39 -0
- package/vendor/hyperframes/dist/upgrade-CT3CPO3E.js +231 -0
- package/vendor/hyperframes/dist/urlDownloader-H6WRI2UE.js +39 -0
- package/vendor/hyperframes/dist/usage-EC3KFUIJ.js +2139 -0
- package/vendor/hyperframes/dist/validate-65QDZJWZ.js +70 -0
- package/vendor/hyperframes/dist/video-FGSGKRSV.js +261 -0
- package/vendor/hyperframes/dist/workspaceBuildCheck-TOLGAI4T.js +133 -0
- package/vendor/hyperframes/package.json +80 -0
|
@@ -0,0 +1,1214 @@
|
|
|
1
|
+
import { createRequire as __hf_createRequire } from "node:module";
|
|
2
|
+
import { fileURLToPath as __hf_fileURLToPath } from "node:url";
|
|
3
|
+
import { dirname as __hf_dirname } from "node:path";
|
|
4
|
+
var require = __hf_createRequire(import.meta.url);
|
|
5
|
+
var __filename = __hf_fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = __hf_dirname(__filename);
|
|
7
|
+
import {
|
|
8
|
+
c
|
|
9
|
+
} from "./chunk-ZTZA4UWZ.js";
|
|
10
|
+
import {
|
|
11
|
+
failCommand
|
|
12
|
+
} from "./chunk-PBN6GBJE.js";
|
|
13
|
+
import {
|
|
14
|
+
normalizeErrorMessage
|
|
15
|
+
} from "./chunk-KNU5COPB.js";
|
|
16
|
+
|
|
17
|
+
// src/auth/errors.ts
|
|
18
|
+
var AuthError = class extends Error {
|
|
19
|
+
code;
|
|
20
|
+
hint;
|
|
21
|
+
constructor(code, message, hint) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = "AuthError";
|
|
24
|
+
this.code = code;
|
|
25
|
+
this.hint = hint;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var ErrNotConfigured = () => new AuthError(
|
|
29
|
+
"NOT_CONFIGURED",
|
|
30
|
+
"No HeyGen credentials found",
|
|
31
|
+
"Run `hyperframes auth login` to sign in."
|
|
32
|
+
);
|
|
33
|
+
var ErrInvalidStore = (detail) => new AuthError(
|
|
34
|
+
"INVALID_STORE",
|
|
35
|
+
`Credential file is unreadable: ${detail}`,
|
|
36
|
+
"Delete ~/.heygen/credentials and run `hyperframes auth login` to re-create it."
|
|
37
|
+
);
|
|
38
|
+
var ErrUnauthenticated = (detail) => new AuthError(
|
|
39
|
+
"UNAUTHENTICATED",
|
|
40
|
+
detail ? `HeyGen rejected the credential: ${detail}` : "HeyGen rejected the credential",
|
|
41
|
+
"Run `hyperframes auth login` to re-authenticate."
|
|
42
|
+
);
|
|
43
|
+
var ErrApi = (status, detail) => new AuthError("API_ERROR", `HeyGen API error (${status}): ${detail}`);
|
|
44
|
+
var ErrOAuthNotConfigured = () => new AuthError(
|
|
45
|
+
"OAUTH_NOT_CONFIGURED",
|
|
46
|
+
"OAuth client is not configured",
|
|
47
|
+
"Set HYPERFRAMES_OAUTH_CLIENT_ID, or run `hyperframes auth login --api-key`."
|
|
48
|
+
);
|
|
49
|
+
var ErrRefreshFailed = (detail) => new AuthError(
|
|
50
|
+
"REFRESH_FAILED",
|
|
51
|
+
detail ? `Failed to refresh OAuth tokens: ${detail}` : "Failed to refresh OAuth tokens",
|
|
52
|
+
"Run `hyperframes auth login` to re-authenticate."
|
|
53
|
+
);
|
|
54
|
+
var ErrLoginExpired = () => new AuthError(
|
|
55
|
+
"LOGIN_EXPIRED",
|
|
56
|
+
"Your HeyGen login expired",
|
|
57
|
+
"Run `hyperframes auth login` to sign in again."
|
|
58
|
+
);
|
|
59
|
+
var ErrLoginChanged = () => new AuthError(
|
|
60
|
+
"LOGIN_CHANGED",
|
|
61
|
+
"Your HeyGen login changed while this command ran",
|
|
62
|
+
"Run the command again."
|
|
63
|
+
);
|
|
64
|
+
var ErrDeviceAuthFailed = (detail) => new AuthError(
|
|
65
|
+
"DEVICE_AUTH_FAILED",
|
|
66
|
+
`Device authorization failed: ${detail}`,
|
|
67
|
+
"Run `hyperframes auth login --device` to start a new code."
|
|
68
|
+
);
|
|
69
|
+
function isAuthError(err) {
|
|
70
|
+
return err instanceof AuthError;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/auth/scrub.ts
|
|
74
|
+
var HEYGEN_KEY = /\b(hg|sk)_[A-Za-z0-9_-]{4,}/g;
|
|
75
|
+
var HEADER_LINE = /(authorization|x-api-key)[ \t]*[:=][ \t]*[^\r\n]+/gi;
|
|
76
|
+
var JWT = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
|
|
77
|
+
var SECRET_FIELDS = [
|
|
78
|
+
"access_token",
|
|
79
|
+
"refresh_token",
|
|
80
|
+
"code_verifier",
|
|
81
|
+
"client_secret",
|
|
82
|
+
"id_token",
|
|
83
|
+
"token",
|
|
84
|
+
"code"
|
|
85
|
+
];
|
|
86
|
+
var FORM_FIELD = new RegExp(`\\b(${SECRET_FIELDS.join("|")})=[^&\\s"']+`, "gi");
|
|
87
|
+
var JSON_FIELD = new RegExp(`("(?:${SECRET_FIELDS.join("|")})"\\s*:\\s*)"[^"]*"`, "gi");
|
|
88
|
+
function scrubCredentials(s) {
|
|
89
|
+
return s.replace(HEYGEN_KEY, "$1_<redacted>").replace(HEADER_LINE, "$1: <redacted>").replace(JWT, "<jwt-redacted>").replace(FORM_FIELD, "$1=<redacted>").replace(JSON_FIELD, '$1"<redacted>"');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/auth/client.ts
|
|
93
|
+
var DEFAULT_BASE_URL = "https://api.heygen.com";
|
|
94
|
+
var HEYGEN_CLI_SOURCE_HEADER = "X-HeyGen-Source";
|
|
95
|
+
var HEYGEN_CLI_SOURCE = "cli";
|
|
96
|
+
var HEYGEN_CLIENT_SOURCE_HEADER = "X-HeyGen-Client-Source";
|
|
97
|
+
var HEYGEN_CLIENT_SOURCE = "hyperframes";
|
|
98
|
+
function apiBaseUrl() {
|
|
99
|
+
const override = process.env["HEYGEN_API_URL"];
|
|
100
|
+
return override && override.length > 0 ? override.replace(/\/+$/, "") : DEFAULT_BASE_URL;
|
|
101
|
+
}
|
|
102
|
+
var AuthClient = class {
|
|
103
|
+
base;
|
|
104
|
+
fetchImpl;
|
|
105
|
+
onRefresh;
|
|
106
|
+
constructor(opts = {}) {
|
|
107
|
+
this.base = (opts.baseUrl ?? apiBaseUrl()).replace(/\/+$/, "");
|
|
108
|
+
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
109
|
+
this.onRefresh = opts.onUnauthenticatedRefresh;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* `GET /v3/users/me`. Throws `ErrUnauthenticated` on 401, `ErrApi`
|
|
113
|
+
* on any other non-2xx or non-JSON body.
|
|
114
|
+
*
|
|
115
|
+
* On OAuth 401 with a refresh hook configured, the request is
|
|
116
|
+
* retried once after refreshing the access token. The retry's
|
|
117
|
+
* outcome is what the caller sees — if the refresh itself fails
|
|
118
|
+
* (REFRESH_FAILED) or the retry still 401s, the user lands on a
|
|
119
|
+
* "please log in again" path upstream.
|
|
120
|
+
*/
|
|
121
|
+
async getCurrentUser(credential) {
|
|
122
|
+
const url = `${this.base}/v3/users/me`;
|
|
123
|
+
return await this.fetchUser(url, credential, true);
|
|
124
|
+
}
|
|
125
|
+
// fallow-ignore-next-line complexity
|
|
126
|
+
async fetchUser(url, credential, allowRefresh) {
|
|
127
|
+
const headers = buildAuthHeaders(credential);
|
|
128
|
+
const res = await this.fetchImpl(url, { method: "GET", headers });
|
|
129
|
+
if (res.status === 401) {
|
|
130
|
+
if (allowRefresh && credential.type === "oauth" && credential.refresh_token && this.onRefresh) {
|
|
131
|
+
const refreshed = await this.tryRefresh(credential.refresh_token);
|
|
132
|
+
if (refreshed) {
|
|
133
|
+
const next = {
|
|
134
|
+
...credential,
|
|
135
|
+
access_token: refreshed.access_token,
|
|
136
|
+
...refreshed.refresh_token ? { refresh_token: refreshed.refresh_token } : {}
|
|
137
|
+
};
|
|
138
|
+
return await this.fetchUser(url, next, false);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const detail = await safeText(res);
|
|
142
|
+
throw ErrUnauthenticated(detail || `${res.status} ${res.statusText}`);
|
|
143
|
+
}
|
|
144
|
+
if (!res.ok) {
|
|
145
|
+
throw ErrApi(res.status, await safeText(res) || res.statusText);
|
|
146
|
+
}
|
|
147
|
+
let payload;
|
|
148
|
+
try {
|
|
149
|
+
payload = await res.json();
|
|
150
|
+
} catch (err) {
|
|
151
|
+
throw ErrApi(res.status, `non-JSON body: ${err.message}`);
|
|
152
|
+
}
|
|
153
|
+
return extractUserInfo(payload);
|
|
154
|
+
}
|
|
155
|
+
async tryRefresh(refresh_token) {
|
|
156
|
+
if (!this.onRefresh) return null;
|
|
157
|
+
try {
|
|
158
|
+
return await this.onRefresh(refresh_token);
|
|
159
|
+
} catch (err) {
|
|
160
|
+
if (isAuthError(err) && err.code === "REFRESH_FAILED") return null;
|
|
161
|
+
throw err;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
function buildAuthHeaders(credential) {
|
|
166
|
+
if (credential.type === "oauth") {
|
|
167
|
+
return {
|
|
168
|
+
authorization: `Bearer ${credential.access_token}`,
|
|
169
|
+
[HEYGEN_CLI_SOURCE_HEADER]: HEYGEN_CLI_SOURCE,
|
|
170
|
+
[HEYGEN_CLIENT_SOURCE_HEADER]: HEYGEN_CLIENT_SOURCE
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return { "x-api-key": credential.key, [HEYGEN_CLIENT_SOURCE_HEADER]: HEYGEN_CLIENT_SOURCE };
|
|
174
|
+
}
|
|
175
|
+
async function safeText(res) {
|
|
176
|
+
try {
|
|
177
|
+
const body = (await res.text()).slice(0, 500);
|
|
178
|
+
return scrubCredentials(body);
|
|
179
|
+
} catch {
|
|
180
|
+
return "";
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function extractUserInfo(payload) {
|
|
184
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) return {};
|
|
185
|
+
const obj = payload;
|
|
186
|
+
const wrapped = obj["data"];
|
|
187
|
+
const data = wrapped && typeof wrapped === "object" && !Array.isArray(wrapped) ? wrapped : obj;
|
|
188
|
+
return {
|
|
189
|
+
username: pickString(data, "username"),
|
|
190
|
+
email: pickString(data, "email"),
|
|
191
|
+
first_name: pickString(data, "first_name"),
|
|
192
|
+
last_name: pickString(data, "last_name"),
|
|
193
|
+
billing_type: pickString(data, "billing_type"),
|
|
194
|
+
wallet: pickObject(data, "wallet"),
|
|
195
|
+
subscription: pickObject(data, "subscription"),
|
|
196
|
+
usage_based: pickObject(data, "usage_based")
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function pickString(obj, key) {
|
|
200
|
+
const v = obj[key];
|
|
201
|
+
return typeof v === "string" ? v : void 0;
|
|
202
|
+
}
|
|
203
|
+
function pickObject(obj, key) {
|
|
204
|
+
const v = obj[key];
|
|
205
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/auth/paths.ts
|
|
209
|
+
import { homedir } from "os";
|
|
210
|
+
import { join } from "path";
|
|
211
|
+
var CREDENTIAL_FILENAME = "credentials";
|
|
212
|
+
function configDir() {
|
|
213
|
+
const override = process.env["HEYGEN_CONFIG_DIR"];
|
|
214
|
+
if (override && override.length > 0) return override;
|
|
215
|
+
return join(homedir(), ".heygen");
|
|
216
|
+
}
|
|
217
|
+
function credentialPath() {
|
|
218
|
+
return join(configDir(), CREDENTIAL_FILENAME);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// src/auth/store.ts
|
|
222
|
+
import { promises as fs } from "fs";
|
|
223
|
+
import { dirname } from "path";
|
|
224
|
+
var FILE_MODE = 384;
|
|
225
|
+
var DIR_MODE = 448;
|
|
226
|
+
var UNKNOWN = /* @__PURE__ */ Symbol("hf.credentials.unknownFields");
|
|
227
|
+
var KNOWN_ROOT_KEYS = /* @__PURE__ */ new Set(["api_key", "oauth", "user"]);
|
|
228
|
+
var KNOWN_OAUTH_KEYS = /* @__PURE__ */ new Set([
|
|
229
|
+
"access_token",
|
|
230
|
+
"refresh_token",
|
|
231
|
+
"expires_at",
|
|
232
|
+
"scope",
|
|
233
|
+
"token_type"
|
|
234
|
+
]);
|
|
235
|
+
var KNOWN_USER_KEYS = /* @__PURE__ */ new Set(["email", "first_name", "last_name", "username"]);
|
|
236
|
+
async function readStore(path = credentialPath()) {
|
|
237
|
+
let raw;
|
|
238
|
+
try {
|
|
239
|
+
raw = await fs.readFile(path, "utf8");
|
|
240
|
+
} catch (err) {
|
|
241
|
+
if (err.code === "ENOENT") {
|
|
242
|
+
return { credentials: {}, source: "absent" };
|
|
243
|
+
}
|
|
244
|
+
throw ErrInvalidStore(`unable to read ${path}: ${err.message}`);
|
|
245
|
+
}
|
|
246
|
+
const trimmed = raw.trim();
|
|
247
|
+
if (trimmed.length === 0) return { credentials: {}, source: "absent" };
|
|
248
|
+
if (trimmed.startsWith("{")) {
|
|
249
|
+
return { credentials: parseJsonStore(trimmed), source: "file_json" };
|
|
250
|
+
}
|
|
251
|
+
if (looksLikeApiKey(trimmed)) {
|
|
252
|
+
return { credentials: { api_key: trimmed }, source: "file_legacy" };
|
|
253
|
+
}
|
|
254
|
+
throw ErrInvalidStore("file is not JSON and does not look like a plain API key");
|
|
255
|
+
}
|
|
256
|
+
async function writeStore(credentials, path = credentialPath()) {
|
|
257
|
+
await ensureDir(dirname(path));
|
|
258
|
+
const body = JSON.stringify(serializeCredentials(credentials), null, 2);
|
|
259
|
+
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
260
|
+
await fs.writeFile(tmp, `${body}
|
|
261
|
+
`, { mode: FILE_MODE, encoding: "utf8" });
|
|
262
|
+
await fs.chmod(tmp, FILE_MODE);
|
|
263
|
+
await fs.rename(tmp, path);
|
|
264
|
+
}
|
|
265
|
+
async function deleteStore(path = credentialPath()) {
|
|
266
|
+
try {
|
|
267
|
+
await fs.unlink(path);
|
|
268
|
+
} catch (err) {
|
|
269
|
+
if (err.code === "ENOENT") return;
|
|
270
|
+
throw err;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function hasPreservedUnknownData(credentials) {
|
|
274
|
+
if (hasUnknownBag(credentials[UNKNOWN])) return true;
|
|
275
|
+
if (hasUnknownBag(credentials.oauth?.[UNKNOWN])) return true;
|
|
276
|
+
if (hasUnknownBag(credentials.user?.[UNKNOWN])) return true;
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
function hasUnknownBag(bag) {
|
|
280
|
+
return bag !== void 0 && Object.keys(bag).length > 0;
|
|
281
|
+
}
|
|
282
|
+
async function clearOAuth(path = credentialPath()) {
|
|
283
|
+
const { credentials, source } = await readStore(path);
|
|
284
|
+
if (source === "absent" || !credentials.oauth) return;
|
|
285
|
+
const next = { ...credentials };
|
|
286
|
+
delete next.oauth;
|
|
287
|
+
if (!next.api_key && !hasPreservedUnknownData(next)) {
|
|
288
|
+
await deleteStore(path);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
await writeStore(next, path);
|
|
292
|
+
}
|
|
293
|
+
async function ensureDir(dir) {
|
|
294
|
+
try {
|
|
295
|
+
const stat = await fs.stat(dir);
|
|
296
|
+
if (!stat.isDirectory()) {
|
|
297
|
+
throw ErrInvalidStore(`${dir} exists and is not a directory`);
|
|
298
|
+
}
|
|
299
|
+
} catch (err) {
|
|
300
|
+
if (err.code !== "ENOENT") throw err;
|
|
301
|
+
await fs.mkdir(dir, { recursive: true, mode: DIR_MODE });
|
|
302
|
+
}
|
|
303
|
+
try {
|
|
304
|
+
await fs.chmod(dir, DIR_MODE);
|
|
305
|
+
} catch {
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function parseJsonStore(text) {
|
|
309
|
+
const obj = parseJsonObject(text, "credential file root");
|
|
310
|
+
const out = {};
|
|
311
|
+
const apiKey = pickRequiredStringOrAbsent(obj, "api_key", "api_key");
|
|
312
|
+
if (apiKey !== void 0) {
|
|
313
|
+
if (!isHeaderSafe(apiKey)) {
|
|
314
|
+
throw ErrInvalidStore("api_key must not contain control characters");
|
|
315
|
+
}
|
|
316
|
+
out.api_key = apiKey;
|
|
317
|
+
}
|
|
318
|
+
if (obj["oauth"] !== void 0 && obj["oauth"] !== null) {
|
|
319
|
+
out.oauth = parseOAuth(obj["oauth"]);
|
|
320
|
+
}
|
|
321
|
+
if (obj["user"] !== void 0 && obj["user"] !== null) {
|
|
322
|
+
out.user = parseUser(obj["user"]);
|
|
323
|
+
}
|
|
324
|
+
const unknownRoot = collectUnknown(obj, KNOWN_ROOT_KEYS);
|
|
325
|
+
if (unknownRoot) out[UNKNOWN] = unknownRoot;
|
|
326
|
+
return out;
|
|
327
|
+
}
|
|
328
|
+
var PICKERS = {
|
|
329
|
+
header_safe: pickHeaderSafeString,
|
|
330
|
+
non_empty: pickNonEmptyString
|
|
331
|
+
};
|
|
332
|
+
function assignOptionalStrings(out, obj, spec) {
|
|
333
|
+
const target = out;
|
|
334
|
+
for (const [field, picker] of spec) {
|
|
335
|
+
const v = PICKERS[picker](obj, field);
|
|
336
|
+
if (v) target[field] = v;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
var OAUTH_OPTIONAL = [
|
|
340
|
+
["refresh_token", "header_safe"],
|
|
341
|
+
["expires_at", "non_empty"],
|
|
342
|
+
["scope", "non_empty"],
|
|
343
|
+
["token_type", "non_empty"]
|
|
344
|
+
];
|
|
345
|
+
function parseOAuth(raw) {
|
|
346
|
+
const obj = asJsonObject(raw, "oauth");
|
|
347
|
+
const accessToken = pickHeaderSafeString(obj, "access_token");
|
|
348
|
+
if (!accessToken) {
|
|
349
|
+
throw ErrInvalidStore("oauth.access_token must be a non-empty string with no control chars");
|
|
350
|
+
}
|
|
351
|
+
const out = { access_token: accessToken };
|
|
352
|
+
assignOptionalStrings(out, obj, OAUTH_OPTIONAL);
|
|
353
|
+
const unknownOAuth = collectUnknown(obj, KNOWN_OAUTH_KEYS);
|
|
354
|
+
if (unknownOAuth) out[UNKNOWN] = unknownOAuth;
|
|
355
|
+
return out;
|
|
356
|
+
}
|
|
357
|
+
var USER_OPTIONAL = [
|
|
358
|
+
["email", "non_empty"],
|
|
359
|
+
["first_name", "non_empty"],
|
|
360
|
+
["last_name", "non_empty"],
|
|
361
|
+
["username", "non_empty"]
|
|
362
|
+
];
|
|
363
|
+
function parseUser(raw) {
|
|
364
|
+
const obj = asJsonObject(raw, "user");
|
|
365
|
+
const out = {};
|
|
366
|
+
assignOptionalStrings(out, obj, USER_OPTIONAL);
|
|
367
|
+
const unknownUser = collectUnknown(obj, KNOWN_USER_KEYS);
|
|
368
|
+
if (unknownUser) out[UNKNOWN] = unknownUser;
|
|
369
|
+
return out;
|
|
370
|
+
}
|
|
371
|
+
function asJsonObject(raw, label) {
|
|
372
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
373
|
+
throw ErrInvalidStore(`${label} must be a JSON object`);
|
|
374
|
+
}
|
|
375
|
+
return raw;
|
|
376
|
+
}
|
|
377
|
+
function collectUnknown(obj, known) {
|
|
378
|
+
let bag;
|
|
379
|
+
for (const key of Object.keys(obj)) {
|
|
380
|
+
if (known.has(key)) continue;
|
|
381
|
+
(bag ??= {})[key] = obj[key];
|
|
382
|
+
}
|
|
383
|
+
return bag;
|
|
384
|
+
}
|
|
385
|
+
function parseJsonObject(text, label) {
|
|
386
|
+
let raw;
|
|
387
|
+
try {
|
|
388
|
+
raw = JSON.parse(text);
|
|
389
|
+
} catch (err) {
|
|
390
|
+
throw ErrInvalidStore(`invalid JSON: ${err.message}`);
|
|
391
|
+
}
|
|
392
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
393
|
+
throw ErrInvalidStore(`${label} must be a JSON object`);
|
|
394
|
+
}
|
|
395
|
+
return raw;
|
|
396
|
+
}
|
|
397
|
+
function pickNonEmptyString(obj, key) {
|
|
398
|
+
const v = obj[key];
|
|
399
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
400
|
+
}
|
|
401
|
+
function pickHeaderSafeString(obj, key) {
|
|
402
|
+
const v = pickNonEmptyString(obj, key);
|
|
403
|
+
return v !== void 0 && isHeaderSafe(v) ? v : void 0;
|
|
404
|
+
}
|
|
405
|
+
function isHeaderSafe(s) {
|
|
406
|
+
for (let i = 0; i < s.length; i++) {
|
|
407
|
+
const c2 = s.charCodeAt(i);
|
|
408
|
+
if (c2 < 32 || c2 === 127) return false;
|
|
409
|
+
}
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
function pickRequiredStringOrAbsent(obj, key, errorLabel) {
|
|
413
|
+
const v = obj[key];
|
|
414
|
+
if (v === void 0 || v === null) return void 0;
|
|
415
|
+
if (typeof v !== "string" || v.length === 0) {
|
|
416
|
+
throw ErrInvalidStore(`${errorLabel} must be a non-empty string`);
|
|
417
|
+
}
|
|
418
|
+
return v;
|
|
419
|
+
}
|
|
420
|
+
function serializeCredentials(c2) {
|
|
421
|
+
const out = { ...c2[UNKNOWN] ?? {} };
|
|
422
|
+
if (c2.api_key) out["api_key"] = c2.api_key;
|
|
423
|
+
if (c2.oauth) out["oauth"] = serializeOAuth(c2.oauth);
|
|
424
|
+
if (c2.user) {
|
|
425
|
+
const user = serializeUser(c2.user);
|
|
426
|
+
if (Object.keys(user).length > 0) out["user"] = user;
|
|
427
|
+
}
|
|
428
|
+
return out;
|
|
429
|
+
}
|
|
430
|
+
function serializeOAuth(o) {
|
|
431
|
+
const oauth = { ...o[UNKNOWN] ?? {} };
|
|
432
|
+
oauth["access_token"] = o.access_token;
|
|
433
|
+
if (o.refresh_token) oauth["refresh_token"] = o.refresh_token;
|
|
434
|
+
if (o.expires_at) oauth["expires_at"] = o.expires_at;
|
|
435
|
+
if (o.scope) oauth["scope"] = o.scope;
|
|
436
|
+
if (o.token_type) oauth["token_type"] = o.token_type;
|
|
437
|
+
return oauth;
|
|
438
|
+
}
|
|
439
|
+
function serializeUser(u) {
|
|
440
|
+
const user = { ...u[UNKNOWN] ?? {} };
|
|
441
|
+
if (u.email) user["email"] = u.email;
|
|
442
|
+
if (u.first_name) user["first_name"] = u.first_name;
|
|
443
|
+
if (u.last_name) user["last_name"] = u.last_name;
|
|
444
|
+
if (u.username) user["username"] = u.username;
|
|
445
|
+
return user;
|
|
446
|
+
}
|
|
447
|
+
function looksLikeApiKey(s) {
|
|
448
|
+
if (s.length < 8) return false;
|
|
449
|
+
if (!isHeaderSafe(s)) return false;
|
|
450
|
+
return /^[!-~]+$/.test(s);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// src/auth/resolver.ts
|
|
454
|
+
var EXPIRY_SKEW_MS = 60 * 1e3;
|
|
455
|
+
async function resolveCredential(opts = {}) {
|
|
456
|
+
const now = (opts.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
457
|
+
const heygenEnv = process.env["HEYGEN_API_KEY"];
|
|
458
|
+
if (heygenEnv && heygenEnv.length > 0) {
|
|
459
|
+
if (!isHeaderSafe(heygenEnv)) {
|
|
460
|
+
throw ErrInvalidStore("HEYGEN_API_KEY contains control characters");
|
|
461
|
+
}
|
|
462
|
+
return { type: "api_key", key: heygenEnv, source: "env" };
|
|
463
|
+
}
|
|
464
|
+
const hfEnv = process.env["HYPERFRAMES_API_KEY"];
|
|
465
|
+
if (hfEnv && hfEnv.length > 0) {
|
|
466
|
+
if (!isHeaderSafe(hfEnv)) {
|
|
467
|
+
throw ErrInvalidStore("HYPERFRAMES_API_KEY contains control characters");
|
|
468
|
+
}
|
|
469
|
+
return { type: "api_key", key: hfEnv, source: "env_alias" };
|
|
470
|
+
}
|
|
471
|
+
const { credentials, source } = await readStore();
|
|
472
|
+
if (source === "absent") throw ErrNotConfigured();
|
|
473
|
+
const fileSource = source === "file_legacy" ? "file_legacy" : "file_json";
|
|
474
|
+
const oauth = credentials.oauth ? pickOAuth(credentials.oauth, now, fileSource) : null;
|
|
475
|
+
if (oauth) return oauth;
|
|
476
|
+
if (credentials.api_key) {
|
|
477
|
+
return { type: "api_key", key: credentials.api_key, source: fileSource };
|
|
478
|
+
}
|
|
479
|
+
throw credentials.oauth ? ErrLoginExpired() : ErrNotConfigured();
|
|
480
|
+
}
|
|
481
|
+
async function tryResolveCredential(opts = {}) {
|
|
482
|
+
try {
|
|
483
|
+
return await resolveCredential(opts);
|
|
484
|
+
} catch (err) {
|
|
485
|
+
if (isAuthError(err) && err.code === "NOT_CONFIGURED") {
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
throw err;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
function pickOAuth(tokens, now, source) {
|
|
492
|
+
const expiresAt = parseDate(tokens.expires_at);
|
|
493
|
+
const expired = isTokenExpired(expiresAt, now);
|
|
494
|
+
if (expired && !tokens.refresh_token) return null;
|
|
495
|
+
const out = {
|
|
496
|
+
type: "oauth",
|
|
497
|
+
access_token: tokens.access_token,
|
|
498
|
+
source,
|
|
499
|
+
refreshable: expired && tokens.refresh_token !== void 0
|
|
500
|
+
};
|
|
501
|
+
if (tokens.refresh_token) out.refresh_token = tokens.refresh_token;
|
|
502
|
+
if (expiresAt) out.expires_at = expiresAt;
|
|
503
|
+
if (tokens.scope) out.scope = tokens.scope;
|
|
504
|
+
return out;
|
|
505
|
+
}
|
|
506
|
+
function isTokenExpired(expiresAt, now) {
|
|
507
|
+
return expiresAt !== void 0 && expiresAt.getTime() - EXPIRY_SKEW_MS < now.getTime();
|
|
508
|
+
}
|
|
509
|
+
function parseDate(s) {
|
|
510
|
+
if (!s) return void 0;
|
|
511
|
+
const d = new Date(s);
|
|
512
|
+
return Number.isNaN(d.getTime()) ? void 0 : d;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// src/auth/pkce.ts
|
|
516
|
+
import { createHash, randomBytes } from "crypto";
|
|
517
|
+
var VERIFIER_BYTES = 64;
|
|
518
|
+
function generatePkcePair() {
|
|
519
|
+
const verifier = base64UrlEncode(randomBytes(VERIFIER_BYTES));
|
|
520
|
+
const challenge = base64UrlEncode(createHash("sha256").update(verifier).digest());
|
|
521
|
+
return { verifier, challenge, method: "S256" };
|
|
522
|
+
}
|
|
523
|
+
function generateState() {
|
|
524
|
+
return base64UrlEncode(randomBytes(32));
|
|
525
|
+
}
|
|
526
|
+
function base64UrlEncode(buf) {
|
|
527
|
+
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// src/auth/loopback.ts
|
|
531
|
+
import { timingSafeEqual } from "crypto";
|
|
532
|
+
import { createServer } from "http";
|
|
533
|
+
var CALLBACK_PATH = "/oauth/callback";
|
|
534
|
+
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
535
|
+
async function startLoopback(opts) {
|
|
536
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
537
|
+
let resolveResult;
|
|
538
|
+
let rejectResult;
|
|
539
|
+
const result = new Promise((resolve, reject) => {
|
|
540
|
+
resolveResult = resolve;
|
|
541
|
+
rejectResult = reject;
|
|
542
|
+
});
|
|
543
|
+
let redirectUri = "";
|
|
544
|
+
const server = createServer(
|
|
545
|
+
(req, res) => handleRequest(req, res, opts.state, redirectUri, resolveResult, rejectResult)
|
|
546
|
+
);
|
|
547
|
+
await listen(server, opts.port ?? 0);
|
|
548
|
+
const address = server.address();
|
|
549
|
+
redirectUri = `http://127.0.0.1:${address.port}${CALLBACK_PATH}`;
|
|
550
|
+
let closed = false;
|
|
551
|
+
const close = async () => {
|
|
552
|
+
if (closed) return;
|
|
553
|
+
closed = true;
|
|
554
|
+
clearTimeout(timer);
|
|
555
|
+
server.closeAllConnections?.();
|
|
556
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
557
|
+
};
|
|
558
|
+
const timer = setTimeout(() => {
|
|
559
|
+
rejectResult(new Error(`OAuth callback timed out after ${timeoutMs}ms`));
|
|
560
|
+
void close();
|
|
561
|
+
}, timeoutMs);
|
|
562
|
+
result.finally(close).catch(() => {
|
|
563
|
+
});
|
|
564
|
+
return { result, redirectUri, close };
|
|
565
|
+
}
|
|
566
|
+
async function listen(server, port) {
|
|
567
|
+
await new Promise((resolve, reject) => {
|
|
568
|
+
server.once("error", reject);
|
|
569
|
+
server.listen(port, "127.0.0.1", () => {
|
|
570
|
+
server.off("error", reject);
|
|
571
|
+
resolve();
|
|
572
|
+
});
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
function handleRequest(req, res, expectedState, redirectUri, resolveResult, rejectResult) {
|
|
576
|
+
if (req.method !== "GET") {
|
|
577
|
+
res.writeHead(405, { "content-type": "text/plain" }).end("Method Not Allowed");
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
581
|
+
if (url.pathname !== CALLBACK_PATH) {
|
|
582
|
+
res.writeHead(404, { "content-type": "text/plain" }).end("Not Found");
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
const params = url.searchParams;
|
|
586
|
+
const error = params.get("error");
|
|
587
|
+
if (error) {
|
|
588
|
+
const desc = params.get("error_description") ?? "";
|
|
589
|
+
respond(res, 400, errorPage(error, desc));
|
|
590
|
+
rejectResult(new Error(`OAuth authorize returned error: ${error}${desc ? ` \u2014 ${desc}` : ""}`));
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
const state = params.get("state");
|
|
594
|
+
if (!state || !stateMatches(state, expectedState)) {
|
|
595
|
+
respond(res, 400, errorPage("invalid_state", "State parameter did not match."));
|
|
596
|
+
rejectResult(new Error("OAuth state mismatch \u2014 possible CSRF, aborting."));
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
const code = params.get("code");
|
|
600
|
+
if (!code) {
|
|
601
|
+
respond(
|
|
602
|
+
res,
|
|
603
|
+
400,
|
|
604
|
+
errorPage("missing_code", "Authorization code is missing from the redirect.")
|
|
605
|
+
);
|
|
606
|
+
rejectResult(new Error("OAuth redirect did not include `code`."));
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
respond(res, 200, successPage());
|
|
610
|
+
resolveResult({ code, redirectUri });
|
|
611
|
+
}
|
|
612
|
+
function stateMatches(actual, expected) {
|
|
613
|
+
const a = Buffer.from(actual, "utf8");
|
|
614
|
+
const b = Buffer.from(expected, "utf8");
|
|
615
|
+
if (a.length !== b.length) return false;
|
|
616
|
+
return timingSafeEqual(a, b);
|
|
617
|
+
}
|
|
618
|
+
function respond(res, status, body) {
|
|
619
|
+
res.writeHead(status, {
|
|
620
|
+
"content-type": "text/html; charset=utf-8",
|
|
621
|
+
"cache-control": "no-store",
|
|
622
|
+
// Tell the browser not to keep the TCP socket alive — otherwise
|
|
623
|
+
// `server.close()` blocks on the idle keep-alive timeout
|
|
624
|
+
// (Chrome ~5min). Combined with `server.closeAllConnections()`
|
|
625
|
+
// in `close()` this guarantees the CLI exits promptly after the
|
|
626
|
+
// user sees the success page.
|
|
627
|
+
connection: "close"
|
|
628
|
+
}).end(body);
|
|
629
|
+
}
|
|
630
|
+
function successPage() {
|
|
631
|
+
return `<!doctype html><html><head><meta charset="utf-8"><title>Signed in to HeyGen</title>
|
|
632
|
+
<style>body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#0b0f14;color:#e6e8eb}main{max-width:480px;text-align:center;padding:32px;border-radius:12px;background:#11161d;border:1px solid #1f2630}h1{font-weight:600;margin:0 0 8px;color:#3CE6AC}p{margin:0;color:#9aa3ad}</style>
|
|
633
|
+
</head><body><main><h1>You're signed in.</h1><p>You can close this tab and return to your terminal.</p></main></body></html>`;
|
|
634
|
+
}
|
|
635
|
+
function errorPage(code, description) {
|
|
636
|
+
const safeCode = escapeHtml(code);
|
|
637
|
+
const safeDesc = escapeHtml(description);
|
|
638
|
+
return `<!doctype html><html><head><meta charset="utf-8"><title>Sign-in failed</title>
|
|
639
|
+
<style>body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#1a0b0b;color:#e6e8eb}main{max-width:480px;text-align:center;padding:32px;border-radius:12px;background:#1d1111;border:1px solid #301f1f}h1{font-weight:600;margin:0 0 8px;color:#ff7a7a}code{background:#2a1414;padding:2px 6px;border-radius:4px}p{margin:8px 0 0;color:#9aa3ad}</style>
|
|
640
|
+
</head><body><main><h1>Sign-in failed</h1><p><code>${safeCode}</code></p><p>${safeDesc}</p></main></body></html>`;
|
|
641
|
+
}
|
|
642
|
+
function escapeHtml(s) {
|
|
643
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// src/auth/browser.ts
|
|
647
|
+
async function openBrowser(url) {
|
|
648
|
+
if (process.env["BROWSER"] === "none" || process.env["HF_NO_BROWSER"] === "1") {
|
|
649
|
+
printManualInstructions(url);
|
|
650
|
+
return { opened: false };
|
|
651
|
+
}
|
|
652
|
+
try {
|
|
653
|
+
const open = (await import("open")).default;
|
|
654
|
+
await open(url);
|
|
655
|
+
return { opened: true };
|
|
656
|
+
} catch (err) {
|
|
657
|
+
printManualInstructions(url, normalizeErrorMessage(err));
|
|
658
|
+
return { opened: false };
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
function printManualInstructions(url, detail) {
|
|
662
|
+
if (detail) {
|
|
663
|
+
console.error(c.warn(`Could not open browser automatically (${detail}).`));
|
|
664
|
+
} else {
|
|
665
|
+
console.error(c.warn("Browser auto-open is disabled."));
|
|
666
|
+
}
|
|
667
|
+
console.error(`Open this URL manually to continue:
|
|
668
|
+
${c.accent(url)}`);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// src/auth/oauth.ts
|
|
672
|
+
var REVOKE_TIMEOUT_MS = 5e3;
|
|
673
|
+
var MIN_EXPIRES_IN_SECONDS = 30;
|
|
674
|
+
var DEFAULT_CLIENT_ID = "q2A2QRSke2LrFTPJhoDbHtXh";
|
|
675
|
+
var DEFAULT_SCOPES = "openid profile email";
|
|
676
|
+
var DEFAULT_AUTHORIZE_URL = "https://app.heygen.com/oauth/authorize";
|
|
677
|
+
var DEFAULT_TOKEN_URL = "https://api2.heygen.com/v1/oauth/token";
|
|
678
|
+
var DEFAULT_REVOKE_URL = "https://api2.heygen.com/v1/oauth/revoke";
|
|
679
|
+
var DEFAULT_DEVICE_AUTHORIZATION_URL = "https://api2.heygen.com/v1/oauth/device_authorization";
|
|
680
|
+
var DEVICE_CODE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
681
|
+
var MAX_DEVICE_FLOW_SECONDS = 30 * 60;
|
|
682
|
+
var MIN_DEVICE_POLL_SECONDS = 5;
|
|
683
|
+
var MAX_DEVICE_POLL_SECONDS = 60;
|
|
684
|
+
var MAX_DEVICE_RESPONSE_BYTES = 64 * 1024;
|
|
685
|
+
var DEVICE_REQUEST_TIMEOUT_MS = 15e3;
|
|
686
|
+
function authorizeEndpoint() {
|
|
687
|
+
return process.env["HYPERFRAMES_OAUTH_AUTHORIZE_URL"] || DEFAULT_AUTHORIZE_URL;
|
|
688
|
+
}
|
|
689
|
+
function tokenEndpoint() {
|
|
690
|
+
return process.env["HYPERFRAMES_OAUTH_TOKEN_URL"] || DEFAULT_TOKEN_URL;
|
|
691
|
+
}
|
|
692
|
+
function revokeEndpoint() {
|
|
693
|
+
return process.env["HYPERFRAMES_OAUTH_REVOKE_URL"] || DEFAULT_REVOKE_URL;
|
|
694
|
+
}
|
|
695
|
+
function deviceAuthorizationEndpoint() {
|
|
696
|
+
return process.env["HYPERFRAMES_OAUTH_DEVICE_URL"] || DEFAULT_DEVICE_AUTHORIZATION_URL;
|
|
697
|
+
}
|
|
698
|
+
function resolveClientId() {
|
|
699
|
+
const override = process.env["HYPERFRAMES_OAUTH_CLIENT_ID"];
|
|
700
|
+
const id = override && override.length > 0 ? override : DEFAULT_CLIENT_ID;
|
|
701
|
+
if (!id || id.length === 0) throw ErrOAuthNotConfigured();
|
|
702
|
+
return id;
|
|
703
|
+
}
|
|
704
|
+
function assertOAuthConfiguredOrExit() {
|
|
705
|
+
try {
|
|
706
|
+
resolveClientId();
|
|
707
|
+
} catch (err) {
|
|
708
|
+
if (isAuthError(err) && err.code === "OAUTH_NOT_CONFIGURED") {
|
|
709
|
+
console.error(`Error: ${err.message}`);
|
|
710
|
+
if (err.hint) console.error(err.hint);
|
|
711
|
+
failCommand();
|
|
712
|
+
}
|
|
713
|
+
throw err;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
async function startAuthorizationCodeFlow(opts = {}) {
|
|
717
|
+
const clientId = resolveClientId();
|
|
718
|
+
const scope = opts.scope ?? DEFAULT_SCOPES;
|
|
719
|
+
const pkce = generatePkcePair();
|
|
720
|
+
const state = generateState();
|
|
721
|
+
const loopback = await startLoopback({ state, timeoutMs: opts.timeoutMs });
|
|
722
|
+
const authorizeUrl = buildAuthorizeUrl({
|
|
723
|
+
clientId,
|
|
724
|
+
redirectUri: loopback.redirectUri,
|
|
725
|
+
scope,
|
|
726
|
+
state,
|
|
727
|
+
challenge: pkce.challenge
|
|
728
|
+
});
|
|
729
|
+
console.log(`Opening browser to ${c.dim(authorizeHost(authorizeUrl))} ...`);
|
|
730
|
+
const { opened } = await openBrowser(authorizeUrl);
|
|
731
|
+
if (!opened) {
|
|
732
|
+
console.log(c.dim("(open the URL above to continue)"));
|
|
733
|
+
}
|
|
734
|
+
console.log(`Waiting for callback on ${c.accent(loopback.redirectUri)} ...`);
|
|
735
|
+
let codeResult;
|
|
736
|
+
try {
|
|
737
|
+
codeResult = await loopback.result;
|
|
738
|
+
} catch (err) {
|
|
739
|
+
await loopback.close().catch(() => {
|
|
740
|
+
});
|
|
741
|
+
throw err;
|
|
742
|
+
}
|
|
743
|
+
const tokens = await exchangeCodeForTokens({
|
|
744
|
+
clientId,
|
|
745
|
+
code: codeResult.code,
|
|
746
|
+
redirectUri: codeResult.redirectUri,
|
|
747
|
+
verifier: pkce.verifier,
|
|
748
|
+
fetchImpl: opts.fetchImpl
|
|
749
|
+
});
|
|
750
|
+
await persistOAuth(tokens);
|
|
751
|
+
return { tokens };
|
|
752
|
+
}
|
|
753
|
+
async function startDeviceAuthorizationFlow(opts = {}) {
|
|
754
|
+
const runtime = {
|
|
755
|
+
clientId: resolveClientId(),
|
|
756
|
+
fetchImpl: opts.fetchImpl ?? fetch,
|
|
757
|
+
sleepImpl: opts.sleepImpl ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
|
|
758
|
+
now: opts.now ?? Date.now,
|
|
759
|
+
requestTimeoutMs: opts.requestTimeoutMs ?? DEVICE_REQUEST_TIMEOUT_MS
|
|
760
|
+
};
|
|
761
|
+
const issuance = await requestDeviceAuthorization(runtime, opts.scope ?? DEFAULT_SCOPES);
|
|
762
|
+
await opts.onChallenge?.({
|
|
763
|
+
userCode: issuance.userCode,
|
|
764
|
+
verificationUri: issuance.verificationUri,
|
|
765
|
+
...issuance.verificationUriComplete ? { verificationUriComplete: issuance.verificationUriComplete } : {}
|
|
766
|
+
});
|
|
767
|
+
return await pollDeviceToken(runtime, issuance);
|
|
768
|
+
}
|
|
769
|
+
async function requestDeviceAuthorization(runtime, scope) {
|
|
770
|
+
return await withDeviceRequestTimeout(
|
|
771
|
+
runtime,
|
|
772
|
+
"could not reach the authorization server",
|
|
773
|
+
async (signal) => {
|
|
774
|
+
const response = await runtime.fetchImpl(deviceAuthorizationEndpoint(), {
|
|
775
|
+
method: "POST",
|
|
776
|
+
headers: {
|
|
777
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
778
|
+
accept: "application/json"
|
|
779
|
+
},
|
|
780
|
+
body: new URLSearchParams({ client_id: runtime.clientId, scope }).toString(),
|
|
781
|
+
signal
|
|
782
|
+
});
|
|
783
|
+
if (!response.ok) {
|
|
784
|
+
throw ErrDeviceAuthFailed(`authorization server returned HTTP ${response.status}`);
|
|
785
|
+
}
|
|
786
|
+
return parseDeviceAuthorizationResponse(await readJsonOrDeviceError(response));
|
|
787
|
+
}
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
async function pollDeviceToken(runtime, issuance) {
|
|
791
|
+
const deadline = runtime.now() + Math.min(issuance.expiresIn, MAX_DEVICE_FLOW_SECONDS) * 1e3;
|
|
792
|
+
let intervalSeconds = issuance.interval;
|
|
793
|
+
while (runtime.now() < deadline) {
|
|
794
|
+
const remainingMs = deadline - runtime.now();
|
|
795
|
+
if (remainingMs <= 0) break;
|
|
796
|
+
await runtime.sleepImpl(Math.min(intervalSeconds * 1e3, remainingMs));
|
|
797
|
+
const result = await requestDeviceToken(runtime, issuance.deviceCode);
|
|
798
|
+
if (result.tokens) return result.tokens;
|
|
799
|
+
if (result.slowDown) {
|
|
800
|
+
intervalSeconds = Math.min(
|
|
801
|
+
Math.max(intervalSeconds + 5, result.retryAfterSeconds ?? 0),
|
|
802
|
+
MAX_DEVICE_POLL_SECONDS
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
throw ErrDeviceAuthFailed("the code expired");
|
|
807
|
+
}
|
|
808
|
+
async function requestDeviceToken(runtime, deviceCode) {
|
|
809
|
+
return await withDeviceRequestTimeout(
|
|
810
|
+
runtime,
|
|
811
|
+
"lost contact with the authorization server",
|
|
812
|
+
async (signal) => {
|
|
813
|
+
const response = await runtime.fetchImpl(tokenEndpoint(), {
|
|
814
|
+
method: "POST",
|
|
815
|
+
headers: {
|
|
816
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
817
|
+
accept: "application/json"
|
|
818
|
+
},
|
|
819
|
+
body: new URLSearchParams({
|
|
820
|
+
grant_type: DEVICE_CODE_GRANT_TYPE,
|
|
821
|
+
device_code: deviceCode,
|
|
822
|
+
client_id: runtime.clientId
|
|
823
|
+
}).toString(),
|
|
824
|
+
signal
|
|
825
|
+
});
|
|
826
|
+
return await evaluateDevicePollResponse(response, runtime.now());
|
|
827
|
+
}
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
async function evaluateDevicePollResponse(response, nowMs) {
|
|
831
|
+
if (response.ok) {
|
|
832
|
+
return { tokens: parseTokenResponse(await readJsonOrDeviceError(response)) };
|
|
833
|
+
}
|
|
834
|
+
const error = await readDeviceOAuthError(response);
|
|
835
|
+
switch (error) {
|
|
836
|
+
case "authorization_pending":
|
|
837
|
+
return {};
|
|
838
|
+
case "slow_down":
|
|
839
|
+
return { slowDown: true, retryAfterSeconds: retryAfterSeconds(response, nowMs) };
|
|
840
|
+
case "access_denied":
|
|
841
|
+
throw ErrDeviceAuthFailed("access was denied");
|
|
842
|
+
case "expired_token":
|
|
843
|
+
throw ErrDeviceAuthFailed("the code expired");
|
|
844
|
+
default:
|
|
845
|
+
if (response.status === 429) {
|
|
846
|
+
return { slowDown: true, retryAfterSeconds: retryAfterSeconds(response, nowMs) };
|
|
847
|
+
}
|
|
848
|
+
throw ErrDeviceAuthFailed(`authorization server returned HTTP ${response.status}`);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
async function withDeviceRequestTimeout(runtime, networkError, operation) {
|
|
852
|
+
const controller = new AbortController();
|
|
853
|
+
const timer = setTimeout(() => controller.abort(), runtime.requestTimeoutMs);
|
|
854
|
+
try {
|
|
855
|
+
return await operation(controller.signal);
|
|
856
|
+
} catch (err) {
|
|
857
|
+
if (controller.signal.aborted) {
|
|
858
|
+
throw ErrDeviceAuthFailed("authorization server request timed out");
|
|
859
|
+
}
|
|
860
|
+
if (isAuthError(err)) throw err;
|
|
861
|
+
throw ErrDeviceAuthFailed(networkError);
|
|
862
|
+
} finally {
|
|
863
|
+
clearTimeout(timer);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
function retryAfterSeconds(response, nowMs) {
|
|
867
|
+
const value = response.headers.get("retry-after")?.trim();
|
|
868
|
+
if (!value) return void 0;
|
|
869
|
+
if (/^\d+$/.test(value)) return Math.min(Number(value), MAX_DEVICE_POLL_SECONDS);
|
|
870
|
+
const retryAt = Date.parse(value);
|
|
871
|
+
if (!Number.isFinite(retryAt)) return void 0;
|
|
872
|
+
return Math.min(Math.max(Math.ceil((retryAt - nowMs) / 1e3), 0), MAX_DEVICE_POLL_SECONDS);
|
|
873
|
+
}
|
|
874
|
+
async function refreshTokens(refresh_token, opts = {}) {
|
|
875
|
+
const clientId = resolveClientId();
|
|
876
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
877
|
+
const body = new URLSearchParams({
|
|
878
|
+
grant_type: "refresh_token",
|
|
879
|
+
refresh_token,
|
|
880
|
+
client_id: clientId
|
|
881
|
+
});
|
|
882
|
+
const res = await fetchImpl(tokenEndpoint(), {
|
|
883
|
+
method: "POST",
|
|
884
|
+
headers: {
|
|
885
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
886
|
+
accept: "application/json"
|
|
887
|
+
},
|
|
888
|
+
body: body.toString()
|
|
889
|
+
});
|
|
890
|
+
if (res.status === 400 || res.status === 401) {
|
|
891
|
+
throw ErrRefreshFailed(await safeText2(res));
|
|
892
|
+
}
|
|
893
|
+
if (!res.ok) {
|
|
894
|
+
throw ErrApi(res.status, await safeText2(res) || res.statusText);
|
|
895
|
+
}
|
|
896
|
+
const payload = await readJsonOrThrow(res);
|
|
897
|
+
const tokens = parseTokenResponse(payload);
|
|
898
|
+
await persistOAuth(tokens, { refreshed: refresh_token });
|
|
899
|
+
return tokens;
|
|
900
|
+
}
|
|
901
|
+
async function revokeTokens(token, opts = {}) {
|
|
902
|
+
let clientId;
|
|
903
|
+
try {
|
|
904
|
+
clientId = resolveClientId();
|
|
905
|
+
} catch {
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
909
|
+
const params = { token, client_id: clientId };
|
|
910
|
+
if (opts.token_type_hint) params["token_type_hint"] = opts.token_type_hint;
|
|
911
|
+
const body = new URLSearchParams(params);
|
|
912
|
+
const controller = new AbortController();
|
|
913
|
+
const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? REVOKE_TIMEOUT_MS);
|
|
914
|
+
try {
|
|
915
|
+
const res = await fetchImpl(revokeEndpoint(), {
|
|
916
|
+
method: "POST",
|
|
917
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
918
|
+
body: body.toString(),
|
|
919
|
+
signal: controller.signal
|
|
920
|
+
});
|
|
921
|
+
if (!res.ok) {
|
|
922
|
+
console.error(
|
|
923
|
+
c.dim(`Note: token revoke returned HTTP ${res.status}; local credentials cleared anyway.`)
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
} catch {
|
|
927
|
+
} finally {
|
|
928
|
+
clearTimeout(timer);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
function authorizeHost(fullUrl) {
|
|
932
|
+
try {
|
|
933
|
+
const u = new URL(fullUrl);
|
|
934
|
+
return `${u.origin}${u.pathname}`;
|
|
935
|
+
} catch {
|
|
936
|
+
return fullUrl.split("?")[0] ?? fullUrl;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
function buildAuthorizeUrl(args) {
|
|
940
|
+
const params = new URLSearchParams({
|
|
941
|
+
response_type: "code",
|
|
942
|
+
client_id: args.clientId,
|
|
943
|
+
redirect_uri: args.redirectUri,
|
|
944
|
+
scope: args.scope,
|
|
945
|
+
state: args.state,
|
|
946
|
+
code_challenge: args.challenge,
|
|
947
|
+
code_challenge_method: "S256"
|
|
948
|
+
});
|
|
949
|
+
return `${authorizeEndpoint()}?${params.toString()}`;
|
|
950
|
+
}
|
|
951
|
+
async function exchangeCodeForTokens(args) {
|
|
952
|
+
const fetchImpl = args.fetchImpl ?? fetch;
|
|
953
|
+
const body = new URLSearchParams({
|
|
954
|
+
grant_type: "authorization_code",
|
|
955
|
+
code: args.code,
|
|
956
|
+
redirect_uri: args.redirectUri,
|
|
957
|
+
client_id: args.clientId,
|
|
958
|
+
code_verifier: args.verifier
|
|
959
|
+
});
|
|
960
|
+
const res = await fetchImpl(tokenEndpoint(), {
|
|
961
|
+
method: "POST",
|
|
962
|
+
headers: {
|
|
963
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
964
|
+
accept: "application/json"
|
|
965
|
+
},
|
|
966
|
+
body: body.toString()
|
|
967
|
+
});
|
|
968
|
+
if (res.status === 400 || res.status === 401) {
|
|
969
|
+
const detail = await safeText2(res) || res.statusText;
|
|
970
|
+
throw ErrRefreshFailed(
|
|
971
|
+
`authorization code rejected (${detail}); please run \`auth login\` again`
|
|
972
|
+
);
|
|
973
|
+
}
|
|
974
|
+
if (!res.ok) {
|
|
975
|
+
throw ErrApi(res.status, await safeText2(res) || res.statusText);
|
|
976
|
+
}
|
|
977
|
+
return parseTokenResponse(await readJsonOrThrow(res));
|
|
978
|
+
}
|
|
979
|
+
function parseTokenResponse(payload) {
|
|
980
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
981
|
+
throw ErrRefreshFailed("token endpoint returned a non-object payload");
|
|
982
|
+
}
|
|
983
|
+
const obj = payload;
|
|
984
|
+
const accessToken = stringField(obj, "access_token");
|
|
985
|
+
if (!accessToken) {
|
|
986
|
+
throw ErrRefreshFailed("token endpoint did not return an access_token");
|
|
987
|
+
}
|
|
988
|
+
if (!isHeaderSafe(accessToken)) {
|
|
989
|
+
throw ErrRefreshFailed("access_token contains control characters");
|
|
990
|
+
}
|
|
991
|
+
const out = { access_token: accessToken };
|
|
992
|
+
const refreshToken = stringField(obj, "refresh_token");
|
|
993
|
+
if (refreshToken) {
|
|
994
|
+
if (!isHeaderSafe(refreshToken)) {
|
|
995
|
+
throw ErrRefreshFailed("refresh_token contains control characters");
|
|
996
|
+
}
|
|
997
|
+
out.refresh_token = refreshToken;
|
|
998
|
+
}
|
|
999
|
+
const tokenType = stringField(obj, "token_type");
|
|
1000
|
+
if (tokenType) out.token_type = tokenType;
|
|
1001
|
+
const scope = stringField(obj, "scope");
|
|
1002
|
+
if (scope) out.scope = scope;
|
|
1003
|
+
const expiresIn = numericField(obj, "expires_in");
|
|
1004
|
+
if (expiresIn !== void 0) {
|
|
1005
|
+
const clamped = Math.max(expiresIn, MIN_EXPIRES_IN_SECONDS);
|
|
1006
|
+
out.expires_at = new Date(Date.now() + clamped * 1e3).toISOString();
|
|
1007
|
+
}
|
|
1008
|
+
return out;
|
|
1009
|
+
}
|
|
1010
|
+
function stringField(obj, key) {
|
|
1011
|
+
const v = obj[key];
|
|
1012
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
1013
|
+
}
|
|
1014
|
+
function numericField(obj, key) {
|
|
1015
|
+
const v = obj[key];
|
|
1016
|
+
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
1017
|
+
if (typeof v === "string") {
|
|
1018
|
+
const n = Number.parseFloat(v);
|
|
1019
|
+
return Number.isFinite(n) ? n : void 0;
|
|
1020
|
+
}
|
|
1021
|
+
return void 0;
|
|
1022
|
+
}
|
|
1023
|
+
async function persistOAuth(tokens, opts = {}) {
|
|
1024
|
+
let existing = {};
|
|
1025
|
+
try {
|
|
1026
|
+
const { credentials } = await readStore();
|
|
1027
|
+
existing = credentials;
|
|
1028
|
+
} catch (err) {
|
|
1029
|
+
if (opts.refreshed !== void 0) throw err;
|
|
1030
|
+
}
|
|
1031
|
+
if (opts.refreshed !== void 0 && existing.oauth?.refresh_token !== opts.refreshed) {
|
|
1032
|
+
throw ErrLoginChanged();
|
|
1033
|
+
}
|
|
1034
|
+
const oauth = opts.refreshed !== void 0 ? { ...existing.oauth, ...tokens } : { ...tokens };
|
|
1035
|
+
await writeStore({ ...existing, oauth });
|
|
1036
|
+
}
|
|
1037
|
+
async function persistVerifiedOAuthSession(tokens, user) {
|
|
1038
|
+
let credentials = {};
|
|
1039
|
+
try {
|
|
1040
|
+
({ credentials } = await readStore());
|
|
1041
|
+
} catch {
|
|
1042
|
+
credentials = {};
|
|
1043
|
+
}
|
|
1044
|
+
const next = {
|
|
1045
|
+
...credentials,
|
|
1046
|
+
oauth: { ...tokens }
|
|
1047
|
+
};
|
|
1048
|
+
if (user.email || user.first_name || user.last_name || user.username) {
|
|
1049
|
+
next.user = {
|
|
1050
|
+
...credentials.user,
|
|
1051
|
+
email: user.email,
|
|
1052
|
+
first_name: user.first_name,
|
|
1053
|
+
last_name: user.last_name,
|
|
1054
|
+
username: user.username
|
|
1055
|
+
};
|
|
1056
|
+
} else {
|
|
1057
|
+
delete next.user;
|
|
1058
|
+
}
|
|
1059
|
+
await writeStore(next);
|
|
1060
|
+
}
|
|
1061
|
+
function parseDeviceAuthorizationResponse(payload) {
|
|
1062
|
+
const data = requireDeviceAuthorizationRecord(payload);
|
|
1063
|
+
const deviceCode = stringField(data, "device_code");
|
|
1064
|
+
const userCode = stringField(data, "user_code");
|
|
1065
|
+
const verificationUri = requiredSafeVerificationUri(data, "verification_uri");
|
|
1066
|
+
const verificationUriComplete = optionalSafeVerificationUri(data, "verification_uri_complete");
|
|
1067
|
+
const expiresIn = strictNumericField(data, "expires_in");
|
|
1068
|
+
const interval = strictNumericField(data, "interval");
|
|
1069
|
+
requireSafeDeviceCode(deviceCode);
|
|
1070
|
+
requireSafeDeviceCode(userCode);
|
|
1071
|
+
const timing = normalizeDeviceAuthorizationTiming(data, expiresIn, interval);
|
|
1072
|
+
return {
|
|
1073
|
+
deviceCode,
|
|
1074
|
+
userCode,
|
|
1075
|
+
verificationUri,
|
|
1076
|
+
...verificationUriComplete ? { verificationUriComplete } : {},
|
|
1077
|
+
...timing
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
function requireSafeDeviceCode(value) {
|
|
1081
|
+
if (!value || !isHeaderSafe(value)) {
|
|
1082
|
+
throw ErrDeviceAuthFailed("authorization server returned an invalid response");
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
function normalizeDeviceAuthorizationTiming(data, expiresIn, interval) {
|
|
1086
|
+
if (!isPositiveNumber(expiresIn) || data["interval"] !== void 0 && !isPositiveNumber(interval)) {
|
|
1087
|
+
throw ErrDeviceAuthFailed("authorization server returned invalid timing values");
|
|
1088
|
+
}
|
|
1089
|
+
return {
|
|
1090
|
+
expiresIn,
|
|
1091
|
+
interval: Math.min(
|
|
1092
|
+
Math.max(Math.ceil(interval ?? MIN_DEVICE_POLL_SECONDS), MIN_DEVICE_POLL_SECONDS),
|
|
1093
|
+
MAX_DEVICE_POLL_SECONDS
|
|
1094
|
+
)
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
function requiredSafeVerificationUri(data, key) {
|
|
1098
|
+
const value = normalizeSafeVerificationUri(stringField(data, key));
|
|
1099
|
+
if (!value) throw ErrDeviceAuthFailed("authorization server returned an unsafe verification URL");
|
|
1100
|
+
return value;
|
|
1101
|
+
}
|
|
1102
|
+
function optionalSafeVerificationUri(data, key) {
|
|
1103
|
+
if (data[key] === void 0) return void 0;
|
|
1104
|
+
return requiredSafeVerificationUri(data, key);
|
|
1105
|
+
}
|
|
1106
|
+
function requireDeviceAuthorizationRecord(payload) {
|
|
1107
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
1108
|
+
throw ErrDeviceAuthFailed("authorization server returned an invalid response");
|
|
1109
|
+
}
|
|
1110
|
+
return payload;
|
|
1111
|
+
}
|
|
1112
|
+
function isPositiveNumber(value) {
|
|
1113
|
+
return value !== void 0 && value > 0;
|
|
1114
|
+
}
|
|
1115
|
+
function normalizeSafeVerificationUri(value) {
|
|
1116
|
+
if (!value || !isHeaderSafe(value)) return void 0;
|
|
1117
|
+
try {
|
|
1118
|
+
const url = new URL(value);
|
|
1119
|
+
if (url.username || url.password) return void 0;
|
|
1120
|
+
const allowed = url.protocol === "https:" || url.protocol === "http:" && ["127.0.0.1", "localhost"].includes(url.hostname);
|
|
1121
|
+
return allowed ? url.href : void 0;
|
|
1122
|
+
} catch {
|
|
1123
|
+
return void 0;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
async function readJsonOrDeviceError(res) {
|
|
1127
|
+
return await readBoundedDeviceJson(res);
|
|
1128
|
+
}
|
|
1129
|
+
async function readDeviceOAuthError(res) {
|
|
1130
|
+
try {
|
|
1131
|
+
const payload = await readBoundedDeviceJson(res);
|
|
1132
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) return void 0;
|
|
1133
|
+
const error = payload["error"];
|
|
1134
|
+
return typeof error === "string" ? error : void 0;
|
|
1135
|
+
} catch {
|
|
1136
|
+
return void 0;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
function strictNumericField(obj, key) {
|
|
1140
|
+
const value = obj[key];
|
|
1141
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
1142
|
+
if (typeof value !== "string" || value.trim() === "") return void 0;
|
|
1143
|
+
const parsed = Number(value);
|
|
1144
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
1145
|
+
}
|
|
1146
|
+
async function readBoundedDeviceJson(res) {
|
|
1147
|
+
if (!res.body) throw ErrDeviceAuthFailed("authorization server returned no data");
|
|
1148
|
+
const reader = res.body.getReader();
|
|
1149
|
+
const chunks = [];
|
|
1150
|
+
let total = 0;
|
|
1151
|
+
try {
|
|
1152
|
+
while (true) {
|
|
1153
|
+
const { done, value } = await reader.read();
|
|
1154
|
+
if (done) break;
|
|
1155
|
+
if (!value) continue;
|
|
1156
|
+
total += value.byteLength;
|
|
1157
|
+
if (total > MAX_DEVICE_RESPONSE_BYTES) {
|
|
1158
|
+
await reader.cancel();
|
|
1159
|
+
throw ErrDeviceAuthFailed("authorization server response was too large");
|
|
1160
|
+
}
|
|
1161
|
+
chunks.push(value);
|
|
1162
|
+
}
|
|
1163
|
+
const body = new Uint8Array(total);
|
|
1164
|
+
let offset = 0;
|
|
1165
|
+
for (const chunk of chunks) {
|
|
1166
|
+
body.set(chunk, offset);
|
|
1167
|
+
offset += chunk.byteLength;
|
|
1168
|
+
}
|
|
1169
|
+
return JSON.parse(new TextDecoder().decode(body));
|
|
1170
|
+
} catch (err) {
|
|
1171
|
+
if (isAuthError(err)) throw err;
|
|
1172
|
+
throw ErrDeviceAuthFailed("authorization server returned non-JSON data");
|
|
1173
|
+
} finally {
|
|
1174
|
+
reader.releaseLock();
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
async function readJsonOrThrow(res) {
|
|
1178
|
+
try {
|
|
1179
|
+
return await res.json();
|
|
1180
|
+
} catch (err) {
|
|
1181
|
+
throw ErrApi(res.status, `non-JSON body: ${err.message}`);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
async function safeText2(res) {
|
|
1185
|
+
try {
|
|
1186
|
+
return scrubCredentials((await res.text()).slice(0, 500));
|
|
1187
|
+
} catch {
|
|
1188
|
+
return "";
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
export {
|
|
1193
|
+
isAuthError,
|
|
1194
|
+
apiBaseUrl,
|
|
1195
|
+
AuthClient,
|
|
1196
|
+
buildAuthHeaders,
|
|
1197
|
+
configDir,
|
|
1198
|
+
credentialPath,
|
|
1199
|
+
readStore,
|
|
1200
|
+
writeStore,
|
|
1201
|
+
deleteStore,
|
|
1202
|
+
hasPreservedUnknownData,
|
|
1203
|
+
clearOAuth,
|
|
1204
|
+
isHeaderSafe,
|
|
1205
|
+
resolveCredential,
|
|
1206
|
+
tryResolveCredential,
|
|
1207
|
+
isTokenExpired,
|
|
1208
|
+
assertOAuthConfiguredOrExit,
|
|
1209
|
+
startAuthorizationCodeFlow,
|
|
1210
|
+
startDeviceAuthorizationFlow,
|
|
1211
|
+
refreshTokens,
|
|
1212
|
+
revokeTokens,
|
|
1213
|
+
persistVerifiedOAuthSession
|
|
1214
|
+
};
|