mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-26 22:50:26 +01:00
Modernized tgui backend (#94573)
## About The Pull Request This has been a long project that has undergone several iterations. I needed to complete #94514 just to get here, and this is surprisingly simpler despite handling much more code. This PR replaces the bespoke redux-based solution with [jotai](https://jotai.org/), a lean state manager. For the most part, this means the UI will be a bit more responsive. I'll post the philosophy from the docs: In the previous TGUI backend state, both DM messages and UI actions were handled through an event message system using actions, selectors, reducers, and middleware. This new event system is designed to handle only DM messages - separating UI actions into direct state access (eg setSomeState(true)) or helpers (eg updateSetting({ thing: true})). The idea behind this was to reduce the amount of abstractions needed and draw a clear line between what is a server message and what is a UI action. There are three components to this system: 1. The event bus, which maintains the list of handlers. 2. The handlers, which delegate backend calls and update application state. 3. The store, ie the application state. ## Why It's Good For The Game The previous solution would do a full tree rerender when any backend message or UI event took place, including pings. We don't need to do this now. We can atomically update the components when they need updated. The code should be easier to maintain (fully documented and concise) The UI should be more reliable ## Changelog N/A
This commit is contained in:
@@ -382,7 +382,7 @@
|
||||
if("payloadChunk")
|
||||
var/payload_id = payload["id"]
|
||||
append_payload_chunk(payload_id, payload["chunk"])
|
||||
send_message("acknowlegePayloadChunk", list("id" = payload_id))
|
||||
send_message("acknowledgePayloadChunk", list("id" = payload_id))
|
||||
|
||||
/datum/tgui_window/vv_edit_var(var_name, var_value)
|
||||
return var_name != NAMEOF(src, id) && ..()
|
||||
|
||||
+139
-133
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 0,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "tgui-workspace",
|
||||
@@ -102,7 +102,7 @@
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@bufbuild/protobuf": ["@bufbuild/protobuf@2.6.0", "", {}, "sha512-6cuonJVNOIL7lTj5zgo/Rc2bKAo4/GvN+rKCrUj7GdEHRzCk8zKOfFwUsL9nAVk5rSIsRmlgcpLzTRysopEeeg=="],
|
||||
"@bufbuild/protobuf": ["@bufbuild/protobuf@2.10.2", "", {}, "sha512-uFsRXwIGyu+r6AMdz+XijIIZJYpoWeYzILt5yZ2d3mCjQrWUTVpVD9WL/jZAbvp+Ed04rOhrsk7FiTcEDseB5A=="],
|
||||
|
||||
"@discoveryjs/json-ext": ["@discoveryjs/json-ext@0.5.7", "", {}, "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw=="],
|
||||
|
||||
@@ -130,21 +130,27 @@
|
||||
|
||||
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg=="],
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||
|
||||
"@jridgewell/source-map": ["@jridgewell/source-map@0.3.10", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q=="],
|
||||
"@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.4", "", {}, "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="],
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="],
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||
|
||||
"@jsonjoy.com/base64": ["@jsonjoy.com/base64@1.1.2", "", { "peerDependencies": { "tslib": "2" } }, "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA=="],
|
||||
|
||||
"@jsonjoy.com/json-pack": ["@jsonjoy.com/json-pack@1.2.0", "", { "dependencies": { "@jsonjoy.com/base64": "^1.1.1", "@jsonjoy.com/util": "^1.1.2", "hyperdyperid": "^1.2.0", "thingies": "^1.20.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-io1zEbbYcElht3tdlqEOFxZ0dMTYrHz9iMf0gqn1pPjZFTCgM5R4R5IMA20Chb2UPYYsxjzs8CgZ7Nb5n2K2rA=="],
|
||||
"@jsonjoy.com/buffers": ["@jsonjoy.com/buffers@1.2.1", "", { "peerDependencies": { "tslib": "2" } }, "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA=="],
|
||||
|
||||
"@jsonjoy.com/util": ["@jsonjoy.com/util@1.6.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-sw/RMbehRhN68WRtcKCpQOPfnH6lLP4GJfqzi3iYej8tnzpZUDr6UkZYJjcjjC0FWEJOJbyM3PTIwxucUmDG2A=="],
|
||||
"@jsonjoy.com/codegen": ["@jsonjoy.com/codegen@1.0.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g=="],
|
||||
|
||||
"@jsonjoy.com/json-pack": ["@jsonjoy.com/json-pack@1.21.0", "", { "dependencies": { "@jsonjoy.com/base64": "^1.1.2", "@jsonjoy.com/buffers": "^1.2.0", "@jsonjoy.com/codegen": "^1.0.0", "@jsonjoy.com/json-pointer": "^1.0.2", "@jsonjoy.com/util": "^1.9.0", "hyperdyperid": "^1.2.0", "thingies": "^2.5.0", "tree-dump": "^1.1.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg=="],
|
||||
|
||||
"@jsonjoy.com/json-pointer": ["@jsonjoy.com/json-pointer@1.0.2", "", { "dependencies": { "@jsonjoy.com/codegen": "^1.0.0", "@jsonjoy.com/util": "^1.9.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg=="],
|
||||
|
||||
"@jsonjoy.com/util": ["@jsonjoy.com/util@1.9.0", "", { "dependencies": { "@jsonjoy.com/buffers": "^1.0.0", "@jsonjoy.com/codegen": "^1.0.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ=="],
|
||||
|
||||
"@leichtgewicht/ip-codec": ["@leichtgewicht/ip-codec@2.0.5", "", {}, "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="],
|
||||
|
||||
@@ -238,19 +244,19 @@
|
||||
|
||||
"@types/bonjour": ["@types/bonjour@3.5.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||
"@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="],
|
||||
|
||||
"@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="],
|
||||
|
||||
"@types/connect-history-api-fallback": ["@types/connect-history-api-fallback@1.5.4", "", { "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" } }, "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw=="],
|
||||
|
||||
"@types/express": ["@types/express@4.17.23", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "*" } }, "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ=="],
|
||||
"@types/express": ["@types/express@4.17.25", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "^1" } }, "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw=="],
|
||||
|
||||
"@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.6", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A=="],
|
||||
"@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.7", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg=="],
|
||||
|
||||
"@types/http-errors": ["@types/http-errors@2.0.5", "", {}, "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="],
|
||||
|
||||
"@types/http-proxy": ["@types/http-proxy@1.17.16", "", { "dependencies": { "@types/node": "*" } }, "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w=="],
|
||||
"@types/http-proxy": ["@types/http-proxy@1.17.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw=="],
|
||||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
@@ -260,25 +266,25 @@
|
||||
|
||||
"@types/node": ["@types/node@20.19.27", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug=="],
|
||||
|
||||
"@types/node-forge": ["@types/node-forge@1.3.12", "", { "dependencies": { "@types/node": "*" } }, "sha512-a0ToKlRVnUw3aXKQq2F+krxZKq7B8LEQijzPn5RdFAMatARD2JX9o8FBpMXOOrjob0uc13aN+V/AXniOXW4d9A=="],
|
||||
"@types/node-forge": ["@types/node-forge@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw=="],
|
||||
|
||||
"@types/qs": ["@types/qs@6.14.0", "", {}, "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ=="],
|
||||
|
||||
"@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="],
|
||||
|
||||
"@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="],
|
||||
"@types/react": ["@types/react@19.2.7", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg=="],
|
||||
|
||||
"@types/react-dom": ["@types/react-dom@19.1.6", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw=="],
|
||||
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
||||
|
||||
"@types/retry": ["@types/retry@0.12.2", "", {}, "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow=="],
|
||||
|
||||
"@types/sax": ["@types/sax@1.2.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A=="],
|
||||
|
||||
"@types/send": ["@types/send@0.17.5", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w=="],
|
||||
"@types/send": ["@types/send@1.2.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ=="],
|
||||
|
||||
"@types/serve-index": ["@types/serve-index@1.9.4", "", { "dependencies": { "@types/express": "*" } }, "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug=="],
|
||||
|
||||
"@types/serve-static": ["@types/serve-static@1.15.8", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "*" } }, "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg=="],
|
||||
"@types/serve-static": ["@types/serve-static@1.15.10", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "<1" } }, "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw=="],
|
||||
|
||||
"@types/sockjs": ["@types/sockjs@0.3.36", "", { "dependencies": { "@types/node": "*" } }, "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q=="],
|
||||
|
||||
@@ -288,7 +294,7 @@
|
||||
|
||||
"@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="],
|
||||
|
||||
"@types/wicg-file-system-access": ["@types/wicg-file-system-access@2023.10.6", "", {}, "sha512-YO/183gNRzZFSdKu+ikkD7ambAj4PhgjFAF2A/Mw/7wroSF6ne8r804RkpZzqrJ/F6DO2/IYlQF/ULOZ/bhKyA=="],
|
||||
"@types/wicg-file-system-access": ["@types/wicg-file-system-access@2023.10.7", "", {}, "sha512-g49ijasEJvCd7ifmAY2D0wdEtt1xRjBbA33PJTiv8mKBr7DoMsPeISoJ8oQOTopSRi+FBWPpPW5ouDj2QPKtGA=="],
|
||||
|
||||
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
||||
|
||||
@@ -336,7 +342,7 @@
|
||||
|
||||
"auto-config-loader": ["auto-config-loader@2.0.2", "", { "dependencies": { "ini": "^5.0.0", "jiti": "^2.4.1", "jsonc-eslint-parser": "^2.3.0", "lodash.merge": "^4.6.2", "sucrase": "^3.35.0", "toml-eslint-parser": "^0.10.0", "yaml-eslint-parser": "^1.2.2" } }, "sha512-0V8gZAGGqiFDP15d6d4/Emi6Gpozbr1S9lSfxJ+lNV8nF+7grhcgbHIgn3O/DQKybS+cDqVMC3rxH8k+o0ISpA=="],
|
||||
|
||||
"axios": ["axios@1.10.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw=="],
|
||||
"axios": ["axios@1.13.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA=="],
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
@@ -346,7 +352,7 @@
|
||||
|
||||
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
||||
|
||||
"body-parser": ["body-parser@1.20.3", "", { "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" } }, "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g=="],
|
||||
"body-parser": ["body-parser@1.20.4", "", { "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "~1.2.0", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", "qs": "~6.14.0", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" } }, "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA=="],
|
||||
|
||||
"bonjour-service": ["bonjour-service@1.3.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" } }, "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA=="],
|
||||
|
||||
@@ -362,7 +368,7 @@
|
||||
|
||||
"bufferstreams": ["bufferstreams@4.0.0", "", { "dependencies": { "readable-stream": "^3.4.0", "yerror": "^8.0.0" } }, "sha512-azX778/2VQ9K2uiYprSUKLgK2K6lR1KtJycJDsMg7u0+Cc994A9HyGaUKb01e/T+M8jse057429iKXurCaT35g=="],
|
||||
|
||||
"bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||
"bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],
|
||||
|
||||
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
|
||||
|
||||
@@ -412,7 +418,7 @@
|
||||
|
||||
"compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="],
|
||||
|
||||
"compression": ["compression@1.8.0", "", { "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", "on-headers": "~1.0.2", "safe-buffer": "5.2.1", "vary": "~1.1.2" } }, "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA=="],
|
||||
"compression": ["compression@1.8.1", "", { "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" } }, "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w=="],
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
@@ -422,9 +428,9 @@
|
||||
|
||||
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
|
||||
|
||||
"cookie": ["cookie@0.7.1", "", {}, "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w=="],
|
||||
"cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
||||
|
||||
"cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="],
|
||||
"cookie-signature": ["cookie-signature@1.0.7", "", {}, "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="],
|
||||
|
||||
"core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
|
||||
|
||||
@@ -442,7 +448,7 @@
|
||||
|
||||
"csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="],
|
||||
|
||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||
|
||||
"cubic2quad": ["cubic2quad@1.2.1", "", {}, "sha512-wT5Y7mO8abrV16gnssKdmIhIbA9wSkeMzhh27jAguKrV82i24wER0vL5TGhUJ9dbJNDcigoRZ0IAHFEEEI4THQ=="],
|
||||
|
||||
@@ -452,11 +458,11 @@
|
||||
|
||||
"debounce": ["debounce@1.2.1", "", {}, "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="],
|
||||
|
||||
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"default-browser": ["default-browser@5.2.1", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg=="],
|
||||
"default-browser": ["default-browser@5.4.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg=="],
|
||||
|
||||
"default-browser-id": ["default-browser-id@5.0.0", "", {}, "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA=="],
|
||||
"default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],
|
||||
|
||||
"define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
|
||||
|
||||
@@ -478,7 +484,7 @@
|
||||
|
||||
"domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
|
||||
|
||||
"dompurify": ["dompurify@3.2.6", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ=="],
|
||||
"dompurify": ["dompurify@3.3.1", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q=="],
|
||||
|
||||
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
|
||||
|
||||
@@ -530,29 +536,31 @@
|
||||
|
||||
"exit-hook": ["exit-hook@4.0.0", "", {}, "sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ=="],
|
||||
|
||||
"exponential-backoff": ["exponential-backoff@3.1.2", "", {}, "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA=="],
|
||||
"exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="],
|
||||
|
||||
"express": ["express@4.21.2", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.19.0", "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA=="],
|
||||
"express": ["express@4.22.1", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "~1.20.3", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.3.1", "fresh": "~0.5.2", "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", "serve-static": "~1.16.2", "setprototypeof": "1.2.0", "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g=="],
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
||||
"fast-uri": ["fast-uri@3.0.6", "", {}, "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw=="],
|
||||
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
|
||||
|
||||
"faye-websocket": ["faye-websocket@0.11.4", "", { "dependencies": { "websocket-driver": ">=0.5.1" } }, "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g=="],
|
||||
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
|
||||
|
||||
"file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
|
||||
|
||||
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
||||
|
||||
"finalhandler": ["finalhandler@1.3.1", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", "statuses": "2.0.1", "unpipe": "~1.0.0" } }, "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ=="],
|
||||
"finalhandler": ["finalhandler@1.3.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "statuses": "~2.0.2", "unpipe": "~1.0.0" } }, "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg=="],
|
||||
|
||||
"follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="],
|
||||
"follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
|
||||
|
||||
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
|
||||
|
||||
"form-data": ["form-data@4.0.3", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA=="],
|
||||
"form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
|
||||
|
||||
"formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
|
||||
|
||||
@@ -580,6 +588,8 @@
|
||||
|
||||
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"glob-to-regex.js": ["glob-to-regex.js@1.2.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ=="],
|
||||
|
||||
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
@@ -610,7 +620,7 @@
|
||||
|
||||
"http-deceiver": ["http-deceiver@1.2.7", "", {}, "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw=="],
|
||||
|
||||
"http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="],
|
||||
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
|
||||
|
||||
"http-parser-js": ["http-parser-js@0.5.10", "", {}, "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA=="],
|
||||
|
||||
@@ -630,7 +640,7 @@
|
||||
|
||||
"image2uri": ["image2uri@2.1.2", "", { "dependencies": { "node-fetch": "^3.3.1" } }, "sha512-3b2zRma8I3zulb4OCkZruRw1VsnysT9phBzOJj+x3lPkwybJtNa5Sz6Dw8jSQI6OL7Ns4H5h8Y26EJbwq4GhQQ=="],
|
||||
|
||||
"immutable": ["immutable@5.1.3", "", {}, "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg=="],
|
||||
"immutable": ["immutable@5.1.4", "", {}, "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA=="],
|
||||
|
||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
@@ -642,9 +652,9 @@
|
||||
|
||||
"ini": ["ini@5.0.0", "", {}, "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw=="],
|
||||
|
||||
"ip-address": ["ip-address@9.0.5", "", { "dependencies": { "jsbn": "1.1.0", "sprintf-js": "^1.1.3" } }, "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g=="],
|
||||
"ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],
|
||||
|
||||
"ipaddr.js": ["ipaddr.js@2.2.0", "", {}, "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA=="],
|
||||
"ipaddr.js": ["ipaddr.js@2.3.0", "", {}, "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg=="],
|
||||
|
||||
"is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
|
||||
|
||||
@@ -662,7 +672,7 @@
|
||||
|
||||
"is-lambda": ["is-lambda@1.0.1", "", {}, "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ=="],
|
||||
|
||||
"is-network-error": ["is-network-error@1.1.0", "", {}, "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g=="],
|
||||
"is-network-error": ["is-network-error@1.3.0", "", {}, "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw=="],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
@@ -676,39 +686,37 @@
|
||||
|
||||
"jackspeak": ["jackspeak@4.1.1", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" } }, "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ=="],
|
||||
|
||||
"jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
|
||||
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
||||
|
||||
"jotai": ["jotai@2.16.0", "", { "peerDependencies": { "@babel/core": ">=7.0.0", "@babel/template": ">=7.0.0", "@types/react": ">=17.0.0", "react": ">=17.0.0" }, "optionalPeers": ["@babel/core", "@babel/template", "@types/react", "react"] }, "sha512-NmkwPBet0SHQ28GBfEb10sqnbVOYyn6DL4iazZgGRDUKxSWL0iqcm+IK4TqTSFC2ixGk+XX2e46Wbv364a3cKg=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
||||
|
||||
"jsbn": ["jsbn@1.1.0", "", {}, "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="],
|
||||
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
|
||||
|
||||
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
|
||||
"jsonc-eslint-parser": ["jsonc-eslint-parser@2.4.0", "", { "dependencies": { "acorn": "^8.5.0", "eslint-visitor-keys": "^3.0.0", "espree": "^9.0.0", "semver": "^7.3.5" } }, "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg=="],
|
||||
"jsonc-eslint-parser": ["jsonc-eslint-parser@2.4.2", "", { "dependencies": { "acorn": "^8.5.0", "eslint-visitor-keys": "^3.0.0", "espree": "^9.0.0", "semver": "^7.3.5" } }, "sha512-1e4qoRgnn448pRuMvKGsFFymUCquZV0mpGgOyIKNgD3JVDTsVJyRBGH/Fm0tBb8WsWGgmB1mDe6/yJMQM37DUA=="],
|
||||
|
||||
"jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="],
|
||||
"jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],
|
||||
|
||||
"launch-editor": ["launch-editor@2.10.0", "", { "dependencies": { "picocolors": "^1.0.0", "shell-quote": "^1.8.1" } }, "sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA=="],
|
||||
"launch-editor": ["launch-editor@2.12.0", "", { "dependencies": { "picocolors": "^1.1.1", "shell-quote": "^1.8.3" } }, "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg=="],
|
||||
|
||||
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||
|
||||
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||
|
||||
"lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
|
||||
"lodash-es": ["lodash-es@4.17.22", "", {}, "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q=="],
|
||||
|
||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||
|
||||
"lru-cache": ["lru-cache@11.1.0", "", {}, "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A=="],
|
||||
"lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="],
|
||||
|
||||
"make-fetch-happen": ["make-fetch-happen@13.0.1", "", { "dependencies": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", "http-cache-semantics": "^4.1.1", "is-lambda": "^1.0.1", "minipass": "^7.0.2", "minipass-fetch": "^3.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "proc-log": "^4.2.0", "promise-retry": "^2.0.1", "ssri": "^10.0.0" } }, "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA=="],
|
||||
|
||||
"marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="],
|
||||
|
||||
"marked-base-url": ["marked-base-url@1.1.7", "", { "peerDependencies": { "marked": ">= 4 < 17" } }, "sha512-CJOfpG2/XOEp8UuI5H0tbELxuS1v8Ud705jamEIpWBQDdkda1i+LrafxLn41rlxhGEeJqo27b/hBFVYHWOYccw=="],
|
||||
"marked-base-url": ["marked-base-url@1.1.8", "", { "peerDependencies": { "marked": ">= 4 < 18" } }, "sha512-RA80m/VTq82jAnpusyK7B4M45TZ3LMB1ymrdAJI3oaSG4+8MzBc8FFlVKIAhkBrfRM7CxeTHTGUVVK59/eiQyA=="],
|
||||
|
||||
"marked-smartypants": ["marked-smartypants@1.1.10", "", { "dependencies": { "smartypants": "^0.2.2" }, "peerDependencies": { "marked": ">=4 <17" } }, "sha512-XGK59M2nhy3Jpa0kdWSXQuKn908VkKbqK1IqF8Rk5QV619OWBs2/rkcg/PVhpKkADlRKJSYe6XqDMZMkZywT4g=="],
|
||||
"marked-smartypants": ["marked-smartypants@1.1.11", "", { "dependencies": { "smartypants": "^0.2.2" }, "peerDependencies": { "marked": ">=4 <18" } }, "sha512-Jt0eq/6rf9oXDfEKPzQ0z7UzVWcEAK3L6QBBQzbwV8bT304OvPVLTqpH3yvkSung9foOM4s120TMHEHP76Metg=="],
|
||||
|
||||
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||
|
||||
@@ -716,7 +724,7 @@
|
||||
|
||||
"media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="],
|
||||
|
||||
"memfs": ["memfs@4.17.2", "", { "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", "@jsonjoy.com/util": "^1.3.0", "tree-dump": "^1.0.1", "tslib": "^2.0.0" } }, "sha512-NgYhCOWgovOXSzvYgUW0LQ7Qy72rWQMGGFJDoWg4G30RHd3z77VbYdtJ4fembJXBy8pMIUA31XNAupobOQlwdg=="],
|
||||
"memfs": ["memfs@4.51.1", "", { "dependencies": { "@jsonjoy.com/json-pack": "^1.11.0", "@jsonjoy.com/util": "^1.9.0", "glob-to-regex.js": "^1.0.1", "thingies": "^2.5.0", "tree-dump": "^1.0.3", "tslib": "^2.0.0" } }, "sha512-Eyt3XrufitN2ZL9c/uIRMyDwXanLI88h/L3MoWqNY747ha3dMR9dWqp8cRT5ntjZ0U1TNuq4U91ZXK0sMBjYOQ=="],
|
||||
|
||||
"merge-descriptors": ["merge-descriptors@1.0.3", "", {}, "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="],
|
||||
|
||||
@@ -760,7 +768,7 @@
|
||||
|
||||
"mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="],
|
||||
|
||||
"nan": ["nan@2.22.2", "", {}, "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ=="],
|
||||
"nan": ["nan@2.24.0", "", {}, "sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||
|
||||
@@ -774,7 +782,7 @@
|
||||
|
||||
"node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
|
||||
|
||||
"node-forge": ["node-forge@1.3.1", "", {}, "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA=="],
|
||||
"node-forge": ["node-forge@1.3.3", "", {}, "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg=="],
|
||||
|
||||
"node-gyp": ["node-gyp@10.3.1", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^10.3.10", "graceful-fs": "^4.2.6", "make-fetch-happen": "^13.0.0", "nopt": "^7.0.0", "proc-log": "^4.1.0", "semver": "^7.3.5", "tar": "^6.2.1", "which": "^4.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ=="],
|
||||
|
||||
@@ -794,11 +802,11 @@
|
||||
|
||||
"on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
|
||||
|
||||
"on-headers": ["on-headers@1.0.2", "", {}, "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="],
|
||||
"on-headers": ["on-headers@1.1.0", "", {}, "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A=="],
|
||||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"open": ["open@10.1.2", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw=="],
|
||||
"open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
|
||||
|
||||
"opener": ["opener@1.5.2", "", { "bin": { "opener": "bin/opener-bin.js" } }, "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A=="],
|
||||
|
||||
@@ -822,7 +830,7 @@
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"path-scurry": ["path-scurry@2.0.0", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg=="],
|
||||
"path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="],
|
||||
|
||||
"path-to-regexp": ["path-to-regexp@0.1.12", "", {}, "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="],
|
||||
|
||||
@@ -842,7 +850,7 @@
|
||||
|
||||
"postcss-modules-values": ["postcss-modules-values@4.0.0", "", { "dependencies": { "icss-utils": "^5.0.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ=="],
|
||||
|
||||
"postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="],
|
||||
"postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="],
|
||||
|
||||
"postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
|
||||
|
||||
@@ -856,17 +864,17 @@
|
||||
|
||||
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
||||
|
||||
"qs": ["qs@6.13.0", "", { "dependencies": { "side-channel": "^1.0.6" } }, "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg=="],
|
||||
"qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
|
||||
|
||||
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
|
||||
|
||||
"raw-body": ["raw-body@2.5.2", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA=="],
|
||||
"raw-body": ["raw-body@2.5.3", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "unpipe": "~1.0.0" } }, "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA=="],
|
||||
|
||||
"react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
|
||||
"react": ["react@19.2.3", "", {}, "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA=="],
|
||||
|
||||
"react-base16-styling": ["react-base16-styling@0.10.0", "", { "dependencies": { "@types/lodash": "^4.17.0", "color": "^4.2.3", "csstype": "^3.1.3", "lodash-es": "^4.17.21" } }, "sha512-H1k2eFB6M45OaiRru3PBXkuCcn2qNmx+gzLb4a9IPMR7tMH8oBRXU5jGbPDYG1Hz+82d88ED0vjR8BmqU3pQdg=="],
|
||||
|
||||
"react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
|
||||
"react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="],
|
||||
|
||||
"react-json-tree": ["react-json-tree@0.20.0", "", { "dependencies": { "@types/lodash": "^4.17.15", "react-base16-styling": "^0.10.0" }, "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-h+f9fUNAxzBx1rbrgUF7+zSWKGHDtt2VPYLErIuB0JyKGnWgFMM21ksqQyb3EXwXNnoMW2rdE5kuAaubgGOx2Q=="],
|
||||
|
||||
@@ -882,7 +890,7 @@
|
||||
|
||||
"retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="],
|
||||
|
||||
"run-applescript": ["run-applescript@7.0.0", "", {}, "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A=="],
|
||||
"run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],
|
||||
|
||||
"rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
|
||||
|
||||
@@ -932,23 +940,23 @@
|
||||
|
||||
"sass-loader": ["sass-loader@16.0.6", "", { "dependencies": { "neo-async": "^2.6.2" }, "peerDependencies": { "@rspack/core": "0.x || 1.x", "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "sass": "^1.3.0", "sass-embedded": "*", "webpack": "^5.0.0" }, "optionalPeers": ["@rspack/core", "node-sass", "sass", "sass-embedded", "webpack"] }, "sha512-sglGzId5gmlfxNs4gK2U3h7HlVRfx278YK6Ono5lwzuvi1jxig80YiuHkaDBVsYIKFhx8wN7XSCI0M2IDS/3qA=="],
|
||||
|
||||
"sax": ["sax@1.4.1", "", {}, "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="],
|
||||
"sax": ["sax@1.4.3", "", {}, "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ=="],
|
||||
|
||||
"scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
|
||||
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||
|
||||
"schema-utils": ["schema-utils@4.3.2", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ=="],
|
||||
"schema-utils": ["schema-utils@4.3.3", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA=="],
|
||||
|
||||
"select-hose": ["select-hose@2.0.0", "", {}, "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg=="],
|
||||
|
||||
"selfsigned": ["selfsigned@2.4.1", "", { "dependencies": { "@types/node-forge": "^1.3.0", "node-forge": "^1" } }, "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q=="],
|
||||
|
||||
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||
|
||||
"send": ["send@0.19.0", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "2.4.1", "range-parser": "~1.2.1", "statuses": "2.0.1" } }, "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw=="],
|
||||
"send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="],
|
||||
|
||||
"serve-index": ["serve-index@1.9.1", "", { "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", "debug": "2.6.9", "escape-html": "~1.0.3", "http-errors": "~1.6.2", "mime-types": "~2.1.17", "parseurl": "~1.3.2" } }, "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw=="],
|
||||
|
||||
"serve-static": ["serve-static@1.16.2", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.19.0" } }, "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw=="],
|
||||
"serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="],
|
||||
|
||||
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
||||
|
||||
@@ -978,11 +986,11 @@
|
||||
|
||||
"sockjs": ["sockjs@0.3.24", "", { "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", "websocket-driver": "^0.7.4" } }, "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ=="],
|
||||
|
||||
"socks": ["socks@2.8.5", "", { "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" } }, "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww=="],
|
||||
"socks": ["socks@2.8.7", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="],
|
||||
|
||||
"socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
|
||||
|
||||
"source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="],
|
||||
"source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
|
||||
|
||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||
|
||||
@@ -992,13 +1000,11 @@
|
||||
|
||||
"spdy-transport": ["spdy-transport@3.0.0", "", { "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", "hpack.js": "^2.1.6", "obuf": "^1.1.2", "readable-stream": "^3.0.6", "wbuf": "^1.7.3" } }, "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw=="],
|
||||
|
||||
"sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="],
|
||||
|
||||
"ssri": ["ssri@10.0.6", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ=="],
|
||||
|
||||
"stacktrace-parser": ["stacktrace-parser@0.1.11", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg=="],
|
||||
|
||||
"statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="],
|
||||
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
||||
|
||||
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
@@ -1010,7 +1016,7 @@
|
||||
|
||||
"strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"sucrase": ["sucrase@3.35.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="],
|
||||
"sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="],
|
||||
|
||||
"supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||
|
||||
@@ -1024,17 +1030,17 @@
|
||||
|
||||
"svgpath": ["svgpath@2.6.0", "", {}, "sha512-OIWR6bKzXvdXYyO4DK/UWa1VA1JeKq8E+0ug2DG98Y/vOmMpfZNj+TIG988HjfYSqtcy/hFOtZq/n/j5GSESNg=="],
|
||||
|
||||
"svgtofont": ["svgtofont@6.3.2", "", { "dependencies": { "auto-config-loader": "^2.0.0", "cheerio": "~1.0.0", "colors-cli": "~1.0.28", "fs-extra": "~11.2.0", "image2uri": "^2.1.2", "nunjucks": "^3.2.4", "svg2ttf": "~6.0.3", "svgicons2svgfont": "~15.0.0", "svgo": "~3.3.0", "ttf2eot": "~3.1.0", "ttf2woff": "~3.0.0", "ttf2woff2": "~6.0.0", "yargs": "^17.7.2" }, "peerDependencies": { "@types/svg2ttf": "~5.0.1" }, "optionalPeers": ["@types/svg2ttf"], "bin": { "svgtofont": "lib/cli.js" } }, "sha512-lK58H4sLLp+BdQYOe8RbMthudbPkS6fCbWqce5R79M34FcLo4UZ7wy5zf0mjrBfueFcqSJlZycoe5JnFnu9yoA=="],
|
||||
"svgtofont": ["svgtofont@6.5.0", "", { "dependencies": { "auto-config-loader": "^2.0.0", "cheerio": "~1.0.0", "colors-cli": "~1.0.28", "fs-extra": "~11.2.0", "image2uri": "^2.1.2", "nunjucks": "^3.2.4", "svg2ttf": "~6.0.3", "svgicons2svgfont": "~15.0.0", "svgo": "~3.3.0", "ttf2eot": "~3.1.0", "ttf2woff": "~3.0.0", "ttf2woff2": "~6.0.0", "yargs": "^17.7.2" }, "peerDependencies": { "@types/svg2ttf": "~5.0.1" }, "optionalPeers": ["@types/svg2ttf"], "bin": { "svgtofont": "lib/cli.js" } }, "sha512-YLtTgSGBERdG0MhXAAIKvG/qjexpqoAw0GUAF1CLreDMI5zkPcRUPji1eNfk4ht5Ffgtm5QIDL7r6z2f+A5GFw=="],
|
||||
|
||||
"sync-child-process": ["sync-child-process@1.0.2", "", { "dependencies": { "sync-message-port": "^1.0.0" } }, "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA=="],
|
||||
|
||||
"sync-message-port": ["sync-message-port@1.1.3", "", {}, "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg=="],
|
||||
|
||||
"tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="],
|
||||
"tabbable": ["tabbable@6.3.0", "", {}, "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ=="],
|
||||
|
||||
"tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
|
||||
|
||||
"terser": ["terser@5.43.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.14.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg=="],
|
||||
"terser": ["terser@5.44.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw=="],
|
||||
|
||||
"tgfont": ["tgfont@workspace:packages/tgfont"],
|
||||
|
||||
@@ -1054,21 +1060,23 @@
|
||||
|
||||
"thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="],
|
||||
|
||||
"thingies": ["thingies@1.21.0", "", { "peerDependencies": { "tslib": "^2" } }, "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g=="],
|
||||
"thingies": ["thingies@2.5.0", "", { "peerDependencies": { "tslib": "^2" } }, "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw=="],
|
||||
|
||||
"thunky": ["thunky@1.1.0", "", {}, "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
||||
|
||||
"toml-eslint-parser": ["toml-eslint-parser@0.10.0", "", { "dependencies": { "eslint-visitor-keys": "^3.0.0" } }, "sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g=="],
|
||||
"toml-eslint-parser": ["toml-eslint-parser@0.10.1", "", { "dependencies": { "eslint-visitor-keys": "^3.0.0" } }, "sha512-9mjy3frhioGIVGcwamlVlUyJ9x+WHw/TXiz9R4YOlmsIuBN43r9Dp8HZ35SF9EKjHrn3BUZj04CF+YqZ2oJ+7w=="],
|
||||
|
||||
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
||||
|
||||
"transformation-matrix": ["transformation-matrix@3.0.0", "", {}, "sha512-C6NlNnD6T8JqDeY4BpGznuve4d8/JlLDZLcJbnnx7gQKoyk01+uk2XYVFjBGqvNsVxJUpUwb3WZpjpdPr+05FQ=="],
|
||||
"transformation-matrix": ["transformation-matrix@3.1.0", "", {}, "sha512-oYubRWTi2tYFHAL2J8DLvPIqIYcYZ0fSOi2vmSy042Ho4jBW2ce6VP7QfD44t65WQz6bw5w1Pk22J7lcUpaTKA=="],
|
||||
|
||||
"tree-dump": ["tree-dump@1.0.3", "", { "peerDependencies": { "tslib": "2" } }, "sha512-il+Cv80yVHFBwokQSfd4bldvr1Md951DpgAGfmhydt04L+YzHgubm2tQ7zueWDcGENKHq0ZvGFR/hjvNXilHEg=="],
|
||||
"tree-dump": ["tree-dump@1.1.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA=="],
|
||||
|
||||
"ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="],
|
||||
|
||||
@@ -1084,9 +1092,9 @@
|
||||
|
||||
"type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="],
|
||||
|
||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"undici": ["undici@6.21.3", "", {}, "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw=="],
|
||||
"undici": ["undici@6.22.0", "", {}, "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw=="],
|
||||
|
||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||
|
||||
@@ -1114,7 +1122,7 @@
|
||||
|
||||
"webpack-bundle-analyzer": ["webpack-bundle-analyzer@4.10.2", "", { "dependencies": { "@discoveryjs/json-ext": "0.5.7", "acorn": "^8.0.4", "acorn-walk": "^8.0.0", "commander": "^7.2.0", "debounce": "^1.2.1", "escape-string-regexp": "^4.0.0", "gzip-size": "^6.0.0", "html-escaper": "^2.0.2", "opener": "^1.5.2", "picocolors": "^1.0.0", "sirv": "^2.0.3", "ws": "^7.3.1" }, "bin": { "webpack-bundle-analyzer": "lib/bin/analyzer.js" } }, "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw=="],
|
||||
|
||||
"webpack-dev-middleware": ["webpack-dev-middleware@7.4.2", "", { "dependencies": { "colorette": "^2.0.10", "memfs": "^4.6.0", "mime-types": "^2.1.31", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" }, "peerDependencies": { "webpack": "^5.0.0" }, "optionalPeers": ["webpack"] }, "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA=="],
|
||||
"webpack-dev-middleware": ["webpack-dev-middleware@7.4.5", "", { "dependencies": { "colorette": "^2.0.10", "memfs": "^4.43.1", "mime-types": "^3.0.1", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" }, "peerDependencies": { "webpack": "^5.0.0" }, "optionalPeers": ["webpack"] }, "sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA=="],
|
||||
|
||||
"webpack-dev-server": ["webpack-dev-server@5.2.2", "", { "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", "@types/express": "^4.17.21", "@types/express-serve-static-core": "^4.17.21", "@types/serve-index": "^1.9.4", "@types/serve-static": "^1.15.5", "@types/sockjs": "^0.3.36", "@types/ws": "^8.5.10", "ansi-html-community": "^0.0.8", "bonjour-service": "^1.2.1", "chokidar": "^3.6.0", "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", "express": "^4.21.2", "graceful-fs": "^4.2.6", "http-proxy-middleware": "^2.0.9", "ipaddr.js": "^2.1.0", "launch-editor": "^2.6.1", "open": "^10.0.3", "p-retry": "^6.2.0", "schema-utils": "^4.2.0", "selfsigned": "^2.4.1", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", "webpack-dev-middleware": "^7.4.2", "ws": "^8.18.0" }, "peerDependencies": { "webpack": "^5.0.0" }, "optionalPeers": ["webpack"], "bin": { "webpack-dev-server": "bin/webpack-dev-server.js" } }, "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg=="],
|
||||
|
||||
@@ -1136,13 +1144,15 @@
|
||||
|
||||
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
||||
|
||||
"wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="],
|
||||
|
||||
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
|
||||
|
||||
"yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"yaml": ["yaml@2.8.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ=="],
|
||||
"yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="],
|
||||
|
||||
"yaml-eslint-parser": ["yaml-eslint-parser@1.3.0", "", { "dependencies": { "eslint-visitor-keys": "^3.0.0", "yaml": "^2.0.0" } }, "sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA=="],
|
||||
"yaml-eslint-parser": ["yaml-eslint-parser@1.3.2", "", { "dependencies": { "eslint-visitor-keys": "^3.0.0", "yaml": "^2.0.0" } }, "sha512-odxVsHAkZYYglR30aPYRY4nUGJnoJ2y1ww2HDvZALo0BDETv9kWbi16J52eHs+PWRNmF4ub6nZqfVOeesOvntg=="],
|
||||
|
||||
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
|
||||
|
||||
@@ -1154,35 +1164,37 @@
|
||||
|
||||
"@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
||||
"@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
|
||||
"@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
|
||||
|
||||
"@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
||||
|
||||
"@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"@types/body-parser/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/body-parser/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/bonjour/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/bonjour/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/connect/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/connect/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/connect-history-api-fallback/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/connect-history-api-fallback/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/express-serve-static-core/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/express-serve-static-core/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/http-proxy/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/http-proxy/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/node-forge/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/node-forge/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/sax/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/sax/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/send/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/send/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/serve-static/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/serve-static/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/sockjs/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/serve-static/@types/send": ["@types/send@0.17.6", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og=="],
|
||||
|
||||
"@types/ws/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"@types/sockjs/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"@types/ws/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
|
||||
|
||||
@@ -1190,11 +1202,11 @@
|
||||
|
||||
"body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
|
||||
|
||||
"bun-types/@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
"bun-types/@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||
|
||||
"cacache/fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="],
|
||||
|
||||
"cacache/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||
"cacache/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
|
||||
|
||||
"cacache/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
@@ -1202,6 +1214,8 @@
|
||||
|
||||
"clean-css/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"compressible/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
||||
|
||||
"compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||
|
||||
"cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
@@ -1224,7 +1238,7 @@
|
||||
|
||||
"minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"node-gyp/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||
"node-gyp/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
|
||||
|
||||
"nunjucks/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="],
|
||||
|
||||
@@ -1240,8 +1254,6 @@
|
||||
|
||||
"send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||
|
||||
"send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
|
||||
|
||||
"serve-index/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||
|
||||
"serve-index/http-errors": ["http-errors@1.6.3", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" } }, "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A=="],
|
||||
@@ -1250,51 +1262,53 @@
|
||||
|
||||
"sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
|
||||
|
||||
"sucrase/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||
|
||||
"svgicons2svgfont/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
|
||||
|
||||
"svgicons2svgfont/glob": ["glob@11.0.3", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA=="],
|
||||
"svgicons2svgfont/glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="],
|
||||
|
||||
"tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="],
|
||||
|
||||
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||
|
||||
"tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"webpack-bundle-analyzer/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
||||
|
||||
"webpack-dev-middleware/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
||||
|
||||
"@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
"@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
|
||||
"@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
|
||||
"@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
|
||||
"@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
||||
|
||||
"@types/body-parser/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/body-parser/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/bonjour/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/bonjour/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/connect-history-api-fallback/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/connect-history-api-fallback/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/connect/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/connect/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/express-serve-static-core/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/express-serve-static-core/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/http-proxy/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/http-proxy/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/node-forge/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/node-forge/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/sax/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/sax/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/send/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/send/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/serve-static/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/serve-static/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/sockjs/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/sockjs/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/ws/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"@types/ws/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"bun-types/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
"bun-types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"cacache/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||
|
||||
@@ -1336,22 +1350,14 @@
|
||||
|
||||
"serve-index/http-errors/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="],
|
||||
|
||||
"sucrase/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||
"svgicons2svgfont/glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="],
|
||||
|
||||
"sucrase/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"sucrase/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||
|
||||
"svgicons2svgfont/glob/minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="],
|
||||
"webpack-dev-middleware/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
||||
|
||||
"cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
|
||||
"node-gyp/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
|
||||
"node-gyp/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"sucrase/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
|
||||
"sucrase/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-2
@@ -193,8 +193,7 @@ const Byond: ByondType = {};
|
||||
|
||||
interface Window {
|
||||
Byond: ByondType;
|
||||
__store__: Store<unknown, AnyAction>;
|
||||
__augmentStack__: (store: Store) => StackAugmentor;
|
||||
__augmentStack__: (stack: string, error?: Error) => string;
|
||||
|
||||
// IE IndexedDB stuff.
|
||||
msIndexedDB: IDBFactory;
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import { describe, expect, it } from 'bun:test';
|
||||
|
||||
import {
|
||||
type Action,
|
||||
applyMiddleware,
|
||||
combineReducers,
|
||||
createAction,
|
||||
createStore,
|
||||
type Reducer,
|
||||
} from './redux';
|
||||
|
||||
// Dummy Reducer
|
||||
const counterReducer: Reducer<number, Action<string>> = (state = 0, action) => {
|
||||
switch (action.type) {
|
||||
case 'INCREMENT':
|
||||
return state + 1;
|
||||
case 'DECREMENT':
|
||||
return state - 1;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
// Dummy Middleware
|
||||
const loggingMiddleware = (storeApi) => (next) => (action) => {
|
||||
console.log('Middleware:', action);
|
||||
return next(action);
|
||||
};
|
||||
|
||||
// Dummy Action Creators
|
||||
const increment = createAction('INCREMENT');
|
||||
const decrement = createAction('DECREMENT');
|
||||
|
||||
describe('Redux implementation tests', () => {
|
||||
it('createStore works', () => {
|
||||
const store = createStore(counterReducer);
|
||||
expect(store.getState()).toBe(0);
|
||||
});
|
||||
|
||||
it('createStore with applyMiddleware works', () => {
|
||||
const store = createStore(
|
||||
counterReducer,
|
||||
applyMiddleware(loggingMiddleware),
|
||||
);
|
||||
expect(store.getState()).toBe(0);
|
||||
});
|
||||
|
||||
it('dispatch works', () => {
|
||||
const store = createStore(counterReducer);
|
||||
store.dispatch(increment());
|
||||
expect(store.getState()).toBe(1);
|
||||
store.dispatch(decrement());
|
||||
expect(store.getState()).toBe(0);
|
||||
});
|
||||
|
||||
it('combineReducers works', () => {
|
||||
const rootReducer = combineReducers({
|
||||
counter: counterReducer,
|
||||
});
|
||||
const store = createStore(rootReducer);
|
||||
expect(store.getState()).toEqual({ counter: 0 });
|
||||
});
|
||||
|
||||
it('createAction works', () => {
|
||||
const incrementAction = increment();
|
||||
expect(incrementAction).toEqual({ type: 'INCREMENT' });
|
||||
const decrementAction = decrement();
|
||||
expect(decrementAction).toEqual({ type: 'DECREMENT' });
|
||||
});
|
||||
});
|
||||
@@ -1,198 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
type Fn = (...args: any[]) => any;
|
||||
|
||||
export type Reducer<State = any, ActionType extends Action = AnyAction> = (
|
||||
state: State | undefined,
|
||||
action: ActionType,
|
||||
) => State;
|
||||
|
||||
export type Store<State = any, ActionType extends Action = AnyAction> = {
|
||||
dispatch: Dispatch<ActionType>;
|
||||
subscribe: (listener: () => void) => void;
|
||||
getState: () => State;
|
||||
};
|
||||
|
||||
type MiddlewareAPI<State = any, ActionType extends Action = AnyAction> = {
|
||||
getState: () => State;
|
||||
dispatch: Dispatch<ActionType>;
|
||||
};
|
||||
|
||||
export type Middleware = <State = any, ActionType extends Action = AnyAction>(
|
||||
storeApi: MiddlewareAPI<State, ActionType>,
|
||||
) => (next: Dispatch<ActionType>) => Dispatch<ActionType>;
|
||||
|
||||
export type Action<TType = any> = {
|
||||
type: TType;
|
||||
};
|
||||
|
||||
export type AnyAction = Action & {
|
||||
[extraProps: string]: any;
|
||||
};
|
||||
|
||||
export type Dispatch<ActionType extends Action = AnyAction> = (
|
||||
action: ActionType,
|
||||
) => void;
|
||||
|
||||
type StoreEnhancer = (createStoreFunction: Fn) => Fn;
|
||||
|
||||
type PreparedAction = {
|
||||
payload?: any;
|
||||
meta?: any;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a Redux store.
|
||||
*/
|
||||
export const createStore = <State, ActionType extends Action = AnyAction>(
|
||||
reducer: Reducer<State, ActionType>,
|
||||
enhancer?: StoreEnhancer,
|
||||
): Store<State, ActionType> => {
|
||||
// Apply a store enhancer (applyMiddleware is one of them).
|
||||
if (enhancer) {
|
||||
return enhancer(createStore)(reducer);
|
||||
}
|
||||
|
||||
let currentState: State;
|
||||
const listeners: Array<() => void> = [];
|
||||
|
||||
const getState = (): State => currentState;
|
||||
|
||||
const subscribe = (listener: () => void): void => {
|
||||
listeners.push(listener);
|
||||
};
|
||||
|
||||
const dispatch = (action: ActionType): void => {
|
||||
currentState = reducer(currentState, action);
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
listeners[i]();
|
||||
}
|
||||
};
|
||||
|
||||
// This creates the initial store by causing each reducer to be called
|
||||
// with an undefined state
|
||||
dispatch({ type: '@@INIT' } as ActionType);
|
||||
|
||||
return {
|
||||
dispatch,
|
||||
subscribe,
|
||||
getState,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a store enhancer which applies middleware to all dispatched
|
||||
* actions.
|
||||
*/
|
||||
export const applyMiddleware = (
|
||||
...middlewares: Middleware[]
|
||||
): StoreEnhancer => {
|
||||
return (
|
||||
createStoreFunction: (reducer: Reducer, enhancer?: StoreEnhancer) => Store,
|
||||
) => {
|
||||
return (reducer, ...args): Store => {
|
||||
const store = createStoreFunction(reducer, ...args);
|
||||
|
||||
let dispatch: Dispatch = (action, ...args) => {
|
||||
throw new Error(
|
||||
'Dispatching while constructing your middleware is not allowed.',
|
||||
);
|
||||
};
|
||||
|
||||
const storeApi: MiddlewareAPI = {
|
||||
getState: store.getState,
|
||||
dispatch: (action, ...args) => dispatch(action, ...args),
|
||||
};
|
||||
|
||||
const chain = middlewares.map((middleware) => middleware(storeApi));
|
||||
dispatch = chain.reduceRight(
|
||||
(next, middleware) => middleware(next),
|
||||
store.dispatch,
|
||||
);
|
||||
|
||||
return {
|
||||
...store,
|
||||
dispatch,
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Combines reducers by running them in their own object namespaces as
|
||||
* defined in reducersObj paramter.
|
||||
*
|
||||
* Main difference from redux/combineReducers is that it preserves keys
|
||||
* in the state that are not present in the reducers object. This function
|
||||
* is also more flexible than the redux counterpart.
|
||||
*/
|
||||
export const combineReducers = (
|
||||
reducersObj: Record<string, Reducer>,
|
||||
): Reducer => {
|
||||
const keys = Object.keys(reducersObj);
|
||||
|
||||
return (prevState = {}, action) => {
|
||||
const nextState = { ...prevState };
|
||||
let hasChanged = false;
|
||||
|
||||
for (const key of keys) {
|
||||
const reducer = reducersObj[key];
|
||||
const prevDomainState = prevState[key];
|
||||
const nextDomainState = reducer(prevDomainState, action);
|
||||
|
||||
if (prevDomainState !== nextDomainState) {
|
||||
hasChanged = true;
|
||||
nextState[key] = nextDomainState;
|
||||
}
|
||||
}
|
||||
|
||||
return hasChanged ? nextState : prevState;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* A utility function to create an action creator for the given action
|
||||
* type string. The action creator accepts a single argument, which will
|
||||
* be included in the action object as a field called payload. The action
|
||||
* creator function will also have its toString() overriden so that it
|
||||
* returns the action type, allowing it to be used in reducer logic that
|
||||
* is looking for that action type.
|
||||
*
|
||||
* @param {string} type The action type to use for created actions.
|
||||
* @param {any} prepare (optional) a method that takes any number of arguments
|
||||
* and returns { payload } or { payload, meta }. If this is given, the
|
||||
* resulting action creator will pass its arguments to this method to
|
||||
* calculate payload & meta.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const createAction = <TAction extends string>(
|
||||
type: TAction,
|
||||
prepare?: (...args: any[]) => PreparedAction,
|
||||
) => {
|
||||
const actionCreator = (...args: any[]) => {
|
||||
let action: Action<TAction> & PreparedAction = { type };
|
||||
|
||||
if (prepare) {
|
||||
const prepared = prepare(...args);
|
||||
if (!prepared) {
|
||||
throw new Error('prepare function did not return an object');
|
||||
}
|
||||
action = { ...action, ...prepared };
|
||||
} else {
|
||||
action.payload = args[0];
|
||||
}
|
||||
|
||||
return action;
|
||||
};
|
||||
|
||||
actionCreator.toString = () => type;
|
||||
actionCreator.type = type;
|
||||
actionCreator.match = (action) => action.type === type;
|
||||
|
||||
return actionCreator;
|
||||
};
|
||||
@@ -5,7 +5,7 @@ import type { ServerWebSocket } from 'bun';
|
||||
import { createLogger, directLog } from '../logging';
|
||||
import { retrace } from './retrace';
|
||||
|
||||
let server: Bun.Server;
|
||||
let server: Bun.Server<unknown>;
|
||||
const logger = createLogger('link');
|
||||
const DEBUG = process.argv.includes('--debug');
|
||||
|
||||
@@ -98,7 +98,7 @@ function handleLinkMessage(
|
||||
logger.log('unhandled message', JSON.stringify(message));
|
||||
}
|
||||
|
||||
function upgradeServer(req: Request, srv: Bun.Server) {
|
||||
function upgradeServer(req: Request, srv: Bun.Server<unknown>) {
|
||||
const client = crypto.randomUUID();
|
||||
|
||||
const upgraded = srv.upgrade(req, {
|
||||
|
||||
@@ -61,7 +61,9 @@ export class RspackCompiler {
|
||||
stats
|
||||
?.toString(this.config.stats)
|
||||
.split('\n')
|
||||
.forEach((line) => logger.log(line));
|
||||
.forEach((line) => {
|
||||
logger.log(line);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { globalStore } from './backend';
|
||||
import { Provider } from 'jotai';
|
||||
import { store } from './events/store';
|
||||
import { IconProvider } from './Icons';
|
||||
import { RoutedComponent } from './routes';
|
||||
|
||||
export function App() {
|
||||
const { getRoutedComponent } = require('./routes');
|
||||
const Component = getRoutedComponent(globalStore);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Component />
|
||||
<Provider store={store}>
|
||||
<RoutedComponent />
|
||||
<IconProvider />
|
||||
</>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Suspense, useEffect } from 'react';
|
||||
import { fetchRetry } from 'tgui-core/http';
|
||||
|
||||
import { resolveAsset } from './assets';
|
||||
import { logger } from './logging';
|
||||
|
||||
|
||||
@@ -1,45 +1,5 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @license MIT
|
||||
*/
|
||||
export const loadedMappings: Record<string, string> = {};
|
||||
|
||||
import type { Dispatch } from 'common/redux';
|
||||
|
||||
import type { Action, AnyAction, Middleware } from '../common/redux';
|
||||
|
||||
const EXCLUDED_PATTERNS = [/v4shim/i];
|
||||
const loadedMappings: Record<string, string> = {};
|
||||
|
||||
export const resolveAsset = (name: string): string =>
|
||||
loadedMappings[name] || name;
|
||||
|
||||
export const assetMiddleware: Middleware =
|
||||
(storeApi) =>
|
||||
<ActionType extends Action = AnyAction>(next: Dispatch<ActionType>) =>
|
||||
(action: ActionType) => {
|
||||
const { type, payload } = action as AnyAction;
|
||||
if (type === 'asset/stylesheet') {
|
||||
Byond.loadCss(payload);
|
||||
return;
|
||||
}
|
||||
if (type === 'asset/mappings') {
|
||||
for (const name of Object.keys(payload)) {
|
||||
// Skip anything that matches excluded patterns
|
||||
if (EXCLUDED_PATTERNS.some((regex) => regex.test(name))) {
|
||||
continue;
|
||||
}
|
||||
const url = payload[name];
|
||||
const ext = name.split('.').pop();
|
||||
loadedMappings[name] = url;
|
||||
if (ext === 'css') {
|
||||
Byond.loadCss(url);
|
||||
}
|
||||
if (ext === 'js') {
|
||||
Byond.loadJs(url);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
next(action);
|
||||
};
|
||||
export function resolveAsset(name: string): string {
|
||||
return loadedMappings[name] || name;
|
||||
}
|
||||
|
||||
+39
-447
@@ -1,425 +1,32 @@
|
||||
import { sendAct } from './events/act';
|
||||
import { backendStateAtom, sharedAtom, store } from './events/store';
|
||||
import type { BackendState } from './events/types';
|
||||
|
||||
/**
|
||||
* This file provides a clear separation layer between backend updates
|
||||
* and what state our React app sees.
|
||||
* Reactive backend state hook. Please use a type to define what the data is
|
||||
* intended to be, e.g.:
|
||||
*
|
||||
* Sometimes backend can response without a "data" field, but our final
|
||||
* state will still contain previous "data" because we are merging
|
||||
* the response with already existing state.
|
||||
* ```ts
|
||||
* type Data = {
|
||||
* username: string;
|
||||
* };
|
||||
*
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { perf } from 'common/perf';
|
||||
import { createAction } from 'common/redux';
|
||||
import type { BooleanLike } from 'tgui-core/react';
|
||||
|
||||
import { setupDrag } from './drag';
|
||||
import { focusMap } from './focus';
|
||||
import { createLogger } from './logging';
|
||||
import { resumeRenderer, suspendRenderer } from './renderer';
|
||||
|
||||
const logger = createLogger('backend');
|
||||
|
||||
export let globalStore;
|
||||
|
||||
export const setGlobalStore = (store) => {
|
||||
globalStore = store;
|
||||
};
|
||||
|
||||
export const backendUpdate = createAction('backend/update');
|
||||
export const backendSetSharedState = createAction('backend/setSharedState');
|
||||
export const backendSuspendStart = createAction('backend/suspendStart');
|
||||
export const backendCreatePayloadQueue = createAction(
|
||||
'backend/createPayloadQueue',
|
||||
);
|
||||
export const backendDequeuePayloadQueue = createAction(
|
||||
'backend/dequeuePayloadQueue',
|
||||
);
|
||||
export const backendRemovePayloadQueue = createAction(
|
||||
'backend/removePayloadQueue',
|
||||
);
|
||||
export const nextPayloadChunk = createAction('nextPayloadChunk');
|
||||
|
||||
export const backendSuspendSuccess = () => ({
|
||||
type: 'backend/suspendSuccess',
|
||||
payload: {
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
});
|
||||
|
||||
const initialState = {
|
||||
config: {},
|
||||
data: {},
|
||||
shared: {},
|
||||
outgoingPayloadQueues: {} as Record<string, string[]>,
|
||||
// Start as suspended
|
||||
suspended: Date.now(),
|
||||
suspending: false,
|
||||
};
|
||||
|
||||
export const backendReducer = (state = initialState, action) => {
|
||||
const { type, payload } = action;
|
||||
|
||||
if (type === 'backend/update') {
|
||||
// Merge config
|
||||
const config = {
|
||||
...state.config,
|
||||
...payload.config,
|
||||
};
|
||||
// Merge data
|
||||
const data = {
|
||||
...state.data,
|
||||
...payload.static_data,
|
||||
...payload.data,
|
||||
};
|
||||
// Merge shared states
|
||||
const shared = { ...state.shared };
|
||||
if (payload.shared) {
|
||||
for (const key of Object.keys(payload.shared)) {
|
||||
const value = payload.shared[key];
|
||||
if (value === '') {
|
||||
shared[key] = undefined;
|
||||
} else {
|
||||
shared[key] = JSON.parse(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return new state
|
||||
return {
|
||||
...state,
|
||||
config,
|
||||
data,
|
||||
shared,
|
||||
suspended: false,
|
||||
};
|
||||
}
|
||||
|
||||
if (type === 'backend/setSharedState') {
|
||||
const { key, nextState } = payload;
|
||||
return {
|
||||
...state,
|
||||
shared: {
|
||||
...state.shared,
|
||||
[key]: nextState,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (type === 'backend/suspendStart') {
|
||||
return {
|
||||
...state,
|
||||
suspending: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (type === 'backend/suspendSuccess') {
|
||||
const { timestamp } = payload;
|
||||
return {
|
||||
...state,
|
||||
data: {},
|
||||
shared: {},
|
||||
config: {
|
||||
...state.config,
|
||||
title: '',
|
||||
status: 1,
|
||||
},
|
||||
suspending: false,
|
||||
suspended: timestamp,
|
||||
};
|
||||
}
|
||||
|
||||
if (type === 'backend/createPayloadQueue') {
|
||||
const { id, chunks } = payload;
|
||||
const { outgoingPayloadQueues } = state;
|
||||
return {
|
||||
...state,
|
||||
outgoingPayloadQueues: {
|
||||
...outgoingPayloadQueues,
|
||||
[id]: chunks,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (type === 'backend/dequeuePayloadQueue') {
|
||||
const { id } = payload;
|
||||
const { outgoingPayloadQueues } = state;
|
||||
const { [id]: targetQueue, ...otherQueues } = outgoingPayloadQueues;
|
||||
const [_, ...rest] = targetQueue;
|
||||
return {
|
||||
...state,
|
||||
outgoingPayloadQueues: rest.length
|
||||
? {
|
||||
...otherQueues,
|
||||
[id]: rest,
|
||||
}
|
||||
: otherQueues,
|
||||
};
|
||||
}
|
||||
|
||||
if (type === 'backend/removePayloadQueue') {
|
||||
const { id } = payload;
|
||||
const { outgoingPayloadQueues } = state;
|
||||
const { [id]: _, ...otherQueues } = outgoingPayloadQueues;
|
||||
return {
|
||||
...state,
|
||||
outgoingPayloadQueues: otherQueues,
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
export const backendMiddleware = (store) => {
|
||||
let suspendInterval;
|
||||
|
||||
return (next) => (action) => {
|
||||
const { suspended, outgoingPayloadQueues } = selectBackend(
|
||||
store.getState(),
|
||||
);
|
||||
const { type, payload } = action;
|
||||
|
||||
if (type === 'update') {
|
||||
store.dispatch(backendUpdate(payload));
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === 'suspend') {
|
||||
store.dispatch(backendSuspendSuccess());
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === 'ping') {
|
||||
Byond.sendMessage('ping/reply');
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === 'backend/suspendStart' && !suspendInterval) {
|
||||
logger.log(`suspending (${Byond.windowId})`);
|
||||
// Keep sending suspend messages until it succeeds.
|
||||
// It may fail multiple times due to topic rate limiting.
|
||||
const suspendFn = () => Byond.sendMessage('suspend');
|
||||
suspendFn();
|
||||
suspendInterval = setInterval(suspendFn, 2000);
|
||||
}
|
||||
|
||||
if (type === 'backend/suspendSuccess') {
|
||||
suspendRenderer();
|
||||
clearInterval(suspendInterval);
|
||||
suspendInterval = undefined;
|
||||
// Tiny window to not show previous content when resumed
|
||||
Byond.winset(Byond.windowId, {
|
||||
size: '1x1',
|
||||
pos: '1,1',
|
||||
'is-visible': false,
|
||||
});
|
||||
setTimeout(() => focusMap());
|
||||
}
|
||||
|
||||
// Resume on incoming update
|
||||
if (type === 'backend/update' && suspended) {
|
||||
// Show the payload
|
||||
logger.log('backend/update', payload);
|
||||
// Signal renderer that we have resumed
|
||||
resumeRenderer();
|
||||
// Setup drag
|
||||
setupDrag();
|
||||
// We schedule this for the next tick here because resizing and unhiding
|
||||
// during the same tick will flash with a white background.
|
||||
setTimeout(() => {
|
||||
perf.mark('resume/start');
|
||||
// Doublecheck if we are not re-suspended.
|
||||
const { suspended } = selectBackend(store.getState());
|
||||
if (suspended) {
|
||||
return;
|
||||
}
|
||||
Byond.winset(Byond.windowId, {
|
||||
'is-visible': true,
|
||||
});
|
||||
Byond.sendMessage('visible');
|
||||
perf.mark('resume/finish');
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
logger.log(
|
||||
'visible in',
|
||||
perf.measure('render/finish', 'resume/finish'),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (type === 'oversizePayloadResponse') {
|
||||
const { allow } = payload;
|
||||
if (allow) {
|
||||
store.dispatch(nextPayloadChunk(payload));
|
||||
} else {
|
||||
store.dispatch(backendRemovePayloadQueue(payload));
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'acknowlegePayloadChunk') {
|
||||
store.dispatch(backendDequeuePayloadQueue(payload));
|
||||
store.dispatch(nextPayloadChunk(payload));
|
||||
}
|
||||
|
||||
if (type === 'nextPayloadChunk') {
|
||||
const { id } = payload;
|
||||
const chunk = outgoingPayloadQueues[id][0];
|
||||
Byond.sendMessage('payloadChunk', {
|
||||
id,
|
||||
chunk,
|
||||
});
|
||||
}
|
||||
|
||||
return next(action);
|
||||
};
|
||||
};
|
||||
|
||||
const encodedLengthBinarySearch = (haystack: string[], length: number) => {
|
||||
const haystackLength = haystack.length;
|
||||
let high = haystackLength - 1;
|
||||
let low = 0;
|
||||
let mid = 0;
|
||||
while (low < high) {
|
||||
mid = Math.round((low + high) / 2);
|
||||
const substringLength = encodeURIComponent(
|
||||
haystack.slice(0, mid).join(''),
|
||||
).length;
|
||||
if (substringLength === length) {
|
||||
break;
|
||||
}
|
||||
if (substringLength < length) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
high = mid - 1;
|
||||
}
|
||||
}
|
||||
return mid;
|
||||
};
|
||||
|
||||
const chunkSplitter = {
|
||||
[Symbol.split]: (string: string) => {
|
||||
const charSeq = string[Symbol.iterator]().toArray();
|
||||
const length = charSeq.length;
|
||||
const chunks: string[] = [];
|
||||
let startIndex = 0;
|
||||
let endIndex = 1024;
|
||||
while (startIndex < length) {
|
||||
const cut = charSeq.slice(
|
||||
startIndex,
|
||||
endIndex < length ? endIndex : undefined,
|
||||
);
|
||||
const cutString = cut.join('');
|
||||
if (encodeURIComponent(cutString).length > 1024) {
|
||||
const splitIndex = startIndex + encodedLengthBinarySearch(cut, 1024);
|
||||
chunks.push(
|
||||
charSeq
|
||||
.slice(startIndex, splitIndex < length ? splitIndex : undefined)
|
||||
.join(''),
|
||||
);
|
||||
startIndex = splitIndex;
|
||||
} else {
|
||||
chunks.push(cutString);
|
||||
startIndex = endIndex;
|
||||
}
|
||||
endIndex = startIndex + 1024;
|
||||
}
|
||||
return chunks;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends an action to `ui_act` on `src_object` that this tgui window
|
||||
* is associated with.
|
||||
*/
|
||||
export const sendAct = (action: string, payload: object = {}) => {
|
||||
// Validate that payload is an object
|
||||
// prettier-ignore
|
||||
const isObject =
|
||||
typeof payload === 'object' && payload !== null && !Array.isArray(payload);
|
||||
if (!isObject) {
|
||||
logger.error(`Payload for act() must be an object, got this:`, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
const stringifiedPayload = JSON.stringify(payload);
|
||||
const urlSize = Object.entries({
|
||||
type: `act/${action}`,
|
||||
payload: stringifiedPayload,
|
||||
tgui: 1,
|
||||
windowId: Byond.windowId,
|
||||
}).reduce(
|
||||
(url, [key, value], i) =>
|
||||
url +
|
||||
`${i > 0 ? '&' : '?'}${encodeURIComponent(key)}=${encodeURIComponent(value)}`,
|
||||
'',
|
||||
).length;
|
||||
if (urlSize > 2048) {
|
||||
const chunks: string[] = stringifiedPayload.split(chunkSplitter);
|
||||
const id = `${Date.now()}`;
|
||||
globalStore?.dispatch(backendCreatePayloadQueue({ id, chunks }));
|
||||
Byond.sendMessage('oversizedPayloadRequest', {
|
||||
type: `act/${action}`,
|
||||
id,
|
||||
chunkCount: chunks.length,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
Byond.sendMessage(`act/${action}`, payload);
|
||||
};
|
||||
|
||||
type BackendState<TData> = {
|
||||
config: {
|
||||
title: string;
|
||||
status: number;
|
||||
interface: {
|
||||
name: string;
|
||||
layout: string;
|
||||
};
|
||||
refreshing: BooleanLike;
|
||||
window: {
|
||||
key: string;
|
||||
size: [number, number];
|
||||
locked: BooleanLike;
|
||||
scale: BooleanLike;
|
||||
};
|
||||
client: {
|
||||
ckey: string;
|
||||
address: string;
|
||||
computer_id: string;
|
||||
};
|
||||
user: {
|
||||
name: string;
|
||||
observer: number;
|
||||
};
|
||||
};
|
||||
data: TData;
|
||||
shared: Record<string, any>;
|
||||
outgoingPayloadQueues: Record<string, any[]>;
|
||||
suspending: boolean;
|
||||
suspended: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Selects a backend-related slice of Redux state
|
||||
*/
|
||||
export const selectBackend = <TData>(state: any): BackendState<TData> =>
|
||||
state.backend || {};
|
||||
|
||||
/**
|
||||
* Get data from tgui backend.
|
||||
* const { data } = useBackend<Data>();
|
||||
*
|
||||
* Includes the `act` function for performing DM actions.
|
||||
* console.log(data.username); // You'll get type safety here
|
||||
* ```
|
||||
*/
|
||||
export const useBackend = <TData>() => {
|
||||
const state: BackendState<TData> = globalStore?.getState()?.backend;
|
||||
export function useBackend<
|
||||
TData extends Record<string, any>,
|
||||
>(): BackendState<TData> {
|
||||
const state = store.get(backendStateAtom);
|
||||
|
||||
return {
|
||||
...state,
|
||||
act: sendAct,
|
||||
...state,
|
||||
data: state.data as TData,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A tuple that contains the state and a setter function for it.
|
||||
@@ -427,7 +34,7 @@ export const useBackend = <TData>() => {
|
||||
type StateWithSetter<T> = [T, (nextState: T) => void];
|
||||
|
||||
/**
|
||||
* Allocates state on Redux store without sharing it with other clients.
|
||||
* Allocates state in the Jotai store without sharing it with other clients.
|
||||
*
|
||||
* Use it when you want to have a stateful variable in your component
|
||||
* that persists between renders, but will be forgotten after you close
|
||||
@@ -435,55 +42,48 @@ type StateWithSetter<T> = [T, (nextState: T) => void];
|
||||
*
|
||||
* It is a lot more performant than `setSharedState`.
|
||||
*
|
||||
* @param context React context.
|
||||
* @param key Key which uniquely identifies this state in Redux store.
|
||||
* @param key Key which uniquely identifies this state in Zustand store.
|
||||
* @param initialState Initializes your global variable with this value.
|
||||
* @deprecated Use useState and useEffect when you can. Pass the state as a prop.
|
||||
*/
|
||||
export const useLocalState = <T>(
|
||||
export const useLocalState = <TState>(
|
||||
key: string,
|
||||
initialState: T,
|
||||
): StateWithSetter<T> => {
|
||||
const state = globalStore?.getState()?.backend;
|
||||
const sharedStates = state?.shared ?? {};
|
||||
initialState: TState,
|
||||
): StateWithSetter<TState> => {
|
||||
const sharedStates = store.get(sharedAtom);
|
||||
const sharedState = key in sharedStates ? sharedStates[key] : initialState;
|
||||
|
||||
return [
|
||||
sharedState,
|
||||
(nextState) => {
|
||||
globalStore.dispatch(
|
||||
backendSetSharedState({
|
||||
key,
|
||||
nextState:
|
||||
typeof nextState === 'function'
|
||||
? nextState(sharedState)
|
||||
: nextState,
|
||||
}),
|
||||
);
|
||||
store.set(sharedAtom, (prev) => ({
|
||||
...prev,
|
||||
[key]: nextState,
|
||||
}));
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocates state on Redux store, and **shares** it with other clients
|
||||
* Allocates state on Jotai store, and **shares** it with other clients
|
||||
* in the game.
|
||||
*
|
||||
* Use it when you want to have a stateful variable in your component
|
||||
* that persists not only between renders, but also gets pushed to other
|
||||
* clients that observe this UI.
|
||||
*
|
||||
* This makes creation of observable s
|
||||
* This makes creation of observable UIs easier.
|
||||
*
|
||||
* @param context React context.
|
||||
* @param key Key which uniquely identifies this state in Redux store.
|
||||
* @param key Key which uniquely identifies this state in Jotai store.
|
||||
* @param initialState Initializes your global variable with this value.
|
||||
*/
|
||||
export const useSharedState = <T>(
|
||||
export const useSharedState = <TState>(
|
||||
key: string,
|
||||
initialState: T,
|
||||
): StateWithSetter<T> => {
|
||||
const state = globalStore?.getState()?.backend;
|
||||
const sharedStates = state?.shared ?? {};
|
||||
initialState: TState,
|
||||
): StateWithSetter<TState> => {
|
||||
const sharedStates = store.get(sharedAtom);
|
||||
const sharedState = key in sharedStates ? sharedStates[key] : initialState;
|
||||
|
||||
return [
|
||||
sharedState,
|
||||
(nextState) => {
|
||||
@@ -500,11 +100,3 @@ export const useSharedState = <T>(
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const useDispatch = () => {
|
||||
return globalStore.dispatch;
|
||||
};
|
||||
|
||||
export const useSelector = (selector: (state: any) => any) => {
|
||||
return selector(globalStore?.getState());
|
||||
};
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { createAction } from 'common/redux';
|
||||
|
||||
export const toggleKitchenSink = createAction('debug/toggleKitchenSink');
|
||||
export const toggleDebugLayout = createAction('debug/toggleDebugLayout');
|
||||
export const openExternalBrowser = createAction('debug/openExternalBrowser');
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { useSelector } from '../backend';
|
||||
import { selectDebug } from './selectors';
|
||||
|
||||
export function useDebug() {
|
||||
return useSelector(selectDebug);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
export { useDebug } from './hooks';
|
||||
export { KitchenSink } from './KitchenSink';
|
||||
export { debugMiddleware, relayMiddleware } from './middleware';
|
||||
export { debugReducer } from './reducer';
|
||||
@@ -1,82 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { globalEvents } from 'tgui-core/events';
|
||||
import { acquireHotKey } from 'tgui-core/hotkeys';
|
||||
import { KEY_BACKSPACE, KEY_F10, KEY_F11, KEY_F12 } from 'tgui-core/keycodes';
|
||||
|
||||
import {
|
||||
openExternalBrowser,
|
||||
toggleDebugLayout,
|
||||
toggleKitchenSink,
|
||||
} from './actions';
|
||||
|
||||
const relayedTypes = ['backend/update', 'chat/message'];
|
||||
|
||||
export function debugMiddleware(store) {
|
||||
acquireHotKey(KEY_F11);
|
||||
acquireHotKey(KEY_F12);
|
||||
globalEvents.on('keydown', (key) => {
|
||||
if (key.code === KEY_F11) {
|
||||
store.dispatch(toggleDebugLayout());
|
||||
}
|
||||
if (key.code === KEY_F12) {
|
||||
store.dispatch(toggleKitchenSink());
|
||||
}
|
||||
if (key.ctrl && key.alt && key.code === KEY_BACKSPACE) {
|
||||
// NOTE: We need to call this in a timeout, because we need a clean
|
||||
// stack in order for this to be a fatal error.
|
||||
setTimeout(() => {
|
||||
throw new Error(
|
||||
'OOPSIE WOOPSIE!! UwU We made a fucky wucky!! A wittle' +
|
||||
' fucko boingo! The code monkeys at our headquarters are' +
|
||||
' working VEWY HAWD to fix this!',
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
return (next) => (action) => next(action);
|
||||
}
|
||||
|
||||
export function relayMiddleware(store) {
|
||||
const devServer = require('tgui-dev-server/link/client.ts');
|
||||
const externalBrowser = location.search === '?external';
|
||||
if (externalBrowser) {
|
||||
devServer.subscribe((msg) => {
|
||||
const { type, payload } = msg;
|
||||
if (type === 'relay' && payload.windowId === Byond.windowId) {
|
||||
store.dispatch({
|
||||
...payload.action,
|
||||
relayed: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
acquireHotKey(KEY_F10);
|
||||
globalEvents.on('keydown', (key) => {
|
||||
if (key === KEY_F10) {
|
||||
store.dispatch(openExternalBrowser());
|
||||
}
|
||||
});
|
||||
}
|
||||
return (next) => (action) => {
|
||||
const { type, relayed } = action;
|
||||
if (type === openExternalBrowser.type) {
|
||||
window.open(`${location.href}?external`, '_blank');
|
||||
return;
|
||||
}
|
||||
if (relayedTypes.includes(type) && !relayed && !externalBrowser) {
|
||||
devServer.sendMessage({
|
||||
type: 'relay',
|
||||
payload: {
|
||||
windowId: Byond.windowId,
|
||||
action,
|
||||
},
|
||||
});
|
||||
}
|
||||
return next(action);
|
||||
};
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
type DebugState = {
|
||||
kitchenSink: boolean;
|
||||
debugLayout: boolean;
|
||||
};
|
||||
|
||||
export function debugReducer(state = {} as DebugState, action) {
|
||||
const { type } = action;
|
||||
if (type === 'debug/toggleKitchenSink') {
|
||||
return {
|
||||
...state,
|
||||
kitchenSink: !state.kitchenSink,
|
||||
};
|
||||
}
|
||||
if (type === 'debug/toggleDebugLayout') {
|
||||
return {
|
||||
...state,
|
||||
debugLayout: !state.debugLayout,
|
||||
};
|
||||
}
|
||||
return state;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
export function selectDebug(state: Record<string, any>) {
|
||||
return state?.debug;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { globalEvents } from 'tgui-core/events';
|
||||
import { acquireHotKey } from 'tgui-core/hotkeys';
|
||||
import { KEY_BACKSPACE, KEY_F11, KEY_F12 } from 'tgui-core/keycodes';
|
||||
import { kitchenSinkAtom, store } from '../events/store';
|
||||
|
||||
export function setDebugHotKeys(): void {
|
||||
acquireHotKey(KEY_F11);
|
||||
acquireHotKey(KEY_F12); // Just to avoid the HUD disappearing on F12
|
||||
|
||||
globalEvents.on('keydown', (evt) => {
|
||||
if (evt.code === KEY_F11) {
|
||||
store.set(kitchenSinkAtom, (prev) => !prev);
|
||||
}
|
||||
|
||||
if (evt.ctrl && evt.alt && evt.code === KEY_BACKSPACE) {
|
||||
// NOTE: We need to call this in a timeout, because we need a clean
|
||||
// stack in order for this to be a fatal error.
|
||||
setTimeout(() => {
|
||||
throw new Error(
|
||||
'OOPSIE WOOPSIE!! UwU We made a fucky wucky!! A wittle' +
|
||||
' fucko boingo! The code monkeys at our headquarters are' +
|
||||
' working VEWY HAWD to fix this!',
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
# Tgui event dispatch
|
||||
|
||||
## Philosophy
|
||||
|
||||
In the previous TGUI backend state, both DM messages and UI actions were handled through an event message system using actions, selectors, reducers, and middleware. This event system is designed to handle only DM messages - separating UI actions into direct state access (eg setSomeState(true)) or helpers (eg updateSetting({ thing: true})).
|
||||
|
||||
The idea behind this was to reduce the amount of abstractions needed and draw a clear line between what is a server message and what is a UI action.
|
||||
|
||||
There are three layers to this system:
|
||||
|
||||
1. The event bus, which maintains the list of handlers.
|
||||
2. The handlers, which delegate backend calls and update application state.
|
||||
3. The store, ie the application state.
|
||||
|
||||
## Usage
|
||||
|
||||
### 1. Creating your event handler:
|
||||
|
||||
> events/handlers/someFunc.ts
|
||||
|
||||
```ts
|
||||
type ExpectedPayload = {
|
||||
greeting: string;
|
||||
};
|
||||
|
||||
export function someFunc(payload: ExpectedPayload) {
|
||||
// Do something with the payload
|
||||
logger.log('Received: ', payload.greeting);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Building the event handler:
|
||||
|
||||
> events/listeners.ts
|
||||
|
||||
```ts
|
||||
import { someFunc } from 'handlers/someFunc';
|
||||
|
||||
export const listeners = {
|
||||
eventType: someFunc,
|
||||
} as const;
|
||||
```
|
||||
|
||||
You can even shorten this by naming your function the same as the event type. An event of type 'myType' would call the myType function directly,
|
||||
|
||||
```ts
|
||||
export function myType(payload: MyPayload) {
|
||||
logger.log('whatever!');
|
||||
}
|
||||
|
||||
export const listeners = {
|
||||
myType,
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Setting up your event dispatch
|
||||
|
||||
> index.tsx
|
||||
|
||||
```ts
|
||||
import { EventBus } from 'common/eventbus';
|
||||
|
||||
const listeners = {
|
||||
myType,
|
||||
'some/Thing': someThingHandler, // valid
|
||||
'other/Thing': () => store.setState(true); // technically okay but can get messy :).
|
||||
};
|
||||
|
||||
export const busName = new EventBus(listeners);
|
||||
```
|
||||
|
||||
### 4. Subscribe to byond events
|
||||
|
||||
> index.tsx
|
||||
|
||||
```ts
|
||||
/// somewhere in setup logic
|
||||
Byond.subscribe((type, payload) => busName.dispatch({ type, payload } as any));
|
||||
```
|
||||
|
||||
## Converting the old system over
|
||||
|
||||
This process takes time! But it's not impossible. For the most part, backend calls can be directly extracted into a function with similar state management.
|
||||
|
||||
> middleware.js
|
||||
|
||||
Ex:
|
||||
|
||||
```ts
|
||||
if (type === 'audio/playMusic') {
|
||||
const { url, ...options } = payload;
|
||||
player.play(url, options);
|
||||
return next(action);
|
||||
}
|
||||
```
|
||||
|
||||
Becomes:
|
||||
|
||||
```ts
|
||||
function audioPlayMusic(payload: PayloadType): void {
|
||||
const { url, ...options } = payload;
|
||||
player.play(url, options);
|
||||
|
||||
// no need to call next, it's all handled here
|
||||
}
|
||||
```
|
||||
|
||||
### When to use store.set/get vs useAtom
|
||||
|
||||
Functionally, there is no difference. If it makes it simpler, you can leave UI actions as external javascript helpers with store.set/get. I've only wrapped functions into React components as the 'technically correct' way to do things. The React way tends to be more concise in the long run.
|
||||
|
||||
### When to create handlers vs direct state access
|
||||
|
||||
Is it a backend call from DM? Put it on the event bus! If it isn't, there's no reason not to have your UI directly interface with a function or the state directly.
|
||||
@@ -0,0 +1,101 @@
|
||||
import { logger } from '../logging';
|
||||
import { createQueue } from './handlers/chunking';
|
||||
|
||||
/**
|
||||
* Sends an action to `ui_act` on `src_object` that this tgui window
|
||||
* is associated with.
|
||||
*/
|
||||
export function sendAct(
|
||||
action: string,
|
||||
payload: Record<string, unknown> = {},
|
||||
): void {
|
||||
// Validate that payload is an object
|
||||
const isObject =
|
||||
typeof payload === 'object' && payload !== null && !Array.isArray(payload);
|
||||
if (!isObject) {
|
||||
logger.error(`Payload for act() must be an object, got this:`, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
const stringifiedPayload = JSON.stringify(payload);
|
||||
const urlSize = Object.entries({
|
||||
type: `act/${action}`,
|
||||
payload: stringifiedPayload,
|
||||
tgui: 1,
|
||||
windowId: Byond.windowId,
|
||||
}).reduce(
|
||||
(url, [key, value], i) =>
|
||||
url +
|
||||
`${i > 0 ? '&' : '?'}${encodeURIComponent(key)}=${encodeURIComponent(value)}`,
|
||||
'',
|
||||
).length;
|
||||
|
||||
if (urlSize > 2048) {
|
||||
const chunks: string[] = stringifiedPayload.split(chunkSplitter);
|
||||
const id = `${Date.now()}`;
|
||||
createQueue({ id, chunks });
|
||||
Byond.sendMessage('oversizedPayloadRequest', {
|
||||
type: `act/${action}`,
|
||||
id,
|
||||
chunkCount: chunks.length,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
Byond.sendMessage(`act/${action}`, payload);
|
||||
}
|
||||
|
||||
function encodedLengthBinarySearch(haystack: string[], length: number): number {
|
||||
const haystackLength = haystack.length;
|
||||
let high = haystackLength - 1;
|
||||
let low = 0;
|
||||
let mid = 0;
|
||||
|
||||
while (low < high) {
|
||||
mid = Math.round((low + high) / 2);
|
||||
const substringLength = encodeURIComponent(
|
||||
haystack.slice(0, mid).join(''),
|
||||
).length;
|
||||
if (substringLength === length) {
|
||||
break;
|
||||
}
|
||||
if (substringLength < length) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
high = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return mid;
|
||||
}
|
||||
|
||||
const chunkSplitter = {
|
||||
[Symbol.split]: (string: string) => {
|
||||
const charSeq = string[Symbol.iterator]().toArray();
|
||||
const length = charSeq.length;
|
||||
const chunks: string[] = [];
|
||||
let startIndex = 0;
|
||||
let endIndex = 1024;
|
||||
while (startIndex < length) {
|
||||
const cut = charSeq.slice(
|
||||
startIndex,
|
||||
endIndex < length ? endIndex : undefined,
|
||||
);
|
||||
const cutString = cut.join('');
|
||||
if (encodeURIComponent(cutString).length > 1024) {
|
||||
const splitIndex = startIndex + encodedLengthBinarySearch(cut, 1024);
|
||||
chunks.push(
|
||||
charSeq
|
||||
.slice(startIndex, splitIndex < length ? splitIndex : undefined)
|
||||
.join(''),
|
||||
);
|
||||
startIndex = splitIndex;
|
||||
} else {
|
||||
chunks.push(cutString);
|
||||
startIndex = endIndex;
|
||||
}
|
||||
endIndex = startIndex + 1024;
|
||||
}
|
||||
return chunks;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { loadMappings } from 'common/assets';
|
||||
import { loadedMappings } from '../../assets';
|
||||
|
||||
/// --------- Handlers ------------------------------------------------------///
|
||||
|
||||
/** This just lets us load in our own independent map */
|
||||
export function handleLoadAssets(payload: Record<string, string>): void {
|
||||
loadMappings(payload, loadedMappings);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { chunkingAtom, store } from '../store';
|
||||
|
||||
/// --------- Handlers ------------------------------------------------------///
|
||||
|
||||
type OversizePayload = {
|
||||
allow: boolean;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export function oversizePayloadResponse(payload: OversizePayload): void {
|
||||
const { allow, id } = payload;
|
||||
|
||||
if (allow) {
|
||||
nextChunk(id);
|
||||
} else {
|
||||
store.set(chunkingAtom, (prev) => {
|
||||
const { [id]: _, ...otherQueues } = prev;
|
||||
return otherQueues;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function acknowledgePayloadChunk(payload: OversizePayload): void {
|
||||
const { id } = payload;
|
||||
|
||||
store.set(chunkingAtom, (prev) => {
|
||||
const { [id]: targetQueue, ...otherQueues } = prev;
|
||||
const [_, ...rest] = targetQueue || [];
|
||||
|
||||
return rest.length
|
||||
? {
|
||||
...otherQueues,
|
||||
[id]: rest,
|
||||
}
|
||||
: otherQueues;
|
||||
});
|
||||
nextChunk(id);
|
||||
}
|
||||
|
||||
/// --------- Helpers -------------------------------------------------------///
|
||||
|
||||
function nextChunk(id: string): void {
|
||||
const queues = store.get(chunkingAtom);
|
||||
const chunk = queues[id]?.[0];
|
||||
|
||||
if (chunk) {
|
||||
Byond.sendMessage('payloadChunk', {
|
||||
id,
|
||||
chunk,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
type CreateQueueParams = {
|
||||
id: string;
|
||||
chunks: string[];
|
||||
};
|
||||
|
||||
export function createQueue(payload: CreateQueueParams): void {
|
||||
const { id, chunks } = payload;
|
||||
|
||||
store.set(chunkingAtom, (prev) => ({
|
||||
...prev,
|
||||
[id]: chunks,
|
||||
}));
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/// --------- Handlers ------------------------------------------------------///
|
||||
|
||||
export function ping(): void {
|
||||
Byond.sendMessage('ping/reply');
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { focusMap } from '../../focus';
|
||||
import { logger } from '../../logging';
|
||||
import { suspendRenderer } from '../../renderer';
|
||||
import {
|
||||
configAtom,
|
||||
resetStore,
|
||||
store,
|
||||
suspendedAtom,
|
||||
suspendingAtom,
|
||||
} from '../store';
|
||||
|
||||
/// --------- Handlers ------------------------------------------------------///
|
||||
|
||||
let suspendInterval: NodeJS.Timeout | null = null;
|
||||
|
||||
/** Resets all state and refocuses byond window */
|
||||
export function suspend(): void {
|
||||
suspendRenderer();
|
||||
resetStore();
|
||||
|
||||
if (suspendInterval) clearInterval(suspendInterval);
|
||||
|
||||
store.set(configAtom, (prev) => ({
|
||||
...prev,
|
||||
title: '',
|
||||
status: 1,
|
||||
}));
|
||||
store.set(suspendingAtom, false);
|
||||
store.set(suspendedAtom, Date.now());
|
||||
|
||||
Byond.winset(Byond.windowId, {
|
||||
'is-visible': false,
|
||||
});
|
||||
|
||||
focusMap();
|
||||
}
|
||||
|
||||
/// --------- Helpers -------------------------------------------------------///
|
||||
|
||||
const TWO_SECONDS = 2000;
|
||||
|
||||
function suspendMsg(): void {
|
||||
Byond.sendMessage('suspend');
|
||||
}
|
||||
|
||||
/** Signals Byond to dismiss the window */
|
||||
export function suspendStart(): void {
|
||||
if (suspendInterval) clearInterval(suspendInterval);
|
||||
|
||||
store.set(suspendingAtom, true);
|
||||
|
||||
logger.log(`suspending (${Byond.windowId})`);
|
||||
suspendMsg();
|
||||
suspendInterval = setInterval(suspendMsg, TWO_SECONDS);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import { perf } from 'common/perf';
|
||||
import { setupDrag } from '../../drag';
|
||||
import { logger } from '../../logging';
|
||||
import { resumeRenderer } from '../../renderer';
|
||||
import {
|
||||
configAtom,
|
||||
gameDataAtom,
|
||||
gameStaticDataAtom,
|
||||
sharedAtom,
|
||||
store,
|
||||
suspendedAtom,
|
||||
} from '../store';
|
||||
import type { BackendState } from '../types';
|
||||
|
||||
/// --------- Handlers ------------------------------------------------------///
|
||||
|
||||
type UpdatePayload = Omit<BackendState<Record<string, unknown>>, 'act'> & {
|
||||
static_data: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export function update(payload: UpdatePayload): void {
|
||||
if (store.get(suspendedAtom)) {
|
||||
resume(payload);
|
||||
store.set(suspendedAtom, false);
|
||||
}
|
||||
updateData(payload);
|
||||
}
|
||||
|
||||
/// --------- Helpers -------------------------------------------------------///
|
||||
|
||||
/** Resumes the tgui window if suspended */
|
||||
function resume(payload: UpdatePayload): void {
|
||||
// Show the payload
|
||||
logger.log('Resuming:', payload);
|
||||
// Signal renderer that we have resumed
|
||||
resumeRenderer();
|
||||
// Setup drag
|
||||
setupDrag();
|
||||
// We schedule this for the next tick here because resizing and unhiding
|
||||
// during the same tick will flash with a white background.
|
||||
setTimeout(() => {
|
||||
perf.mark('resume/start');
|
||||
// Doublecheck if we are not re-suspended.
|
||||
if (store.get(suspendedAtom)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Byond.winset(Byond.windowId, {
|
||||
'is-visible': true,
|
||||
});
|
||||
Byond.sendMessage('visible');
|
||||
perf.mark('resume/finish');
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
logger.log('visible in', perf.measure('render/finish', 'resume/finish'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Delegates update data to the appropriate store */
|
||||
function updateData(payload: UpdatePayload): void {
|
||||
if (payload.config) {
|
||||
store.set(configAtom, (prev) => ({
|
||||
...prev,
|
||||
...payload.config,
|
||||
}));
|
||||
}
|
||||
|
||||
if (payload.static_data) {
|
||||
store.set(gameStaticDataAtom, (prev) => ({
|
||||
...prev,
|
||||
...payload.static_data,
|
||||
}));
|
||||
}
|
||||
|
||||
if (payload.data) {
|
||||
store.set(gameDataAtom, (prev) => ({
|
||||
...prev,
|
||||
...payload.data,
|
||||
}));
|
||||
}
|
||||
|
||||
if (payload.shared) {
|
||||
const newShared = {} as Record<string, unknown>;
|
||||
|
||||
for (const key in payload.shared) {
|
||||
const value = payload.shared[key];
|
||||
if (value === '') {
|
||||
newShared[key] = undefined;
|
||||
} else {
|
||||
newShared[key] = JSON.parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
store.set(sharedAtom, (prev) => ({
|
||||
...prev,
|
||||
...newShared,
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { loadStyleSheet } from 'common/assets';
|
||||
import { EventBus } from 'tgui-core/eventbus';
|
||||
import { handleLoadAssets } from './handlers/assets';
|
||||
import {
|
||||
acknowledgePayloadChunk,
|
||||
oversizePayloadResponse,
|
||||
} from './handlers/chunking';
|
||||
import { ping } from './handlers/ping';
|
||||
import { suspend } from './handlers/suspense';
|
||||
import { update } from './handlers/update';
|
||||
|
||||
/**
|
||||
* A string/handler map.
|
||||
* Ideally, these reference a function named after the respective event type.
|
||||
*/
|
||||
const listeners = {
|
||||
// Assets
|
||||
'asset/mappings': handleLoadAssets,
|
||||
'asset/stylesheet': loadStyleSheet,
|
||||
// Standard window events
|
||||
ping,
|
||||
suspend,
|
||||
update,
|
||||
// Chunking
|
||||
oversizePayloadResponse,
|
||||
acknowledgePayloadChunk,
|
||||
} as const;
|
||||
|
||||
export const bus = new EventBus(listeners);
|
||||
@@ -0,0 +1,37 @@
|
||||
import { atom, createStore } from 'jotai';
|
||||
import type { Config } from './types';
|
||||
|
||||
export const chunkingAtom = atom<Record<string, any>>({});
|
||||
export const configAtom = atom<Config>({} as Config);
|
||||
export const debugLayoutAtom = atom(false);
|
||||
export const gameDataAtom = atom<Record<string, any>>({});
|
||||
export const gameStaticDataAtom = atom<Record<string, any>>({});
|
||||
export const kitchenSinkAtom = atom(false);
|
||||
export const sharedAtom = atom<Record<string, any>>({});
|
||||
export const suspendedAtom = atom<number | false>(Date.now()); // Start as suspended
|
||||
export const suspendingAtom = atom(false);
|
||||
|
||||
export const backendStateAtom = atom((get) => ({
|
||||
config: get(configAtom),
|
||||
data: {
|
||||
...get(gameDataAtom),
|
||||
...get(gameStaticDataAtom),
|
||||
},
|
||||
debug: {
|
||||
debugLayout: get(debugLayoutAtom),
|
||||
kitchenSink: get(kitchenSinkAtom),
|
||||
},
|
||||
outgoingPayloadQueues: get(chunkingAtom),
|
||||
shared: get(sharedAtom),
|
||||
staticData: get(gameStaticDataAtom),
|
||||
suspended: get(suspendedAtom),
|
||||
suspending: get(suspendingAtom),
|
||||
}));
|
||||
|
||||
export const store = createStore();
|
||||
|
||||
export function resetStore() {
|
||||
store.set(gameDataAtom, {});
|
||||
store.set(gameStaticDataAtom, {});
|
||||
store.set(sharedAtom, {});
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import type { ExtractAtomValue } from 'jotai';
|
||||
import type { sendAct } from './act';
|
||||
import type { backendStateAtom } from './store';
|
||||
|
||||
type BinaryIO = 0 | 1;
|
||||
|
||||
type Client = {
|
||||
address: string;
|
||||
ckey: string;
|
||||
computer_id: string;
|
||||
};
|
||||
|
||||
type IFace = {
|
||||
layout: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
type TguiWindow = {
|
||||
fancy: BinaryIO;
|
||||
key: string;
|
||||
locked: BinaryIO;
|
||||
scale: BinaryIO;
|
||||
size: [number, number];
|
||||
};
|
||||
|
||||
type User = {
|
||||
name: string;
|
||||
observer: number;
|
||||
};
|
||||
|
||||
export type Config = {
|
||||
client: Client;
|
||||
interface: IFace;
|
||||
refreshing: BinaryIO;
|
||||
status: number;
|
||||
title: string;
|
||||
user: User;
|
||||
window: TguiWindow;
|
||||
};
|
||||
|
||||
export type DebugState = {
|
||||
debugLayout: boolean;
|
||||
kitchenSink: boolean;
|
||||
};
|
||||
|
||||
export type BackendState<TData> = ExtractAtomValue<typeof backendStateAtom> & {
|
||||
act: typeof sendAct;
|
||||
data: TData;
|
||||
};
|
||||
@@ -7,20 +7,15 @@
|
||||
// Themes
|
||||
import './styles/main.scss';
|
||||
|
||||
import { perf } from 'common/perf';
|
||||
import { setupGlobalEvents } from 'tgui-core/events';
|
||||
import { setupHotKeys } from 'tgui-core/hotkeys';
|
||||
import { captureExternalLinks } from 'tgui-core/links';
|
||||
import { setupHotReloading } from 'tgui-dev-server/link/client';
|
||||
import { App } from './App';
|
||||
import { setGlobalStore } from './backend';
|
||||
import { setDebugHotKeys } from './debug/use-debug';
|
||||
import { bus } from './events/listeners';
|
||||
import { render } from './renderer';
|
||||
import { configureStore } from './store';
|
||||
|
||||
perf.mark('inception', window.performance?.timeOrigin);
|
||||
perf.mark('init');
|
||||
|
||||
const store = configureStore();
|
||||
import { createStackAugmentor } from './stack';
|
||||
|
||||
function setupApp() {
|
||||
// Delay setup
|
||||
@@ -28,8 +23,7 @@ function setupApp() {
|
||||
document.addEventListener('DOMContentLoaded', setupApp);
|
||||
return;
|
||||
}
|
||||
|
||||
setGlobalStore(store);
|
||||
window.__augmentStack__ = createStackAugmentor();
|
||||
|
||||
setupGlobalEvents();
|
||||
setupHotKeys({
|
||||
@@ -40,19 +34,16 @@ function setupApp() {
|
||||
});
|
||||
captureExternalLinks();
|
||||
|
||||
store.subscribe(() => render(<App />));
|
||||
Byond.subscribe((type, payload) => bus.dispatch({ type, payload }));
|
||||
|
||||
// Dispatch incoming messages as store actions
|
||||
Byond.subscribe((type, payload) => store.dispatch({ type, payload }));
|
||||
render(<App />);
|
||||
|
||||
// Enable hot module reloading
|
||||
if (import.meta.webpackHot) {
|
||||
setDebugHotKeys();
|
||||
setupHotReloading();
|
||||
import.meta.webpackHot.accept(
|
||||
['./debug', './layouts', './routes', './App'],
|
||||
() => {
|
||||
render(<App />);
|
||||
},
|
||||
import.meta.webpackHot.accept(['./layouts', './routes', './App'], () =>
|
||||
render(<App />),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { classes } from 'tgui-core/react';
|
||||
|
||||
import { resolveAsset } from '../assets';
|
||||
import { useBackend } from '../backend';
|
||||
import { sendAct as act } from '../events/act';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
const icons = {
|
||||
@@ -68,7 +69,6 @@ export class Changelog extends Component {
|
||||
}
|
||||
|
||||
getData = (date, attemptNumber = 1) => {
|
||||
const { act } = useBackend();
|
||||
const self = this;
|
||||
const maxAttempts = 6;
|
||||
|
||||
@@ -101,9 +101,9 @@ export class Changelog extends Component {
|
||||
} = useBackend();
|
||||
|
||||
if (dates) {
|
||||
dates.forEach((date) =>
|
||||
this.dateChoices.push(dateformat(date, 'mmmm yyyy', true)),
|
||||
);
|
||||
dates.forEach((date) => {
|
||||
this.dateChoices.push(dateformat(date, 'mmmm yyyy', true));
|
||||
});
|
||||
this.setSelectedDate(this.dateChoices[0]);
|
||||
this.getData(dates[0]);
|
||||
}
|
||||
|
||||
@@ -304,12 +304,15 @@ const FilterMatrixEntry = (props) => {
|
||||
selected={matrix.length}
|
||||
options={matrix_sizes.map((size) => `${size} elements`)}
|
||||
onSelected={(option) =>
|
||||
matrix.length === parseInt(option.split(' '))
|
||||
matrix.length === parseInt(option.split(' '), 10)
|
||||
? null
|
||||
: act('modify_filter_value', {
|
||||
name: filterName,
|
||||
new_data: {
|
||||
[name]: resize_matrix(matrix, parseInt(option.split(' '))),
|
||||
[name]: resize_matrix(
|
||||
matrix,
|
||||
parseInt(option.split(' '), 10),
|
||||
),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ export const Log = (props: LogProps) => {
|
||||
const { act, data } = useBackend<LuaEditorData>();
|
||||
const { stateLog } = data;
|
||||
const { setViewedChunk, setModal } = props;
|
||||
|
||||
return stateLog.map((element, i) => {
|
||||
const { status, repeats } = element;
|
||||
let output;
|
||||
@@ -181,7 +182,7 @@ export const Log = (props: LogProps) => {
|
||||
logger.warn(`unknown log status ${status}`);
|
||||
}
|
||||
if (output === undefined) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
const { chunk } = element;
|
||||
if (chunk) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import { Log } from './Log';
|
||||
import { StateSelectModal } from './StateSelectModal';
|
||||
import { TaskManager } from './TaskManager';
|
||||
import type { CallInfo, LuaEditorData, LuaEditorModal } from './types';
|
||||
|
||||
hljs.registerLanguage('lua', lua);
|
||||
|
||||
export const LuaEditor = () => {
|
||||
@@ -153,6 +154,13 @@ export const LuaEditor = () => {
|
||||
};
|
||||
};
|
||||
|
||||
async function onDropHandler(event: React.DragEvent<HTMLTextAreaElement>) {
|
||||
if (event.dataTransfer?.files.length) {
|
||||
event.preventDefault();
|
||||
setScriptInput(await event.dataTransfer.files[0].text());
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Window width={1280} height={720}>
|
||||
<Window.Content>
|
||||
@@ -226,17 +234,8 @@ export const LuaEditor = () => {
|
||||
}}
|
||||
/>
|
||||
}*/
|
||||
/** @ts-ignore */
|
||||
onDrop={async (
|
||||
event: React.DragEvent<HTMLDivElement>,
|
||||
) => {
|
||||
if (event.dataTransfer?.files.length) {
|
||||
event.preventDefault();
|
||||
setScriptInput(
|
||||
await event.dataTransfer.files[0].text(),
|
||||
);
|
||||
}
|
||||
}}
|
||||
|
||||
onDrop={onDropHandler}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
|
||||
@@ -206,23 +206,23 @@ const PaiOptions = (props) => {
|
||||
</Button>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Holoform Range">
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="fa-circle-minus"
|
||||
onClick={() => act('decrease_range')}
|
||||
disabled={range === range_min}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item mt={0.5}>{range}</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="fa-circle-plus"
|
||||
onClick={() => act('increase_range')}
|
||||
disabled={range === range_max}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="fa-circle-minus"
|
||||
onClick={() => act('decrease_range')}
|
||||
disabled={range === range_min}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item mt={0.5}>{range}</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="fa-circle-plus"
|
||||
onClick={() => act('increase_range')}
|
||||
disabled={range === range_max}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Transmit">
|
||||
<Button
|
||||
|
||||
@@ -327,7 +327,7 @@ function JoblessRoleDropdown(props) {
|
||||
|
||||
const selection = options?.find(
|
||||
(option) => option.value === selected,
|
||||
)!.displayText;
|
||||
)?.displayText;
|
||||
|
||||
return (
|
||||
<Box position="absolute" right={0} width="30%">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { sortBy } from 'es-toolkit';
|
||||
import { filter, map } from 'es-toolkit/compat';
|
||||
import { type ReactNode, useState } from 'react';
|
||||
import { type sendAct, useBackend } from 'tgui/backend';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { sendAct } from 'tgui/events/act';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -13,7 +14,6 @@ import {
|
||||
} from 'tgui-core/components';
|
||||
import { classes } from 'tgui-core/react';
|
||||
import { createSearch } from 'tgui-core/string';
|
||||
|
||||
import { CharacterPreview } from '../../common/CharacterPreview';
|
||||
import { RandomizationButton } from '../components/RandomizationButton';
|
||||
import { features } from '../preferences/features';
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
type FeatureChoicedServerData,
|
||||
FeatureValueInput,
|
||||
} from '../preferences/features/base';
|
||||
import { Gender, GENDERS } from '../preferences/gender';
|
||||
import { GENDERS, Gender } from '../preferences/gender';
|
||||
import {
|
||||
createSetPreference,
|
||||
type PreferencesMenuData,
|
||||
@@ -337,8 +337,8 @@ function MainFeature(props: MainFeatureProps) {
|
||||
}
|
||||
|
||||
const createSetRandomization =
|
||||
(act: typeof sendAct, preference: string) => (newSetting: RandomSetting) => {
|
||||
act('set_random_preference', {
|
||||
(preference: string) => (newSetting: RandomSetting) => {
|
||||
sendAct('set_random_preference', {
|
||||
preference,
|
||||
value: newSetting,
|
||||
});
|
||||
@@ -396,7 +396,7 @@ export function PreferenceList(props: PreferenceListProps) {
|
||||
{randomSetting && (
|
||||
<Stack.Item>
|
||||
<RandomizationButton
|
||||
setValue={createSetRandomization(act, featureId)}
|
||||
setValue={createSetRandomization(featureId)}
|
||||
value={randomSetting}
|
||||
/>
|
||||
</Stack.Item>
|
||||
@@ -426,13 +426,9 @@ export function getRandomization(
|
||||
serverData: ServerData | undefined,
|
||||
randomBodyEnabled: boolean,
|
||||
): Record<string, RandomSetting> {
|
||||
if (!serverData) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const { data } = useBackend<PreferencesMenuData>();
|
||||
|
||||
if (!randomBodyEnabled) {
|
||||
if (!randomBodyEnabled || !serverData) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -455,6 +451,7 @@ type MainPageProps = {
|
||||
|
||||
export function MainPage(props: MainPageProps) {
|
||||
const { act, data } = useBackend<PreferencesMenuData>();
|
||||
|
||||
const [deleteCharacterPopupOpen, setDeleteCharacterPopupOpen] =
|
||||
useState(false);
|
||||
const [multiNameInputOpen, setMultiNameInputOpen] = useState(false);
|
||||
@@ -584,10 +581,7 @@ export function MainPage(props: MainPageProps) {
|
||||
currentValue={clothing}
|
||||
handleSelect={createSetPreference(act, clothingKey)}
|
||||
randomization={randomizationOfMainFeatures[clothingKey]}
|
||||
setRandomization={createSetRandomization(
|
||||
act,
|
||||
clothingKey,
|
||||
)}
|
||||
setRandomization={createSetRandomization(clothingKey)}
|
||||
/>
|
||||
)}
|
||||
</Stack.Item>
|
||||
|
||||
+1
-2
@@ -1,4 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -10,8 +11,6 @@ import {
|
||||
Stack,
|
||||
} from 'tgui-core/components';
|
||||
import { createSearch } from 'tgui-core/string';
|
||||
|
||||
import { useBackend } from '../../../backend';
|
||||
import type { Personality, PreferencesMenuData } from '../types';
|
||||
import { useServerPrefs } from '../useServerPrefs';
|
||||
|
||||
|
||||
@@ -38,6 +38,17 @@ function PrefsWindowInner(props) {
|
||||
const [serverData, setServerData] = useState<ServerData>();
|
||||
const randomization = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
fetchRetry(resolveAsset('preferences.json'))
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
setServerData(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.log('Failed to fetch preferences.json', error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
let content;
|
||||
let title;
|
||||
switch (window) {
|
||||
@@ -61,17 +72,6 @@ function PrefsWindowInner(props) {
|
||||
exhaustiveCheck(window);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchRetry(resolveAsset('preferences.json'))
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
setServerData(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.log('Failed to fetch preferences.json', error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ServerPrefs.Provider value={serverData}>
|
||||
<RandomToggleState.Provider value={randomization}>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { BooleanLike } from 'tgui-core/react';
|
||||
|
||||
import type { sendAct } from '../../backend';
|
||||
import type { sendAct } from '../../events/act';
|
||||
import type {
|
||||
LoadoutCategory,
|
||||
LoadoutList,
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
Tooltip,
|
||||
} from 'tgui-core/components';
|
||||
import type { BooleanLike } from 'tgui-core/react';
|
||||
|
||||
import { useBackend, useSharedState } from '../backend';
|
||||
import { Window } from '../layouts';
|
||||
import { LoadingScreen } from './common/LoadingScreen';
|
||||
|
||||
@@ -20,13 +20,13 @@ import type {
|
||||
SpawnPanelPreferences,
|
||||
} from './types';
|
||||
|
||||
interface SpawnPanelData {
|
||||
type SpawnPanelData = {
|
||||
icon: string;
|
||||
iconState: string;
|
||||
selected_object?: string;
|
||||
copied_type?: string;
|
||||
preferences?: SpawnPanelPreferences;
|
||||
}
|
||||
};
|
||||
|
||||
interface SpawnPreferences {
|
||||
hide_icons: boolean;
|
||||
|
||||
@@ -4,13 +4,13 @@ import { Button, Dropdown, Slider, Table } from 'tgui-core/components';
|
||||
import { useBackend } from '../../backend';
|
||||
import type { IconSettings } from './index';
|
||||
|
||||
interface SpawnPanelData {
|
||||
type SpawnPanelData = {
|
||||
icon: string;
|
||||
iconState: string;
|
||||
iconStates: string[];
|
||||
selected_object?: string;
|
||||
apply_icon_override?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
interface CreateObjectAdvancedSettingsProps {
|
||||
iconSettings: IconSettings;
|
||||
|
||||
@@ -19,13 +19,13 @@ import {
|
||||
} from './constants';
|
||||
import type { IconSettings } from './index';
|
||||
|
||||
export interface SpawnPanelData {
|
||||
export type SpawnPanelData = {
|
||||
icon: string;
|
||||
iconState: string;
|
||||
iconStates: string[];
|
||||
selected_object?: string;
|
||||
precise_mode: string;
|
||||
}
|
||||
};
|
||||
|
||||
interface CreateObjectSettingsProps {
|
||||
onCreateObject?: (obj: Record<string, unknown>) => void;
|
||||
|
||||
@@ -259,11 +259,11 @@ function ContractsTab(props) {
|
||||
>
|
||||
{contracts.map((contract) => {
|
||||
if (ongoing_contract && contract.status !== CONTRACT.Active) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
const active = contract.status > CONTRACT.Inactive;
|
||||
if (contract.status >= CONTRACT.Complete) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Section
|
||||
|
||||
@@ -95,7 +95,7 @@ export const Vending = () => {
|
||||
}
|
||||
|
||||
const filteredCategories = Object.fromEntries(
|
||||
Object.entries(data.categories).filter(([categoryName]) => {
|
||||
Object.entries(categories).filter(([categoryName]) => {
|
||||
return inventory.find((product) => {
|
||||
if ('category' in product) {
|
||||
return product.category === categoryName;
|
||||
|
||||
@@ -58,7 +58,7 @@ export const Connections = (props: {
|
||||
const from = val.from;
|
||||
const to = val.to;
|
||||
if (!to || !from) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
val.color = val.color || 'blue';
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { useSetAtom } from 'jotai';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { Button, Icon } from 'tgui-core/components';
|
||||
import { UI_DISABLED, UI_INTERACTIVE, UI_UPDATE } from 'tgui-core/constants';
|
||||
import { type BooleanLike, classes } from 'tgui-core/react';
|
||||
import { toTitleCase } from 'tgui-core/string';
|
||||
|
||||
import { globalStore } from '../backend';
|
||||
import { toggleKitchenSink } from '../debug/actions';
|
||||
import { kitchenSinkAtom } from '../events/store';
|
||||
|
||||
type TitleBarProps = Partial<{
|
||||
className: string;
|
||||
@@ -31,7 +30,8 @@ function statusToColor(status: number): string {
|
||||
export function TitleBar(props: TitleBarProps) {
|
||||
const { className, title, status, canClose, onDragStart, onClose, children } =
|
||||
props;
|
||||
const dispatch = globalStore.dispatch;
|
||||
|
||||
const setKitchenSink = useSetAtom(kitchenSinkAtom);
|
||||
|
||||
const finalTitle =
|
||||
(typeof title === 'string' &&
|
||||
@@ -60,7 +60,7 @@ export function TitleBar(props: TitleBarProps) {
|
||||
<Button
|
||||
className="TitleBar__buttons TitleBar__KitchenSink"
|
||||
icon="bug"
|
||||
onClick={() => dispatch(toggleKitchenSink())}
|
||||
onClick={() => setKitchenSink((prev) => !prev)}
|
||||
/>
|
||||
)}
|
||||
{!!canClose && (
|
||||
|
||||
@@ -12,26 +12,25 @@ import {
|
||||
useLayoutEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { KeyListener, type Box } from 'tgui-core/components';
|
||||
import { type Box, KeyListener } from 'tgui-core/components';
|
||||
import { UI_DISABLED, UI_INTERACTIVE } from 'tgui-core/constants';
|
||||
import type { KeyEvent } from 'tgui-core/events';
|
||||
import { KEY_ALT } from 'tgui-core/keycodes';
|
||||
import { type BooleanLike, classes } from 'tgui-core/react';
|
||||
import { decodeHtmlEntities } from 'tgui-core/string';
|
||||
|
||||
import { backendSuspendStart, globalStore, useBackend } from '../backend';
|
||||
import { useDebug } from '../debug';
|
||||
import { useBackend } from '../backend';
|
||||
import {
|
||||
dragStartHandler,
|
||||
recallWindowGeometry,
|
||||
resizeStartHandler,
|
||||
setWindowKey,
|
||||
setWindowPosition,
|
||||
storeWindowGeometry
|
||||
storeWindowGeometry,
|
||||
} from '../drag';
|
||||
import { suspendStart } from '../events/handlers/suspense';
|
||||
import { createLogger } from '../logging';
|
||||
import { Layout } from './Layout';
|
||||
import { TitleBar } from './TitleBar';
|
||||
import { KeyEvent } from 'tgui-core/events';
|
||||
import { KEY_ALT } from 'tgui-core/keycodes';
|
||||
|
||||
const logger = createLogger('Window');
|
||||
const DEFAULT_SIZE: [number, number] = [400, 600];
|
||||
@@ -57,8 +56,8 @@ export const Window = (props: Props) => {
|
||||
height,
|
||||
} = props;
|
||||
|
||||
const { config, suspended } = useBackend();
|
||||
const { debugLayout = false } = useDebug();
|
||||
const { config, suspended, debug } = useBackend();
|
||||
|
||||
const [isReadyToRender, setIsReadyToRender] = useState(false);
|
||||
|
||||
// We need to set the window to be invisible before we can set its geometry
|
||||
@@ -70,7 +69,7 @@ export const Window = (props: Props) => {
|
||||
setIsReadyToRender(true);
|
||||
}, []);
|
||||
|
||||
const { scale } = config.window;
|
||||
const { scale } = config?.window || false;
|
||||
|
||||
useEffect(() => {
|
||||
if (!suspended && isReadyToRender) {
|
||||
@@ -98,15 +97,12 @@ export const Window = (props: Props) => {
|
||||
});
|
||||
logger.log('mounting');
|
||||
updateGeometry();
|
||||
|
||||
return () => {
|
||||
logger.log('unmounting');
|
||||
};
|
||||
}
|
||||
return () => {
|
||||
logger.log('unmounting');
|
||||
};
|
||||
}, [isReadyToRender, width, height, scale]);
|
||||
|
||||
const dispatch = globalStore.dispatch;
|
||||
|
||||
// Determine when to show dimmer
|
||||
const showDimmer =
|
||||
config.user &&
|
||||
@@ -120,15 +116,17 @@ export const Window = (props: Props) => {
|
||||
title={title || decodeHtmlEntities(config.title)}
|
||||
status={config.status}
|
||||
onDragStart={dragStartHandler}
|
||||
onClose={() => {
|
||||
logger.log('pressed close');
|
||||
dispatch(backendSuspendStart());
|
||||
}}
|
||||
onClose={suspendStart}
|
||||
canClose={canClose}
|
||||
>
|
||||
{buttons}
|
||||
</TitleBar>
|
||||
<div className={classes(['Window__rest', debugLayout && 'debug-layout'])}>
|
||||
<div
|
||||
className={classes([
|
||||
'Window__rest',
|
||||
debug.debugLayout && 'debug-layout',
|
||||
])}
|
||||
>
|
||||
{!suspended && children}
|
||||
{showDimmer && <div className="Window__dimmer" />}
|
||||
</div>
|
||||
@@ -162,29 +160,35 @@ const WindowContent = (props: ContentProps) => {
|
||||
const [altDown, setAltDown] = useState(false);
|
||||
|
||||
var dragStartIfAltHeld = (event) => {
|
||||
if(altDown)
|
||||
{
|
||||
if (altDown) {
|
||||
dragStartHandler(event);
|
||||
}
|
||||
};
|
||||
|
||||
Byond.subscribeTo('resetposition', function (payload) {
|
||||
Byond.subscribeTo('resetposition', (payload) => {
|
||||
setWindowPosition([0, 0]);
|
||||
storeWindowGeometry();
|
||||
});
|
||||
return (
|
||||
<Layout.Content onMouseDown={dragStartIfAltHeld}
|
||||
<Layout.Content
|
||||
onMouseDown={dragStartIfAltHeld}
|
||||
className={classes(['Window__content', className])}
|
||||
{...rest}
|
||||
>
|
||||
<KeyListener
|
||||
onKeyDown={(e: KeyEvent) => {
|
||||
if(KEY_ALT === e.code) { setAltDown(true); logger.log(`alt on ${altDown}`) }
|
||||
if (KEY_ALT === e.code) {
|
||||
setAltDown(true);
|
||||
logger.log(`alt on ${altDown}`);
|
||||
}
|
||||
}}
|
||||
onKeyUp ={(e: KeyEvent) => {
|
||||
if(KEY_ALT === e.code) { setAltDown(false); logger.log(`alt off ${altDown}`)}
|
||||
onKeyUp={(e: KeyEvent) => {
|
||||
if (KEY_ALT === e.code) {
|
||||
setAltDown(false);
|
||||
logger.log(`alt off ${altDown}`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
/>
|
||||
|
||||
{(fitted && children) || (
|
||||
<div className="Window__contentPadding">{children}</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { perf } from 'common/perf';
|
||||
import type { ReactNode } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
|
||||
import { createLogger } from './logging';
|
||||
|
||||
const logger = createLogger('renderer');
|
||||
|
||||
@@ -4,32 +4,40 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { useBackend } from './backend';
|
||||
import { useDebug } from './debug';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { KitchenSink } from './debug/KitchenSink';
|
||||
import { backendStateAtom } from './events/store';
|
||||
import { LoadingScreen } from './interfaces/common/LoadingScreen';
|
||||
import { Window } from './layouts';
|
||||
|
||||
const requireInterface = require.context('./interfaces');
|
||||
|
||||
const routingError =
|
||||
(type: 'notFound' | 'missingExport', name: string) => () => {
|
||||
return (
|
||||
<Window>
|
||||
<Window.Content scrollable>
|
||||
{type === 'notFound' && (
|
||||
<div>
|
||||
Interface <b>{name}</b> was not found.
|
||||
</div>
|
||||
)}
|
||||
{type === 'missingExport' && (
|
||||
<div>
|
||||
Interface <b>{name}</b> is missing an export.
|
||||
</div>
|
||||
)}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
type RoutingErrorProps = {
|
||||
type: 'notFound' | 'missingExport' | 'unknown';
|
||||
name: string;
|
||||
};
|
||||
|
||||
function RoutingErrorWindow(props: RoutingErrorProps) {
|
||||
const { type, name } = props;
|
||||
|
||||
return (
|
||||
<Window>
|
||||
<Window.Content scrollable>
|
||||
{type === 'notFound' && (
|
||||
<div>
|
||||
Interface <b>{name}</b> was not found.
|
||||
</div>
|
||||
)}
|
||||
{type === 'missingExport' && (
|
||||
<div>
|
||||
Interface <b>{name}</b> is missing an export.
|
||||
</div>
|
||||
)}
|
||||
{type === 'unknown' && <div>An unknown error has occurred.</div>}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
}
|
||||
|
||||
// Displays an empty Window with scrollable content
|
||||
function SuspendedWindow() {
|
||||
@@ -52,25 +60,7 @@ function RefreshingWindow() {
|
||||
}
|
||||
|
||||
// Get the component for the current route
|
||||
export function getRoutedComponent() {
|
||||
const { suspended, config } = useBackend();
|
||||
const { kitchenSink = false } = useDebug();
|
||||
|
||||
if (suspended) {
|
||||
return SuspendedWindow;
|
||||
}
|
||||
if (config?.refreshing) {
|
||||
return RefreshingWindow;
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// Show a kitchen sink
|
||||
if (kitchenSink) {
|
||||
return require('./debug').KitchenSink;
|
||||
}
|
||||
}
|
||||
|
||||
const name = config?.interface?.name;
|
||||
export function getRoutedComponent(name: string) {
|
||||
const interfacePathBuilders = [
|
||||
(name: string) => `./${name}.tsx`,
|
||||
(name: string) => `./${name}.jsx`,
|
||||
@@ -86,19 +76,56 @@ export function getRoutedComponent() {
|
||||
esModule = requireInterface(interfacePath);
|
||||
} catch (err) {
|
||||
if (err.code !== 'MODULE_NOT_FOUND') {
|
||||
throw err;
|
||||
throw new Error('notFound');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!esModule) {
|
||||
return routingError('notFound', name);
|
||||
throw new Error('notFound');
|
||||
}
|
||||
|
||||
const Component = esModule[name];
|
||||
if (!Component) {
|
||||
return routingError('missingExport', name);
|
||||
throw new Error('missingExport');
|
||||
}
|
||||
|
||||
return Component;
|
||||
}
|
||||
|
||||
export function RoutedComponent() {
|
||||
const { suspended, config, debug } = useAtomValue(backendStateAtom);
|
||||
|
||||
if (suspended) {
|
||||
return <SuspendedWindow />;
|
||||
}
|
||||
if (config.refreshing) {
|
||||
return <RefreshingWindow />;
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (debug.kitchenSink) {
|
||||
return <KitchenSink />;
|
||||
}
|
||||
}
|
||||
|
||||
const name = config?.interface?.name;
|
||||
if (!name) {
|
||||
return <RoutingErrorWindow type="notFound" name="(undefined)" />;
|
||||
}
|
||||
|
||||
try {
|
||||
const Component = getRoutedComponent(name);
|
||||
|
||||
return <Component />;
|
||||
} catch (err) {
|
||||
switch (err.message) {
|
||||
case 'notFound':
|
||||
return <RoutingErrorWindow type="notFound" name={name} />;
|
||||
case 'missingExport':
|
||||
return <RoutingErrorWindow type="missingExport" name={name} />;
|
||||
default:
|
||||
return <RoutingErrorWindow type="unknown" name={name} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { configAtom, store } from './events/store';
|
||||
import { logger } from './logging';
|
||||
|
||||
/**
|
||||
* Creates a function, which can be assigned to window.__augmentStack__
|
||||
* to augment reported stack traces with useful data for debugging.
|
||||
*/
|
||||
export const createStackAugmentor =
|
||||
() =>
|
||||
(stack: string, error?: Error): string => {
|
||||
error = error || new Error(stack.split('\n')[0]);
|
||||
error.stack = error.stack || stack;
|
||||
|
||||
logger.log('FatalError:', error);
|
||||
const config = store.get(configAtom);
|
||||
|
||||
return (
|
||||
stack +
|
||||
'\nUser Agent: ' +
|
||||
navigator.userAgent +
|
||||
'\nState: ' +
|
||||
JSON.stringify({
|
||||
ckey: config?.client?.ckey,
|
||||
interface: config?.interface,
|
||||
window: config?.window,
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -1,111 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import {
|
||||
applyMiddleware,
|
||||
combineReducers,
|
||||
createStore,
|
||||
type Middleware,
|
||||
type Reducer,
|
||||
type Store,
|
||||
} from 'common/redux';
|
||||
import { flow } from 'tgui-core/fp';
|
||||
|
||||
import { assetMiddleware } from './assets';
|
||||
import { backendMiddleware, backendReducer } from './backend';
|
||||
import { debugMiddleware, debugReducer, relayMiddleware } from './debug';
|
||||
import { createLogger } from './logging';
|
||||
|
||||
type ConfigureStoreOptions = {
|
||||
sideEffects?: boolean;
|
||||
reducer?: Reducer;
|
||||
middleware?: {
|
||||
pre?: Middleware[];
|
||||
post?: Middleware[];
|
||||
};
|
||||
};
|
||||
|
||||
type StackAugmentor = (stack: string, error?: Error) => string;
|
||||
|
||||
type StoreProviderProps = {
|
||||
store: Store;
|
||||
children: any;
|
||||
};
|
||||
|
||||
const logger = createLogger('store');
|
||||
|
||||
export const configureStore = (options: ConfigureStoreOptions = {}): Store => {
|
||||
const { sideEffects = true, reducer, middleware } = options;
|
||||
const rootReducer: Reducer = flow([
|
||||
combineReducers({
|
||||
debug: debugReducer,
|
||||
backend: backendReducer,
|
||||
}),
|
||||
reducer as any,
|
||||
]);
|
||||
|
||||
const middlewares: Middleware[] = !sideEffects
|
||||
? []
|
||||
: [
|
||||
...(middleware?.pre || []),
|
||||
assetMiddleware,
|
||||
backendMiddleware,
|
||||
...(middleware?.post || []),
|
||||
];
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// We are using two if statements because Webpack is capable of
|
||||
// removing this specific block as dead code.
|
||||
if (sideEffects) {
|
||||
middlewares.unshift(loggingMiddleware, debugMiddleware, relayMiddleware);
|
||||
}
|
||||
}
|
||||
|
||||
const enhancer = applyMiddleware(...middlewares);
|
||||
const store = createStore(rootReducer, enhancer);
|
||||
|
||||
// Globals
|
||||
window.__store__ = store;
|
||||
window.__augmentStack__ = createStackAugmentor(store);
|
||||
|
||||
return store;
|
||||
};
|
||||
|
||||
const loggingMiddleware: Middleware = (store) => (next) => (action) => {
|
||||
const { type } = action;
|
||||
logger.debug(
|
||||
'action',
|
||||
type === 'update' || type === 'backend/update' ? { type } : action,
|
||||
);
|
||||
return next(action);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a function, which can be assigned to window.__augmentStack__
|
||||
* to augment reported stack traces with useful data for debugging.
|
||||
*/
|
||||
const createStackAugmentor =
|
||||
(store: Store): StackAugmentor =>
|
||||
(stack, error) => {
|
||||
error = error || new Error(stack.split('\n')[0]);
|
||||
error.stack = error.stack || stack;
|
||||
|
||||
logger.log('FatalError:', error);
|
||||
const state = store.getState();
|
||||
const config = state?.backend?.config;
|
||||
|
||||
return (
|
||||
stack +
|
||||
'\nUser Agent: ' +
|
||||
navigator.userAgent +
|
||||
'\nState: ' +
|
||||
JSON.stringify({
|
||||
ckey: config?.client?.ckey,
|
||||
interface: config?.interface,
|
||||
window: config?.window,
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -117,6 +117,10 @@ export default defineConfig({
|
||||
new rspack.EnvironmentPlugin({
|
||||
NODE_ENV: 'production',
|
||||
}),
|
||||
new rspack.CircularDependencyRspackPlugin({
|
||||
failOnError: true,
|
||||
exclude: /node_modules/,
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.js', '.jsx'],
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"baseUrl": ".",
|
||||
"checkJs": false,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
@@ -11,6 +12,16 @@
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"noEmit": true,
|
||||
"paths": {
|
||||
"tgui": ["packages/tgui"],
|
||||
"tgui/*": ["packages/tgui/*"],
|
||||
"tgui-panel": ["packages/tgui-panel"],
|
||||
"tgui-panel/*": ["packages/tgui-panel/*"],
|
||||
"tgui-say": ["packages/tgui-say"],
|
||||
"tgui-say/*": ["packages/tgui-say/*"],
|
||||
"tgui-dev-server": ["packages/tgui-dev-server"],
|
||||
"tgui-dev-server/*": ["packages/tgui-dev-server/*"]
|
||||
},
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
|
||||
Reference in New Issue
Block a user