diff --git a/.gitignore b/.gitignore index 10545088..3f264739 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,10 @@ Thumbs.db **/.vitepress/cache/ **/.vitepress/dist/ **/doc/api/ + +# Secrets and credentials +.env +.env.* +.npmrc.local +.npmrc +!.npmrc diff --git a/CHANGELOG.md b/CHANGELOG.md index 23915e4a..d2e97dd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [2.10.0] - 2026-05-11 + +### Added +- **Licensing Architecture Preparation**: Initial work to support licensed plugins and features. + +### Changed +- **Term Collision Enforcement**: Term plugin registration now throws a fatal error on naming collisions (key/scope) to prevent silent configuration failures. + +## [2.9.3] - 2026-05-11 + +### Added +- **Fractional Resolution**: Numeric inputs now support fractional components with nanosecond precision using BigInt math. +- **Hardened AliasContext**: Improved chainable context for functional aliases with full API parity. +- **Epoch Support**: Enhanced detection for 9-10 digit Epoch timestamps. + +### Fixed +- **Mutation Safety**: Eliminated side-effects on global configuration during parsing. +- **Normalizer Memory**: Fixed state leakage in alias resolution. ## [2.8.0] - 2026-04-30 diff --git a/package-lock.json b/package-lock.json index fe84f12c..6fd82587 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,32 +1,50 @@ { "name": "tempo-monorepo", - "version": "2.9.3", + "version": "2.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tempo-monorepo", - "version": "2.9.3", + "version": "2.10.0", "workspaces": [ "packages/*" ], "devDependencies": { "@js-temporal/polyfill": "^0.5.1", "@rollup/plugin-node-resolve": "^16.0.3", - "@types/google.maps": "^3.64.0", + "@types/google.maps": "^3.64.1", "@types/hammerjs": "^2.0.46", "@types/jquery": "^4.0.0", - "@types/node": "^25.6.2", + "@types/node": "^25.8.0", "@vitest/ui": "^2.1.9", "cross-env": "^10.1.0", "markdown-it-mathjax3": "^4.3.2", - "rollup": "^4.60.3", + "rollup": "^4.60.4", "tslib": "^2.8.1", - "tsx": "^4.21.0", + "tsx": "^4.22.0", "typescript": "^6.0.3", "vitest": "^2.1.9" } }, + "../tempo-plugin/packages/_core": { + "name": "@magmacomputing/tempo-plugin-_core", + "version": "1.0.0", + "extraneous": true, + "dependencies": { + "@magmacomputing/tempo": "^2.9.3", + "jose": "^6.2.3" + } + }, + "../tempo-plugin/packages/@core": { + "name": "@magmacomputing/tempo-plugin-@core", + "version": "1.0.0", + "extraneous": true, + "dependencies": { + "@magmacomputing/tempo": "^2.9.3", + "jose": "^6.2.3" + } + }, "node_modules/@algolia/abtesting": { "version": "1.16.2", "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.16.2.tgz", @@ -750,23 +768,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/sunos-x64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", @@ -866,6 +867,63 @@ "dev": true, "license": "MIT" }, + "node_modules/@inversifyjs/common": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@inversifyjs/common/-/common-1.3.3.tgz", + "integrity": "sha512-ZH0wrgaJwIo3s9gMCDM2wZoxqrJ6gB97jWXncROfYdqZJv8f3EkqT57faZqN5OTeHWgtziQ6F6g3L8rCvGceCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@inversifyjs/core": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@inversifyjs/core/-/core-1.3.4.tgz", + "integrity": "sha512-gCCmA4BdbHEFwvVZ2elWgHuXZWk6AOu/1frxsS+2fWhjEk2c/IhtypLo5ytSUie1BCiT6i9qnEo4bruBomQsAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inversifyjs/common": "1.3.3", + "@inversifyjs/reflect-metadata-utils": "0.2.3" + } + }, + "node_modules/@inversifyjs/reflect-metadata-utils": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@inversifyjs/reflect-metadata-utils/-/reflect-metadata-utils-0.2.3.tgz", + "integrity": "sha512-d3D0o9TeSlvaGM2I24wcNw/Aj3rc4OYvHXOKDC09YEph5fMMiKd6fq1VTQd9tOkDNWvVbw+cnt45Wy9P/t5Lvw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "reflect-metadata": "0.2.2" + } + }, + "node_modules/@javascript-obfuscator/escodegen": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@javascript-obfuscator/escodegen/-/escodegen-2.4.1.tgz", + "integrity": "sha512-YrEJJDr4cb+pIQKWzHFoDlDkQzatcrNB6OhAD6iTSwiKwzZUMVdobwbOuLpF4EiLxUj0qP28Xl1saTHYzIPCLg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@javascript-obfuscator/estraverse": "^5.3.0", + "esprima": "^4.0.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/@javascript-obfuscator/estraverse": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@javascript-obfuscator/estraverse/-/estraverse-5.4.0.tgz", + "integrity": "sha512-CZFX7UZVN9VopGbjTx4UXaXsi9ewoM1buL0kY7j1ftYdSs7p2spv9opxFjHlQ/QGTgh4UqufYqJJ0WKLml7b6w==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -975,9 +1033,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.3.tgz", - "integrity": "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", + "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", "cpu": [ "arm" ], @@ -989,9 +1047,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.3.tgz", - "integrity": "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", + "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", "cpu": [ "arm64" ], @@ -1003,9 +1061,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.3.tgz", - "integrity": "sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", + "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", "cpu": [ "arm64" ], @@ -1017,9 +1075,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.3.tgz", - "integrity": "sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", + "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", "cpu": [ "x64" ], @@ -1031,9 +1089,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.3.tgz", - "integrity": "sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", + "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", "cpu": [ "arm64" ], @@ -1045,9 +1103,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.3.tgz", - "integrity": "sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", + "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", "cpu": [ "x64" ], @@ -1059,9 +1117,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.3.tgz", - "integrity": "sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", + "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", "cpu": [ "arm" ], @@ -1076,9 +1134,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.3.tgz", - "integrity": "sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", + "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", "cpu": [ "arm" ], @@ -1093,9 +1151,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.3.tgz", - "integrity": "sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", + "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", "cpu": [ "arm64" ], @@ -1110,9 +1168,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.3.tgz", - "integrity": "sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", + "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", "cpu": [ "arm64" ], @@ -1127,9 +1185,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.3.tgz", - "integrity": "sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", + "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", "cpu": [ "loong64" ], @@ -1144,9 +1202,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.3.tgz", - "integrity": "sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", + "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", "cpu": [ "loong64" ], @@ -1161,9 +1219,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.3.tgz", - "integrity": "sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", + "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", "cpu": [ "ppc64" ], @@ -1178,9 +1236,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.3.tgz", - "integrity": "sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", + "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", "cpu": [ "ppc64" ], @@ -1195,9 +1253,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.3.tgz", - "integrity": "sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", + "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", "cpu": [ "riscv64" ], @@ -1212,9 +1270,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.3.tgz", - "integrity": "sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", + "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", "cpu": [ "riscv64" ], @@ -1229,9 +1287,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.3.tgz", - "integrity": "sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", + "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", "cpu": [ "s390x" ], @@ -1246,9 +1304,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.3.tgz", - "integrity": "sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", + "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", "cpu": [ "x64" ], @@ -1263,9 +1321,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.3.tgz", - "integrity": "sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", + "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", "cpu": [ "x64" ], @@ -1280,9 +1338,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.3.tgz", - "integrity": "sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", + "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", "cpu": [ "x64" ], @@ -1294,9 +1352,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.3.tgz", - "integrity": "sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", + "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", "cpu": [ "arm64" ], @@ -1308,9 +1366,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.3.tgz", - "integrity": "sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", + "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", "cpu": [ "arm64" ], @@ -1322,9 +1380,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.3.tgz", - "integrity": "sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", + "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", "cpu": [ "ia32" ], @@ -1336,9 +1394,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.3.tgz", - "integrity": "sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", + "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", "cpu": [ "x64" ], @@ -1350,9 +1408,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.3.tgz", - "integrity": "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", + "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", "cpu": [ "x64" ], @@ -1502,9 +1560,9 @@ "license": "MIT" }, "node_modules/@types/google.maps": { - "version": "3.64.0", - "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.64.0.tgz", - "integrity": "sha512-dN0H6tB4lgLQLovcbPXFYYOEV41TpyyJghzb5jrzjB96FZmjeOghevVdC+BMGd6YqyCqXaggyEtqRXLRjzCBZA==", + "version": "3.64.1", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.64.1.tgz", + "integrity": "sha512-nEBoa6iDNipICtxJ5VlrOgPNZQ6ixIg5nuv8iryFj0Z/1NLgxyg3pQCVegPuCzGCyTQwQI/N3uZvLUysqAzaaw==", "dev": true, "license": "MIT" }, @@ -1567,14 +1625,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { - "version": "25.6.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.2.tgz", - "integrity": "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw==", + "version": "25.8.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.8.0.tgz", + "integrity": "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.19.0" + "undici-types": ">=7.24.0 <7.24.7" } }, "node_modules/@types/resolve": { @@ -1591,6 +1656,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/validator": { + "version": "13.15.10", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz", + "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/web-bluetooth": { "version": "0.0.21", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", @@ -1605,6 +1677,23 @@ "dev": true, "license": "ISC" }, + "node_modules/@vercel/blob": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@vercel/blob/-/blob-2.3.3.tgz", + "integrity": "sha512-MtD7VLo6hU07eHR7bmk5SIMD290q574UaNYTe46qeyRT+hWrCy26CoAqfd7PnIefVXvRehRZBzukxuTO9iGTVg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async-retry": "^1.3.3", + "is-buffer": "^2.0.5", + "is-node-process": "^1.2.0", + "throttleit": "^2.1.0", + "undici": "^6.23.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@vitejs/plugin-vue": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", @@ -2042,6 +2131,29 @@ "node": ">=14.6" } }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/algoliasearch": { "version": "5.50.2", "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.50.2.tgz", @@ -2078,6 +2190,22 @@ "node": ">=6" } }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2085,6 +2213,50 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -2095,6 +2267,39 @@ "node": ">=12" } }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/birpc": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", @@ -2112,6 +2317,17 @@ "dev": true, "license": "ISC" }, + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -2122,6 +2338,56 @@ "node": ">=8" } }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ccount": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", @@ -2150,6 +2416,40 @@ "node": ">=18" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chance": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.13.tgz", + "integrity": "sha512-V6lQCljcLznE7tUYUM9EOAnnKXbctE6j/rdQkYOHIWbfGQbrzTsAXNW9CdU5XCo4ArXQCj/rb6HgxPlmGJcaUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/character-entities-html4": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", @@ -2172,6 +2472,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, "node_modules/check-error": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", @@ -2221,6 +2531,38 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/class-validator": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.3.tgz", + "integrity": "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/validator": "^13.15.3", + "libphonenumber-js": "^1.11.1", + "validator": "^13.15.20" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -2242,6 +2584,13 @@ "node": ">= 6" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, "node_modules/copy-anything": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", @@ -2291,6 +2640,16 @@ "node": ">= 8" } }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, "node_modules/css-select": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", @@ -2356,6 +2715,13 @@ "node": ">=6" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -2366,6 +2732,42 @@ "node": ">=0.10.0" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -2459,14 +2861,29 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/emoji-regex-xs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", - "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, - "license": "MIT" - }, - "node_modules/entities": { + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", @@ -2479,6 +2896,42 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/env-paths": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-4.0.0.tgz", + "integrity": "sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-safe-filename": "^0.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", @@ -2486,6 +2939,19 @@ "dev": true, "license": "MIT" }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", @@ -2558,6 +3024,36 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -2568,6 +3064,43 @@ "node": ">=6" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -2578,6 +3111,16 @@ "@types/estree": "^1.0.0" } }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/expect-type": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", @@ -2588,6 +3131,20 @@ "node": ">=12.0.0" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -2629,6 +3186,22 @@ "tabbable": "^6.4.0" } }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2654,10 +3227,59 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-tsconfig": { - "version": "4.13.6", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", - "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", "dev": true, "license": "MIT", "dependencies": { @@ -2667,6 +3289,71 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2766,6 +3453,78 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/inversify": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.1.4.tgz", + "integrity": "sha512-PbxrZH/gTa1fpPEEGAjJQzK8tKMIp5gRg6EFNJlCtzUcycuNdmhv3uk5P8Itm/RIjgHJO16oQRLo9IHzQN51bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inversifyjs/common": "1.3.3", + "@inversifyjs/core": "1.3.4" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -2782,6 +3541,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", @@ -2789,25 +3568,155 @@ "dev": true, "license": "MIT" }, - "node_modules/is-what": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", - "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/mesqueeb" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", "dev": true, - "license": "ISC" + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-safe-filename": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-safe-filename/-/is-safe-filename-0.1.1.tgz", + "integrity": "sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/javascript-obfuscator": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/javascript-obfuscator/-/javascript-obfuscator-5.4.2.tgz", + "integrity": "sha512-VUcjC6IPDuB5vAFVZ7qhGRkyewGWV5p05GuCWr3wwQjAym8icDprqz7B9595pqN6aI8EgyazgogOuac89xIgxw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@javascript-obfuscator/escodegen": "2.4.1", + "@javascript-obfuscator/estraverse": "5.4.0", + "@vercel/blob": ">=0.23.0", + "acorn": "8.15.0", + "acorn-import-attributes": "^1.9.5", + "assert": "2.1.0", + "chalk": "4.1.2", + "chance": "1.1.13", + "class-validator": "0.14.3", + "commander": "12.1.0", + "env-paths": "4.0.0", + "eslint-scope": "8.4.0", + "eslint-visitor-keys": "4.2.1", + "fast-deep-equal": "3.1.3", + "inversify": "6.1.4", + "js-string-escape": "1.0.1", + "md5": "2.3.0", + "multimatch": "5.0.0", + "process": "0.11.10", + "reflect-metadata": "0.2.2", + "string-template": "1.0.0", + "stringz": "2.1.0", + "tslib": "2.8.1" + }, + "bin": { + "javascript-obfuscator": "bin/javascript-obfuscator" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/javascript-obfuscator/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, "node_modules/jsbi": { "version": "4.3.2", @@ -2836,6 +3745,27 @@ "node": ">=10.0.0" } }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/libphonenumber-js": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.13.2.tgz", + "integrity": "sha512-S3kmBrptp3yRTm83NUcHy9g1vbwiWMzI8WvY22+koBJ6zkRteLnedBL2VX0MIAGwx2yiyxX4J85pceZyQ6ffgg==", + "dev": true, + "license": "MIT" + }, "node_modules/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", @@ -2906,6 +3836,16 @@ "mathjax-full": "^3.2.0" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mathjax-full": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.1.tgz", @@ -2919,6 +3859,25 @@ "speech-rule-engine": "^4.0.6" } }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/md5/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "license": "MIT" + }, "node_modules/mdast-util-to-hast": { "version": "13.2.1", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", @@ -3069,6 +4028,19 @@ "node": ">=4.0.0" } }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/minisearch": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", @@ -3107,6 +4079,26 @@ "dev": true, "license": "MIT" }, + "node_modules/multimatch": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -3160,6 +4152,54 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/oniguruma-to-es": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz", @@ -3172,6 +4212,24 @@ "regex-recursion": "^6.0.2" } }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -3250,6 +4308,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.5.12", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.12.tgz", @@ -3290,6 +4358,25 @@ "url": "https://opencollective.com/preact" } }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/property-information": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", @@ -3311,6 +4398,13 @@ "node": ">=6" } }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", @@ -3369,6 +4463,16 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/rfdc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", @@ -3377,9 +4481,9 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.3.tgz", - "integrity": "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", + "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", "dev": true, "license": "MIT", "dependencies": { @@ -3393,34 +4497,72 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.3", - "@rollup/rollup-android-arm64": "4.60.3", - "@rollup/rollup-darwin-arm64": "4.60.3", - "@rollup/rollup-darwin-x64": "4.60.3", - "@rollup/rollup-freebsd-arm64": "4.60.3", - "@rollup/rollup-freebsd-x64": "4.60.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.3", - "@rollup/rollup-linux-arm-musleabihf": "4.60.3", - "@rollup/rollup-linux-arm64-gnu": "4.60.3", - "@rollup/rollup-linux-arm64-musl": "4.60.3", - "@rollup/rollup-linux-loong64-gnu": "4.60.3", - "@rollup/rollup-linux-loong64-musl": "4.60.3", - "@rollup/rollup-linux-ppc64-gnu": "4.60.3", - "@rollup/rollup-linux-ppc64-musl": "4.60.3", - "@rollup/rollup-linux-riscv64-gnu": "4.60.3", - "@rollup/rollup-linux-riscv64-musl": "4.60.3", - "@rollup/rollup-linux-s390x-gnu": "4.60.3", - "@rollup/rollup-linux-x64-gnu": "4.60.3", - "@rollup/rollup-linux-x64-musl": "4.60.3", - "@rollup/rollup-openbsd-x64": "4.60.3", - "@rollup/rollup-openharmony-arm64": "4.60.3", - "@rollup/rollup-win32-arm64-msvc": "4.60.3", - "@rollup/rollup-win32-ia32-msvc": "4.60.3", - "@rollup/rollup-win32-x64-gnu": "4.60.3", - "@rollup/rollup-win32-x64-msvc": "4.60.3", + "@rollup/rollup-android-arm-eabi": "4.60.4", + "@rollup/rollup-android-arm64": "4.60.4", + "@rollup/rollup-darwin-arm64": "4.60.4", + "@rollup/rollup-darwin-x64": "4.60.4", + "@rollup/rollup-freebsd-arm64": "4.60.4", + "@rollup/rollup-freebsd-x64": "4.60.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", + "@rollup/rollup-linux-arm-musleabihf": "4.60.4", + "@rollup/rollup-linux-arm64-gnu": "4.60.4", + "@rollup/rollup-linux-arm64-musl": "4.60.4", + "@rollup/rollup-linux-loong64-gnu": "4.60.4", + "@rollup/rollup-linux-loong64-musl": "4.60.4", + "@rollup/rollup-linux-ppc64-gnu": "4.60.4", + "@rollup/rollup-linux-ppc64-musl": "4.60.4", + "@rollup/rollup-linux-riscv64-gnu": "4.60.4", + "@rollup/rollup-linux-riscv64-musl": "4.60.4", + "@rollup/rollup-linux-s390x-gnu": "4.60.4", + "@rollup/rollup-linux-x64-gnu": "4.60.4", + "@rollup/rollup-linux-x64-musl": "4.60.4", + "@rollup/rollup-openbsd-x64": "4.60.4", + "@rollup/rollup-openharmony-arm64": "4.60.4", + "@rollup/rollup-win32-arm64-msvc": "4.60.4", + "@rollup/rollup-win32-ia32-msvc": "4.60.4", + "@rollup/rollup-win32-x64-gnu": "4.60.4", + "@rollup/rollup-win32-x64-msvc": "4.60.4", "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-esbuild": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-6.2.1.tgz", + "integrity": "sha512-jTNOMGoMRhs0JuueJrJqbW8tOwxumaWYq+V5i+PD+8ecSCVkuX27tGW7BXqDgoULQ55rO7IdNxPcnsWtshz3AA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "get-tsconfig": "^4.10.0", + "unplugin-utils": "^0.2.4" + }, + "engines": { + "node": ">=14.18.0" + }, + "peerDependencies": { + "esbuild": ">=0.18.0", + "rollup": "^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/search-insights": { "version": "2.17.3", "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", @@ -3429,6 +4571,24 @@ "license": "MIT", "peer": true }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3543,6 +4703,17 @@ "node": "*" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -3613,6 +4784,13 @@ "dev": true, "license": "MIT" }, + "node_modules/string-template": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-1.0.0.tgz", + "integrity": "sha512-SLqR3GBUXuoPP5MmYtD7ompvXiG87QjT6lzOszyXjTM86Uu7At7vNnt2xgyTLq5o9T4IxTYFyGxcULqpsmsfdg==", + "dev": true, + "license": "MIT" + }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -3625,622 +4803,203 @@ }, "funding": { "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/superjson": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", - "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "copy-anything": "^4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tabbable": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", - "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinypool": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], + "node_modules/stringz": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/stringz/-/stringz-2.1.0.tgz", + "integrity": "sha512-KlywLT+MZ+v0IRepfMxRtnSvDCMc3nR1qqCs3m/qIbSOWkNZYT8XHQA31rS3TnKp0c5xjZu3M4GY/2aRKSi/6A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "char-regex": "^1.0.2" } }, - "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "copy-anything": "^4" + }, "engines": { - "node": ">=18" + "node": ">=16" } }, - "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "dev": true, + "license": "MIT" + }, + "node_modules/throttleit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-2.1.0.tgz", + "integrity": "sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, "engines": { - "node": ">=18" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], "engines": { - "node": ">=18" + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], "engines": { - "node": ">=18" + "node": ">=14.0.0" } }, - "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=18" + "node": ">=14.0.0" } }, - "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=18" + "node": ">=6" } }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.0.tgz", + "integrity": "sha512-8ccZMPD69s1AbKXx0C5ddTNZfNjwV04iIKgjZmKfKxMynEtSYcK0Lh7iQFh53fI5Yu4pb9usgAiqyPmEONaALg==", "dev": true, - "hasInstallScript": true, "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, "bin": { - "esbuild": "bin/esbuild" + "tsx": "dist/cli.mjs" }, "engines": { - "node": ">=18" + "node": ">=18.0.0" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" + "fsevents": "~2.3.3" + } + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" } }, "node_modules/typedoc": { @@ -4350,10 +5109,20 @@ "dev": true, "license": "MIT" }, + "node_modules/undici": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", + "integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/undici-types": { - "version": "7.19.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", - "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", "dev": true, "license": "MIT" }, @@ -4430,6 +5199,44 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unplugin-utils": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.2.5.tgz", + "integrity": "sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/unplugin-utils/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/valid-data-url": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz", @@ -4440,6 +5247,16 @@ "node": ">=10" } }, + "node_modules/validator": { + "version": "13.15.35", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.35.tgz", + "integrity": "sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -4788,6 +5605,28 @@ "node": ">= 8" } }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -4812,6 +5651,16 @@ "dev": true, "license": "MIT" }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/yaml": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", @@ -4841,7 +5690,7 @@ }, "packages/library": { "name": "@magmacomputing/library", - "version": "2.9.3", + "version": "2.10.0", "license": "MIT", "dependencies": { "tslib": "^2.8.1" @@ -4860,21 +5709,34 @@ }, "packages/tempo": { "name": "@magmacomputing/tempo", - "version": "2.9.3", + "version": "2.10.0", "license": "MIT", "dependencies": { "tslib": "^2.8.1" }, "devDependencies": { "@js-temporal/polyfill": "^0.5.1", - "@magmacomputing/library": "2.9.3", + "@magmacomputing/library": "2.10.0", + "@magmacomputing/tempo-plugin-_core": "file:./test/support/license-stub-pkg", "@rollup/plugin-alias": "^6.0.0", + "esbuild": "^0.25.12", + "javascript-obfuscator": "^5.4.2", "magic-string": "^0.30.21", + "rollup-plugin-esbuild": "^6.2.1", "typedoc": "^0.28.19", "typedoc-plugin-markdown": "^4.11.0", "typedoc-vitepress-theme": "^1.1.2", "vitepress": "^1.6.4" } + }, + "packages/tempo/node_modules/@magmacomputing/tempo-plugin-_core": { + "resolved": "packages/tempo/test/support/license-stub-pkg", + "link": true + }, + "packages/tempo/test/support/license-stub-pkg": { + "name": "@magmacomputing/tempo-plugin-_core", + "version": "1.0.0", + "dev": true } } } diff --git a/package.json b/package.json index 4ce43acd..a2d58984 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tempo-monorepo", - "version": "2.9.3", + "version": "2.10.0", "private": true, "description": "Magma Computing Monorepo", "repository": { @@ -26,16 +26,16 @@ "devDependencies": { "@js-temporal/polyfill": "^0.5.1", "@rollup/plugin-node-resolve": "^16.0.3", - "@types/google.maps": "^3.64.0", + "@types/google.maps": "^3.64.1", "@types/hammerjs": "^2.0.46", "@types/jquery": "^4.0.0", - "@types/node": "^25.6.2", + "@types/node": "^25.8.0", "@vitest/ui": "^2.1.9", "cross-env": "^10.1.0", "markdown-it-mathjax3": "^4.3.2", - "rollup": "^4.60.3", + "rollup": "^4.60.4", "tslib": "^2.8.1", - "tsx": "^4.21.0", + "tsx": "^4.22.0", "typescript": "^6.0.3", "vitest": "^2.1.9" }, diff --git a/packages/library/LICENSE b/packages/library/LICENSE new file mode 100644 index 00000000..dd7db2d9 --- /dev/null +++ b/packages/library/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Magma Computing + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/library/package.json b/packages/library/package.json index f930b597..23f07625 100644 --- a/packages/library/package.json +++ b/packages/library/package.json @@ -1,6 +1,6 @@ { "name": "@magmacomputing/library", - "version": "2.9.3", + "version": "2.10.0", "description": "Shared utility library for Tempo", "author": "Magma Computing Solutions", "license": "MIT", @@ -9,6 +9,9 @@ "url": "git+https://github.com/magmacomputing/magma.git", "directory": "packages/library" }, + "publishConfig": { + "access": "public" + }, "homepage": "https://github.com/magmacomputing/magma/tree/main/packages/library#readme", "bugs": { "url": "https://github.com/magmacomputing/magma/issues" diff --git a/packages/library/src/common/storage.library.ts b/packages/library/src/common/storage.library.ts index e9361fc3..4eb068ac 100644 --- a/packages/library/src/common/storage.library.ts +++ b/packages/library/src/common/storage.library.ts @@ -50,9 +50,10 @@ export function getStorage(key?: string, dflt?: T): T | undefined { case CONTEXT.NodeJS: store = context.global.process.env[key]; - if (key === '$Tempo' && !store) { - // skip debug log for production/test clean-up - } + break; + + case CONTEXT.Deno: + store = context.global.Deno.env.get(key); break; case CONTEXT.GoogleAppsScript: diff --git a/packages/library/src/common/utility.library.ts b/packages/library/src/common/utility.library.ts index 0f74c72d..eee5a70a 100644 --- a/packages/library/src/common/utility.library.ts +++ b/packages/library/src/common/utility.library.ts @@ -5,6 +5,32 @@ import type { Secure, ValueOf } from '#library/type.library.js'; /** General utility functions */ +/** fast, unverified decode of a JWT payload */ +export const decodeJWT = (jwt: string): T | null => { + try { + const part = jwt.split('.')[1]; + if (!part) return null; + // 🛡️ Base64URL Normalization: replace -/_ with +/ and add padding + const base64 = part.replace(/-/g, '+').replace(/_/g, '/').padEnd(part.length + (4 - part.length % 4) % 4, '='); + const payload = typeof atob === 'function' ? atob(base64) : Buffer.from(base64, 'base64').toString(); + return JSON.parse(payload); + } catch { return null; } +} + +/** portable base64 encoder for universal support */ +export const base64Encode = (input: string): string => { + if (typeof Buffer !== 'undefined') + return Buffer.from(input).toString('base64'); + + const bytes = new TextEncoder().encode(input); + let binary = ''; + + for (let i = 0; i < bytes.byteLength; i++) + binary += String.fromCharCode(bytes[i]); + + return btoa(binary); +} + /** analyze the Call Stack to determine calling Function's name */ export const getCaller = () => { const stackTrace = new Error().stack // only tested in latest FF and Chrome @@ -58,6 +84,9 @@ export const getContext = (): Context => { if (isDefined(global.window?.document)) return { global, type: CONTEXT.Browser }; + if (isDefined(global.Deno)) + return { global, type: CONTEXT.Deno }; + if (isDefined(global.process?.versions?.node)) return { global, type: CONTEXT.NodeJS }; @@ -85,7 +114,7 @@ export function deepFreeze(obj: T, options?: { skip?: We export function deepFreeze(obj: T, options?: { skip?: WeakSet } | WeakSet, seen: WeakSet = new WeakSet()): Secure { // Support both old and new signatures for backward compatibility const skip = (options instanceof WeakSet) ? options : (options?.skip ?? EMPTY_SKIP); - + if (isPrimitive(obj) || Object.isFrozen(obj) || seen.has(obj) || skip.has(obj)) return obj as Secure; diff --git a/packages/library/src/tsconfig.json b/packages/library/src/tsconfig.json index 5387dbfd..c213dda2 100644 --- a/packages/library/src/tsconfig.json +++ b/packages/library/src/tsconfig.json @@ -6,6 +6,7 @@ "composite": true, "lib": [ "ESNext", + "ESNext.Temporal", "DOM" ], "types": [ diff --git a/packages/library/test/tsconfig.json b/packages/library/test/tsconfig.json index bb611650..84f58900 100644 --- a/packages/library/test/tsconfig.json +++ b/packages/library/test/tsconfig.json @@ -26,12 +26,6 @@ ], "#server/*": [ "../src/server/*" - ], - "#tempo": [ - "../../tempo/src/tempo.index.ts" - ], - "#tempo/*": [ - "../../tempo/src/*" ] } }, diff --git a/packages/library/tsconfig.json b/packages/library/tsconfig.json index 98488674..7c513882 100644 --- a/packages/library/tsconfig.json +++ b/packages/library/tsconfig.json @@ -24,12 +24,6 @@ ], "#server/*": [ "./src/server/*" - ], - "#tempo": [ - "../tempo/src/tempo.index.ts" - ], - "#tempo/*": [ - "../tempo/src/*" ] } }, diff --git a/packages/tempo/.vitepress/config.ts b/packages/tempo/.vitepress/config.ts index 7a78bd00..d750f97b 100644 --- a/packages/tempo/.vitepress/config.ts +++ b/packages/tempo/.vitepress/config.ts @@ -46,10 +46,16 @@ export default defineConfig({ { text: 'Parse Planner', link: '/doc/tempo.planner' }, { text: 'Regional Parsing (MDY)', link: '/doc/tempo.month-day' }, { text: 'Smart Formatting', link: '/doc/tempo.format' }, + { text: 'Layout Patterns', link: '/doc/tempo.layout' } + ] + }, + { + text: 'Extensions & Plugins', + items: [ { text: 'Modularity', link: '/doc/tempo.modularity' }, - { text: 'Layout Patterns', link: '/doc/tempo.layout' }, { text: 'Terms System', link: '/doc/tempo.term' }, - { text: 'Ticker Plugin', link: '/doc/tempo.ticker' } + { text: 'Ticker Plugin', link: '/doc/tempo.ticker' }, + { text: 'License Keys', link: '/doc/tempo.license' } ] }, { diff --git a/packages/tempo/CHANGELOG.md b/packages/tempo/CHANGELOG.md index b133985d..6cf3b2da 100644 --- a/packages/tempo/CHANGELOG.md +++ b/packages/tempo/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.10.0] - 2026-05-11 + +### Added +- **Licensing Architecture**: Implemented a standalone "No-Op" licensing engine (`support.license.ts`) in the public core. This ensures the repository is 100% buildable and testable by the community without private dependencies. +- **Automatic Premium Injection**: Optimized the build pipeline (Rollup/Vitest) to automatically detect and inject the proprietary licensing engine from a side-by-side repository during official builds. +- **Portable Encoding**: Migrated `base64Encode` to the shared library for universal, environment-agnostic token handling. + +### Changed +- **Hardened Licensing Resolution**: Updated the term resolution pipeline with a dual-identity race-condition guard (JTI + Key) and a late-binding resolution guard to securely handle `Pending` to `Revoked` state transitions. +- **Decoupled CI Resolution**: Eliminated the need for private registries or stubs in GitHub Actions by utilizing the internal No-Op engine for standard test runs. +- **Term Collision Enforcement**: Term plugin registration now throws a fatal error on naming collisions (key/scope) to prevent silent configuration failures. + ## [2.9.3] - 2026-05-11 ### Added diff --git a/packages/tempo/README.md b/packages/tempo/README.md index d4160b46..a2b995a6 100644 --- a/packages/tempo/README.md +++ b/packages/tempo/README.md @@ -89,7 +89,7 @@ For granular "Lite" builds, see the [Full Installation Guide](https://magmacompu ## ✨ Why Tempo? * **🏗️ Future Standard**: Built natively on the TC39 `Temporal` proposal. Inherit the reliability of the future standard. -* **🗣️ Natural Language**: Resolve complex terms like `#quarter.last` or "two days ago" with zero configuration. +* **🗣️ Natural Language**: Resolve complex terms like "two days ago" with zero configuration. * **🧠 Functional Aliases**: Extend the parser with custom logic using a powerful resolution context for relative date math. * **🔄 Cycle Persistence**: Shift by semantic terms (Quarters, Seasons) while preserving your relative day-of-period offset. * **⚡ Zero-Cost Parsing**: Lazy evaluation and smart matching ensure instantiation overhead is near-zero. diff --git a/packages/tempo/bin/resolve-types.ts b/packages/tempo/bin/resolve-types.ts index 3682d56d..08bd1fe5 100644 --- a/packages/tempo/bin/resolve-types.ts +++ b/packages/tempo/bin/resolve-types.ts @@ -13,6 +13,9 @@ const DIST_DIR = path.resolve('dist'); const LIB_SRC_DIR = path.resolve('../library/dist/common'); const LIB_DEST_DIR = path.resolve(DIST_DIR, 'lib'); +const LIC_SRC_DIR = path.resolve('../../../tempo-plugin/packages/@core/dist'); +const LIC_DEST_DIR = path.resolve(DIST_DIR, 'lic'); + console.log('Resolving type definitions...'); // 1. Ensure lib directory exists @@ -34,6 +37,25 @@ usedModules.forEach(mod => { } }); +// 4. Copy licensing core types +if (fs.existsSync(LIC_SRC_DIR)) { + if (!fs.existsSync(LIC_DEST_DIR)) fs.mkdirSync(LIC_DEST_DIR, { recursive: true }); + const licFiles = fs.readdirSync(LIC_SRC_DIR).filter(f => f.endsWith('.d.ts')); + licFiles.forEach(file => { + fs.copyFileSync(path.join(LIC_SRC_DIR, file), path.join(LIC_DEST_DIR, file)); + }); +} else { + console.warn(`\n⚠️ WARNING: External license directory not found: ${LIC_SRC_DIR}`); + console.warn(`⚠️ Creating fallback minimal types in ${LIC_DEST_DIR}\n`); + if (!fs.existsSync(LIC_DEST_DIR)) fs.mkdirSync(LIC_DEST_DIR, { recursive: true }); + const fallbackSrc = path.join(DIST_DIR, 'support', 'support.license.d.ts'); + if (fs.existsSync(fallbackSrc)) { + fs.copyFileSync(fallbackSrc, path.join(LIC_DEST_DIR, 'index.d.ts')); + } else { + fs.writeFileSync(path.join(LIC_DEST_DIR, 'index.d.ts'), 'export {};\n'); + } +} + // 4. Walk through all .d.ts files in dist/ to rewrite aliases function walk(dir: string) { const files = fs.readdirSync(dir); @@ -64,6 +86,17 @@ function rewrite(filePath: string) { replacement = `${prefix || './'}lib/`; } + // Handle #tempo/license resolution + let licReplacement: string; + const isInsideLic = relToDist.startsWith('lic'); + if (isInsideLic) { + licReplacement = './'; + } else { + let prefix = ''; + for (let i = 0; i < depth; i++) prefix += '../'; + licReplacement = `${prefix || './'}lic/`; + } + const updatedContent = content .replace(/#library\/([^"')]+\.js)/g, (match, libPath) => { // NOTE: We use path.basename here because the @magmacomputing/library distribution @@ -72,7 +105,8 @@ function rewrite(filePath: string) { const fileName = path.basename(libPath); return `${replacement}${fileName}`; }) - .replace(/#library(['"])/g, (match, quote) => `${replacement}index.js${quote}`); + .replace(/#library(['"])/g, (match, quote) => `${replacement}index.js${quote}`) + .replace(/#tempo\/license(['"])/g, (match, quote) => `${licReplacement}index.js${quote}`); if (content !== updatedContent) { fs.writeFileSync(filePath, updatedContent); diff --git a/packages/tempo/doc/architecture.md b/packages/tempo/doc/architecture.md index 9495c033..7c9f4916 100644 --- a/packages/tempo/doc/architecture.md +++ b/packages/tempo/doc/architecture.md @@ -49,7 +49,7 @@ Tempo employs two distinct methodologies for protecting its internal state. Thes | :--- | :--- | :--- | | **Primary Target** | `Tempo.#term`, `Tempo.#fmt` (Instance State) | `NUMBER`, `FORMAT` (Global Registries) | | **Scope** | **Instance-Specific**: Unique to every separate `new Tempo()` call. | **Global-Shared**: One single source of truth used by all instances. | -| **Primary Goal** | **Performance**: Avoid computing expensive terms (e.g., `qtr` or `szn`) until they are needed, | **Extensibility**: Allow plugins to safely append new data to registries at runtime. | +| **Primary Goal** | **Performance**: Avoid computing expensive Terms (e.g., `qtr` or `szn`) until they are needed, | **Extensibility**: Allow plugins to safely append new data to registries at runtime. | | **Mechanism** | `Object.create(proto)` + Prototype Shadowing. | `new Proxy(target)` + Symbol-bypass. | | **Why this one?** | **Memory Efficiency**: Thousands of instances share the same base prototype. | **Reference Stability**: Shared registries must stay at the same object reference. | @@ -59,10 +59,10 @@ Tempo employs two distinct methodologies for protecting its internal state. Thes Tempo is built with a **"Performance First"** mindset, specifically targeting the overhead of the class constructor. In high-frequency applications (like Tickers or real-time Dashboards), creating thousands of objects must be nearly as cheap as a primitive assignment. This objective is achieved through two primary architectural pillars: -1. **Lazy Evaluation ([Section 1](#1-lazy-evaluation-shadowing))**: Deferring the expensive work of string parsing and term computation until the first property access. +1. **Lazy Evaluation ([Section 1](#1-lazy-evaluation-shadowing))**: Deferring the expensive work of string parsing and Term computation until the first property access. 2. **Master Guard ([Section 3](#3-master-guard-fast-fail-sync-point))**: Implementing a high-speed "fast-fail" gatekeeper to instantly reject invalid inputs when parsing *is* eventually triggered. -Together, these ensure that `new Tempo()` maintains an $O(1)$ constructor execution time by deferring $O(N)$ full-parse work until the first property access, regardless of how many plugins or custom terms are registered in the global system. +Together, these ensure that `new Tempo()` maintains an $O(1)$ constructor execution time by deferring $O(N)$ full-parse work until the first property access, regardless of how many plugins or custom Terms are registered in the global system. --- @@ -94,7 +94,7 @@ The **Instance Shadowing** pattern is designed for massive scale. When a library ### How it works: - **Stage 0**: All instances initially point to the same base `#term` object containing un-evaluated getters. -- **Stage 1**: When a term (e.g., `.qtr`) is accessed, the value is computed once. +- **Stage 1**: When a Term (e.g., `.qtr`) is accessed, the value is computed once. - **Stage 2**: Tempo uses a **Generic Lazy Delegator** Proxy (via `getLazyDelegator`) which catches property access and evaluates it on-demand. - **Result**: The JS engine executes lookups via an optimized Proxy handler, making lookups nearly as fast as raw property access while keeping the state strictly immutable. @@ -162,7 +162,7 @@ Tempo maintains system-wide synchronization through a private, Symbol-based hook ### Reactive Registration When a plugin is imported via a side-effect (`import '@magmacomputing/tempo/ticker'`), it triggers a **`sym.$Register`** hook. - **Auto-Sync**: The `Tempo` class listens for these hooks and automatically updates its internal registries. -- **Guard Rebuild**: Every time a new term or layout is registered, the **Master Guard** is automatically rebuilt to include the new tokens, ensuring the "Zero-Cost Constructor" always stays up to date. +- **Guard Rebuild**: Every time a new Term or layout is registered, the **Master Guard** is automatically rebuilt to include the new tokens, ensuring the "Zero-Cost Constructor" always stays up to date. ### Disposable Engine (`Symbol.dispose`) The `Tempo` class implements the explicit resource management pattern. diff --git a/packages/tempo/doc/commercial.md b/packages/tempo/doc/commercial.md index 70f56d41..539a555e 100644 --- a/packages/tempo/doc/commercial.md +++ b/packages/tempo/doc/commercial.md @@ -23,9 +23,11 @@ For mission-critical applications, we provide priority support, security auditin ## 💎 Premium Extensions -In addition to our open-source core, we offer a suite of **Premium Plugins** that are available via a private NPM registry or commercial license. These extensions provide advanced logic for enterprise-scale requirements. +In addition to our open-source core, we offer a suite of **Premium Plugins** published directly to the standard public NPM registry (`npmjs.com`), secured by a commercial License Key. These extensions provide advanced, proprietary logic for enterprise-scale requirements. -**[Browse the Plugin Marketplace](./tempo.plugin.md)** +More details on browsing the 'Tempo Store' will be provided soon... + +For details on how to unlock and use these features, see our [License Key Guide](./tempo.license.md). --- diff --git a/packages/tempo/doc/comparison.md b/packages/tempo/doc/comparison.md index 85eb48c8..9c8c5776 100644 --- a/packages/tempo/doc/comparison.md +++ b/packages/tempo/doc/comparison.md @@ -8,25 +8,25 @@ If you are choosing a date library today, you are likely looking at **Day.js**, ## At a Glance -| Feature | Tempo 💎 | Day.js / Moment | Luxon | date-fns | -| :--- | :--- | :--- | :--- | :--- | -| **Foundation** | **Native Temporal** | Legacy `Date` | Legacy `Intl` + `Date` | Legacy `Date` | -| **Precision** | **Nanoseconds** | Milliseconds | Milliseconds | Milliseconds | -| **Parsing** | **Human-Centric** | Strict / Plugin | Strict | Modular / Strict | -| **Business Logic** | **Terms System** | Manual Math | Manual Math | Manual Math | -| **Time Zones** | **First-Class** | Plugin-based | Built-in | Separate Lib | -| **Future-Proof** | **100% (Native)** | Deprecated/Legacy | Legacy Bridge | Legacy Bridge | +| Feature | Tempo 💎 | Raw Temporal API | Day.js / Moment | Luxon | date-fns | +| :--- | :--- | :--- | :--- | :--- | :--- | +| **Foundation** | **Native Temporal** | Native Temporal | Legacy `Date` | Legacy `Intl` + `Date` | Legacy `Date` | +| **Precision** | **Nanoseconds** | Nanoseconds | Milliseconds | Milliseconds | Milliseconds | +| **Parsing** | **Human-Centric** | Strict ISO Only | Strict / Plugin | Strict | Modular / Strict | +| **Business Logic** | **Terms System** | Manual Math | Manual Math | Manual Math | Manual Math | +| **Time Zones** | **First-Class** | First-Class | Plugin-based | Built-in | Separate Lib | +| **Future-Proof** | **100% (Native)** | 100% (Native) | Deprecated/Legacy | Legacy Bridge | Legacy Bridge | --- ## 💎 Why Tempo Wins ### 1. The "Terms" Engine (Business Intelligence) -Most libraries stop at "adding 2 days." Tempo introduces the **Terms** system, allowing you to encode domain-specific logic (Fiscal Quarters, Meteorological Seasons, Academic Terms, Zodiac Signs) directly into the tempo `term` object. +Most libraries stop at "adding 2 days." Tempo introduces the **Terms** system, allowing you to encode domain-specific logic (Fiscal Quarters, Meteorological Seasons, Academic terms, Zodiac Signs) directly into the tempo `term` object. > *Competition:* You have to write custom utility functions and import them everywhere. ### 2. Human-Centric Parsing -Day.js and Luxon are quite strict. If your string isn't in exactly the right format, they fail. Tempo’s **Snippet & Layout** engine is designed to be "forgiving" and human-centric, handling relative dates like "next Friday" or "Christmas" out of the box. +Day.js and Luxon are quite strict. If your string isn't in exactly the right format, they fail. Tempo’s **Snippet & Layout** engine is designed to be forgiving, extensible, and human-centric, handling relative dates like `"next Friday"` or `"Christmas"` out of the box. > *Competition:* Often requires an external library like `Chrono` or complex regex boilerplate. ### 3. Nanosecond Precision diff --git a/packages/tempo/doc/lazy-evaluation-pattern.md b/packages/tempo/doc/lazy-evaluation-pattern.md index f09b2aff..36890b5f 100644 --- a/packages/tempo/doc/lazy-evaluation-pattern.md +++ b/packages/tempo/doc/lazy-evaluation-pattern.md @@ -62,6 +62,6 @@ As of **v2.1.2**, Tempo uses a **Proxy-Delegator** that combines the security of 1. **Lazy by Default**: Properties are only evaluated when accessed, keeping the constructor near-instant. 2. **Memoized Evaluation**: Once accessed (e.g., `t.term.quarter`), the result is "baked" into the instance using `Object.defineProperty`. 3. **$O(1)$ Performance**: Every access *after* the first is a direct property lookup—no Proxy traps, no prototype traversal. -4. **Transparent Discovery**: Because properties are enumerable, `console.log(t.term)` or `JSON.stringify` will trigger the evaluation of all registered terms at once, providing a perfect "snapshot" of the instance state. +4. **Transparent Discovery**: Because properties are enumerable, `console.log(t.term)` or `JSON.stringify` will trigger the evaluation of all registered Terms at once, providing a perfect "snapshot" of the instance state. To prevent diagnostic noise during these full-evaluation events, initialize Tempo with **`silent: true`**. diff --git a/packages/tempo/doc/migration-guide.md b/packages/tempo/doc/migration-guide.md index bcabb62e..c90e2121 100644 --- a/packages/tempo/doc/migration-guide.md +++ b/packages/tempo/doc/migration-guide.md @@ -31,8 +31,8 @@ import '@magmacomputing/tempo/ticker'; ## 🗓️ Term Logic Refactor The way Terms (Quarters, Seasons, Zodiacs, etc.) are handled has been unified. -- **v1.x:** Some term properties were ad-hoc on the instance. -- **v2.x:** All term logic is centralized under the `.term` property or accessible via the `#` shorthand in `.set()` and `.add()`. +- **v1.x:** Some Term properties were ad-hoc on the instance. +- **v2.x:** All Term logic is centralized under the `.term` property or accessible via the `#` shorthand in `.set()` and `.add()`. Example of new syntax: ```javascript @@ -88,7 +88,7 @@ As Tempo grows, it has become much more efficient for our developers to logicall ## 🔁 Migrating from version 2.6.0 -Season term scope output has been simplified. +Season Term scope output has been simplified. **Action Required**: 1. If you previously relied on the Chinese-specific object attached to `term.season` scope output, remove that dependency. diff --git a/packages/tempo/doc/releases/v1.x.md b/packages/tempo/doc/releases/v1.x.md index a860c2ad..b58729f1 100644 --- a/packages/tempo/doc/releases/v1.x.md +++ b/packages/tempo/doc/releases/v1.x.md @@ -5,7 +5,7 @@ Browser: persistent storage wrapper, multi‑tap gesture helper, geolocation + maps/address utilities, simple alert/prompt/confirm helpers. Server: sandboxed temp‑file API, HTTP helpers with timeouts, Base64 encode/decode, JWT payload decoder. -Tempo v2.0.0: lazy initialization, unified term math/format tokens (#{...}), anchor/term utilities and faster startup. +Tempo v2.0.0: lazy initialization, unified Term math/format tokens (#{...}), anchor/term utilities and faster startup. ### Documentation Expanded API/type docs, architecture, benchmarks, migration and cookbook guidance. @@ -16,7 +16,7 @@ Package scope renamed to @magmacomputing/*; new build/release scripts and update ## [v1.1.2] - 2026-03-23 ### New Features -Unified plugin system via Tempo.load() for plugins, term plugins, and discovery configuration. +Unified plugin system via Tempo.load() for plugins, Term plugins, and discovery configuration. Made Pledge thenable and awaitable via .then() method support. Enhanced makeTemplate() with safe placeholder substitution instead of code evaluation. ### Bug Fixes @@ -33,7 +33,7 @@ Expanded Node.js documentation with native subpath import details. Plugin-based extension architecture for extending Tempo functionality Automatic plugin discovery via static Tempo.discover() method -New subpath exports for enums, serialisation, Pledge utility, and ticker plugin +New subpath exports for enums, serialisation, Pledge utility, and Ticker plugin ### Changed Ticker functionality now available as optional plugin; requires explicit installation @@ -50,7 +50,7 @@ Dedicated Pledge utility documentation added Introduced Tempo.ticker() — reactive clock streams via async-generator (for await...of) or callback subscription with stop control. ### Documentation -Added a dedicated ticker guide and updated Tempo docs with examples and API reference. +Added a dedicated Ticker guide and updated Tempo docs with examples and API reference. ### Tests Added unit tests covering callback mode, async-iterator mode and input validation. diff --git a/packages/tempo/doc/releases/v2.x.md b/packages/tempo/doc/releases/v2.x.md index c2a7d270..b39b6e98 100644 --- a/packages/tempo/doc/releases/v2.x.md +++ b/packages/tempo/doc/releases/v2.x.md @@ -1,5 +1,22 @@ # 📜 Version 2.x History +## [v2.10.0] = 2026-05-20 +### New Features + +- Added licensing system with JWT validation and revocation checks +- Introduced Tempo.license public API for license state management +- Enhanced Terms display with license metadata support +- Term registration now enforces naming collision detection + +### Bug Fixes + +- Fixed parsing side-effects and state leakage issues +- Improved epoch timestamp precision with nanosecond-level fractional resolution for 9–10 digit timestamps + +### Documentation +- Comprehensive licensing architecture and strategy documentation added. +- Added guidance for CI-safe licensing stubs and cross-repo dependency management. + ## [v2.9.3] - 2026-05-10 ### 🏗️ Engine Stabilization & Hardening - **Timestamp Resolution Fix**: Corrected configuration propagation for `timeStamp` settings, ensuring consistent persistence across nested Tempo instances. @@ -44,7 +61,7 @@ ### ⚙️ Parser & Registry Refinement - **Consolidated Host Context**: Modularized the construction of the functional alias "pseudo-Tempo" context, improving separation of concerns in the parsing pipeline. -- **Legacy Decoupling**: Successfully decoupled term-based alias registration from internal raw objects, moving toward a more encapsulated and secure registry design. +- **Legacy Decoupling**: Successfully decoupled Term-based alias registration from internal raw objects, moving toward a more encapsulated and secure registry design. ### 📚 Documentation Fixes - **VitePress 404 Patch**: Corrected root directory resolution to fix "404 Not Found" errors on the landing page. @@ -166,7 +183,7 @@ Added v2.6.0 migration guide for season changes. ## [v2.2.5] - 2026-04-20 ### 🏗️ Modular Hardening - **Singleton Resilience**: Replaced `instanceof` checks in `TempoRuntime` with a cross-bundle brand check, ensuring singletons are correctly adopted across bundle boundaries and HMR reloads. -- **Unified Discovery**: Consolidated internal storage for term and extension plugins into a single, validated `pluginsDb` structure. +- **Unified Discovery**: Consolidated internal storage for Term and extension plugins into a single, validated `pluginsDb` structure. - **Resolved Shadowing**: Eliminated parameter shadowing in runtime hook methods to ensure reliable event emission. ### 🔍 Term Resolution Refinements @@ -276,7 +293,7 @@ Terms (like Quarters and Seasons) are now fully integrated: - Use `{#term}` in `format()` to embed semantic labels (e.g. "Second Quarter") directly into strings (e.g., `t.format('Today is {yyyy}-{mm}-{dd} in the {#quarter}')`. ### ➗ Relational Term Math -A category-first feature. Shift dates by semantic "steps" with `.add({ '#quarter': 1 })`. Tempo preserves your relative duration within the term, jumping across gaps and handling overflows with mathematical precision. +A category-first feature. Shift dates by semantic "steps" with `.add({ '#quarter': 1 })`. Tempo preserves your relative duration within the Term, jumping across gaps and handling overflows with mathematical precision. ### 🔗 Fluent Immutable Boundaries Term ranges now return fully functional, frozen `Tempo` instances for `start` and `end`. This allows for seamless chaining: diff --git a/packages/tempo/doc/releases/v3.x.md b/packages/tempo/doc/releases/v3.x.md index 98413ac1..962c369a 100644 --- a/packages/tempo/doc/releases/v3.x.md +++ b/packages/tempo/doc/releases/v3.x.md @@ -2,7 +2,7 @@ ## [v3.0.0] - (Planned) ### 🚨 Major Breaking Changes -- **Term Registry Consolidation**: Removed the legacy and deprecated `term` property from the `Discovery` configuration object. All term-based plugins must now be registered via the `terms` (plural) array. +- **Term Registry Consolidation**: Removed the legacy and deprecated `term` property from the `Discovery` configuration object. All Term-based plugins must now be registered via the `terms` (plural) array. - **Shorthand Configuration Removal**: Removed support for shorthand root-level properties in the `Discovery` object that have been superseded by nested configuration groups: - `relativeTime` shorthand has been removed; use `intl.relativeTime` instead. - `term` shorthand has been removed; use `terms` instead. diff --git a/packages/tempo/doc/tempo-vs-temporal.md b/packages/tempo/doc/tempo-vs-temporal.md index aa9b516b..8996467e 100644 --- a/packages/tempo/doc/tempo-vs-temporal.md +++ b/packages/tempo/doc/tempo-vs-temporal.md @@ -6,7 +6,7 @@ To enhance (not replace) Temporal's strictness, Tempo adds: * flexibility (through its parsing engine and output formatting), * convenience (through its many getters and methods), * configurability (through its dynamic aliases (events, periods)), -* business logic (through its lazy-loaded plugin system (terms)) +* business logic (through its lazy-loaded plugin system (Terms)) Here is a side-by-side comparison of how you achieve the same outcomes, as well as things Tempo can do that native Temporal cannot easily. @@ -49,39 +49,60 @@ t.fmt.date; // Output: "2026-01-24" ### 3. Business Logic & Complex Terms -Native Temporal deals with standard calendar units (days, months, years). Tempo extends this with business-aware concepts, relative querying, and rich getters. +Native Temporal deals strictly with standard calendar units (days, months, years). If you need to map a date to domain-specific business logic (like a fiscal quarter or a meteorological season), you have to write and maintain your own math utilities. **Native Temporal 🐢** ```javascript const date = Temporal.Now.plainDateISO(); -// To find if it's a weekend, you need: -const isWeekend = date.dayOfWeek === 6 || date.dayOfWeek === 7; -// To find the fiscal/calendar quarter... write your own math logic +// To find the fiscal/calendar quarter... +const month = date.month; +const fiscalQuarter = `Q${Math.ceil(month / 3)}`; // Manual math + +// What if your fiscal year starts in July? Or you need meteorological seasons? +// Write more complex utility functions and import them everywhere. ``` **Tempo 🚀** -This is a perfect example of where Tempo adds business logic (something that Temporal does not do). -To add a 'term' that defines 'isWeekend' to Tempo, you would write a plugin that defines the term. -From that point, the plugin is available to new Tempo instances. - -See the section on [plugin](tempo.term.md) for more information. +Tempo solves this elegantly using the **Terms** plugin system. Terms are lazy-loaded plugins that evaluate the current date against semantic boundaries without adding memory bloat. -```typescript +```javascript const t = new Tempo(); -const isWeekend = t.term.isWeekend; // through plugin -// Built-in complex terms via plugin -t.term.qtr; // returns calculated 'fiscal quarter' based on current instance (date and hemisphere) e.g., 'Q1' -t.term.szn; // returns calculated 'meteorological season' based on current instance (date and hemisphere) e.g., 'Summer' +// Built-in complex Terms via the standard plugin +t.term.qtr; // → 'Q1' (Calculates fiscal quarter) +t.term.szn; // → 'Summer' (Calculates meteorological season, respecting hemisphere) +``` + +For more information on adding your own business logic, see the [Terms Guide](tempo.term.md). + +### 4. Relative Time & Duration Strings + +Calculating the difference between two dates in native Temporal is mathematically sound, but it strictly returns a `Temporal.Duration` object. Tempo gives you the flexibility to return a `Duration` object, a precise floating-point number, or a human-readable string. + +**Native Temporal 🐢** +```javascript +const now = Temporal.Now.plainDateTimeISO(); +const target = Temporal.PlainDateTime.from('2026-12-25T00:00:00'); +const duration = now.until(target); // Returns a complex Duration object +``` + +**Tempo 🚀** +Tempo understands natural language targets and can format the resulting difference flexibly. `t.until()` and `t.since()` have distinct return types: + +```javascript +const t = new Tempo(); -// Time since/until (native Temporal only returns Duration objects, not strings) +// t.until(target, unit) → number (precise floating-point) +t.until('afternoon', 'minutes'); // → 302.57749424408334 +t.until('xmas', 'days'); // → 289 -t.until('3pm','minutes'); // 5.046264992345 +// t.until(target) → Tempo.Duration object (with .iso, .years, .days, … fields) +t.until('xmas'); // → { iso: "P289DT14H22M9.102S", years: 0, months: 9, days: 14, ... } -t.until('xmas', 'days'); // "289.58470466349036" -t.until('xmas'); // if no 'unit' provided, then duration object "{years:0, months:9, ... }" +// t.since(target, unit) → human-readable string via Intl.RelativeTimeFormat +t.since('yesterday', 'days'); // → "1d ago" -t.since('yesterday', 'days'); // unit-argument determines granularity "1d ago" -t.since('yesterday afternoon'); // if no 'unit' provided, then duration string "-P1DT9H32M19.402536059S" +// t.since(target) → ISO 8601 Duration string +t.since('yesterday afternoon'); // → "-P1DT9H32M19.402S" ``` \ No newline at end of file diff --git a/packages/tempo/doc/tempo.benchmarks.md b/packages/tempo/doc/tempo.benchmarks.md index 03087e07..9361ca10 100644 --- a/packages/tempo/doc/tempo.benchmarks.md +++ b/packages/tempo/doc/tempo.benchmarks.md @@ -19,7 +19,7 @@ Timings were captured over **1,000 iterations** to measure micro-overhead and co ### 1. Proxy-Delegator Delegation ($O(1)$) -By using a **Proxy-Delegator** pattern, the constructor returns near-instantly without populating the formatting (`fmt`) or term (`term`) objects. These registries are only discovered and memoized on the first property access. +By using a **Proxy-Delegator** pattern, the constructor returns near-instantly without populating the formatting (`fmt`) or Term (`term`) objects. These registries are only discovered and memoized on the first property access. - **Gain**: ~65% reduction in instantiation overhead. - **v2.1.2 Update**: The Scan-and-Consume guard further stabilizes the "Zero-Cost Constructor" by ensuring that even with massive plugin lists, the entry-point remains $O(1)$. diff --git a/packages/tempo/doc/tempo.config.md b/packages/tempo/doc/tempo.config.md index 46695b82..910f3fc9 100644 --- a/packages/tempo/doc/tempo.config.md +++ b/packages/tempo/doc/tempo.config.md @@ -98,7 +98,7 @@ Tempo looks for the following structure: | :--- | :--- | :--- | | `options` | `Options \| (() => Options)` | Configuration options merged into global state. | | `plugins` | `Plugin \| Plugin[]` | Modular plugin(s) to be extended onto Tempo automatically. | -| `terms` | `TermPlugin \| TermPlugin[]` | Custom term plugin to be registered. | +| `terms` | `TermPlugin \| TermPlugin[]` | Custom Term plugin to be registered. | | `timeZones` | `Record` | Custom timezone aliases to be merged. | | `numbers` | `Record` | Custom number-word aliases merged into the NUMBER registry. | | `formats` | `Record` | Custom format strings to be merged into `Tempo.FORMAT`. | @@ -197,7 +197,7 @@ const delivery = new Tempo('deadline'); // Parsed using your custom logic, adds ### ⚡ 5.2 Deferring Initialization (`mode: 'defer'`) -By default (`mode: 'auto'`), Tempo uses the **Master Guard** to determine if a string can be lazily evaluated. For exceptionally high-volume scenarios where you may be creating thousands of Tempo instances but only using them for calculations (not formats or terms), you can force a standard lazy behavior using `mode: 'defer'`. +By default (`mode: 'auto'`), Tempo uses the **Master Guard** to determine if a string can be lazily evaluated. For exceptionally high-volume scenarios where you may be creating thousands of Tempo instances but only using them for calculations (not formats or Terms), you can force a standard lazy behavior using `mode: 'defer'`. When `mode: 'defer'` is set, the registry-discovery logic is deferred until the first time you access a property on `t.fmt` or `t.term`. diff --git a/packages/tempo/doc/tempo.cookbook.md b/packages/tempo/doc/tempo.cookbook.md index c6887122..d2fc7250 100644 --- a/packages/tempo/doc/tempo.cookbook.md +++ b/packages/tempo/doc/tempo.cookbook.md @@ -132,7 +132,7 @@ console.log(`${daysLeft} days remaining`); ``` ### Precision Manipulation (`end` vs `mid`) -When using `.set()` with a term anchor (like `#qtr`), you can specify whether to land on the inclusive end or the exact center. +When using `.set()` with a Term anchor (like `#qtr`), you can specify whether to land on the inclusive end or the exact center. ```typescript // Lands on 30-Sep 23:59:59.999... (Inclusive End) const qtrEnd = new Tempo().set({ end: '#qtr' }); @@ -205,14 +205,14 @@ console.log(new Tempo({ timeZone: 'Australia/Sydney' }).term.szn); // "Winter" ``` ### Unified Term Math -Tempo allows you to shift dates by semantic "steps" while preserving your relative position within the term. +Tempo allows you to shift dates by semantic "steps" while preserving your relative position within the Term. ```typescript const t1 = new Tempo('2024-05-15'); // Middle of Q2 const t2 = t1.add({ '#quarter': 1 }); // Middle of Q3: "2024-08-14" (approx) ``` ### Semantic Formatting -Use specific term tokens like `{#quarter}` or `{#season}` to automatically embed a Term's label (or key) into a format string. +Use specific Term tokens like `{#quarter}` or `{#season}` to automatically embed a Term's label (or key) into a format string. ```typescript const t = new Tempo(); console.log(t.format('We are currently in the {#quarter}')); // "We are currently in the First Quarter" @@ -225,7 +225,7 @@ The examples below use the `using` and `await using` syntax, which require **Typ ::: ### Subscription Billing (Recurring Payments) -Use a `seed` to anchor your subscription to a specific day, then use a month-based ticker. +Use a `seed` to anchor your subscription to a specific day, then use a month-based Ticker. ```typescript // Anchor to the 15th of the month @@ -268,7 +268,7 @@ using dailyTicker = Tempo.ticker({ '#period': 'morning' }, (t) => { ``` ### Manual Sync (Action-Triggered) -Sometimes you want a ticker's logic but need to trigger it from an external event. +Sometimes you want a Ticker's logic but need to trigger it from an external event. ```typescript const heartbeat = Tempo.ticker({ seconds: 5 }); diff --git a/packages/tempo/doc/tempo.debugging.md b/packages/tempo/doc/tempo.debugging.md index 86d2429c..7d1f4c0f 100644 --- a/packages/tempo/doc/tempo.debugging.md +++ b/packages/tempo/doc/tempo.debugging.md @@ -17,7 +17,7 @@ Returns the collection of current *global* configuration settings that act as th Returns the collection of *initial*, out-of-the-box defaults that `Tempo` ships with, unaffected by any modifications made via [Global Discovery](../README.md#global-discovery) or [`Tempo.init()`](./tempo.config.md). ### `Tempo.terms` -Returns an array of all currently registered term plugins. This is useful to verify which plugins have been loaded via [`Tempo.extend()`](./tempo.plugin.md). +Returns an array of all currently registered Term plugins. This is useful to verify which plugins have been loaded via [`Tempo.extend()`](./tempo.plugin.md). ### `Tempo.properties` Returns an array of the available static getters on the `Tempo` class. @@ -45,10 +45,10 @@ Because `Tempo` is chainable (e.g., `new Tempo('xmas').set({ period: 'afternoon' * `anchor`: The **active reference point** used for this specific match. This provides a "breadcrumb" trail during complex parses where the anchor might shift as components are resolved. ### `this.parse.anchor` -Returns the **initial reference point** used for the current parsing operation. This is the baseline "Now" against which relative terms (like `next Monday` or `ago`) are calculated. +Returns the **initial reference point** used for the current parsing operation. This is the baseline "Now" against which relative Terms (like `next Monday` or `ago`) are calculated. ### `this.term` -Returns a collection containing the evaluated results of all registered term plugins for this specific instance. +Returns a collection containing the evaluated results of all registered Term plugins for this specific instance. ### `this.fmt` Returns a collection containing the pre-calculated string outputs for all currently registered formatting codes. diff --git a/packages/tempo/doc/tempo.license.md b/packages/tempo/doc/tempo.license.md new file mode 100644 index 00000000..e52df346 --- /dev/null +++ b/packages/tempo/doc/tempo.license.md @@ -0,0 +1,99 @@ +# 🔑 License Keys + +To support the ongoing development of the open-source core, Magma Computing provides specialized, proprietary plugins known as **Premium Extensions**. + +Unlike typical commercial software that requires complex authentication with private registries, we publish all our packages (including Premium Extensions) directly to the standard public NPM registry (`npmjs.com`). However, access to the advanced capabilities within these premium packages is protected by a cryptographically secure **License Key**. + +## 🌟 Free Showcase: Astronomical Seasons Plugin + +To demonstrate the power of the Terms engine and the seamless License Key integration, we offer our **Astronomical Seasons** premium plugin completely free of charge. + +This extension calculates the exact astronomical season (Equinoxes and Solstices) for any date using the **Jean Meeus polynomial algorithm**. Because it is a true astronomical calculation rather than a fixed calendar date, it precisely determines the exact minute the sun crosses the celestial equator. It is also **hemisphere-aware**: by configuring your Tempo instance with a `sphere` (e.g., `sphere: 'south'`), the plugin accurately flips the Vernal Equinox from Spring to Autumn. + +::: info Meteorological vs Astronomical +Unlike Tempo's built-in **Meteorological** `season` Term — which rigidly snaps to the 1st day of calendar months — this **Astronomical** plugin calculates the dynamic, true solar boundaries that shift slightly year-over-year. +::: + +It introduces the `astro` Term, giving you access to both a short identifier (`t.term.astro`) and a rich metadata object (`t.term.astronomy`): + +::: tip Prerequisites +The following preview assumes that `Tempo` has been initialized with a valid license and the Astro plugin has been successfully registered. See **Applying Your License Key** below for full setup instructions. +::: + +```typescript +const t = new Tempo('2026-04-10', { sphere: 'north' }); +console.log(t.term.astronomy); +``` + +```json +{ + "key": "Vernal", + "group": "astronomy", + "year": 2026, + "month": 3, + "day": 20, + "hour": 14, + "minute": 45, + "second": 0 + // ... including sub-second precision fields +} +``` + +**How to get it:** +1. Run `npm install @magmacomputing/tempo-plugin-astro` in your project. +2. Send us an email at [contact@magmacomputing.com.au](mailto:contact@magmacomputing.com.au) with your preferred email address, and we will issue a **one-year expiry key** straight to your inbox. + +## ⚙️ Applying Your License Key + +Once you receive your License Key, you must provide it to your Tempo-enabled codebase so the engine can verify and unlock the premium features. + +There are two supported ways to provide your key: + +### 1. Environment Variable (Recommended for Node/SSR) +The easiest method for backend or server-side rendered environments is to expose the key via an environment variable. Tempo will automatically detect it during initialization. + +```bash +# Set this in your deployment environment or .env file +export TEMPO_LICENSE_KEY="key..." +``` + +### 2. Programmatic Initialization (Recommended for Browsers) +If you are running Tempo in a client-side browser environment or prefer explicit configuration, you can pass the key directly into the `Tempo.init()` method before instantiating any dates or registering the premium plugins. + +```typescript +import { Tempo } from '@magmacomputing/tempo/core'; +import { AstroTerm } from '@magmacomputing/tempo-plugin-astro'; + +// 1. Initialize the core engine with your license key +Tempo.init({ + license: 'key...' +}); + +// 2. Extend Tempo with the premium plugin +Tempo.extend(AstroTerm); + +// 3. The premium Term is unlocked and ready to use! +const t = new Tempo('21-Mar-2026'); + +console.log(t.term.astro); +// → 'Spring' + +console.log(t.term.astronomy); +// → { key: 'Spring', year: 2026, month: 3, day: 20, hour: 14, minute: 45, ... } +``` + +::: tip ESM Hoisting & Registration Order +In standard JavaScript (ESM) environments, `import` statements are hoisted and executed before any regular code. + +Because of this, the plugin's automatic self-registration runs *before* your synchronous `Tempo.init({ license: '...' })` call. Since `Tempo.init()` resets the active registry, you **must explicitly call `Tempo.extend(AstroTerm)` after initialization** (as shown in Step 2 above) to re-register the plugin into the licensed registry. + +Alternatively, you can initialize Tempo in a separate entry/bootstrap file (e.g., `bootstrap.ts`) before loading the rest of your application. +::: + +## 🤝 Commercialize Your Own Plugin + +Are you a developer who has built an incredibly useful, domain-specific Tempo plugin (e.g., medical billing cycles, legal discovery windows, complex religious calendars)? + +If you would like to monetize your logic without having to build your own licensing infrastructure, **we want to partner with you**. + +Get in touch with us with your proposed code and use-case. If it meets our quality and performance standards, we can publish it as an official Premium Extension secured behind the Tempo License Key system, under a mutually beneficial commercial revenue-sharing arrangement. diff --git a/packages/tempo/doc/tempo.modularity.md b/packages/tempo/doc/tempo.modularity.md index 58a0a31c..2e73b209 100644 --- a/packages/tempo/doc/tempo.modularity.md +++ b/packages/tempo/doc/tempo.modularity.md @@ -52,10 +52,10 @@ Handles string parsing and token extraction. This is included automatically in t Adds support for reactive time-pulsing via the static `Tempo.ticker()` method. ### Terms Module (@magmacomputing/tempo/term) -Adds support for semantic terms like `quarter`, `season`, `zodiac`, and `period`. There are three ways to enable terms: +Adds support for semantic Terms like `quarter`, `season`, `zodiac`, and `period`. There are three ways to enable Terms: #### 1. The Side-Effect (Standard Activation) -Fastest way to enable all standard terms in a Core environment. +Fastest way to enable all standard Terms in a Core environment. ```typescript import '@magmacomputing/tempo/term'; // One-line activation ``` @@ -106,7 +106,7 @@ There is a subtle but important distinction between how features are activated i * **`Tempo.init()`**: This is **Discovery-Driven**. It scans the global environment for any plugins that were imported via side effects (e.g., `import '@magmacomputing/tempo/ticker'`) and hydrates the engine all at once. ::: danger -**The Initialization Lifecycle**: `Tempo.init()` performs a **full state refresh**. It resets configuration, term registries, and formatting maps to defaults before re-applying all currently discovered plugins. To ensure your custom logic is managed correctly, always use `Tempo.extend()` or encapsulate changes within a formal plugin. +**The Initialization Lifecycle**: `Tempo.init()` performs a **full state refresh**. It resets configuration, Term registries, and formatting maps to defaults before re-applying all currently discovered plugins. To ensure your custom logic is managed correctly, always use `Tempo.extend()` or encapsulate changes within a formal plugin. ::: **The Side-Effect Trap**: If you import a side-effect plugin *after* you have already called `Tempo.init()`, the feature will **not** automatically appear on the `Tempo` class. Because `Tempo.init()` short-circuits once state already exists, re-calling it will not load those late modules. Use `Tempo.extend()` explicitly to activate late-loaded modules instead of trying to re-run `Tempo.init()`. diff --git a/packages/tempo/doc/tempo.parse.md b/packages/tempo/doc/tempo.parse.md index b47bb4c1..c5385447 100644 --- a/packages/tempo/doc/tempo.parse.md +++ b/packages/tempo/doc/tempo.parse.md @@ -21,7 +21,7 @@ console.log(zdt.toString()); // 2026-04-28T15:00:00+10:00[Australia/Sydney] * **Strict by Default**: The standalone function defaults to `mode: 'strict'`, ensuring that it won't "guess" if the input is ambiguous. ::: warning -**Terms and Standalone Parsing**: Standalone `parse()` supports all standard natural language patterns but does not resolve **Global Terms** or aliases unless they are part of the core pattern registry. For full term-dispatch and instance-aware resolution, use the `Tempo` class. +**Terms and Standalone Parsing**: Standalone `parse()` supports all standard natural language patterns but does not resolve **Global Terms** or aliases unless they are part of the core pattern registry. For full Term-dispatch and instance-aware resolution, use the `Tempo` class. ::: ### ⚠️ Standalone vs. Class-Based diff --git a/packages/tempo/doc/tempo.pledge.md b/packages/tempo/doc/tempo.pledge.md index 09837956..cf805af4 100644 --- a/packages/tempo/doc/tempo.pledge.md +++ b/packages/tempo/doc/tempo.pledge.md @@ -20,7 +20,7 @@ p.resolve('Success!'); const result = await p.promise; // Note: resolve/reject are idempotent. Calling them on an already-settled -// pledge is safe; it will log a warning but won't change the state. +// `Pledge` is safe; it will log a warning but won't change the state. ``` ## 2. Then-ability diff --git a/packages/tempo/doc/tempo.plugin.md b/packages/tempo/doc/tempo.plugin.md index 51b3d132..da27d7e5 100644 --- a/packages/tempo/doc/tempo.plugin.md +++ b/packages/tempo/doc/tempo.plugin.md @@ -1,6 +1,6 @@ # Extending Tempo with Plugin -Tempo is designed with a "lean core" philosophy. Whilst it provides robust date-time manipulation and parsing out of the box, advanced functionality (like reactive tickers or domain-specific business logic) is added through a flexible **Plugin System**. +Tempo is designed with a "lean core" philosophy. Whilst it provides robust date-time manipulation and parsing out of the box, advanced functionality (like reactive Tickers or domain-specific business logic) is added through a flexible **Plugin System**. To manually register a plugin, use the static `extend` method. This is typically used for "opt-in" features or when you need to provide specific configuration to a plugin factory. @@ -99,9 +99,8 @@ Tempo.init(); // 3. Discover and activat const pulse = Tempo.ticker(1); ``` -::: info -**Import Order**: While older versions of Tempo were sensitive to import order, current versions handle sequencing robustly. `Tempo.init()` is automatically called during bootstrap to ensure all discovered plugin are integrated. If you dynamically load plugin later, you can call `Tempo.init()` manually to refresh the registry. -::: +> [!NOTE] Import Order +> While older versions of Tempo were sensitive to import order, current versions handle sequencing robustly. `Tempo.init()` is automatically called during bootstrap to ensure all discovered plugin are integrated. If you dynamically load plugin later, you can call `Tempo.init()` manually to refresh the registry. --- @@ -153,10 +152,10 @@ This pattern ensures that Tempo remains robust in production environments while ### 6. Term Key/Scope Collisions If your plugin registers a **Term** (`key` / optional `scope`), keep both identifiers globally unique. -- Avoid reusing an existing term `key` (e.g., another plugin already uses `qtr`). +- Avoid reusing an existing Term `key` (e.g., another plugin already uses `qtr`). - Avoid reusing an existing `scope` alias (e.g., another plugin already uses `quarter`). -Current behavior is not ideal for collisions: duplicate term keys are ignored, while scope alias resolution is order-dependent and can shadow another term. Treat collisions as unsupported and choose unique names to ensure deterministic behavior. +Current behavior is not ideal for collisions: duplicate Term keys are ignored, while scope alias resolution is order-dependent and can shadow another Term. Treat collisions as unsupported and choose unique names to ensure deterministic behavior. ## Advanced Pattern: Stateful Classes & Callable Proxies @@ -249,6 +248,21 @@ export const MyFeatureModule = defineModule((TempoClass, options) => { }); ``` +### Commercial & Premium Plugins +If you are distributing a commercial plugin that requires a valid Tempo license to run, use the **`definePremiumPlugin`** wrapper. This automatically injects licensing validation into the plugin's `install` lifecycle, guaranteeing that the plugin will only execute if the user has provided a valid, active license key via `Tempo.init()` that grants the requested scope. + +```typescript +// index.ts +import { defineModule, definePremiumPlugin } from '@magmacomputing/tempo/plugin'; + +const CoreModule = defineModule((TempoClass, options) => { + TempoClass.prototype.myPremiumMethod = function() { ... } +}); + +// Wrap the module and specify the required license scope key +export const MyPremiumModule = definePremiumPlugin('my_premium_scope', CoreModule); +``` + --- ## Consuming a Plugin diff --git a/packages/tempo/doc/tempo.shorthand.md b/packages/tempo/doc/tempo.shorthand.md index 5e61a73b..de406d7c 100644 --- a/packages/tempo/doc/tempo.shorthand.md +++ b/packages/tempo/doc/tempo.shorthand.md @@ -32,7 +32,7 @@ t.set({ '#qtr': 2 }); // Aligns to the start of the 2nd quarter of the current y ### C. Structural Mode (Key Shorthand) **Used in:** `.set()`. **Pattern:** `{ start: '#namespace', end: '#namespace' }` -**Best for:** Snapping a date to the precise boundaries of its current term. +**Best for:** Snapping a date to the precise boundaries of its current Term. ```javascript t.set({ start: '#qtr' }); // Snaps to the exact start of the current quarter @@ -49,11 +49,11 @@ Modifiers control the direction and inclusivity of the search. | :--- | :--- | :--- | | `>` | **Forward (Exclusive)** | Finds the next boundary strictly *after* the current time. | | `<` | **Backward (Exclusive)** | Finds the previous boundary strictly *before* the current time. | -| `>=` | **Forward (Inclusive)** | Returns the current term if it contains the cursor; otherwise, the next. | -| `<=` | **Backward (Inclusive)** | Returns the current term if it contains the cursor; otherwise, the previous. | +| `>=` | **Forward (Inclusive)** | Returns the current Term if it contains the cursor; otherwise, the next. | +| `<=` | **Backward (Inclusive)** | Returns the current Term if it contains the cursor; otherwise, the previous. | | `+` | **Relative Future** | Alias for `>`. | | `-` | **Relative Past** | Alias for `<`. | -| `this` | **Identity** | Resolves the term currently containing the cursor. | +| `this` | **Identity** | Resolves the Term currently containing the cursor. | --- @@ -71,14 +71,14 @@ When you use a shifter like `>q1`, Tempo uses **Chronological Momentum**. It ign ## 4. The "Cycle Preservation" Guarantee -One of Tempo's premium features is its ability to maintain your **relative offset** when shifting across terms. +One of Tempo's premium features is its ability to maintain your **relative offset** when shifting across Terms. If you are 45% of the way through a **Morning** period and you call `t.add({ '#period': 1 })`, Tempo doesn't just add a fixed number of hours. It: 1. Determines your relative percentage/offset within the current Morning. 2. Finds the boundaries of the *next* registered period (e.g., Afternoon). 3. Calculates the same 45% point within that new period. -This ensures that "shifting by a quarter" or "shifting by a period" feels mathematically correct even when those terms have different durations. +This ensures that "shifting by a quarter" or "shifting by a period" feels mathematically correct even when those Terms have different durations. --- @@ -102,6 +102,6 @@ The [Range-Keys](#5-development-constraints) rule does not reserve `-` even thou ## 6. Best Practices -- **Explicit Spheres**: Always set `sphere: 'north'` or `'south'` in your config if using seasonal terms. +- **Explicit Spheres**: Always set `sphere: 'north'` or `'south'` in your config if using seasonal Terms. - **Method Intent**: Use **String shorthand** for "Jumping" to boundaries and **Object shorthand** for "Shifting" relative to your current time. - **Fail-Safe**: Use `catch: true` in your global config to allow shorthand resolution to fail silently (returning a `void` instance) instead of throwing. diff --git a/packages/tempo/doc/tempo.term.md b/packages/tempo/doc/tempo.term.md index 495f2b7c..a0385a75 100644 --- a/packages/tempo/doc/tempo.term.md +++ b/packages/tempo/doc/tempo.term.md @@ -12,12 +12,12 @@ new Tempo('25-Dec-2024').term.season // ← computed on first access, cached ``` ::: tip -**Transparent Discovery**: As of **v2.0.1**, all term properties are **enumerable**. Whilst modern `console.log` environments (like Node.js) will typically display these as `[Getter]` to preserve laziness, they *are* visible to property-scanning tools. This means a serializer (like `JSON.stringify`) or a deep-clone utility **will** trigger the eager evaluation of *every* registered term at once. To prevent terminal noise during these events (e.g., for invalid dates), initialize Tempo with **`silent: true`**. +**Transparent Discovery**: As of **v2.0.1**, all Term properties are **enumerable**. Whilst modern `console.log` environments (like Node.js) will typically display these as `[Getter]` to preserve laziness, they *are* visible to property-scanning tools. This means a serializer (like `JSON.stringify`) or a deep-clone utility **will** trigger the eager evaluation of *every* registered Term at once. To prevent terminal noise during these events (e.g., for invalid dates), initialize Tempo with **`silent: true`**. ::: ## What a Term Does -A term plugin answers a single question: +A Term plugin answers a single question: > *"Where does this `Tempo` instance sit within a pre-defined date-time range?"* @@ -33,6 +33,10 @@ The `` and `` are defined by the plugin author, where the intent of ## Provided Plugin +::: info +The examples given below for Fiscal Quarters and Meteorological Seasons assume a Northern Hemisphere configuration (sphere: 'north'), unless they explicitly state otherwise. +::: + ### `qtr` / `quarter` — Fiscal Quarters Divides the calendar year into four fiscal quarters. @@ -57,11 +61,11 @@ Maps the current date to the appropriate meteorological season. Hemisphere-aware (northern / southern boundaries differ). ```ts -const t = new Tempo('01-Jul-2025', { sphere: 'south' }); +const t = new Tempo('01-Jul-2025'); -t.term.szn // → 'Winter' (southern hemisphere) +t.term.szn // → 'Summer' (northern hemisphere) t.term.season -// → { key: 'Winter', day: 1, month: 6, symbol: 'Snowflake', sphere: 'south' } +// → { key: 'Summer', day: 1, month: 6, symbol: 'Sun', sphere: 'north' } ``` ```ts @@ -124,10 +128,10 @@ Tempo.terms ## Activating Terms -In **Tempo Full**, all standard terms are enabled by default. In **Tempo Core**, you have three ways to opt-in: +In **Tempo Full**, all standard Terms are enabled by default. In **Tempo Core**, you have three ways to opt-in: ### 1. Standard Activation (Recommended) -The fastest way to enable all built-in terms (`qtr`, `szn`, `zdc`, `per`). +The fastest way to enable all built-in Terms (`qtr`, `szn`, `zdc`, `per`). ```typescript import '@magmacomputing/tempo/term'; // One-line side-effect activation ``` @@ -142,7 +146,7 @@ Tempo.extend(TermsModule); ``` ### 3. Surgical Opt-in (Maximum Lite) -Best for maximum bundle-size optimization—you only load the specific terms you use. +Best for maximum bundle-size optimization—you only load the specific Terms you use. ```typescript import { Tempo } from '@magmacomputing/tempo/core'; import { QuarterTerm } from '@magmacomputing/tempo/term/quarter'; @@ -152,7 +156,9 @@ Tempo.extend(QuarterTerm); ## How to Define a Term Plugin -A term plugin is ideally created using the **`defineTerm`** factory function provided by the library. This ensures correct type-inference and automatically handles registration during the discovery phase. +A Term plugin is ideally created using the **`defineTerm`** factory function provided by the library. This ensures correct type-inference and automatically handles registration during the discovery phase. + +For commercial plugins that require a valid license to execute, use the **`definePremiumTerm`** factory instead. This wrapper automatically intercepts property evaluations and validates the `license` state in the global Tempo registry, securely guarding your plugin's functionality. ### Plugin Definition @@ -212,12 +218,12 @@ A `Range` object must include a `key` and any subset of the date-time fields bel `getTermRange` sorts ranges in descending chronological order and returns the **first range whose boundary the instance has reached or passed**. ### 🔄 Sync to Alias Engine -When a term plugin defines `ranges` with string-based `key` values, Tempo automatically synchronizes these keys with the internal **Alias Engine**. +When a Term plugin defines `ranges` with string-based `key` values, Tempo automatically synchronizes these keys with the internal **Alias Engine**. * **Period Scopes**: Ranges defined in a `period` scope (like `midnight` or `morning`) are registered as **Period Aliases**. * **Event Scopes**: Ranges defined in an `event` scope are registered as **Event Aliases**. -This synchronization happens during `Tempo.extend()` and `Tempo.init()`, ensuring that any named range boundaries are immediately available for use in the natural-language parsing engine. For example, if you define a custom term with a range key `"bedtime"`, you can immediately create a new instance using `new Tempo('bedtime')`. +This synchronization happens during `Tempo.extend()` and `Tempo.init()`, ensuring that any named range boundaries are immediately available for use in the natural-language parsing engine. For example, if you define a custom Term with a range key `"bedtime"`, you can immediately create a new instance using `new Tempo('bedtime')`. ```ts type Range = { @@ -235,7 +241,7 @@ type Range = { ### Registering the plugin -Use the static **`Tempo.extend()`** method. This allows you to add terms dynamically without modifying the library source. +Use the static **`Tempo.extend()`** method. This allows you to add Terms dynamically without modifying the library source. ```ts import { Tempo } from '@magmacomputing/tempo/core'; @@ -245,11 +251,11 @@ import { MySeasonTerm } from './term.myseason.js'; Tempo.extend(MySeasonTerm); ``` -Every `Tempo` instance created after that point will have the custom term available. +Every `Tempo` instance created after that point will have the custom Term available. ### Using Custom Configuration in Terms -Since `Tempo` preserves non-standard configuration options in its internal `config` object, you can use `Tempo.init()` to provide values that your custom term plugin can later reference. +Since `Tempo` preserves non-standard configuration options in its internal `config` object, you can use `Tempo.init()` to provide values that your custom Term plugin can later reference. ```ts // 1. Initialize with a custom 'business' config option @@ -306,7 +312,7 @@ return keyOnly ? 'MyTerm' : { ``` ## 🕒 Terms in Tickers -Any term that provides `start` and `end` boundaries can be used to drive a `Tempo.ticker`. This is ideal for logic that doesn't follow a fixed duration (like seasons or fiscal quarters). +Any Term that provides `start` and `end` boundaries can be used to drive a `Tempo.ticker`. This is ideal for logic that doesn't follow a fixed duration (like seasons or fiscal quarters). ```ts // Pulse every time a new fiscal quarter begins @@ -324,14 +330,14 @@ To ensure a custom `Term` plugin integrates fully with Tempo, follow these guide 1. **Static `ranges` Export**: Always include the `ranges` property in your `defineTerm` configuration. This enables **programmatic discovery** via `Tempo.terms` and allows the Ticker to automatically calculate next-pulse intervals. 2. **Metadata-First Boundaries**: If your plugin handles multiple sets (e.g. hemispheres or cultural calendars), avoid using array indices like `ranges[0]`. Instead, add marker fields like **`sphere`** or **`group`** to each range object and use `.filter()` inside your `define` function. 3. **Memoization Safety**: Keep the `define` function pure. It will only be called once per instance access. -4. **Math Readiness**: Always use `getTermRange` or provide boundaries. Without them, users cannot use your term in `add()`, `set()`, or `ticker()`. -5. **Key consistency**: It is valid to remap the returned scope `key` (for example, `cfy` -> `FY2024`) when that is the semantic value your term represents. Be intentional and keep it consistent with your `ranges` lookup and consumer expectations. -6. **Unique Names**: Keep `key` and `scope` globally unique across all registered terms. Collisions are unsupported and may produce order-dependent lookups. +4. **Math Readiness**: Always use `getTermRange` or provide boundaries. Without them, users cannot use your Term in `add()`, `set()`, or `ticker()`. +5. **Key consistency**: It is valid to remap the returned scope `key` (for example, `cfy` -> `FY2024`) when that is the semantic value your Term represents. Be intentional and keep it consistent with your `ranges` lookup and consumer expectations. +6. **Unique Names**: Keep `key` and `scope` globally unique across all registered Terms. Collisions are unsupported and may produce order-dependent lookups. ## 🧭 Best Practices: Idempotency & Side-Effects ::: warning -Because term lookups are **memoized** (cached) on the instance, the `define` function must be **pure and idempotent**. It should only depend on the current `Tempo` instance state and its configuration (`this.config`). +Because Term lookups are **memoized** (cached) on the instance, the `define` function must be **pure and idempotent**. It should only depend on the current `Tempo` instance state and its configuration (`this.config`). -**Never apply side-effects** or modify external state within a term definition. The function is only guaranteed to run once per instance access; subsequent reads will return the cached value directly without re-executing your logic. +**Never apply side-effects** or modify external state within a Term definition. The function is only guaranteed to run once per instance access; subsequent reads will return the cached value directly without re-executing your logic. ::: diff --git a/packages/tempo/doc/tempo.ticker.md b/packages/tempo/doc/tempo.ticker.md index 91f251e0..cd9be6bf 100644 --- a/packages/tempo/doc/tempo.ticker.md +++ b/packages/tempo/doc/tempo.ticker.md @@ -4,7 +4,7 @@ ## Installation -To use the ticker, you can import the module as a side effect or import the `TickerModule` directly. The side-effect import (`import '@magmacomputing/tempo/ticker'`) registers the `Tempo.ticker` method automatically, while importing the `TickerModule` explicitly requires you to call `Tempo.extend(TickerModule)` to register it with the core library: +To use the Ticker, you can import the module as a side effect or import the `TickerModule` directly. The side-effect import (`import '@magmacomputing/tempo/ticker'`) registers the `Tempo.ticker` method automatically, while importing the `TickerModule` explicitly requires you to call `Tempo.extend(TickerModule)` to register it with the core library: ```typescript // Pattern A: One-line activation (Side effect) @@ -18,7 +18,7 @@ Tempo.extend(TickerModule); ``` ### Direct Access -If you need to access the [Reporting & Registry](#reporting--registry) API (like `Ticker.active`), you should import the `Ticker` namespace: +If you need to access the [Reporting & Registry](#reporting-registry) API (like `Ticker.active`), you should import the `Ticker` namespace: ```typescript import { Ticker } from '@magmacomputing/tempo/ticker'; @@ -28,7 +28,7 @@ console.log(Ticker.active); ## 🚀 Enhancements -The ticker now supports a unified **Options** object, enabling professional resource management and semantic duration-based intervals. +The Ticker supports a unified **Options** object, enabling professional resource management and semantic duration-based intervals. ### 1. Semantic Intervals (Duration Objects) Instead of raw numeric seconds, you can use `DurationLike` objects for clarity. This is especially powerful for variable-length intervals like **months**. @@ -80,7 +80,7 @@ await using daily = Tempo.ticker({ ``` ### 5. Backwards Tickers (Countdowns) -By providing a **negative** interval, you can create a ticker that moves backwards in time. +By providing a **negative** interval, you can create a Ticker that moves backwards in time. ```typescript // Count down from 10 seconds, moving backwards 1s at a time @@ -94,7 +94,7 @@ using countdown = Tempo.ticker({ seconds: -1, seed: "00:00:10" }, (t, stop) => { ### 1. Resource Management (Recommended) -Using the `using` and `await using` keywords ensures that tickers are automatically stopped when they go out of scope. +Using the `using` and `await using` keywords ensures that Tickers are automatically stopped when they go out of scope. ```typescript // Pattern A: Automatic cleanup for callback-based ticker @@ -113,7 +113,7 @@ Using the `using` and `await using` keywords ensures that tickers are automatica ### 2. Manual Control (Programmatic Stop) -If you are not using the `using` or `await using` keywords, or if you need to stop the ticker from outside its own loop (e.g., in a separate event handler), you can manually call the `stop()` method on the ticker object. +If you are not using the `using` or `await using` keywords, or if you need to stop the Ticker from outside its own loop (e.g., in a separate event handler), you can manually call the `stop()` method on the Ticker object. ```typescript // Pattern A: Stop a callback-based ticker @@ -149,7 +149,7 @@ ticker.on('stop', (t) => console.log('Ticker stopped at:', t.fmt.weekTime)); For `'stop'` listeners, the `stop` callback argument is included for signature consistency; however, invoking it after stop has already occurred is a no-op. ### 4. Manual Pulsing (.pulse) -In some scenarios, you may want to drive a ticker manually (e.g., from a UI event or a WebSocket message) while still benefiting from the ticker's internal state management and listeners. +In some scenarios, you may want to drive a Ticker manually (e.g., from a UI event or a WebSocket message) while still benefiting from the Ticker's internal state management and listeners. ```typescript const ticker = Tempo.ticker({ seconds: 1 }); // Still has a 1s duration logic @@ -157,33 +157,16 @@ const ticker = Tempo.ticker({ seconds: 1 }); // Still has a 1s duration logic ticker.pulse(); // Manually advance and notify listeners ``` -### 5. Reporting & Management -The `Ticker` class provides a centralized way to monitor all active (non-stopped) tickers. This is essential for debugging and ensuring that resources are properly disposed. -#### Ticker.active -A static getter that returns an array of snapshots for every live ticker. -```typescript -import { Ticker } from '@magmacomputing/tempo/ticker'; - -// Monitor all active tickers -const monitoring = Ticker.active; - -console.log(`There are ${monitoring.length} active tickers.`); - -monitoring.forEach(({ ticks, next, interval }) => { - console.log(`- Pulsed ${ticks} times. Next at: ${next}. Interval:`, interval); -}); -``` - -## 🧟 Zombie Tickers (Warning) +## 🧟 Zombie Tickers (Warning) {#zombie-tickers-warning} -In a Node.js environment, `Tempo.ticker()` uses background timers (`setTimeout`) to drive its pulses. If you do not explicitly stop a ticker, it becomes a **"Zombie Ticker"** that continues to run indefinitely, even if the variable that created it has gone out of scope. +In a Node.js environment, `Tempo.ticker()` uses background timers (`setTimeout`) to drive its pulses. If you do not explicitly stop a Ticker, it becomes a **"Zombie Ticker"** that continues to run indefinitely, even if the variable that created it has gone out of scope. ### The Risks: -- **Process Hangs**: Node.js will not exit a process if there are active timers. Undisposed tickers are a common cause of "mysterious hangs" at the end of test runs. -- **Test Inconsistency**: Leaked tickers can continue to fire while subsequent tests are running, leading to flaky assertions and "impossible" state changes. -- **Memory Leaks**: Each active ticker maintains closures that prevent garbage collection of the `Tempo` instance and its listeners. +- **Process Hangs**: Node.js will not exit a process if there are active timers. Undisposed Tickers are a common cause of "mysterious hangs" at the end of test runs. +- **Test Inconsistency**: Leaked Tickers can continue to fire while subsequent tests are running, leading to flaky assertions and "impossible" state changes. +- **Memory Leaks**: Each active Ticker maintains closures that prevent garbage collection of the `Tempo` instance and its listeners. ### The Solution: Always use the **Disposer Pattern** (`using` or `await using`) or a `try...finally` block to guarantee cleanup: @@ -217,17 +200,17 @@ The object returned by `Tempo.ticker()` (or an instance of the `Ticker` class) i | `on(event, cb)` | Registers a listener for the `'pulse'`, `'stop'`, or `'catch'` events. | | `pulse()` | Manually triggers a pulse, advances state, and notifies listeners. Returns the new `Tempo`. | | `info` | Read-only getter returning `{ next, ticks, limit, interval, stopped }`. | -| `stop()` | Stops the ticker, clears active timers, and immediately resolves any pending async iteration Promises. | +| `stop()` | Stops the Ticker, clears active timers, and immediately resolves any pending async iteration Promises. | | `[Symbol.dispose]` | Standard cleanup for `using` blocks. | | `[Symbol.asyncDispose]` | Standard async cleanup for `await using` blocks. | | `[Symbol.asyncIterator]` | Standard async iteration support (for `for await` loops). | -## 📊 Reporting & Registry +## Reporting & Registry {#reporting-registry} -The `Ticker` class maintains a static registry of all currently active tickers. This is useful for debugging, monitoring, or cleanup checks. +The `Ticker` class maintains a static registry of all currently active Tickers. This is useful for debugging, monitoring, or cleanup checks. ### `Ticker.active` -A static getter that returns an array of [`Ticker.Snapshot`](#tickersnapshot) objects for all active (non-stopped) tickers. +A static getter that returns an array of [`Ticker.Snapshot`](#tickersnapshot) objects for all active (non-stopped) Tickers. ```typescript import { Ticker } from '@magmacomputing/tempo/ticker'; @@ -254,14 +237,14 @@ type Snapshot = { ## 🎯 One-Shot Ticker (Meeting Alerts) -You can use the ticker as a "one-shot" timer for specific events by simply specifying a **seed** value. This is perfect for setting up a single alert (e.g., for a meeting) that cleans itself up immediately after firing. +You can use the Ticker as a "one-shot" timer for specific events by simply specifying a **seed** value. This is perfect for setting up a single alert (e.g., for a meeting) that cleans itself up immediately after firing. ::: tip **Seed-Only Logic**: Providing a `seed` (as a string or in an options object) without any other duration-based keys (`seconds`, `minutes`, etc.) or a `limit` implies a `limit: 1`. -Effectively, `Tempo.ticker('Fri 10am')` and `Tempo.ticker({ seed: 'Fri 10am' })` and `Tempo.ticker({ seed: 'Fri 10am', limit: 1 })` are all treated as one-shot tickers. +Effectively, `Tempo.ticker('Fri 10am')` and `Tempo.ticker({ seed: 'Fri 10am' })` and `Tempo.ticker({ seed: 'Fri 10am', limit: 1 })` are all treated as one-shot Tickers. -**Inclusive Boundaries**: Termination conditions (`limit` and `until`) are **inclusive**. A ticker with `limit: 1` will pulse exactly once before stopping. +**Inclusive Boundaries**: Termination conditions (`limit` and `until`) are **inclusive**. A Ticker with `limit: 1` will pulse exactly once before stopping. ::: ```typescript @@ -289,12 +272,12 @@ Tempo.ticker({ ::: ::: warning -While `limit: 1` handles the stop condition automatically, always remember that if you are using long-running tickers without a limit, you **must** use the [Disposer Pattern](#zombie-tickers-warning) or manual `stop()` to avoid memory leaks and zombie processes. +While `limit: 1` handles the stop condition automatically, always remember that if you are using long-running Tickers without a limit, you **must** use the [Disposer Pattern](#zombie-tickers-warning) or manual `stop()` to avoid memory leaks and zombie processes. ::: ## 🧭 Advanced: Syncing Multiple Clocks -If you need to show multiple timezones on a dashboard, avoid creating multiple tickers. Instead, use a single **Master Ticker** to drive all views. This prevents "drift" between the clocks and is much more efficient. +If you need to show multiple timezones on a dashboard, avoid creating multiple Tickers. Instead, use a single **Master Ticker** to drive all views. This prevents "drift" between the clocks and is much more efficient. ### Using Signals (Recommended) diff --git a/packages/tempo/package.json b/packages/tempo/package.json index c5a1f33e..91d572f6 100644 --- a/packages/tempo/package.json +++ b/packages/tempo/package.json @@ -1,6 +1,6 @@ { "name": "@magmacomputing/tempo", - "version": "2.9.3", + "version": "2.10.0", "description": "The Tempo core library", "author": "Magma Computing Solutions", "license": "MIT", @@ -21,6 +21,9 @@ "fluent", "parsing" ], + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, "type": "module", "sideEffects": [ "**/tempo.index.js", @@ -113,6 +116,10 @@ "development": "./src/module/module.index.ts", "default": "./dist/module/module.index.js" }, + "#tempo/license": { + "development": "./src/support/support.license.ts", + "default": "./dist/support/support.license.js" + }, "#tempo/*.js": { "development": "./src/*.ts", "default": "./dist/*.js" @@ -199,12 +206,12 @@ "bare": "tsx --conditions=development -i --harmony-temporal", "core": "cross-env TEMPO_LITE=true tsx --conditions=development -i --harmony-temporal --import ./bin/core.ts", "parse": "cross-env TEMPO_LITE=true tsx --conditions=development -i --harmony-temporal --import ./bin/parse.ts", - "build": "npm run clean && tsc -b && npm run build:bundle && npm run build:resolve", + "build": "npm run clean && tsc -b && npm run build:bundle && npm run build:resolve && if [ ! -f dist/support/support.license.js ]; then echo '🚨 ERROR: dist/support/support.license.js is missing from dist!'; exit 1; fi", "build:bundle": "rollup -c", "build:resolve": "tsx bin/resolve-types.ts", "clean": "rm -rf dist && (tsc -b --clean || true)", "publish": "npm publish --access public", - "prepublishOnly": "if [ $(git rev-parse --abbrev-ref HEAD) != main ]; then echo 'ERROR: Must be on main branch to publish.'; exit 1; fi && npm run build", + "prepublishOnly": "if [ $(git rev-parse --abbrev-ref HEAD) != main ]; then echo 'ERROR: Must be on main branch to publish.'; exit 1; fi && if [ -z \"$TEMPO_LICENSE_PATH\" ] || [ ! -f \"$TEMPO_LICENSE_PATH\" ]; then echo '🚨 ERROR: TEMPO_LICENSE_PATH is missing or invalid. Cannot publish Premium build.'; exit 1; fi && npm run build", "docs:api": "typedoc", "docs:dev": "npm run build && npm run docs:api && vitepress dev", "docs:build": "npm run build && npm run docs:api && vitepress build", @@ -219,9 +226,12 @@ }, "devDependencies": { "@js-temporal/polyfill": "^0.5.1", - "@magmacomputing/library": "2.9.3", + "@magmacomputing/library": "2.10.0", "@rollup/plugin-alias": "^6.0.0", + "esbuild": "^0.25.12", + "javascript-obfuscator": "^5.4.2", "magic-string": "^0.30.21", + "rollup-plugin-esbuild": "^6.2.1", "typedoc": "^0.28.19", "typedoc-plugin-markdown": "^4.11.0", "typedoc-vitepress-theme": "^1.1.2", @@ -231,4 +241,4 @@ "doc": "doc", "test": "test" } -} +} \ No newline at end of file diff --git a/packages/tempo/plan/licensing_architecture.md b/packages/tempo/plan/licensing_architecture.md index 04f43e61..490edb19 100644 --- a/packages/tempo/plan/licensing_architecture.md +++ b/packages/tempo/plan/licensing_architecture.md @@ -1,48 +1,81 @@ -# Tempo Licensing Architecture (v2.9.4 Proposal) +# Tempo Licensing Architecture & Plugin Strategy ## Objective -Enable a robust, secure, and flexible licensing mechanism for premium Tempo plugins without bloating the core engine or compromising user security. +Implement a secure, user-friendly licensing system for Tempo plugins that enables monetization and IP protection without creating high friction for developers. -## Architectural Decisions +## The "No-PAT" Distribution Model +To eliminate developer friction (configuring registries/PATs), all plugins are distributed via the public npmjs registry. -### 1. Separation of Concerns -- **Core Tempo**: Acts only as a "Parking Spot" for the license string. It does NOT contain logic for decoding JWTs or verifying signatures. -- **Plugins**: House all enforcement logic. The plugin's `install()` method is responsible for fetching the license from the state and validating it. +- **Storage**: Private source code resides in Magma Computing's GitHub organization. +- **Distribution**: Plugins are built, minified, and obfuscated before being published as public packages under the `@magmacomputing` scope (e.g., `@magmacomputing/plugin-term`). +- **Access**: Anyone can `npm install`, but functionality is gated by the "Tempo Activation Key" (JWT). +- **Free Tier**: The "Astrological Sign" plugin serves as a free reference implementation for users to test the activation and support model. -### 2. Internal State Branching -To prevent sensitive license keys from appearing in diagnostic logs: -- **Location**: The license will reside in a separate branch of the internal state (e.g., `state.auth` or directly on `state.license`). -- **Isolation**: It must NOT be part of the `config` or `parse` objects, which are frequently passed to `Logify` for debugging. +## Activation & Validation -### 3. Cascade of License Discovery -The engine will look for a license key in the following order: +### 1. The Tempo Activation Key (JWT) +The key is a JSON Web Token issued to the customer. It supports three tiers of usage: + +| Claim | Standard/Trial | Enterprise/Distribution | +| :--- | :--- | :--- | +| `aud` (Audience) | Array of domains (e.g. `["localhost", "site.com"]`) | `"*"` (Wildcard - works on any domain) | +| `exp` (Expiry) | Unix timestamp (e.g. 1 year from issue) | `0` (Perpetual - never expires) | +| `jti` | Unique ID for revocation | Unique ID for revocation | + +### 2. Cascade of License Discovery +Plugins will look for the activation key in the following order: 1. **Explicit**: `Tempo.init({ license: '...' })` -2. **Discovery**: `globalThis[TEMPO_DISCOVERY].license` +2. **Discovery**: `globalThis.__TEMPO_DISCOVERY__.license` 3. **Environment**: `process.env.TEMPO_LICENSE` (Server-side) -4. **Storage**: `localStorage.getItem('tempo_license')` (Client-side) +4. **Configuration**: `.temporc` or `tempo.config.json` (CWD) +5. **Storage**: `localStorage.getItem('tempo_license')` (Client-side) + +### 3. Verification Logic +- **Domain Locking**: The plugin verifies `window.location.hostname` against the `aud` claim (unless `aud` is `*`). +- **Grace Period**: If a key is expired, the plugin enters a 7-day "Grace Period," allowing full functionality while emitting a `console.warn`. +- **Revocation**: + - Plugins fetch a **Signed Revocation List** (JWS) from Magma's servers every **7 days**. + - The fetch is shared across all Tempo plugins to minimize overhead. + - If offline, the plugin "Fails Open" and relies on the JWT's internal expiry. + - The list is self-cleaning; keys are removed once they naturally expire. + +### 4. The License "Wallet" (Discovery & Persistence) +To prevent "Token Fatigue" and the need to re-supply keys, Tempo and its plugins treat the environment as a persistent wallet. -## Security & Risks -- **XSS**: Keys in `localStorage` are vulnerable; documentation must warn users to prefer secure server-side injection where possible. -- **Leakage**: Even with separate branching, we must ensure internal state dumps (for support) redact this branch by default. +- **One Key, Many Scopes**: A single JWT can contain multiple plugin identifiers in its `scope` claim (e.g., `scope: ["term", "ticker"]`). +- **Global Discovery (Browser)**: Developers can define `window.__TEMPO_DISCOVERY__ = { license: '...' }` at the very top of their HTML. Any Tempo instance or plugin will automatically "hydrate" from this global wallet. +- **Internal Stashing**: Once a license is discovered or provided via `init()`, Tempo core caches it in its internal static state. This ensures that a plugin imported in a different module (or a secondary Tempo instance) can still find the active license without being explicitly passed a key. +- **Cross-Session Persistence (Opt-in & Unsafe)**: By default, Tempo avoids `localStorage` due to XSS token-theft risks. Persistence is **opt-in** via the `enableCrossSessionPersistence` flag. + - **Recommended**: Use memory or `sessionStorage` for sensitive keys. + - **Mitigation Checklist**: + - Implement strict Content Security Policy (CSP). + - Use HttpOnly cookies for token delivery where possible. + - Ensure rigorous input sanitization. + - Use short TTLs and rotate/revoke tokens frequently. -## Remote Invalidation & Revocation +### 5. Revocation Infrastructure (The Control Tower) +To maintain security without manual intervention on the customer side: -Since Tempo is designed for offline-first stability, we avoid a "mandatory phone-home" on every instance. Instead, we propose the following strategies for invalidating compromised licenses: +- **Host**: `api.magmacomputing.com.au` +- **Endpoint**: `/tempo/v1/revoked.jws` (Versioned for future-proofing). +- **Format**: The list is a Signed JWS. Plugins verify it using an embedded Public Key. +- **Management**: + - A local `registry/` folder in the private `tempo-plugin` repo tracks the revocation state. + - CLI tools (`npm run license:revoke`) handle the signing and deployment of the updated JWS to the production host. +- **Security**: The **Private Key** for signing is stored as a GH Secret and never committed. The **Public Key** is baked into the obfuscated plugin source. +- **Fail-Safe**: If the endpoint is unreachable, plugins "Fail Open" and rely on the internal JWT expiry to ensure no service disruption for legitimate users. -### 1. Short-lived JWTs (Rotation) -- Issue licenses with 30- or 90-day expiry. -- Use a lightweight refresh mechanism to update the license during application build or bootstrap. -- **Benefit**: Naturally limits the window of exposure for any single leaked key. +## Implementation Roadmap -### 2. Revocation Lists (Blacklisting) -- Plugins can periodically fetch a `revoked.json` list of blacklisted JWT IDs (`jti`). -- If a breach is detected, the `jti` is added to the list, and the plugin disables itself upon the next update/fetch. +### Phase 1: Support Infrastructure +- [ ] Add `license` to `Internal.State` and `BaseOptions` in Tempo Core. +- [ ] Implement the Discovery Cascade and Shared Revocation Service. +- [ ] Ensure `Logify` and internal state dumps redact the `state.license` branch. -### 3. Graceful Fallback -- If a license is invalid or expired, the plugin should not crash the application. -- **Behavior**: Downgrade to "Limited" mode, log a warning, but ensure the core Tempo engine continues to function. +### Phase 2: Reference Plugin (Astro) +- [ ] Create the `@magmacomputing/plugin-astro` workspace. +- [ ] Implement JWS signature verification and JWT decoding. +- [ ] Set up the obfuscated build pipeline for public npmjs distribution. -## Next Steps (v2.9.4) -- Add `license` to `Internal.State` and `BaseOptions`. -- Update `support.init.ts` to implement the Discovery Cascade. -- Provide a reference implementation in the `tempo-plugin` mono-repo showing how to decode a JWT using Tempo's native date utilities. +### Phase 3: Commercial Plugins +- [ ] Roll out `term`, `ticker`, and other premium extensions using the proven Astro model. diff --git a/packages/tempo/plan/licensing_strategy.md b/packages/tempo/plan/licensing_strategy.md new file mode 100644 index 00000000..c8f7fbe6 --- /dev/null +++ b/packages/tempo/plan/licensing_strategy.md @@ -0,0 +1,212 @@ +Now that we have the 'Plugin' architecture, we need to determine how this will merge into the Tempo v2 strategy. + +(All of the scenarios below assume the user has already installed Tempo and the desired Plugins) +$ npm install @magmacomputing/tempo +$ npm install @magmacomputing/tempo-plugin-astro + +in the final static{} block of the tempo.class, we are running Tempo.init() automatically to bootstrap the application. + +To keep Tempo feeling 'light' +*> if auto Tempo.init() discovers that there is no License Key, then it should not fetch the JWS revocation list. +*> if auto Tempo.init() discovers that there is a License Key, then it should kick off the **Optimistic Sync** process. +*> The license state should be stored in the `TempoRuntime` singleton (via the global `$Bridge` symbol) to ensure it is shared across all bundles and plugins. +*> If the license key is invalid / expired / revoked, a `console.warn` is issued immediately upon background detection, but application execution is not halted. + +#### Architectural Roles + +To maintain a clean separation of concerns, the licensing system is divided into three distinct roles: + +1. **The Validator (#tempo/license module)**: + * **Async Heavyweight**: Only loaded via `import()` if a license key is discovered. + * **Cryptographic Authority**: Performs the actual RSA/ECDSA verification of the JWT against the Public Key. + * **JWS Synchronization**: Fetches and caches the JWS revocation list (persisted for 7 days). + * **State Enforcement**: If verification fails or a license is revoked, it updates the `TempoRuntime` status to `'revoked'` and wipes the Term cache for premium plugins. +2. **The Gatekeeper (Tempo Core)**: + * **Discovery Cascade**: Finds the license key string. + * **Optimistic Decoder**: Performs a synchronous Base64 decode of the JWT (without verification) to read the intended scopes and expiry. + * **Lazy Proxy Guard**: Implements the Proxy on `.term` that uses the current `TempoRuntime` state to decide whether to allow access. +3. **The Plugins (e.g., Astro)**: + * **License Agnostic**: They contain **zero** licensing or validation logic. They simply register their terms and trust the Gatekeeper. + +#### Optimistic Sync & Background Verification + +To keep `Tempo.init()` synchronous and the UX instantaneous, Tempo uses an optimistic model: + +1. **Init (Sync)**: Tempo discovers the key and does a "fast-decode" to see if it *claims* to have the right scopes. It sets the state to `'pending'`. +2. **Access (Sync)**: The Proxy allows access to `.astro` based on the optimistic decode. +3. **Verify (Async)**: In the background, Tempo dynamic-imports the `#tempo/license` module. The Validator then performs the real cryptographic check and JWS fetch. +4. **The Reckoning**: If the background check fails (fake key or revoked), the Validator flips the state to `'revoked'`, wipes the premium caches, and logs a warning. This typically happens within 50ms of startup. + +#### Discovery Cascade + +Tempo will search for a license key in the following order (from most explicit to most global): + +1. **Explicit**: `Tempo.init({ license: '...' })` +2. **Discovery**: `globalThis.__TEMPO_DISCOVERY__.license` +3. **Environment**: `process.env.TEMPO_LICENSE` +4. **Configuration**: `.temporc` or `tempo.config.json` +5. **Global**: `globalThis.TEMPO_LICENSE` (Legacy / Convenience) + +#### Scalability & 3rd-Party Plugin Support + +The "Decoupled Gatekeeper" architecture is designed to scale into a **Licensing as a Service (LaaS)** platform for 3rd-party developers. + +1. **Magma Authority Model**: Tempo Core acts as the centralized authority. A single "Magma Public Key" is used to verify all licenses, regardless of the plugin author. +2. **Multi-Author Scopes**: License JWTs can contain granular scopes (e.g., `['astro', 'vendor-xyz-finance']`). The Core's Lazy Proxy Guard automatically handles the "Gatekeeping" for these 3rd-party keys without requiring the author to write any licensing logic. +3. **Unified Marketplace**: This allows for "Bundle Licenses" where a single key can unlock a suite of plugins from different authors. +4. **Zero Overhead for Authors**: 3rd-party plugins remain lightweight and focus solely on their functional logic, trusting Tempo to manage the monetization and security layer. + + +Here is the UX I am hoping to create for our Users: + +### Scenario 1 +The user has *not* purchased a License Key +```typescript +import {Tempo} from '@magmacomputing/tempo'; + +console.log(new Tempo().term.astro); + +``` +Expected outcome: +*> the 'Tempo.init()' that is part of the package import looks for a license key (discovery cascade) and finds nothing. +*> there is *no* fetch for the latest JWS revocation list. +*> console.log's "undefined" + +### Scenario 2 +The user has *not* purchased a License key +```typescript +import {Tempo} from '@magmacomputing/tempo'; +import '@magmacomputing/tempo-plugin-astro'; + +console.log(new Tempo().term.astro); + +``` +Expected outcome: +*> Tempo.init()'s discovery cascade looks for a license key and finds nothing. +*> there is no fetch for the latest JWS revocation list. +*> the side-effect import of 'tempo-plugin-astro' loads the AstroTerm. +*> No checking of the license is done *until* an 'astro' property is accessed. +*> console.log's undefined, and warn's that the 'astro' term is not available and can be obtained by purchasing a license key. + +### Scenario 3 +The user has a valid License Key + +```typescript +import {Tempo} from '@magmacomputing/tempo'; +import '@magmacomputing/tempo-plugin-astro'; + +console.log(new Tempo().term.astro); +``` + +Expected Outcome: +*> If the license key is found in the discovery cascade, it fetches the JWS revocation list. +*> If the license is valid and not revoked, it returns the 'astro' term. + +### Scenario 4 +The user has an **Expired** License Key + +```typescript +// Assume process.env.TEMPO_LICENSE is set to an expired JWT +import {Tempo} from '@magmacomputing/tempo'; +import '@magmacomputing/tempo-plugin-astro'; + +console.log(new Tempo().term.astro); +``` + +Expected Outcome: +*> `Tempo.init()` detects the key, fetches the JWS. +*> Detection of expiry logs a warning: `⚠️ Tempo: License 'xxx' has expired.` +*> Accessing `.astro` returns `undefined` and logs: `⚠️ Tempo: 'astro' requires an active license.` + +### Scenario 5 +The user has a **Revoked** License Key + +```typescript +// Assume the license JTI is present in the latest JWS revocation list +import {Tempo} from '@magmacomputing/tempo'; +import '@magmacomputing/tempo-plugin-astro'; + +console.log(new Tempo().term.astro); +``` + +Expected Outcome: +*> `Tempo.init()` fetches the JWS list. +*> Validation detects the license JTI is revoked. +*> Immediate warning: `⚠️ Tempo: License 'xxx' has been revoked and is no longer valid.` +*> Accessing `.astro` returns `undefined`. + +### Scenario 6 +**Late Initialization** (Programmatic) + +```typescript +import {Tempo} from '@magmacomputing/tempo'; +import '@magmacomputing/tempo-plugin-astro'; + +// 1. Initial access without license +console.log(new Tempo().term.astro); // undefined + warning + +// 2. Late initialization +Tempo.init({ license: 'VALID_JWT' }); + +// 3. Subsequent access +console.log(new Tempo().term.astro); // Returns AstroTerm +``` + +Expected Outcome: +*> The Proxy on `.term` re-evaluates the license state after a manual `Tempo.init()` call. +*> Transition from `undefined` to a valid Term is seamless within the same application process. + +### Scenario 7 +**Offline Mode / Network Failure** + +```typescript +// Assume the JWS fetch fails due to network issues +import {Tempo} from '@magmacomputing/tempo'; +import '@magmacomputing/tempo-plugin-astro'; + +console.log(new Tempo().term.astro); +``` + +Expected Outcome: +*> `Tempo.init()` attempts to fetch the JWS and fails. +*> Tempo "fails-safe": it logs a warning about the network failure but **allows** the license to remain valid (assuming the JWT itself is cryptographically sound and not yet expired). +*> Logic: Revocation checks are "best effort." We do not punish users for temporary offline status unless the license itself has expired. + +#### Discoverability + +To allow developers to inspect the license state (e.g., in a CLI or dashboard), a static `license` getter is provided. + +**The `Pledge` Model**: +The JWS revocation fetch is an asynchronous operation. To handle this gracefully, `Tempo.license.jws` returns a **Pledge** (a specialized Tempo async container). + +```typescript +// Example: Checking status in a CLI or REPL +console.log(Tempo.license.status); // 'active' | 'expired' | 'revoked' | 'none' +console.log(Tempo.license.jws.status); // 'pending' | 'resolved' | 'rejected' + +// Waiting for the fetch to complete +await Tempo.license.jws; +console.log(Tempo.license.status); // Guaranteed to be final +``` + +### Scenario 8 +**Discoverability and Async Handling** + +```typescript +import {Tempo} from '@magmacomputing/tempo'; + +// 1. Immediate check +console.log(Tempo.license.jws.status); // 'pending' + +// 2. Await the Pledge +await Tempo.license.jws; + +// 3. Final check +console.log(Tempo.license.jws.status); // 'resolved' +console.log(Tempo.license.plugins.astro.status); // 'active' +``` + +Expected Outcome: +*> `Tempo.license` provides a synchronous snapshot of the `TempoRuntime`. +*> `Tempo.license.jws` acts as a `Pledge` that can be awaited to ensure the revocation list has been processed. +*> This allows the library to stay non-blocking while providing a standard way to synchronize when needed. diff --git a/packages/tempo/plan/v3-architecture-discoverability.md b/packages/tempo/plan/v3-architecture-discoverability.md new file mode 100644 index 00000000..bb05da31 --- /dev/null +++ b/packages/tempo/plan/v3-architecture-discoverability.md @@ -0,0 +1,51 @@ +# Tempo v3.0.0: Architecture & Discoverability Plan + +## Objective +Transition Tempo from a "Self-Contained" bundle to a "Modular Monorepo" participant. This involves decoupling `@magmacomputing/library` into a standalone, reachable package to support a growing ecosystem of private monorepos. + +## Current State (v2.x) +- **Bundled Library**: The `#library` workspace is compiled directly into `tempo/dist/lib`. +- **Consumption**: Tempo is published as a zero-dependency package. +- **Limitation**: `library` is not easily reachable by other monorepos (e.g., the `white` repo). +- **Inefficiency**: Multiple packages using `library` results in duplicate code in the final user bundle. + +## The v3.0.0 Vision + +### 1. Library Publication +- **Registry**: Move `@magmacomputing/library` to npmjs as a public package. +- **Versioning**: Ensure independent versioning for the library to support multiple consumers at different lifecycles. + +### 2. Dependency Management +- **ESM Builds**: Tempo will list `@magmacomputing/library` as a formal `dependency`. This allows modern bundlers (Vite, Webpack) to deduplicate the library code across multiple internal packages. +- **Hybrid Bundling**: + - **Granular ESM**: No longer carries `lib/`. Imports from `@magmacomputing/library`. + - **Global Bundle (IIFE)**: Remains self-contained for easy `