@astralyn/sash 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/CHANGELOG.md +184 -0
- package/LICENSE +21 -0
- package/README.md +71 -0
- package/THIRD_PARTY_NOTICES.md +54 -0
- package/dist/api.js +103 -0
- package/dist/browser.js +25 -0
- package/dist/cli-errors.js +15 -0
- package/dist/cli.js +122 -0
- package/dist/commands/lifecycle.js +50 -0
- package/dist/commands/logs.js +54 -0
- package/dist/commands/shared.js +8 -0
- package/dist/commands/status.js +39 -0
- package/dist/commands/update.js +5 -0
- package/dist/commands/upgrade.js +43 -0
- package/dist/commands/web.js +33 -0
- package/dist/contracts.js +412 -0
- package/dist/core-config-validation.js +72 -0
- package/dist/core-install-record.js +55 -0
- package/dist/core-install-transaction.js +114 -0
- package/dist/core-update-coordination.js +105 -0
- package/dist/core-update-service.js +245 -0
- package/dist/core-update.js +804 -0
- package/dist/core-version.js +18 -0
- package/dist/core.js +206 -0
- package/dist/daemon/app.js +157 -0
- package/dist/daemon/context.js +40 -0
- package/dist/daemon/entry.js +67 -0
- package/dist/daemon/errors.js +47 -0
- package/dist/daemon/handlers/core.js +17 -0
- package/dist/daemon/handlers/daemon.js +66 -0
- package/dist/daemon/handlers/profiles.js +57 -0
- package/dist/daemon/handlers/proxy.js +12 -0
- package/dist/daemon/handlers/settings.js +48 -0
- package/dist/daemon/router.js +312 -0
- package/dist/daemon/scheduler.js +33 -0
- package/dist/daemon/server.js +121 -0
- package/dist/daemon-auth.js +71 -0
- package/dist/daemon-client.js +55 -0
- package/dist/daemon-entry.js +13 -0
- package/dist/daemon-http.js +93 -0
- package/dist/daemon-lifecycle.js +378 -0
- package/dist/daemon-proxy.js +176 -0
- package/dist/daemon-static.js +106 -0
- package/dist/daemon.js +3 -0
- package/dist/error-utils.js +14 -0
- package/dist/fs-atomic.js +123 -0
- package/dist/github.js +187 -0
- package/dist/http.js +282 -0
- package/dist/json-shape.js +17 -0
- package/dist/log-follow.js +280 -0
- package/dist/log.js +17 -0
- package/dist/managed-state-transaction.js +377 -0
- package/dist/mihomo-config.js +334 -0
- package/dist/node-version-guard.js +8 -0
- package/dist/offline-mutation.js +58 -0
- package/dist/paths.js +57 -0
- package/dist/process.js +572 -0
- package/dist/profile-migration.js +101 -0
- package/dist/profile-service.js +667 -0
- package/dist/profiles.js +182 -0
- package/dist/runtime-lifecycle.js +205 -0
- package/dist/runtime-owner.js +87 -0
- package/dist/runtime-recovery.js +31 -0
- package/dist/sash-client.js +163 -0
- package/dist/settings-service.js +242 -0
- package/dist/settings.js +314 -0
- package/dist/state-lock.js +331 -0
- package/dist/status.js +279 -0
- package/dist/supervisor.js +301 -0
- package/dist/sysproxy/common.js +99 -0
- package/dist/sysproxy/darwin.js +287 -0
- package/dist/sysproxy/factory.js +71 -0
- package/dist/sysproxy/gnome.js +181 -0
- package/dist/sysproxy/legacy.js +58 -0
- package/dist/sysproxy/snapshot.js +284 -0
- package/dist/sysproxy/types.js +24 -0
- package/dist/sysproxy/windows.js +216 -0
- package/dist/sysproxy.js +8 -0
- package/dist/system-proxy-manager.js +460 -0
- package/dist/tun-guidance.js +11 -0
- package/dist/ui/assets/05129d5ad91a6181d272cc3d031363d6-DJkDXMrK.woff2 +0 -0
- package/dist/ui/assets/0526ebf94418638dfd5b6cd9b06c07d4-BzWe4Lji.woff2 +0 -0
- package/dist/ui/assets/053f2647a78f659f6f8a3ae8436bd265-BocXYDl5.woff2 +0 -0
- package/dist/ui/assets/078f666863424d3fd2d98e3ea528704c-DQ_QCvOt.woff2 +0 -0
- package/dist/ui/assets/07f3ff379663ffa0222c12f241421dd9-Cma7oDlr.woff2 +0 -0
- package/dist/ui/assets/08427b8d865853bbd7c439321b26495f-CJmC8fWx.woff2 +0 -0
- package/dist/ui/assets/095224e4db29d40c54098da02b266b0a-DjsP0nQn.woff2 +0 -0
- package/dist/ui/assets/0ada18ca45940b08accde5c61ee871e3-E1BZD3RX.woff2 +0 -0
- package/dist/ui/assets/0be242294f7d791af850c6df38ac78a0-2cL6Ntwf.woff2 +0 -0
- package/dist/ui/assets/0bf18c938d0c27cce06c39f855405fdb-CruLZZZJ.woff2 +0 -0
- package/dist/ui/assets/0cfb3e9f4edf60839c37dc83e6f75ea3-DzAtRHvi.woff2 +0 -0
- package/dist/ui/assets/0fbbd340d0467dfe3101d58846f30cb0-gtFcO250.woff2 +0 -0
- package/dist/ui/assets/1063fa2dc7334d1f383e30824e016eae-B7U-kD-0.woff2 +0 -0
- package/dist/ui/assets/109e26e62ddc85d946e699464afbece7-BLnUjAEV.woff2 +0 -0
- package/dist/ui/assets/12a443b0ae9748a993b5395f8fad412b-Btjff2Lz.woff2 +0 -0
- package/dist/ui/assets/135c4621de7a4d85d852e03d416f13ee-DdSuW36e.woff2 +0 -0
- package/dist/ui/assets/13aa415469ee761c968749b1c0c56ec6-Dwe-Wa_w.woff2 +0 -0
- package/dist/ui/assets/1435b1ad447bd9c0e8bc52035c9dcfa8-C05ldXtw.woff2 +0 -0
- package/dist/ui/assets/175e0915aa874e7446b79b6bc9b00721-Dp0-l77L.woff2 +0 -0
- package/dist/ui/assets/1876e7d02187f006e2b7f769391c3089-CNjpRdap.woff2 +0 -0
- package/dist/ui/assets/1886dc284b3b845e3b5fe04aa2107276-Bh_wHwL1.woff2 +0 -0
- package/dist/ui/assets/19a3dda6611aaf5d787403bd1159fe15-zoEBvdpA.woff2 +0 -0
- package/dist/ui/assets/1afa74e14da193125e45d4783d358a4f-BgjSTENX.woff2 +0 -0
- package/dist/ui/assets/1cd26a6a6d784720b4a43053e9058bcf-TAP3dvNi.woff2 +0 -0
- package/dist/ui/assets/1ce19bddc3beab385a863b1e05685678-BCdXitZw.woff2 +0 -0
- package/dist/ui/assets/1d3459ac6578c80502bdb876a4824a93-CSwdnEGP.woff2 +0 -0
- package/dist/ui/assets/1d479e364dab4af01c539f0a6a7ac036-ZFI-djGt.woff2 +0 -0
- package/dist/ui/assets/1dcea2408d17fcec4197adce50f8b32d-CnK2xXR-.woff2 +0 -0
- package/dist/ui/assets/1e855385699999e24a33f7df8aed0489-DGFHkDVQ.woff2 +0 -0
- package/dist/ui/assets/1f55944b8f7972580e3029694462a6b0-CB7ogVJ9.woff2 +0 -0
- package/dist/ui/assets/1f96eda70929089762dc3c4feb33f9c8-DtSQ6YOf.woff2 +0 -0
- package/dist/ui/assets/1fb275532caadc746455881b31da27c4-BHFTsg74.woff2 +0 -0
- package/dist/ui/assets/20e679bdc00d06f802ea71fd9154b284-D9gRjq_v.woff2 +0 -0
- package/dist/ui/assets/25aff66c4a9f8cb801cbd525f4a923e4-Dgi87hP7.woff2 +0 -0
- package/dist/ui/assets/28e6700380b023b23e77f2d75aee624f-b19D855Q.woff2 +0 -0
- package/dist/ui/assets/2a1c50aa9cd99ce3a0197f5d49948e63-DrztdXCB.woff2 +0 -0
- package/dist/ui/assets/2b4e0ae0bf3af610b97717dfd66a012d-CBoapvha.woff2 +0 -0
- package/dist/ui/assets/2be2b7a672b616bc2f07059a67bfaad8-BUR0aNML.woff2 +0 -0
- package/dist/ui/assets/2e0a358ada78ea98ec8ba86002a27eac-DvgbSr9v.woff2 +0 -0
- package/dist/ui/assets/2e1cf63a2a22a50516c49b1dc521ea8a-CmltIxig.woff2 +0 -0
- package/dist/ui/assets/2e4481801925fcb6573c4337c73f15d7-DYOoCk-m.woff2 +0 -0
- package/dist/ui/assets/2fe5e634c568cd874f94d24b8f02bfd1-DcEHY35G.woff2 +0 -0
- package/dist/ui/assets/309c33f63f29887fb557115aa24d4bb5-CUgqrXIj.woff2 +0 -0
- package/dist/ui/assets/3158f45c959e1b346b0bbd6f3193dbf0-kimcClqp.woff2 +0 -0
- package/dist/ui/assets/316adbc8037a36f8d804637b053bbe5e-CjbZmJf9.woff2 +0 -0
- package/dist/ui/assets/319e9631bc29fc7235b70fc9aac43cd9-IV6yZuHZ.woff2 +0 -0
- package/dist/ui/assets/32054f9bb88d9431b1cdf023f770e614-CYrpCgqK.woff2 +0 -0
- package/dist/ui/assets/3245fa1aac6338c1d9d04befb7c346f8-CzvPhVPA.woff2 +0 -0
- package/dist/ui/assets/326c730f98afa476057957f2743c81e2-GPHJ3Fpu.woff2 +0 -0
- package/dist/ui/assets/33885558dc783bf9bae6c5d4668fef07-D33us0yR.woff2 +0 -0
- package/dist/ui/assets/33cd11f5e61556e4618801c8231f2744-CoR_Tv3X.woff2 +0 -0
- package/dist/ui/assets/34a170749cb7e6c5851acc510882af6b-BCZwsihk.woff2 +0 -0
- package/dist/ui/assets/3538de2d387591258d7e9908aad803b9-CewOkERZ.woff2 +0 -0
- package/dist/ui/assets/38d7b029c036080067a2e94211098171-CettR5Qv.woff2 +0 -0
- package/dist/ui/assets/393f47efeefc9f9e9cca83eb10a82c69-Brhz4z1y.woff2 +0 -0
- package/dist/ui/assets/396a51f2b274d01f6ba606a94f3e5fe2-DgRk-jtI.woff2 +0 -0
- package/dist/ui/assets/3991bf955d4c925e84b4a6542760d4d5-II4HtRkQ.woff2 +0 -0
- package/dist/ui/assets/39b6cb6ae8d1ea0e9832b88d2c21ef99-CbJm-q6b.woff2 +0 -0
- package/dist/ui/assets/3a1133157fbd259f1a51aaa9f8418a26-3FmUjjvi.woff2 +0 -0
- package/dist/ui/assets/3a34cff07dca7a65ed2486be19229290-B7ml2yBN.woff2 +0 -0
- package/dist/ui/assets/3c339dd7c27e6b8a06eea431733e076f-dGQqXaEj.woff2 +0 -0
- package/dist/ui/assets/3d074ea67f60953b816ce7cf5d87a980-B5VkPOmg.woff2 +0 -0
- package/dist/ui/assets/3d38f54dcf4a9f4a50165d5849becf71-CVDtFSZn.woff2 +0 -0
- package/dist/ui/assets/3e3fc9a19a27f94e4ff1b815b55b2671-Ci736GLi.woff2 +0 -0
- package/dist/ui/assets/3e8abb1f606f29e2f0a8a8a6b702d263-C5sOSf5L.woff2 +0 -0
- package/dist/ui/assets/3f0ab4e1cd99bdbfdf9acbc8f4bcb9ce-0DcdTLxV.woff2 +0 -0
- package/dist/ui/assets/3f30c0482650345c981d66920f56ab61-CTD2CsZI.woff2 +0 -0
- package/dist/ui/assets/41a9aa12ad9a60758b304c1a998fb781-BTQUDLf1.woff2 +0 -0
- package/dist/ui/assets/424010b2bc5cee540b92b28da49b61bf-DT8upW2M.woff2 +0 -0
- package/dist/ui/assets/42fbdafff2d44b76c6665d51bb2cee9d-_UrojhXD.woff2 +0 -0
- package/dist/ui/assets/4341db13c311b3cb0eaaf6b4c71b89e5-CzjA7MzG.woff2 +0 -0
- package/dist/ui/assets/434db5a796128131fde78d4389d14b71-AeNdWKua.woff2 +0 -0
- package/dist/ui/assets/43cb51fc70a15274d49e2d956c5ec3b4-BQbufd96.woff2 +0 -0
- package/dist/ui/assets/43e79de1c7815f21efbc966ff96fcbd6-DlCQvOsQ.woff2 +0 -0
- package/dist/ui/assets/43faf6a8a3cde1088bd5f7c830890a89-SvDzF3nA.woff2 +0 -0
- package/dist/ui/assets/44731ae21d7690ce538d0f8242755833-CEmu9Z88.woff2 +0 -0
- package/dist/ui/assets/45324b2a64cc0c0db797d5c09e239d34-BuFudtvM.woff2 +0 -0
- package/dist/ui/assets/4584df05d00aa75ae6e1f850fdc9df1d-GNHt6xwM.woff2 +0 -0
- package/dist/ui/assets/48d539539e98481fb511a761031c59fd-Cd9gdi8B.woff2 +0 -0
- package/dist/ui/assets/49a1fb9fc6a35796b2e0d3539088ede8-CD1cRDOy.woff2 +0 -0
- package/dist/ui/assets/4bec02eb0c2371e59bfb7d41a141ea1e-CmBnNPo0.woff2 +0 -0
- package/dist/ui/assets/4c5a81ef5683f6fbf9935e640de804e7-B4wQxzVs.woff2 +0 -0
- package/dist/ui/assets/4f11c9c75e86214b7f69ddee3a9f8076-DHsQ2xpE.woff2 +0 -0
- package/dist/ui/assets/50434b8ff88e27101d1c67ba953ee873-PH_hIqxu.woff2 +0 -0
- package/dist/ui/assets/5107fd5153d52c6a3f8d43ff214dd6c2-ls3eo5Qd.woff2 +0 -0
- package/dist/ui/assets/520cb7d3683dee99e767650efc0aa5b1-Lkd4z-9S.woff2 +0 -0
- package/dist/ui/assets/5455087df2f091b7bf3d38c5a102a2e7-QNkiOxwe.woff2 +0 -0
- package/dist/ui/assets/556450fdf0978d329cf8277e3b71dcdb-CtypGAPw.woff2 +0 -0
- package/dist/ui/assets/5a1b5c1b71cad50c51a79a7f4825e6e6-DQA407Ec.woff2 +0 -0
- package/dist/ui/assets/5ba02e809d2ef4f7639178e7a7d654c0-Dty0omtl.woff2 +0 -0
- package/dist/ui/assets/5bd654afe48e094f95e5142e4eaadc75-D9pUq71R.woff2 +0 -0
- package/dist/ui/assets/5c4c3ca0a3f4115879a61a96d02e3efc-RcVLBj31.woff2 +0 -0
- package/dist/ui/assets/5c737d740638e8d764f12c1e5c1cd144-D2Npjq-N.woff2 +0 -0
- package/dist/ui/assets/5e78019102102aa5741aa591313fd5b5-V7Azrw-2.woff2 +0 -0
- package/dist/ui/assets/6287cacac64e1849941f7b7d7e6316c5-DzkbPOID.woff2 +0 -0
- package/dist/ui/assets/643df7194160d54edc48d16d76e5ba74-BKmmIRjw.woff2 +0 -0
- package/dist/ui/assets/65d3b214c69ff6786fd1cab06f8394b7-B0cRUJAr.woff2 +0 -0
- package/dist/ui/assets/6698103c11bfe260d44fcf00c6d8b623-DVWYOeyb.woff2 +0 -0
- package/dist/ui/assets/692e07b3a609a8f1a21c15c45631f348-DJW5LcZH.woff2 +0 -0
- package/dist/ui/assets/694e87456af181279c2bfd551aa3c6e3-Cu7kRuJB.woff2 +0 -0
- package/dist/ui/assets/6b88066bdc7a6e8bc823128dbd0f6f3b-BG38UZSq.woff2 +0 -0
- package/dist/ui/assets/6d6f36f15381826d113832bfdd41b021-Bgh7YPiq.woff2 +0 -0
- package/dist/ui/assets/6e22361162bd0a5cd189ca3c98d23d52-DqnptHqF.woff2 +0 -0
- package/dist/ui/assets/6e884dd501b8da24ecd37425a9b3d51d-BVNqra8s.woff2 +0 -0
- package/dist/ui/assets/71200dbc7497fbafa28db5cfeae74acb-B6xMqoC6.woff2 +0 -0
- package/dist/ui/assets/72a85441a9757146440e3985f3b02075-CzTSlCPZ.woff2 +0 -0
- package/dist/ui/assets/7472d7e02045dea3ff288eac850e38eb-CboJEy4X.woff2 +0 -0
- package/dist/ui/assets/795ffa953bea666763ae79ac88aa7e5a-C6UsoDmi.woff2 +0 -0
- package/dist/ui/assets/7aa8647d6c52d249169b73417aa8e444-kJejhQ0-.woff2 +0 -0
- package/dist/ui/assets/7be6b794fc233ccd8b5769496301313a-Ba2iZC0a.woff2 +0 -0
- package/dist/ui/assets/7c0748f04d52086809c9f551c5aaded7-DSzO_ybF.woff2 +0 -0
- package/dist/ui/assets/7c858bb53a7652227fab8cf9753d3e1f-Bi9fbvIF.woff2 +0 -0
- package/dist/ui/assets/7e7026091b4e6061b05963bdb3a7f944-CrmRDJpc.woff2 +0 -0
- package/dist/ui/assets/7f80369a7479d568ab8bf492000282bd-CqcI5ZOp.woff2 +0 -0
- package/dist/ui/assets/834ce2f2571aaa26e47a618c4ad55e58-DZfWJrxo.woff2 +0 -0
- package/dist/ui/assets/834faab602d9c795341bc7dfd6578fe5-B1VeBVWh.woff2 +0 -0
- package/dist/ui/assets/8513a8eea35b460a047a16a87c36f8bb-H259w_6b.woff2 +0 -0
- package/dist/ui/assets/8699e8a36465bf46671dc28ce24e188c-YlkPpQ6h.woff2 +0 -0
- package/dist/ui/assets/86ae8881eae9eac7e9c0182c8ce6c627-Ch2r3LNs.woff2 +0 -0
- package/dist/ui/assets/86b3ae1be58d76f7147793f09264451b-CpgTfcn-.woff2 +0 -0
- package/dist/ui/assets/8769f8d7d45adcfcbd3f80460d22720d-DV_yqcTo.woff2 +0 -0
- package/dist/ui/assets/87bb0ceea9f5515490c832bdf6ebf641-CJpxd8e6.woff2 +0 -0
- package/dist/ui/assets/8928b9a50b5efbaaafa039674a3c7301-C-42WRD6.woff2 +0 -0
- package/dist/ui/assets/899f2c2a36cbeac473a7caeeaabc46b1-xrIcXJXU.woff2 +0 -0
- package/dist/ui/assets/8a075d4043e6bf66740808b492186438-Dq0346Qm.woff2 +0 -0
- package/dist/ui/assets/8b86676936792154c53205ab5d90b797-BGH_CGsg.woff2 +0 -0
- package/dist/ui/assets/8c63ca479653200a0e12f428242e1171-CsBTcPwY.woff2 +0 -0
- package/dist/ui/assets/8c9c7ff8342f5fed60e73c4a7ad67325-CGSYpt52.woff2 +0 -0
- package/dist/ui/assets/8ca655fcc5d9cf33d49815e231f3f356-b8PyEeZg.woff2 +0 -0
- package/dist/ui/assets/8e96f0f9385ef826f900587d0fc18b3d-D7GIG6Uq.woff2 +0 -0
- package/dist/ui/assets/8ea917252cf2c1e664f06ee5badffeea-CDZ1AFr0.woff2 +0 -0
- package/dist/ui/assets/8f42f890fc37e292017446af85af2745-Qx6oGI0z.woff2 +0 -0
- package/dist/ui/assets/8f9589e71c53bb753749a9c412f15c01-BVR5mPJl.woff2 +0 -0
- package/dist/ui/assets/90e70b52a3cc2491bbb2b4c0caf0ae7e-BdwPu67j.woff2 +0 -0
- package/dist/ui/assets/92ac4ca42fe050c1e680c585551abd9c-CXLyuj7l.woff2 +0 -0
- package/dist/ui/assets/92c12bb794c491930fd06f3f97299807-u_0ognJ0.woff2 +0 -0
- package/dist/ui/assets/92f0b4d2bb274a801aac10fc34c1e0cc-DFHB6dyu.woff2 +0 -0
- package/dist/ui/assets/93247aebd628367f5518eafdb2770ce9-o1N4zvTO.woff2 +0 -0
- package/dist/ui/assets/940446ea160995af66a9ee223cc3d4d1-C-_7aPYO.woff2 +0 -0
- package/dist/ui/assets/94be430de618453b6ae27bd366827ba2-1YYf1n5N.woff2 +0 -0
- package/dist/ui/assets/98cd7d62095e466e55885b34f63c86f1-z33YCk0X.woff2 +0 -0
- package/dist/ui/assets/99049fd5cec5894cafe2a1e5e13d1e03-DNrg8nIk.woff2 +0 -0
- package/dist/ui/assets/99e2752b7351aaa7681b4d91db80e89a-b3hi7miY.woff2 +0 -0
- package/dist/ui/assets/9d1b670cbfd64716ac685dea26237d95-DAZ9U6es.woff2 +0 -0
- package/dist/ui/assets/CodeEditorModal-6m0TJWyF.css +1 -0
- package/dist/ui/assets/CodeEditorModal-CFEnWsyh.js +14 -0
- package/dist/ui/assets/ConnectionsView-DHo6yvU6.css +1 -0
- package/dist/ui/assets/ConnectionsView-DNGmZBSU.js +1 -0
- package/dist/ui/assets/LogsView-BoeE92VF.css +1 -0
- package/dist/ui/assets/LogsView-fSiaxQ13.js +1 -0
- package/dist/ui/assets/PaginationFooter-B3kHzRfB.js +1 -0
- package/dist/ui/assets/PaginationFooter-BNkpcNoB.css +1 -0
- package/dist/ui/assets/ProfileEditorDialog-BydoZthX.js +1 -0
- package/dist/ui/assets/ProfilesView-Btc1DOxE.js +2 -0
- package/dist/ui/assets/ProfilesView-ByqdFNHN.css +1 -0
- package/dist/ui/assets/RulesView-CHyynVqA.css +1 -0
- package/dist/ui/assets/RulesView-D9vZBiJ1.js +1 -0
- package/dist/ui/assets/SettingsFileDialog-CNFEAVs4.js +1 -0
- package/dist/ui/assets/SettingsView-BlDhZkXQ.js +2 -0
- package/dist/ui/assets/SettingsView-CngS3vBM.css +1 -0
- package/dist/ui/assets/a0f2d41645a113d821e7ff0891daad1e-XK0rDAci.woff2 +0 -0
- package/dist/ui/assets/a1d1345d8407dd6169f39c28ff6b1708-Bn7hMmv8.woff2 +0 -0
- package/dist/ui/assets/a29f51b4ebb6776e43e7492a036be28e-CrAKKz8u.woff2 +0 -0
- package/dist/ui/assets/a3252ac86b2c4e88bfb9baecabcad817-qnA_3LNE.woff2 +0 -0
- package/dist/ui/assets/a3d63a61e7eb2bb497dbc2da65bd0873-BRMJAm0m.woff2 +0 -0
- package/dist/ui/assets/a45eea933252dbe3529f30a0323c2661-D4kBOrXR.woff2 +0 -0
- package/dist/ui/assets/a4886c4ebed8c8b1f8a87b5b491a39aa-CBQdRqpF.woff2 +0 -0
- package/dist/ui/assets/a50b4ab745c7676d9d3ceb3c0a023a3d-CW990pgI.woff2 +0 -0
- package/dist/ui/assets/a5851ae4d7e58996d8bd681f80d4727c-BBytdb0t.woff2 +0 -0
- package/dist/ui/assets/a5cdaa96bf7d1db6c671432f9ab7bccb-slKJjgfX.woff2 +0 -0
- package/dist/ui/assets/a640dd2e962cf72c7fcf76234c973303-CUCWUDBY.woff2 +0 -0
- package/dist/ui/assets/a67e457bbd366aef5104ce743a2cf6d4-DkE8fLlE.woff2 +0 -0
- package/dist/ui/assets/a6c3f2257315d45aa212bd2e86a02852-CxDbXnZV.woff2 +0 -0
- package/dist/ui/assets/a73399a40a5f81fb7314b8b9a10cd221-DRAvJPKI.woff2 +0 -0
- package/dist/ui/assets/a73a64b0941803d9d807b9ec082df641-BbPpPyy5.woff2 +0 -0
- package/dist/ui/assets/a73d1a0a1dfd4f4234f7a0649ece4da4-BHeqktY9.woff2 +0 -0
- package/dist/ui/assets/a740044e77a400a450e71fcdea55523f-Co5hpBNK.woff2 +0 -0
- package/dist/ui/assets/a7669b29f404662c179c71b87e67c8d2-CVnuBgHy.woff2 +0 -0
- package/dist/ui/assets/a964a4def15811e91b05a91740a1cf37-CzcDfCRn.woff2 +0 -0
- package/dist/ui/assets/aac3f69132da164921fda75d2d90bfb7-B6rUZQ4_.woff2 +0 -0
- package/dist/ui/assets/aacd263c3bb4ba163a4d5079c159680a-DtrDLFlk.woff2 +0 -0
- package/dist/ui/assets/ac62ec881ded2cdb450e542b396e24d0-CRlVJvPa.woff2 +0 -0
- package/dist/ui/assets/aebcb9b7d4b174ab5a4b911206f24036-BuleSpgP.woff2 +0 -0
- package/dist/ui/assets/af70712dadc05c7b18d248996a5ab0a9-gCZSZGzb.woff2 +0 -0
- package/dist/ui/assets/afbd3a8a4cfaa4561b7848c28bc6c4f8-DgnqceEw.woff2 +0 -0
- package/dist/ui/assets/b02d3867e6e2ea921d2845b44c4a5a31-C9v4FrqD.woff2 +0 -0
- package/dist/ui/assets/b1b22825b930688403337d4fd7bbba62-vmMs2pJf.woff2 +0 -0
- package/dist/ui/assets/b3206c979bfb28d12d7ad6df58e74b9f-X1PqLaCR.woff2 +0 -0
- package/dist/ui/assets/b6280e42d4f11dcab70594f9d6774936-CtezImLG.woff2 +0 -0
- package/dist/ui/assets/b71b8cd1a70405c3dbc0e7a44055ca9a-Cd6cIOEr.woff2 +0 -0
- package/dist/ui/assets/b9198c4f220a4ca075f8daa4db529e50-Bgc7zlEt.woff2 +0 -0
- package/dist/ui/assets/baad304a58d7d42d0af29235c5e9490b-BQZYwARB.woff2 +0 -0
- package/dist/ui/assets/bb99e34f8784cc44f0eeadbe735dd238-UHFYI827.woff2 +0 -0
- package/dist/ui/assets/bc1cb0f523c8a2ff566a047aeddf90fd-BSlXQn97.woff2 +0 -0
- package/dist/ui/assets/bd3171e975d62612e50148bf38b2158f-CtZKzCzQ.woff2 +0 -0
- package/dist/ui/assets/be10640c403263dd5917ad65c4d453a6-B-rbuuja.woff2 +0 -0
- package/dist/ui/assets/be764e101e78b50b749aa1414d4810a7-yIPaQQih.woff2 +0 -0
- package/dist/ui/assets/bfa682a7f5f12945b41230c35eb859f6-CzagcI5f.woff2 +0 -0
- package/dist/ui/assets/bfa9753ed26f2e1f81ab7020167bd1a0-C6ZNQQ2p.woff2 +0 -0
- package/dist/ui/assets/branding/sash-cat.png +0 -0
- package/dist/ui/assets/c0e78c6ad709b19ce437677c91033489-BtwtlApg.woff2 +0 -0
- package/dist/ui/assets/c5a59409c610cc8c265d1691eb3f71eb-DmI_ky2X.woff2 +0 -0
- package/dist/ui/assets/c5ff66a1a57f2a29424e8de5d4ef3756-C9pOsaV1.woff2 +0 -0
- package/dist/ui/assets/c607bdee84a0e5b69721367ccc0c9c31-eoHbdXeg.woff2 +0 -0
- package/dist/ui/assets/c8095033941d18db730496eb4c863757-DoexTYks.woff2 +0 -0
- package/dist/ui/assets/c8295519e16f4cf3a350e9729f07653a-C8bAtIO_.woff2 +0 -0
- package/dist/ui/assets/c91f9c9f4db81afeba37c8e73afb0bfd-BGIl2iKW.woff2 +0 -0
- package/dist/ui/assets/c9ad9caa4afdd40766add91d321b0350-HfuiRq1k.woff2 +0 -0
- package/dist/ui/assets/cc4f271c90f9ea5157db9c0a4edc976b-MAjuDvHE.woff2 +0 -0
- package/dist/ui/assets/cdf7c3d96ba172214d7e1e9fe5e6ba8b-CUx4fWQE.woff2 +0 -0
- package/dist/ui/assets/cf70d5821ea7c3ca34653169ac763606-CE0T0Svc.woff2 +0 -0
- package/dist/ui/assets/d0d5efe92496b1ceea38e180b0ac97d3-7G71Z6v3.woff2 +0 -0
- package/dist/ui/assets/d1977142eceb878b06440375e64c4372-mr-7LWm-.woff2 +0 -0
- package/dist/ui/assets/d42feb13392b4dd9214c61b61a6e5ae8-DjnKADf_.woff2 +0 -0
- package/dist/ui/assets/d46a696ec6a077c6873fc39043c3c082-C62E-13k.woff2 +0 -0
- package/dist/ui/assets/d4c0bbf1605a8a9c36fff5a2ead81bb5-C2F6tzOj.woff2 +0 -0
- package/dist/ui/assets/d918d4e47697b7c752ea223e0d0d4c81-twovU2ty.woff2 +0 -0
- package/dist/ui/assets/d988c05da0b5624267dd825fedd133d1-Bgbc9SVH.woff2 +0 -0
- package/dist/ui/assets/da3a071df79531f4f033b7c8499651d0-0tgZJL_N.woff2 +0 -0
- package/dist/ui/assets/da8eba4acbf93048645043006de1c5f0-Ce0dmHn_.woff2 +0 -0
- package/dist/ui/assets/dc3f16892e20a85a8fcad2d3097e622b-8PRrFPJt.woff2 +0 -0
- package/dist/ui/assets/dd5f808ec691f911483a2eb60b5049bd-BhVupSbT.woff2 +0 -0
- package/dist/ui/assets/e2b04534cc697a76afd70e885119cb8c-DO303iCb.woff2 +0 -0
- package/dist/ui/assets/e307280eb2fb7809adee14ff0d247d32-DHMLXvSs.woff2 +0 -0
- package/dist/ui/assets/e3b484bec850c669094f713570870b3a-BI_9kRw8.woff2 +0 -0
- package/dist/ui/assets/e7b1d196949b7530cbda0ad956fbb2cc-i2m2Id0q.woff2 +0 -0
- package/dist/ui/assets/e7c2e5fb387880508811cadc2926e13a-BfROXX4U.woff2 +0 -0
- package/dist/ui/assets/e8a5fe283c8b9e173097bee0b5757ab6-BvfjDjYP.woff2 +0 -0
- package/dist/ui/assets/e8e3465d48435612e9c3509be3984188-BeUPU5-9.woff2 +0 -0
- package/dist/ui/assets/e93903f4604b007fc1b7134a74f5c534-B1M4h46T.woff2 +0 -0
- package/dist/ui/assets/eb0994906efd969102d522b6d8b3aff2-i9SHU5CJ.woff2 +0 -0
- package/dist/ui/assets/eb32eee23ceadd3fc4eb5763d3573f57-B3h9kgf3.woff2 +0 -0
- package/dist/ui/assets/ebadbc005027fb3e2b1c2d15be38c66b-qVQSBwBu.woff2 +0 -0
- package/dist/ui/assets/ecbbb464ff6934b5012cf33c80c7a907-CBEPqZfS.woff2 +0 -0
- package/dist/ui/assets/ed79ac25c014b6434f22fe1e2549bc26-mWhz7hkU.woff2 +0 -0
- package/dist/ui/assets/eed64f40443554cb9f65edaca176abb0-Cqw29XTm.woff2 +0 -0
- package/dist/ui/assets/efc749471476cce09e12e7038c757950-BhSWPf1Q.woff2 +0 -0
- package/dist/ui/assets/f2a7c2cb375662aa93d8f31116d39c20-D1zsMYCW.woff2 +0 -0
- package/dist/ui/assets/f5ba0fb4332ccceadc481e47134023d3-CAKMPiu5.woff2 +0 -0
- package/dist/ui/assets/f6326eb5031e18478aa4588598f96965-Dj3uu55n.woff2 +0 -0
- package/dist/ui/assets/f8678cbaab9caef95e1986731dcbd92f-CnIuR3EN.woff2 +0 -0
- package/dist/ui/assets/f8d9d55e2a811e9839c9af5f8f2d62ac-DIUQRBsH.woff2 +0 -0
- package/dist/ui/assets/f98b117e363eb51f4d7c7d1056da7688-O9MtqjIW.woff2 +0 -0
- package/dist/ui/assets/f9ab5d9163148ceb211e5b4f15a3d8e0-Dtqse-AT.woff2 +0 -0
- package/dist/ui/assets/fa69ce224ff0a6c0ff97b10a829779c2-pX45dCNY.woff2 +0 -0
- package/dist/ui/assets/fc38d1da3930d39dd8e286f708105765-DmbOHwTI.woff2 +0 -0
- package/dist/ui/assets/fe03c1dfaffc1cad3521fe55f1541d6b-BW8aEqCj.woff2 +0 -0
- package/dist/ui/assets/fe0b2421eb4d1f4f8949c602871a317c-BsBLV6jH.woff2 +0 -0
- package/dist/ui/assets/fe9c75d0cb3d808023412d26dfc9d388-eXjcgUPI.woff2 +0 -0
- package/dist/ui/assets/index-B61V60w_.js +19 -0
- package/dist/ui/assets/index-bkyxJG8J.css +1 -0
- package/dist/ui/assets/theme-BNq4FkXS.js +1 -0
- package/dist/ui/index.html +52 -0
- package/dist/webui.js +21 -0
- package/docs/backend.md +260 -0
- package/docs/frontend.md +125 -0
- package/docs/remix-icon-license.txt +186 -0
- package/docs/usage.md +227 -0
- package/package.json +82 -0
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { atomicWriteFileSync, durableRemoveFileSync } from "./fs-atomic.js";
|
|
3
|
+
import { hasExactOwnKeys, isCanonicalIsoTimestamp, isPlainObject } from "./json-shape.js";
|
|
4
|
+
import { profileFilePath, serializeProfiles } from "./profiles.js";
|
|
5
|
+
const MAX_JOURNAL_BYTES = 36 * 1024 * 1024;
|
|
6
|
+
const MAX_SNAPSHOT_BYTES = 24 * 1024 * 1024;
|
|
7
|
+
export const defaultManagedStateFileOperations = {
|
|
8
|
+
write: atomicWriteFileSync,
|
|
9
|
+
remove: durableRemoveFileSync,
|
|
10
|
+
};
|
|
11
|
+
function decodeSnapshot(value, role) {
|
|
12
|
+
if (!isPlainObject(value) || !hasExactOwnKeys(value, ["data"])) {
|
|
13
|
+
throw new Error(`Managed-state transaction journal has invalid ${role} snapshot`);
|
|
14
|
+
}
|
|
15
|
+
if (value.data === null)
|
|
16
|
+
return null;
|
|
17
|
+
if (typeof value.data !== "string") {
|
|
18
|
+
throw new Error(`Managed-state transaction journal has invalid ${role} snapshot data`);
|
|
19
|
+
}
|
|
20
|
+
const decoded = Buffer.from(value.data, "base64");
|
|
21
|
+
if (decoded.toString("base64") !== value.data) {
|
|
22
|
+
throw new Error(`Managed-state transaction journal has non-canonical ${role} snapshot data`);
|
|
23
|
+
}
|
|
24
|
+
return decoded;
|
|
25
|
+
}
|
|
26
|
+
function parseJournal(raw) {
|
|
27
|
+
if (!isPlainObject(raw)) {
|
|
28
|
+
throw new Error("Managed-state transaction journal has an invalid root shape");
|
|
29
|
+
}
|
|
30
|
+
const legacy = raw.version === 1;
|
|
31
|
+
const coordinated = raw.version === 3;
|
|
32
|
+
const allowed = legacy
|
|
33
|
+
? ["version", "createdAt", "index", "profile", "config"]
|
|
34
|
+
: [
|
|
35
|
+
"version",
|
|
36
|
+
"phase",
|
|
37
|
+
"createdAt",
|
|
38
|
+
"index",
|
|
39
|
+
"profile",
|
|
40
|
+
"config",
|
|
41
|
+
"settings",
|
|
42
|
+
...(coordinated ? ["coordination"] : []),
|
|
43
|
+
];
|
|
44
|
+
const required = legacy
|
|
45
|
+
? ["version", "createdAt", "index"]
|
|
46
|
+
: ["version", "phase", "createdAt", ...(coordinated ? ["coordination"] : [])];
|
|
47
|
+
if (Object.keys(raw).some((key) => !allowed.includes(key)) ||
|
|
48
|
+
!required.every((key) => key in raw)) {
|
|
49
|
+
throw new Error("Managed-state transaction journal has an invalid root shape");
|
|
50
|
+
}
|
|
51
|
+
if (raw.version !== 1 && raw.version !== 2 && raw.version !== 3) {
|
|
52
|
+
throw new Error("Managed-state transaction journal has an unsupported version");
|
|
53
|
+
}
|
|
54
|
+
let phase;
|
|
55
|
+
if (raw.version === 1) {
|
|
56
|
+
phase = "publishing";
|
|
57
|
+
}
|
|
58
|
+
else if (raw.phase === "publishing" ||
|
|
59
|
+
raw.phase === "committed" ||
|
|
60
|
+
(raw.version === 3 && raw.phase === "retained")) {
|
|
61
|
+
phase = raw.phase;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
throw new Error("Managed-state transaction journal has an invalid phase");
|
|
65
|
+
}
|
|
66
|
+
if (!isCanonicalIsoTimestamp(raw.createdAt)) {
|
|
67
|
+
throw new Error("Managed-state transaction journal has an invalid timestamp");
|
|
68
|
+
}
|
|
69
|
+
const coordination = raw.version === 3 && raw.coordination === "core-update" ? raw.coordination : undefined;
|
|
70
|
+
if (raw.version === 3 && !coordination) {
|
|
71
|
+
throw new Error("Managed-state transaction journal has invalid coordination");
|
|
72
|
+
}
|
|
73
|
+
const index = raw.index === undefined ? undefined : decodeSnapshot(raw.index, "index");
|
|
74
|
+
let profile;
|
|
75
|
+
if (raw.profile !== undefined) {
|
|
76
|
+
if (!isPlainObject(raw.profile) || !hasExactOwnKeys(raw.profile, ["id", "data"])) {
|
|
77
|
+
throw new Error("Managed-state transaction journal has an invalid profile snapshot");
|
|
78
|
+
}
|
|
79
|
+
if (typeof raw.profile.id !== "string" || !/^[0-9]+$/.test(raw.profile.id)) {
|
|
80
|
+
throw new Error("Managed-state transaction journal has an invalid profile id");
|
|
81
|
+
}
|
|
82
|
+
profile = { id: raw.profile.id, data: decodeSnapshot({ data: raw.profile.data }, "profile") };
|
|
83
|
+
}
|
|
84
|
+
const config = raw.config === undefined ? undefined : decodeSnapshot(raw.config, "config");
|
|
85
|
+
const settings = raw.settings === undefined ? undefined : decodeSnapshot(raw.settings, "settings");
|
|
86
|
+
const decodedSize = (index?.length ?? 0) +
|
|
87
|
+
(profile?.data?.length ?? 0) +
|
|
88
|
+
(config?.length ?? 0) +
|
|
89
|
+
(settings?.length ?? 0);
|
|
90
|
+
if (decodedSize > MAX_SNAPSHOT_BYTES) {
|
|
91
|
+
throw new Error("Managed-state transaction journal snapshots exceed the size limit");
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
phase,
|
|
95
|
+
createdAt: raw.createdAt,
|
|
96
|
+
...(coordination ? { coordination } : {}),
|
|
97
|
+
snapshots: [
|
|
98
|
+
...(profile ? [{ path: profile.id, data: profile.data }] : []),
|
|
99
|
+
...(index !== undefined ? [{ path: "index", data: index }] : []),
|
|
100
|
+
...(config !== undefined ? [{ path: "config", data: config }] : []),
|
|
101
|
+
...(settings !== undefined ? [{ path: "settings", data: settings }] : []),
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function readJournal(layout) {
|
|
106
|
+
let text;
|
|
107
|
+
try {
|
|
108
|
+
const stat = fs.lstatSync(layout.managedStateTransactionFile);
|
|
109
|
+
if (!stat.isFile() || stat.size > MAX_JOURNAL_BYTES) {
|
|
110
|
+
throw new Error("Managed-state transaction journal is not a bounded regular file");
|
|
111
|
+
}
|
|
112
|
+
text = fs.readFileSync(layout.managedStateTransactionFile, "utf8");
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
if (err.code === "ENOENT")
|
|
116
|
+
return undefined;
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
let raw;
|
|
120
|
+
try {
|
|
121
|
+
raw = JSON.parse(text);
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
throw new Error(`Managed-state transaction journal is invalid JSON: ${err.message}`);
|
|
125
|
+
}
|
|
126
|
+
return parseJournal(raw);
|
|
127
|
+
}
|
|
128
|
+
export function readManagedStateTransactionStatus(layout) {
|
|
129
|
+
const stored = readJournal(layout);
|
|
130
|
+
if (!stored)
|
|
131
|
+
return undefined;
|
|
132
|
+
return {
|
|
133
|
+
phase: stored.phase,
|
|
134
|
+
createdAt: stored.createdAt,
|
|
135
|
+
...(stored.coordination ? { coordination: stored.coordination } : {}),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function snapshot(paths) {
|
|
139
|
+
return [...new Set(paths)].map((file) => {
|
|
140
|
+
try {
|
|
141
|
+
return { path: file, data: fs.readFileSync(file) };
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
if (err.code === "ENOENT")
|
|
145
|
+
return { path: file, data: null };
|
|
146
|
+
throw err;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function journalFromSnapshots(snapshots, layout, profileId, coordination) {
|
|
151
|
+
const indexEntry = snapshots.find((entry) => entry.path === layout.profilesIndexFile);
|
|
152
|
+
const profileEntry = profileId
|
|
153
|
+
? snapshots.find((entry) => entry.path === profileFilePath(layout, profileId))
|
|
154
|
+
: undefined;
|
|
155
|
+
const configEntry = snapshots.find((entry) => entry.path === layout.configFile);
|
|
156
|
+
const settingsEntry = snapshots.find((entry) => entry.path === layout.settingsFile);
|
|
157
|
+
const size = (indexEntry?.data?.length ?? 0) +
|
|
158
|
+
(profileEntry?.data?.length ?? 0) +
|
|
159
|
+
(configEntry?.data?.length ?? 0) +
|
|
160
|
+
(settingsEntry?.data?.length ?? 0);
|
|
161
|
+
if (size > MAX_SNAPSHOT_BYTES) {
|
|
162
|
+
throw new Error("Managed-state transaction snapshots exceed the journal size limit");
|
|
163
|
+
}
|
|
164
|
+
const entries = {
|
|
165
|
+
createdAt: new Date().toISOString(),
|
|
166
|
+
...(indexEntry ? { index: { data: indexEntry.data?.toString("base64") ?? null } } : {}),
|
|
167
|
+
...(profileEntry && profileId
|
|
168
|
+
? {
|
|
169
|
+
profile: {
|
|
170
|
+
id: profileId,
|
|
171
|
+
data: profileEntry.data?.toString("base64") ?? null,
|
|
172
|
+
},
|
|
173
|
+
}
|
|
174
|
+
: {}),
|
|
175
|
+
...(configEntry ? { config: { data: configEntry.data?.toString("base64") ?? null } } : {}),
|
|
176
|
+
...(settingsEntry
|
|
177
|
+
? { settings: { data: settingsEntry.data?.toString("base64") ?? null } }
|
|
178
|
+
: {}),
|
|
179
|
+
};
|
|
180
|
+
return coordination
|
|
181
|
+
? { version: 3, phase: "publishing", coordination, ...entries }
|
|
182
|
+
: { version: 2, phase: "publishing", ...entries };
|
|
183
|
+
}
|
|
184
|
+
function restore(snapshots, files) {
|
|
185
|
+
const errors = [];
|
|
186
|
+
for (const entry of snapshots) {
|
|
187
|
+
try {
|
|
188
|
+
if (entry.data === null)
|
|
189
|
+
files.remove(entry.path);
|
|
190
|
+
else
|
|
191
|
+
files.write(entry.path, entry.data);
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
errors.push(`${entry.path}: ${err.message}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return errors;
|
|
198
|
+
}
|
|
199
|
+
function resolvedSnapshots(stored, layout) {
|
|
200
|
+
return stored.snapshots.map((entry) => ({
|
|
201
|
+
path: entry.path === "index"
|
|
202
|
+
? layout.profilesIndexFile
|
|
203
|
+
: entry.path === "config"
|
|
204
|
+
? layout.configFile
|
|
205
|
+
: entry.path === "settings"
|
|
206
|
+
? layout.settingsFile
|
|
207
|
+
: profileFilePath(layout, entry.path),
|
|
208
|
+
data: entry.data,
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
function transactionSnapshots(layout, transaction) {
|
|
212
|
+
const profilePath = transaction.profile
|
|
213
|
+
? profileFilePath(layout, transaction.profile.id)
|
|
214
|
+
: undefined;
|
|
215
|
+
return {
|
|
216
|
+
...(profilePath ? { profilePath } : {}),
|
|
217
|
+
snapshots: snapshot([
|
|
218
|
+
...(profilePath ? [profilePath] : []),
|
|
219
|
+
...(transaction.index ? [layout.profilesIndexFile] : []),
|
|
220
|
+
...(transaction.config ? [layout.configFile] : []),
|
|
221
|
+
...(transaction.settings ? [layout.settingsFile] : []),
|
|
222
|
+
]),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function publishFiles(layout, transaction, profilePath, files) {
|
|
226
|
+
if (profilePath && transaction.profile) {
|
|
227
|
+
if (transaction.profile.yamlText === null)
|
|
228
|
+
files.remove(profilePath);
|
|
229
|
+
else
|
|
230
|
+
files.write(profilePath, transaction.profile.yamlText);
|
|
231
|
+
}
|
|
232
|
+
if (transaction.index) {
|
|
233
|
+
files.write(layout.profilesIndexFile, serializeProfiles(transaction.index));
|
|
234
|
+
}
|
|
235
|
+
if (transaction.config)
|
|
236
|
+
files.write(layout.configFile, transaction.config.yaml);
|
|
237
|
+
if (transaction.settings) {
|
|
238
|
+
files.write(layout.settingsFile, `${JSON.stringify(transaction.settings, null, 2)}\n`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function writeJournal(layout, journal) {
|
|
242
|
+
atomicWriteFileSync(layout.managedStateTransactionFile, `${JSON.stringify(journal)}\n`);
|
|
243
|
+
}
|
|
244
|
+
function restoreAndClear(stored, layout, files, errorPrefix) {
|
|
245
|
+
const errors = restore(resolvedSnapshots(stored, layout), files);
|
|
246
|
+
if (errors.length === 0) {
|
|
247
|
+
try {
|
|
248
|
+
durableRemoveFileSync(layout.managedStateTransactionFile);
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
errors.push(`journal: ${err.message}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (errors.length)
|
|
255
|
+
throw new Error(`${errorPrefix}: ${errors.join("; ")}`);
|
|
256
|
+
}
|
|
257
|
+
export function recoverManagedStateTransaction(layout, files = defaultManagedStateFileOperations) {
|
|
258
|
+
const stored = readJournal(layout);
|
|
259
|
+
if (!stored)
|
|
260
|
+
return;
|
|
261
|
+
if (stored.phase === "committed") {
|
|
262
|
+
durableRemoveFileSync(layout.managedStateTransactionFile);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (stored.phase === "retained") {
|
|
266
|
+
throw new Error("A retained managed-state transaction requires coordinated Core update recovery");
|
|
267
|
+
}
|
|
268
|
+
restoreAndClear(stored, layout, files, "Managed-state transaction recovery failed");
|
|
269
|
+
}
|
|
270
|
+
export async function retainManagedStateTransaction(layout, transaction, files = defaultManagedStateFileOperations) {
|
|
271
|
+
if (transaction.applyRuntime || transaction.reloadRuntime === true || transaction.settings) {
|
|
272
|
+
throw new Error("Retained Core update publications cannot transition runtime or publish settings");
|
|
273
|
+
}
|
|
274
|
+
recoverManagedStateTransaction(layout, files);
|
|
275
|
+
const { profilePath, snapshots } = transactionSnapshots(layout, transaction);
|
|
276
|
+
const journal = journalFromSnapshots(snapshots, layout, transaction.profile?.id, "core-update");
|
|
277
|
+
if (journal.version !== 3) {
|
|
278
|
+
throw new Error("Failed to create a coordinated managed-state transaction");
|
|
279
|
+
}
|
|
280
|
+
writeJournal(layout, journal);
|
|
281
|
+
try {
|
|
282
|
+
publishFiles(layout, transaction, profilePath, files);
|
|
283
|
+
writeJournal(layout, { ...journal, phase: "retained" });
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
const rollbackErrors = restore(snapshots, files);
|
|
287
|
+
if (rollbackErrors.length === 0) {
|
|
288
|
+
try {
|
|
289
|
+
durableRemoveFileSync(layout.managedStateTransactionFile);
|
|
290
|
+
}
|
|
291
|
+
catch (clearErr) {
|
|
292
|
+
rollbackErrors.push(`journal: ${clearErr.message}`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const suffix = rollbackErrors.length
|
|
296
|
+
? `; managed-state transaction rollback failed: ${rollbackErrors.join("; ")}`
|
|
297
|
+
: "";
|
|
298
|
+
throw new Error(`${err.message}${suffix}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
export function rollbackRetainedManagedStateTransaction(layout, files = defaultManagedStateFileOperations) {
|
|
302
|
+
const stored = readJournal(layout);
|
|
303
|
+
if (!stored)
|
|
304
|
+
return false;
|
|
305
|
+
if (stored.coordination !== "core-update" || stored.phase === "committed") {
|
|
306
|
+
throw new Error("Managed-state transaction is not a retained Core update publication");
|
|
307
|
+
}
|
|
308
|
+
restoreAndClear(stored, layout, files, "Retained managed-state transaction rollback failed");
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
export function markRetainedManagedStateTransactionCommitted(layout) {
|
|
312
|
+
const stored = readJournal(layout);
|
|
313
|
+
if (!stored)
|
|
314
|
+
return false;
|
|
315
|
+
if (stored.coordination !== "core-update" || stored.phase !== "retained") {
|
|
316
|
+
throw new Error("Managed-state transaction is not ready for coordinated commit");
|
|
317
|
+
}
|
|
318
|
+
const raw = JSON.parse(fs.readFileSync(layout.managedStateTransactionFile, "utf8"));
|
|
319
|
+
if (raw?.version !== 3 || raw.coordination !== "core-update") {
|
|
320
|
+
throw new Error("Managed-state transaction changed during coordinated commit");
|
|
321
|
+
}
|
|
322
|
+
writeJournal(layout, { ...raw, phase: "committed" });
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
export function clearCommittedManagedStateTransaction(layout) {
|
|
326
|
+
const stored = readJournal(layout);
|
|
327
|
+
if (!stored)
|
|
328
|
+
return false;
|
|
329
|
+
if (stored.coordination !== "core-update" || stored.phase !== "committed") {
|
|
330
|
+
throw new Error("Managed-state transaction is not committed coordinated state");
|
|
331
|
+
}
|
|
332
|
+
durableRemoveFileSync(layout.managedStateTransactionFile);
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
export async function commitManagedStateTransaction(layout, transaction, reloadConfig, files = defaultManagedStateFileOperations) {
|
|
336
|
+
recoverManagedStateTransaction(layout, files);
|
|
337
|
+
const { profilePath, snapshots } = transactionSnapshots(layout, transaction);
|
|
338
|
+
const journal = journalFromSnapshots(snapshots, layout, transaction.profile?.id);
|
|
339
|
+
writeJournal(layout, journal);
|
|
340
|
+
let reloadAttempted = false;
|
|
341
|
+
try {
|
|
342
|
+
publishFiles(layout, transaction, profilePath, files);
|
|
343
|
+
if (transaction.config && transaction.reloadRuntime !== false && reloadConfig) {
|
|
344
|
+
reloadAttempted = true;
|
|
345
|
+
await reloadConfig(layout.configFile);
|
|
346
|
+
}
|
|
347
|
+
await transaction.applyRuntime?.();
|
|
348
|
+
writeJournal(layout, { ...journal, phase: "committed" });
|
|
349
|
+
durableRemoveFileSync(layout.managedStateTransactionFile);
|
|
350
|
+
}
|
|
351
|
+
catch (err) {
|
|
352
|
+
const rollbackErrors = restore(snapshots, files);
|
|
353
|
+
if (reloadAttempted && transaction.config && reloadConfig) {
|
|
354
|
+
const oldConfig = snapshots.find((entry) => entry.path === layout.configFile);
|
|
355
|
+
if (oldConfig?.data !== null) {
|
|
356
|
+
try {
|
|
357
|
+
await reloadConfig(layout.configFile);
|
|
358
|
+
}
|
|
359
|
+
catch (reloadErr) {
|
|
360
|
+
rollbackErrors.push(`config rollback reload failed: ${reloadErr.message}`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (rollbackErrors.length === 0) {
|
|
365
|
+
try {
|
|
366
|
+
durableRemoveFileSync(layout.managedStateTransactionFile);
|
|
367
|
+
}
|
|
368
|
+
catch (clearErr) {
|
|
369
|
+
rollbackErrors.push(`journal: ${clearErr.message}`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
const suffix = rollbackErrors.length
|
|
373
|
+
? `; managed-state transaction rollback failed: ${rollbackErrors.join("; ")}`
|
|
374
|
+
: "";
|
|
375
|
+
throw new Error(`${err.message}${suffix}`);
|
|
376
|
+
}
|
|
377
|
+
}
|